blob: ea4d33ba4ab81c93b446e2806185c8ed4eb66017 [file] [log] [blame]
Sonal Kasliwala0bbe6c2020-01-06 10:46:30 +00001/*
2 * Copyright 2016-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.opencord.cordmcast;
17
18import static org.junit.Assert.assertNotNull;
19import static org.junit.Assert.assertTrue;
20
21import java.util.Arrays;
22import java.util.Collection;
23import java.util.Dictionary;
24import java.util.HashSet;
25import java.util.Hashtable;
26import java.util.Map;
27import java.util.Set;
28import static org.easymock.EasyMock.expect;
29import static org.easymock.EasyMock.replay;
30import org.easymock.EasyMock;
31import org.junit.After;
32import org.junit.Before;
33import org.junit.Test;
34import org.onosproject.cfg.ComponentConfigService;
35import org.onosproject.mcast.api.McastEvent;
36import org.onosproject.mcast.api.McastRouteUpdate;
37import org.onosproject.mcast.api.MulticastRouteService;
38import org.onosproject.net.ConnectPoint;
39import org.onosproject.net.DeviceId;
40import org.onosproject.net.HostId;
41import org.onosproject.net.config.NetworkConfigRegistryAdapter;
42import org.onosproject.net.device.DeviceServiceAdapter;
43import org.onosproject.net.flow.TrafficSelector;
44import org.onosproject.net.flow.TrafficTreatment;
45import org.onosproject.net.flow.criteria.IPCriterion;
46import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
47import org.onosproject.net.flowobjective.Objective;
48import org.onosproject.store.service.StorageServiceAdapter;
49import org.onosproject.store.service.TestConsistentMap;
50import org.osgi.service.component.ComponentContext;
51import com.google.common.collect.ImmutableMap;
52import com.google.common.collect.Sets;
53import static org.onlab.junit.TestTools.assertAfter;
54
55public class McastTest extends McastTestBase {
56
57 private CordMcast cordMcast;
58
59 private static final int WAIT_TIMEOUT = 1000;
60 private static final int WAIT = 250;
61 McastRouteUpdate previousSubject, currentSubject;
62
63 @Before
64 public void setUp() {
65 cordMcast = new CordMcast();
66
67 cordMcast.coreService = new MockCoreService();
68 cordMcast.flowObjectiveService = new MockFlowObjectiveService();
69 cordMcast.mastershipService = new TestMastershipService();
70 cordMcast.deviceService = new DeviceServiceAdapter();
71 cordMcast.networkConfig = new NetworkConfigRegistryAdapter();
72 cordMcast.cordConfigService = new MockCordConfigService();
73
74 cordMcast.storageService =
75 EasyMock.createMock(StorageServiceAdapter.class);
76 expect(cordMcast.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>());
77 replay(cordMcast.storageService);
78
79 Dictionary<String, Object> cfgDict = new Hashtable<String, Object>();
80 cfgDict.put("vlanEnabled", false);
81 cordMcast.componentConfigService =
82 EasyMock.createNiceMock(ComponentConfigService.class);
83 replay(cordMcast.componentConfigService);
84
85 cordMcast.mcastService = EasyMock.createNiceMock(MulticastRouteService.class);
86 expect(cordMcast.mcastService.getRoutes()).andReturn(Sets.newHashSet());
87 replay(cordMcast.mcastService);
88
89 ComponentContext componentContext = EasyMock.createMock(ComponentContext.class);
90 expect(componentContext.getProperties()).andReturn(cfgDict);
91 replay(componentContext);
92
93 cordMcast.activate(componentContext);
94
95 }
96
97 @After
98 public void tearDown() {
99 cordMcast.deactivate();
100 forwardMap.clear();
101 nextMap.clear();
102 }
103
104 @Test
105 public void testAddingSinkEvent() throws InterruptedException {
106
107 Set<ConnectPoint> sinks2Cp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B));
108 Map<HostId, Set<ConnectPoint>> sinks2 = ImmutableMap.of(HOST_ID_NONE, sinks2Cp);
109
110 //Adding the details to create different routes
111 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
112 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks2);
113 // Creating new mcast event for adding sink
114 McastEvent event = new McastEvent(McastEvent.Type.SINKS_ADDED, previousSubject, currentSubject);
115 cordMcast.listener.event(event);
116 synchronized (forwardMap) {
117 forwardMap.wait(WAIT_TIMEOUT);
118 }
119
120 // ForwardMap will contain the operation "Add" in the flowObjective. None -> CP_B
121 assertNotNull(forwardMap.get(DEVICE_ID_OF_A));
122 assertTrue(forwardMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.ADD);
123
124 // Output port number will be PORT_B i.e. 16
125 Collection<TrafficTreatment> traffictreatMentCollection =
126 nextMap.get(DEVICE_ID_OF_A).next();
127 assertTrue(1 == traffictreatMentCollection.size());
128 OutputInstruction output = null;
129 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
130 output = outputPort(trafficTreatment);
131 }
132 assertNotNull(output);
133 assertTrue(PORT_B == output.port());
134 // Checking the group ip address
135 TrafficSelector trafficSelector = forwardMap.get(DEVICE_ID_OF_A).selector();
136 IPCriterion ipCriterion = ipAddress(trafficSelector);
137 assertNotNull(ipCriterion);
138 assertTrue(MULTICAST_IP.equals(ipCriterion.ip().address()));
139
140 }
141
142 @Test
143 public void testAddToExistingSinkEvent() throws InterruptedException {
144
145 // Adding first sink (none --> CP_B)
146 testAddingSinkEvent();
147
148 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B));
149 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
150 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
151 sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B, CONNECT_POINT_C));
152 sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
153 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
154 // Again listening the mcast event with different output port ( none --> CP_B, CP_C)
155 McastEvent event = new McastEvent(McastEvent.Type.SINKS_ADDED, previousSubject, currentSubject);
156 cordMcast.listener.event(event);
157
158 // NextMap will contain the operation "ADD_TO_EXISTING" in the DefaultNextObjective.
159 assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
160 assertTrue(nextMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.ADD_TO_EXISTING));
161 // Output port number will be changed to 24 i.e. PORT_C
162 Collection<TrafficTreatment> traffictreatMentCollection = nextMap.get(DEVICE_ID_OF_A).next();
163 assertTrue(1 == traffictreatMentCollection.size());
164 OutputInstruction output = null;
165 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
166 output = outputPort(trafficTreatment);
167 }
168 assertNotNull(output);
169 assertTrue(PORT_C == output.port());
170 }
171
172 @Test
173 public void testRemoveSinkEvent() throws InterruptedException {
174
175 testAddToExistingSinkEvent();
176 // Handling the mcast event for removing sink.
177 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B, CONNECT_POINT_C));
178 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
179 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
180 sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_C));
181 sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
182 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
183 McastEvent event = new McastEvent(McastEvent.Type.SINKS_REMOVED, previousSubject, currentSubject);
184 cordMcast.listener.event(event);
185 // Operation will be REMOVE_FROM_EXISTING and nextMap will be updated. ( None --> CP_C)
186 assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
187 assertTrue(nextMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.REMOVE_FROM_EXISTING));
188
189 // Output port number will be PORT_B i.e. 16
190 // Port_B is removed from the group.
191 Collection<TrafficTreatment> traffictreatMentCollection =
192 nextMap.get(DEVICE_ID_OF_A).next();
193 assertTrue(1 == traffictreatMentCollection.size());
194 OutputInstruction output = null;
195 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
196 output = outputPort(trafficTreatment);
197 }
198 assertNotNull(output);
199 assertTrue(PORT_B == output.port());
200
201 }
202
203 @Test
204 public void testRemoveLastSinkEvent() throws InterruptedException {
205
206 testRemoveSinkEvent();
207 // Handling the mcast event for removing sink.
208 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_C));
209 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
210 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
211 sinksCp = new HashSet<ConnectPoint>(Arrays.asList());
212 sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
213 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
214 McastEvent event = new McastEvent(McastEvent.Type.SINKS_REMOVED, previousSubject, currentSubject);
215 cordMcast.listener.event(event);
216
217 // Operation will be REMOVE_FROM_EXISTING and nextMap will be updated. None --> { }
218 assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
219 assertTrue(nextMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.REMOVE_FROM_EXISTING));
220
221 // Output port number will be changed to 24 i.e. PORT_C
222 Collection<TrafficTreatment> traffictreatMentCollection = nextMap.get(DEVICE_ID_OF_A).next();
223 assertTrue(1 == traffictreatMentCollection.size());
224 OutputInstruction output = null;
225 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
226 output = outputPort(trafficTreatment);
227 }
228 assertNotNull(output);
229 assertTrue(PORT_C == output.port());
230 }
231
232 @Test
233 public void testUnkownOltDevice() throws InterruptedException {
234
235 // Configuration of mcast event for unknown olt device
236 final DeviceId deviceIdOfB = DeviceId.deviceId("of:1");
237
238 ConnectPoint connectPointA = new ConnectPoint(deviceIdOfB, PORT_A);
239 ConnectPoint connectPointB = new ConnectPoint(deviceIdOfB, PORT_B);
240 Set<ConnectPoint> sourcesCp = new HashSet<ConnectPoint>(Arrays.asList(connectPointA));
241 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList());
242 Set<ConnectPoint> sinks2Cp = new HashSet<ConnectPoint>(Arrays.asList(connectPointB));
243 Map<HostId, Set<ConnectPoint>> sources = ImmutableMap.of(HOST_ID_NONE, sourcesCp);
244
245 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
246 Map<HostId, Set<ConnectPoint>> sinks2 = ImmutableMap.of(HOST_ID_NONE, sinks2Cp);
247 //Adding the details to create different routes
248 McastRouteUpdate previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
249 McastRouteUpdate currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks2);
250 // Creating new mcast event for adding sink
251 McastEvent event = new McastEvent(McastEvent.Type.SINKS_ADDED, previousSubject, currentSubject);
252 cordMcast.listener.event(event);
253 // OltInfo flag is set to true when olt device is unkown
254 assertAfter(WAIT, WAIT * 2, () -> assertTrue(knownOltFlag));
255 assertTrue(0 == forwardMap.size());
256 assertTrue(0 == nextMap.size());
257
258 }
259
260 @Test
261 public void testRouteAddedEvent() throws InterruptedException {
262
263 //Adding the details to create different routes
264 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
265 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
266 // Creating new mcast event for route adding
267 McastEvent event = new McastEvent(McastEvent.Type.ROUTE_ADDED, previousSubject, currentSubject);
268 cordMcast.listener.event(event);
269 // There will be no forwarding objective
270 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
271 assertTrue(0 == nextMap.size());
272
273 }
274
275
276 @Test
277 public void testRouteRemovedEvent() throws InterruptedException {
278
279 testRouteAddedEvent();
280
281 //Adding the details to create different routes
282 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
283 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
284 // Creating new mcast event for route removing
285 McastEvent event = new McastEvent(McastEvent.Type.ROUTE_REMOVED, previousSubject, currentSubject);
286 cordMcast.listener.event(event);
287 // There will be no forwarding objective
288 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
289 assertTrue(0 == nextMap.size());
290
291 }
292
293
294 @Test
295 public void testSourceAddedEvent() throws InterruptedException {
296
297 // Adding route before adding source.
298 testRouteAddedEvent();
299
300 //Adding the details to create different routes
301 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
302 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
303 // Creating new mcast event for source adding
304 McastEvent event = new McastEvent(McastEvent.Type.SOURCES_ADDED, previousSubject, currentSubject);
305 cordMcast.listener.event(event);
306 // There will be no forwarding objective
307 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
308 assertTrue(0 == nextMap.size());
309
310 }
311
312 @Test
313 public void testSourcesRemovedEvent() throws InterruptedException {
314
315 testSourceAddedEvent();
316
317 //Adding the details to create different routes
318 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
319 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
320 // Creating new mcast event for removing source
321 // Warning message of unknown event will be displayed.
322 McastEvent event = new McastEvent(McastEvent.Type.SOURCES_REMOVED, previousSubject, currentSubject);
323 cordMcast.listener.event(event);
324 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
325 assertTrue(0 == nextMap.size());
326 }
327
328}