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