blob: fa4e504da9ff5edab66269d0bc2e8227a883aff6 [file] [log] [blame]
Sonal Kasliwalddc3ff22019-11-18 11:52:49 +00001/*
2 * Copyright 2017-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.igmpproxy;
17
18import java.io.IOException;
19import java.nio.ByteBuffer;
20import java.util.ArrayList;
21import java.util.Arrays;
22import java.util.HashSet;
23import java.util.LinkedList;
24import java.util.List;
25import java.util.Optional;
26import java.util.Set;
27
28import org.onlab.packet.Ethernet;
29import org.onlab.packet.Ip4Address;
30import org.onlab.packet.IpAddress;
31import org.onlab.packet.VlanId;
32import org.onosproject.core.ApplicationId;
33import org.onosproject.mastership.MastershipServiceAdapter;
34import org.onosproject.mcast.api.McastListener;
35import org.onosproject.mcast.api.McastRoute;
36import org.onosproject.mcast.api.McastRouteData;
37import org.onosproject.mcast.api.MulticastRouteService;
38import org.onosproject.net.config.ConfigFactory;
39import org.onosproject.net.config.NetworkConfigRegistryAdapter;
40import org.onosproject.net.AnnotationKeys;
41import org.onosproject.net.Annotations;
42import org.onosproject.net.ConnectPoint;
43import org.onosproject.net.DefaultAnnotations;
44import org.onosproject.net.DefaultDevice;
45import org.onosproject.net.Device;
46import org.onosproject.net.DeviceId;
47import org.onosproject.net.HostId;
48import org.onosproject.net.Port;
49import org.onosproject.net.PortNumber;
50import org.onosproject.net.SparseAnnotations;
51import org.onosproject.net.config.Config;
52import org.onosproject.net.config.basics.McastConfig;
53import org.onosproject.net.config.basics.SubjectFactories;
54import org.onosproject.net.device.DeviceServiceAdapter;
55import org.onosproject.net.packet.DefaultInboundPacket;
56import org.onosproject.net.packet.DefaultPacketContext;
57import org.onosproject.net.packet.InboundPacket;
58import org.onosproject.net.packet.OutboundPacket;
59import org.onosproject.net.packet.PacketContext;
60import org.onosproject.net.packet.PacketProcessor;
61import org.onosproject.net.packet.PacketServiceAdapter;
62import org.opencord.cordconfig.access.AccessDeviceConfig;
63import org.opencord.cordconfig.access.AccessDeviceData;
64import org.slf4j.Logger;
65import org.slf4j.LoggerFactory;
66
67import com.fasterxml.jackson.databind.JsonNode;
68import com.fasterxml.jackson.databind.ObjectMapper;
69
70public class IgmpManagerBase {
71
72 // Device configuration
73 protected static final DeviceId DEVICE_ID_OF_A = DeviceId.deviceId("of:1");
74 protected static final DeviceId DEVICE_ID_OF_B = DeviceId.deviceId("of:2");
75
76 //Multicast ip address
77 protected static final Ip4Address GROUP_IP = Ip4Address.valueOf("224.0.0.0");
78 // Source ip address of two different device.
79 protected static final Ip4Address SOURCE_IP_OF_A = Ip4Address.valueOf("10.177.125.4");
80 protected static final Ip4Address SOURCE_IP_OF_B = Ip4Address.valueOf("10.177.125.5");
81
82 // Common connect point of aggregation switch used by all devices.
83 protected static final ConnectPoint COMMON_CONNECT_POINT =
84 ConnectPoint.deviceConnectPoint("of:00000000000000003/3");
85 // Uplink ports for two olts A and B
86 protected static final PortNumber PORT_A = PortNumber.portNumber(1);
87 protected static final PortNumber PORT_B = PortNumber.portNumber(2);
88
89 // Connect Point mode for two olts
90 protected static final ConnectPoint CONNECT_POINT_A = new ConnectPoint(DEVICE_ID_OF_A, PORT_A);
91 protected static final ConnectPoint CONNECT_POINT_B = new ConnectPoint(DEVICE_ID_OF_B, PORT_B);
92
93 // setOfDevices which will store device id of two olts
94 protected Set<DeviceId> setOfDevices = new HashSet<DeviceId>(Arrays.asList(DEVICE_ID_OF_A, DEVICE_ID_OF_B));
95 protected List<Port> lsPorts = new ArrayList<Port>();
96 // Flag for adding two different devices in oltData
97 protected boolean flagForDevice = true;
98 PacketContext context;
99 // Flag for sending two different packets
100 protected boolean flagForPacket = true;
101 // List to store the packets emitted
102 protected List<OutboundPacket> savedPackets;
103 protected PacketProcessor packetProcessor;
104 private Logger log = LoggerFactory.getLogger(getClass());
105
106 class MockDeviceService extends DeviceServiceAdapter {
107
108 @Override
109 public Device getDevice(DeviceId deviceId) {
110 if (flagForDevice) {
111 DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
112 .set(AnnotationKeys.MANAGEMENT_ADDRESS, SOURCE_IP_OF_A.toString());
113 SparseAnnotations annotations = annotationsBuilder.build();
114 Annotations[] da = {annotations };
115 Device deviceA = new DefaultDevice(null, DEVICE_ID_OF_A, Device.Type.OTHER, "", "", "", "", null, da);
116 flagForDevice = false;
117 return deviceA;
118 } else {
119 DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
120 .set(AnnotationKeys.MANAGEMENT_ADDRESS, SOURCE_IP_OF_B.toString());
121 SparseAnnotations annotations = annotationsBuilder.build();
122 Annotations[] da = {annotations };
123 Device deviceB = new DefaultDevice(null, DEVICE_ID_OF_B, Device.Type.OTHER, "", "", "", "", null, da);
124 return deviceB;
125 }
126 }
127 @Override
128 public List<Port> getPorts(DeviceId deviceId) {
129 return lsPorts;
130 }
131 }
132
133 static final Class<AccessDeviceConfig> CONFIG_CLASS = AccessDeviceConfig.class;
134 static final Class<IgmpproxyConfig> IGMPPROXY_CONFIG_CLASS = IgmpproxyConfig.class;
135 static final Class<IgmpproxySsmTranslateConfig> IGMPPROXY_SSM_CONFIG_CLASS = IgmpproxySsmTranslateConfig.class;
136 static final Class<McastConfig> MCAST_CONFIG_CLASS = McastConfig.class;
137 ConfigFactory<ApplicationId, IgmpproxyConfig> igmpproxyConfigFactory =
138 new ConfigFactory<ApplicationId, IgmpproxyConfig>(
139 SubjectFactories.APP_SUBJECT_FACTORY, IGMPPROXY_CONFIG_CLASS, "igmpproxy") {
140 @Override
141 public IgmpproxyConfig createConfig() {
142 return new IgmpproxyConfig();
143 }
144 };
145
146 ConfigFactory<ApplicationId, IgmpproxySsmTranslateConfig> igmpproxySsmConfigFactory =
147 new ConfigFactory<ApplicationId, IgmpproxySsmTranslateConfig>(
148 SubjectFactories.APP_SUBJECT_FACTORY, IGMPPROXY_SSM_CONFIG_CLASS, "ssmTranslate", true) {
149
150 @Override
151 public IgmpproxySsmTranslateConfig createConfig() {
152 return new IgmpproxySsmTranslateConfig();
153 }
154 };
155
156
157 class MockIgmpProxyConfig extends IgmpproxyConfig {
158 boolean igmpOnPodBasis = true;
159
160 MockIgmpProxyConfig(boolean igmpFlagValue) {
161 igmpOnPodBasis = igmpFlagValue;
162 }
163 @Override
164 public boolean igmpOnPodBasis() {
165 return igmpOnPodBasis;
166 }
167
168 @Override
169 public ConnectPoint getSourceDeviceAndPort() {
170 return COMMON_CONNECT_POINT;
171 }
172
173 @Override
174 public ConnectPoint connectPoint() {
175 return COMMON_CONNECT_POINT;
176 }
177 }
178
179
180 static class MockAccessDeviceConfig extends AccessDeviceConfig {
181
182 public MockAccessDeviceConfig() {
183 super();
184 }
185
186 public MockAccessDeviceConfig(DeviceId id) {
187 super();
188 subject = id;
189 }
190
191 @Override
192 public AccessDeviceData getAccessDevice() {
193 PortNumber uplink = PortNumber.portNumber(3);
194 VlanId vlan = VlanId.vlanId((short) 0);
195 ObjectMapper mapper = new ObjectMapper();
196 JsonNode defaultVlanNode = null;
197 try {
198 defaultVlanNode = (JsonNode) mapper.readTree("{\"driver\":\"pmc-olt\" , \"type \" : \"OLT\"}");
199 } catch (IOException e) {
200 e.printStackTrace();
201 }
202
203 Optional<VlanId> defaultVlan;
204 if (defaultVlanNode.isMissingNode()) {
205 defaultVlan = Optional.empty();
206 } else {
207 defaultVlan = Optional.of(VlanId.vlanId(defaultVlanNode.shortValue()));
208 }
209 return new AccessDeviceData(subject, uplink, vlan, defaultVlan);
210 }
211 }
212
213 ConfigFactory<DeviceId, AccessDeviceConfig> cf =
214 new ConfigFactory<DeviceId, AccessDeviceConfig>(
215 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
216 @Override
217 public AccessDeviceConfig createConfig() {
218 return new MockAccessDeviceConfig();
219 }
220 };
221
222 class TestNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
223 Boolean igmpOnPodFlag = false;
224 TestNetworkConfigRegistry(Boolean igmpFlag) {
225 igmpOnPodFlag = igmpFlag;
226 }
227 @SuppressWarnings("unchecked")
228 @Override
229 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
230 if (configClass.getName().equalsIgnoreCase("org.opencord.igmpproxy.IgmpproxyConfig")) {
231 IgmpproxyConfig igmpproxyConfig = new MockIgmpProxyConfig(igmpOnPodFlag);
232 return (C) igmpproxyConfig;
233 } else if (configClass.getName().equalsIgnoreCase("org.opencord.cordconfig.access.AccessDeviceConfig")) {
234
235 if (subject.toString().equals(DEVICE_ID_OF_A.toString())) {
236 AccessDeviceConfig accessDeviceConfig = new MockAccessDeviceConfig(DEVICE_ID_OF_A);
237 return (C) accessDeviceConfig;
238 } else {
239 AccessDeviceConfig accessDeviceConfig = new MockAccessDeviceConfig(DEVICE_ID_OF_B);
240 return (C) accessDeviceConfig;
241 }
242 } else {
243 super.getConfig(subject, configClass);
244 }
245 return null;
246 }
247
248 @SuppressWarnings("unchecked")
249 @Override
250 public <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass) {
251 return (ConfigFactory<S, C>) cf;
252 }
253
254 @SuppressWarnings("unchecked")
255 @Override
256 public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
257 return (Set<S>) setOfDevices;
258 }
259 }
260
261
262 /**
263 * Keeps a reference to the PacketProcessor and saves the OutboundPackets. Adds
264 * the emitted packet in savedPackets list
265 */
266 class MockPacketService extends PacketServiceAdapter {
267
268 public MockPacketService() {
269 savedPackets = new LinkedList<>();
270 }
271
272 @Override
273 public void addProcessor(PacketProcessor processor, int priority) {
274 packetProcessor = processor;
275 }
276
277 @Override
278 public void emit(OutboundPacket packet) {
279 synchronized (savedPackets) {
280 savedPackets.add(packet);
281 savedPackets.notify();
282 }
283 }
284 }
285
286
287 class MockMastershipService extends MastershipServiceAdapter {
288 @Override
289 public boolean isLocalMaster(DeviceId deviceId) {
290 return true;
291 }
292 }
293
294 final class TestMulticastRouteService implements MulticastRouteService {
295 @Override
296 public void addListener(McastListener listener) {
297 }
298
299 @Override
300 public void removeListener(McastListener listener) {
301 }
302
303 @Override
304 public void add(McastRoute route) {
305 }
306
307 @Override
308 public void remove(McastRoute route) {
309 }
310
311 @Override
312 public Set<McastRoute> getRoutes() {
313 return null;
314 }
315
316 @Override
317 public Set<McastRoute> getRoute(IpAddress groupIp, IpAddress sourceIp) {
318 return null;
319 }
320
321 @Override
322 public void addSource(McastRoute route, HostId source) {
323 }
324
325 @Override
326 public void addSources(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints) {
327 }
328
329 @Override
330 public void addSources(McastRoute route, Set<ConnectPoint> sources) {
331
332 }
333
334 @Override
335 public void removeSources(McastRoute route) {
336
337 }
338
339 @Override
340 public void removeSource(McastRoute route, HostId source) {
341
342 }
343
344 @Override
345 public void addSink(McastRoute route, HostId hostId) {
346
347 }
348
349 @Override
350 public void addSinks(McastRoute route, HostId hostId, Set<ConnectPoint> connectPoints) {
351
352 }
353
354 @Override
355 public void addSinks(McastRoute route, Set<ConnectPoint> sinks) {
356
357 }
358
359 @Override
360 public void removeSinks(McastRoute route) {
361
362 }
363
364 @Override
365 public void removeSink(McastRoute route, HostId hostId) {
366
367 }
368
369 @Override
370 public void removeSinks(McastRoute route, Set<ConnectPoint> sink) {
371
372 }
373
374 @Override
375 public McastRouteData routeData(McastRoute route) {
376 return null;
377 }
378
379 @Override
380 public Set<ConnectPoint> sources(McastRoute route) {
381 return null;
382 }
383
384 @Override
385 public Set<ConnectPoint> sources(McastRoute route, HostId hostId) {
386 return null;
387 }
388
389 @Override
390 public Set<ConnectPoint> sinks(McastRoute route) {
391 return null;
392 }
393
394 @Override
395 public Set<ConnectPoint> sinks(McastRoute route, HostId hostId) {
396 return null;
397 }
398
399 @Override
400 public Set<ConnectPoint> nonHostSinks(McastRoute route) {
401 return null;
402 }
403
404 }
405
406
407 /**
408 * Mocks the DefaultPacketContext.
409 */
410 final class TestPacketContext extends DefaultPacketContext {
411 TestPacketContext(long time, InboundPacket inPkt, OutboundPacket outPkt, boolean block) {
412 super(time, inPkt, outPkt, block);
413 }
414
415 @Override
416 public void send() {
417 // We don't send anything out.
418 }
419 }
420
421 /**
422 * Sends an Ethernet packet to the process method of the Packet Processor.
423 *
424 * @param reply Ethernet packet
425 * @throws InterruptedException
426 */
427 void sendPacket(Ethernet reply) {
428
429 final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());
430
431 if (flagForPacket) {
432 InboundPacket inPacket = new DefaultInboundPacket(CONNECT_POINT_A, reply, byteBuffer);
433 context = new TestPacketContext(127L, inPacket, null, false);
434 flagForPacket = false;
435
436 packetProcessor.process(context);
437 } else {
438 InboundPacket inBoundPacket = new DefaultInboundPacket(CONNECT_POINT_B, reply, byteBuffer);
439 context = new TestPacketContext(127L, inBoundPacket, null, false);
440 flagForPacket = true;
441
442 packetProcessor.process(context);
443 }
444 }
445
446}