blob: 4b778666186bea10282772cca7802d64a8333036 [file] [log] [blame]
Sonal Kasliwalee230262020-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;
Sonal Kasliwalee230262020-01-06 10:46:30 +000042import org.onosproject.net.flow.FlowRuleServiceAdapter;
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.flowRuleService = new FlowRuleServiceAdapter();
Esin Karaman09050642020-03-06 14:31:14 +000071 cordMcast.deviceService = new MockDeviceService();
Sonal Kasliwalee230262020-01-06 10:46:30 +000072 cordMcast.networkConfig = new NetworkConfigRegistryAdapter();
Esin Karaman09050642020-03-06 14:31:14 +000073 cordMcast.sadisService = new MockSadisService();
Sonal Kasliwalee230262020-01-06 10:46:30 +000074
75 cordMcast.storageService =
76 EasyMock.createMock(StorageServiceAdapter.class);
77 expect(cordMcast.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>());
78 replay(cordMcast.storageService);
79
80 Dictionary<String, Object> cfgDict = new Hashtable<String, Object>();
81 cfgDict.put("vlanEnabled", false);
82 cordMcast.componentConfigService =
83 EasyMock.createNiceMock(ComponentConfigService.class);
84 replay(cordMcast.componentConfigService);
85
86 cordMcast.mcastService = EasyMock.createNiceMock(MulticastRouteService.class);
87 expect(cordMcast.mcastService.getRoutes()).andReturn(Sets.newHashSet());
88 replay(cordMcast.mcastService);
89
90 ComponentContext componentContext = EasyMock.createMock(ComponentContext.class);
91 expect(componentContext.getProperties()).andReturn(cfgDict);
92 replay(componentContext);
93
94 cordMcast.activate(componentContext);
95
96 }
97
98 @After
99 public void tearDown() {
100 cordMcast.deactivate();
101 forwardMap.clear();
102 nextMap.clear();
103 }
104
105 @Test
106 public void testAddingSinkEvent() throws InterruptedException {
107
108 Set<ConnectPoint> sinks2Cp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B));
109 Map<HostId, Set<ConnectPoint>> sinks2 = ImmutableMap.of(HOST_ID_NONE, sinks2Cp);
110
111 //Adding the details to create different routes
112 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
113 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks2);
114 // Creating new mcast event for adding sink
115 McastEvent event = new McastEvent(McastEvent.Type.SINKS_ADDED, previousSubject, currentSubject);
116 cordMcast.listener.event(event);
117 synchronized (forwardMap) {
118 forwardMap.wait(WAIT_TIMEOUT);
119 }
120
121 // ForwardMap will contain the operation "Add" in the flowObjective. None -> CP_B
122 assertNotNull(forwardMap.get(DEVICE_ID_OF_A));
123 assertTrue(forwardMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.ADD);
124
125 // Output port number will be PORT_B i.e. 16
126 Collection<TrafficTreatment> traffictreatMentCollection =
127 nextMap.get(DEVICE_ID_OF_A).next();
128 assertTrue(1 == traffictreatMentCollection.size());
129 OutputInstruction output = null;
130 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
131 output = outputPort(trafficTreatment);
132 }
133 assertNotNull(output);
134 assertTrue(PORT_B == output.port());
135 // Checking the group ip address
136 TrafficSelector trafficSelector = forwardMap.get(DEVICE_ID_OF_A).selector();
137 IPCriterion ipCriterion = ipAddress(trafficSelector);
138 assertNotNull(ipCriterion);
139 assertTrue(MULTICAST_IP.equals(ipCriterion.ip().address()));
140
141 }
142
143 @Test
144 public void testAddToExistingSinkEvent() throws InterruptedException {
145
146 // Adding first sink (none --> CP_B)
147 testAddingSinkEvent();
148
149 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B));
150 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
151 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
152 sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B, CONNECT_POINT_C));
153 sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
154 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
155 // Again listening the mcast event with different output port ( none --> CP_B, CP_C)
156 McastEvent event = new McastEvent(McastEvent.Type.SINKS_ADDED, previousSubject, currentSubject);
157 cordMcast.listener.event(event);
158
159 // NextMap will contain the operation "ADD_TO_EXISTING" in the DefaultNextObjective.
160 assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
161 assertTrue(nextMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.ADD_TO_EXISTING));
162 // Output port number will be changed to 24 i.e. PORT_C
163 Collection<TrafficTreatment> traffictreatMentCollection = nextMap.get(DEVICE_ID_OF_A).next();
164 assertTrue(1 == traffictreatMentCollection.size());
165 OutputInstruction output = null;
166 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
167 output = outputPort(trafficTreatment);
168 }
169 assertNotNull(output);
170 assertTrue(PORT_C == output.port());
171 }
172
173 @Test
174 public void testRemoveSinkEvent() throws InterruptedException {
175
176 testAddToExistingSinkEvent();
177 // Handling the mcast event for removing sink.
178 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_B, CONNECT_POINT_C));
179 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
180 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
181 sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_C));
182 sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
183 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
184 McastEvent event = new McastEvent(McastEvent.Type.SINKS_REMOVED, previousSubject, currentSubject);
185 cordMcast.listener.event(event);
186 // Operation will be REMOVE_FROM_EXISTING and nextMap will be updated. ( None --> CP_C)
187 assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
188 assertTrue(nextMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.REMOVE_FROM_EXISTING));
189
190 // Output port number will be PORT_B i.e. 16
191 // Port_B is removed from the group.
192 Collection<TrafficTreatment> traffictreatMentCollection =
193 nextMap.get(DEVICE_ID_OF_A).next();
194 assertTrue(1 == traffictreatMentCollection.size());
195 OutputInstruction output = null;
196 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
197 output = outputPort(trafficTreatment);
198 }
199 assertNotNull(output);
200 assertTrue(PORT_B == output.port());
201
202 }
203
204 @Test
205 public void testRemoveLastSinkEvent() throws InterruptedException {
206
207 testRemoveSinkEvent();
208 // Handling the mcast event for removing sink.
209 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList(CONNECT_POINT_C));
210 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
211 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
212 sinksCp = new HashSet<ConnectPoint>(Arrays.asList());
213 sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
214 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
215 McastEvent event = new McastEvent(McastEvent.Type.SINKS_REMOVED, previousSubject, currentSubject);
216 cordMcast.listener.event(event);
217
218 // Operation will be REMOVE_FROM_EXISTING and nextMap will be updated. None --> { }
219 assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
220 assertTrue(nextMap.get(DEVICE_ID_OF_A).op() == Objective.Operation.REMOVE_FROM_EXISTING));
221
222 // Output port number will be changed to 24 i.e. PORT_C
223 Collection<TrafficTreatment> traffictreatMentCollection = nextMap.get(DEVICE_ID_OF_A).next();
224 assertTrue(1 == traffictreatMentCollection.size());
225 OutputInstruction output = null;
226 for (TrafficTreatment trafficTreatment : traffictreatMentCollection) {
227 output = outputPort(trafficTreatment);
228 }
229 assertNotNull(output);
230 assertTrue(PORT_C == output.port());
231 }
232
233 @Test
234 public void testUnkownOltDevice() throws InterruptedException {
235
236 // Configuration of mcast event for unknown olt device
237 final DeviceId deviceIdOfB = DeviceId.deviceId("of:1");
238
239 ConnectPoint connectPointA = new ConnectPoint(deviceIdOfB, PORT_A);
240 ConnectPoint connectPointB = new ConnectPoint(deviceIdOfB, PORT_B);
241 Set<ConnectPoint> sourcesCp = new HashSet<ConnectPoint>(Arrays.asList(connectPointA));
242 Set<ConnectPoint> sinksCp = new HashSet<ConnectPoint>(Arrays.asList());
243 Set<ConnectPoint> sinks2Cp = new HashSet<ConnectPoint>(Arrays.asList(connectPointB));
244 Map<HostId, Set<ConnectPoint>> sources = ImmutableMap.of(HOST_ID_NONE, sourcesCp);
245
246 Map<HostId, Set<ConnectPoint>> sinks = ImmutableMap.of(HOST_ID_NONE, sinksCp);
247 Map<HostId, Set<ConnectPoint>> sinks2 = ImmutableMap.of(HOST_ID_NONE, sinks2Cp);
248 //Adding the details to create different routes
249 McastRouteUpdate previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
250 McastRouteUpdate currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks2);
251 // Creating new mcast event for adding sink
252 McastEvent event = new McastEvent(McastEvent.Type.SINKS_ADDED, previousSubject, currentSubject);
253 cordMcast.listener.event(event);
254 // OltInfo flag is set to true when olt device is unkown
255 assertAfter(WAIT, WAIT * 2, () -> assertTrue(knownOltFlag));
256 assertTrue(0 == forwardMap.size());
257 assertTrue(0 == nextMap.size());
258
259 }
260
261 @Test
262 public void testRouteAddedEvent() throws InterruptedException {
263
264 //Adding the details to create different routes
265 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
266 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
267 // Creating new mcast event for route adding
268 McastEvent event = new McastEvent(McastEvent.Type.ROUTE_ADDED, previousSubject, currentSubject);
269 cordMcast.listener.event(event);
270 // There will be no forwarding objective
271 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
272 assertTrue(0 == nextMap.size());
273
274 }
275
276
277 @Test
278 public void testRouteRemovedEvent() throws InterruptedException {
279
280 testRouteAddedEvent();
281
282 //Adding the details to create different routes
283 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
284 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
285 // Creating new mcast event for route removing
286 McastEvent event = new McastEvent(McastEvent.Type.ROUTE_REMOVED, previousSubject, currentSubject);
287 cordMcast.listener.event(event);
288 // There will be no forwarding objective
289 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
290 assertTrue(0 == nextMap.size());
291
292 }
293
294
295 @Test
296 public void testSourceAddedEvent() throws InterruptedException {
297
298 // Adding route before adding source.
299 testRouteAddedEvent();
300
301 //Adding the details to create different routes
302 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
303 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
304 // Creating new mcast event for source adding
305 McastEvent event = new McastEvent(McastEvent.Type.SOURCES_ADDED, previousSubject, currentSubject);
306 cordMcast.listener.event(event);
307 // There will be no forwarding objective
308 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
309 assertTrue(0 == nextMap.size());
310
311 }
312
313 @Test
314 public void testSourcesRemovedEvent() throws InterruptedException {
315
316 testSourceAddedEvent();
317
318 //Adding the details to create different routes
319 previousSubject = McastRouteUpdate.mcastRouteUpdate(route1, sources, sinks);
320 currentSubject = McastRouteUpdate.mcastRouteUpdate(route1, emptySource, sinks);
321 // Creating new mcast event for removing source
322 // Warning message of unknown event will be displayed.
323 McastEvent event = new McastEvent(McastEvent.Type.SOURCES_REMOVED, previousSubject, currentSubject);
324 cordMcast.listener.event(event);
325 assertAfter(WAIT, WAIT * 2, () -> assertTrue(0 == forwardMap.size()));
326 assertTrue(0 == nextMap.size());
327 }
328
329}