blob: 0393ed9ecc81ac35cedea0731fe1fa4fecb0c06f [file] [log] [blame]
alshabibeff00542015-09-23 13:22:33 -07001/*
2 * Copyright 2015 Open Networking Laboratory
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 */
alshabib79e52872015-12-07 16:01:01 -080016package org.onosproject.igmp;
alshabibeff00542015-09-23 13:22:33 -070017
alshabibeff00542015-09-23 13:22:33 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
alshabib79e52872015-12-07 16:01:01 -080021import org.apache.felix.scr.annotations.Property;
alshabibeff00542015-09-23 13:22:33 -070022import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabib03adb492016-02-01 17:25:00 -080024import org.onlab.packet.EthType;
alshabibeff00542015-09-23 13:22:33 -070025import org.onlab.packet.Ethernet;
alshabib03adb492016-02-01 17:25:00 -080026import org.onlab.packet.IGMP;
Jonathan Hart6ccfc5a2016-02-12 19:26:02 -080027import org.onlab.packet.IGMPMembership;
alshabib42d32eb2016-02-14 19:53:42 -080028import org.onlab.packet.IGMPQuery;
alshabibeff00542015-09-23 13:22:33 -070029import org.onlab.packet.IPv4;
30import org.onlab.packet.Ip4Address;
31import org.onlab.packet.IpAddress;
32import org.onlab.packet.IpPrefix;
alshabib42d32eb2016-02-14 19:53:42 -080033import org.onlab.util.SafeRecurringTask;
alshabibeff00542015-09-23 13:22:33 -070034import org.onosproject.core.ApplicationId;
35import org.onosproject.core.CoreService;
alshabib79e52872015-12-07 16:01:01 -080036import org.onosproject.net.ConnectPoint;
37import org.onosproject.net.DeviceId;
alshabib03adb492016-02-01 17:25:00 -080038import org.onosproject.net.Port;
39import org.onosproject.net.PortNumber;
alshabibfe69e9a2016-02-11 17:31:36 -080040import org.onosproject.net.config.ConfigFactory;
41import org.onosproject.net.config.NetworkConfigEvent;
42import org.onosproject.net.config.NetworkConfigListener;
alshabib79e52872015-12-07 16:01:01 -080043import org.onosproject.net.config.NetworkConfigRegistry;
alshabibfe69e9a2016-02-11 17:31:36 -080044import org.onosproject.net.config.basics.SubjectFactories;
alshabib03adb492016-02-01 17:25:00 -080045import org.onosproject.net.device.DeviceEvent;
46import org.onosproject.net.device.DeviceListener;
47import org.onosproject.net.device.DeviceService;
48import org.onosproject.net.flow.DefaultTrafficTreatment;
alshabib42d32eb2016-02-14 19:53:42 -080049import org.onosproject.net.flow.TrafficTreatment;
alshabib03adb492016-02-01 17:25:00 -080050import org.onosproject.net.flow.criteria.Criteria;
51import org.onosproject.net.flowobjective.DefaultFilteringObjective;
52import org.onosproject.net.flowobjective.FilteringObjective;
53import org.onosproject.net.flowobjective.FlowObjectiveService;
54import org.onosproject.net.flowobjective.Objective;
55import org.onosproject.net.flowobjective.ObjectiveContext;
56import org.onosproject.net.flowobjective.ObjectiveError;
alshabib79e52872015-12-07 16:01:01 -080057import org.onosproject.net.mcast.McastRoute;
58import org.onosproject.net.mcast.MulticastRouteService;
alshabib42d32eb2016-02-14 19:53:42 -080059import org.onosproject.net.packet.DefaultOutboundPacket;
alshabibeff00542015-09-23 13:22:33 -070060import org.onosproject.net.packet.InboundPacket;
61import org.onosproject.net.packet.PacketContext;
alshabibeff00542015-09-23 13:22:33 -070062import org.onosproject.net.packet.PacketProcessor;
63import org.onosproject.net.packet.PacketService;
alshabib03adb492016-02-01 17:25:00 -080064import org.onosproject.olt.AccessDeviceConfig;
65import org.onosproject.olt.AccessDeviceData;
alshabibeff00542015-09-23 13:22:33 -070066import org.slf4j.Logger;
67
alshabib42d32eb2016-02-14 19:53:42 -080068import java.nio.ByteBuffer;
Jonathan Hart5e8689c2016-02-16 13:06:26 -080069import java.util.Collection;
alshabibfe69e9a2016-02-11 17:31:36 -080070import java.util.List;
alshabib03adb492016-02-01 17:25:00 -080071import java.util.Map;
72import java.util.concurrent.ConcurrentHashMap;
alshabib42d32eb2016-02-14 19:53:42 -080073import java.util.concurrent.Executors;
74import java.util.concurrent.ScheduledExecutorService;
75import java.util.concurrent.ScheduledFuture;
76import java.util.concurrent.TimeUnit;
alshabib03adb492016-02-01 17:25:00 -080077
alshabib42d32eb2016-02-14 19:53:42 -080078import static org.onlab.util.Tools.groupedThreads;
alshabib03adb492016-02-01 17:25:00 -080079import static org.slf4j.LoggerFactory.getLogger;
alshabib79e52872015-12-07 16:01:01 -080080
alshabibeff00542015-09-23 13:22:33 -070081/**
82 * Internet Group Management Protocol.
83 */
84@Component(immediate = true)
alshabib79e52872015-12-07 16:01:01 -080085public class IgmpSnoop {
alshabib42d32eb2016-02-14 19:53:42 -080086
87
alshabibeff00542015-09-23 13:22:33 -070088 private final Logger log = getLogger(getClass());
89
alshabib42d32eb2016-02-14 19:53:42 -080090 private static final String DEST_MAC = "01:00:5E:00:00:01";
91 private static final String DEST_IP = "224.0.0.1";
92
93 private static final int DEFAULT_QUERY_PERIOD_SECS = 60;
94 private static final byte DEFAULT_IGMP_RESP_CODE = 0;
alshabib79e52872015-12-07 16:01:01 -080095 private static final String DEFAULT_MCAST_ADDR = "224.0.0.0/4";
96
97 @Property(name = "multicastAddress",
Jonathan Hart6ccfc5a2016-02-12 19:26:02 -080098 label = "Define the multicast base range to listen to")
alshabib79e52872015-12-07 16:01:01 -080099 private String multicastAddress = DEFAULT_MCAST_ADDR;
100
alshabib42d32eb2016-02-14 19:53:42 -0800101 @Property(name = "queryPeriod", intValue = DEFAULT_QUERY_PERIOD_SECS,
102 label = "Delay in seconds between successive query runs")
103 private int queryPeriod = DEFAULT_QUERY_PERIOD_SECS;
104
105 @Property(name = "maxRespCode", byteValue = DEFAULT_IGMP_RESP_CODE,
106 label = "Maximum time allowed before sending a responding report")
107 private byte maxRespCode = DEFAULT_IGMP_RESP_CODE;
108
alshabibeff00542015-09-23 13:22:33 -0700109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib03adb492016-02-01 17:25:00 -0800110 protected FlowObjectiveService flowObjectiveService;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibeff00542015-09-23 13:22:33 -0700113 protected PacketService packetService;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected CoreService coreService;
117
alshabib79e52872015-12-07 16:01:01 -0800118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected NetworkConfigRegistry networkConfig;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected MulticastRouteService multicastService;
123
alshabib03adb492016-02-01 17:25:00 -0800124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 protected DeviceService deviceService;
126
alshabib42d32eb2016-02-14 19:53:42 -0800127
128 private ScheduledFuture<?> queryTask;
129 private final ScheduledExecutorService queryService =
130 Executors.newSingleThreadScheduledExecutor(groupedThreads("onos/igmp-query",
131 "membership-query"));
132
alshabib03adb492016-02-01 17:25:00 -0800133 private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
134
Jonathan Hart5e8689c2016-02-16 13:06:26 -0800135 private Map<IpAddress, IpAddress> ssmTranslateTable = new ConcurrentHashMap<>();
136
alshabib03adb492016-02-01 17:25:00 -0800137 private DeviceListener deviceListener = new InternalDeviceListener();
alshabib79e52872015-12-07 16:01:01 -0800138 private IgmpPacketProcessor processor = new IgmpPacketProcessor();
alshabibeff00542015-09-23 13:22:33 -0700139 private static ApplicationId appId;
140
alshabibfe69e9a2016-02-11 17:31:36 -0800141 private InternalNetworkConfigListener configListener =
142 new InternalNetworkConfigListener();
143
144 private static final Class<AccessDeviceConfig> CONFIG_CLASS =
145 AccessDeviceConfig.class;
146
147 private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
148 new ConfigFactory<DeviceId, AccessDeviceConfig>(
149 SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
150 @Override
151 public AccessDeviceConfig createConfig() {
152 return new AccessDeviceConfig();
153 }
154 };
155
Jonathan Hart5e8689c2016-02-16 13:06:26 -0800156 private ConfigFactory<ApplicationId, IgmpSsmTranslateConfig> ssmTranslateConfigFactory =
157 new ConfigFactory<ApplicationId, IgmpSsmTranslateConfig>(
158 SubjectFactories.APP_SUBJECT_FACTORY, IgmpSsmTranslateConfig.class, "ssmTranslate", true) {
159 @Override
160 public IgmpSsmTranslateConfig createConfig() {
161 return new IgmpSsmTranslateConfig();
162 }
163 };
164
alshabibfe69e9a2016-02-11 17:31:36 -0800165
alshabib42d32eb2016-02-14 19:53:42 -0800166 private ByteBuffer queryPacket;
167
168
alshabibeff00542015-09-23 13:22:33 -0700169 @Activate
170 public void activate() {
171 appId = coreService.registerApplication("org.onosproject.igmp");
172
173 packetService.addProcessor(processor, PacketProcessor.director(1));
174
alshabibfe69e9a2016-02-11 17:31:36 -0800175 networkConfig.registerConfigFactory(configFactory);
Jonathan Hart5e8689c2016-02-16 13:06:26 -0800176 networkConfig.registerConfigFactory(ssmTranslateConfigFactory);
alshabibfe69e9a2016-02-11 17:31:36 -0800177 networkConfig.addListener(configListener);
178
alshabib03adb492016-02-01 17:25:00 -0800179 networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
alshabib79e52872015-12-07 16:01:01 -0800180 subject -> {
alshabib03adb492016-02-01 17:25:00 -0800181 AccessDeviceConfig config = networkConfig.getConfig(subject,
182 AccessDeviceConfig.class);
alshabib79e52872015-12-07 16:01:01 -0800183 if (config != null) {
alshabib03adb492016-02-01 17:25:00 -0800184 AccessDeviceData data = config.getOlt();
185 oltData.put(data.deviceId(), data);
alshabibfe69e9a2016-02-11 17:31:36 -0800186
alshabib79e52872015-12-07 16:01:01 -0800187 }
188 }
189 );
alshabibeff00542015-09-23 13:22:33 -0700190
Jonathan Hart5e8689c2016-02-16 13:06:26 -0800191 IgmpSsmTranslateConfig ssmTranslateConfig =
192 networkConfig.getConfig(appId, IgmpSsmTranslateConfig.class);
193
194 if (ssmTranslateConfig != null) {
195 Collection<McastRoute> translations = ssmTranslateConfig.getSsmTranslations();
196 for (McastRoute route : translations) {
197 ssmTranslateTable.put(route.group(), route.source());
198 }
199 }
200
alshabibfe69e9a2016-02-11 17:31:36 -0800201 oltData.keySet().stream()
202 .flatMap(did -> deviceService.getPorts(did).stream())
203 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
204 .filter(p -> p.isEnabled())
205 .forEach(p -> processFilterObjective((DeviceId) p.element().id(), p, false));
206
alshabib03adb492016-02-01 17:25:00 -0800207 deviceService.addListener(deviceListener);
208
alshabib42d32eb2016-02-14 19:53:42 -0800209 queryPacket = buildQueryPacket();
210
211 queryTask = queryService.scheduleWithFixedDelay(
212 SafeRecurringTask.wrap(this::querySubscribers),
213 0,
214 queryPeriod,
215 TimeUnit.SECONDS);
216
alshabibeff00542015-09-23 13:22:33 -0700217 log.info("Started");
218 }
219
220 @Deactivate
221 public void deactivate() {
222 packetService.removeProcessor(processor);
223 processor = null;
alshabib03adb492016-02-01 17:25:00 -0800224 deviceService.removeListener(deviceListener);
alshabibfe69e9a2016-02-11 17:31:36 -0800225 networkConfig.removeListener(configListener);
226 networkConfig.unregisterConfigFactory(configFactory);
Jonathan Hart5e8689c2016-02-16 13:06:26 -0800227 networkConfig.unregisterConfigFactory(ssmTranslateConfigFactory);
alshabib42d32eb2016-02-14 19:53:42 -0800228 queryTask.cancel(true);
229 queryService.shutdownNow();
alshabibeff00542015-09-23 13:22:33 -0700230 log.info("Stopped");
231 }
232
alshabib03adb492016-02-01 17:25:00 -0800233 private void processFilterObjective(DeviceId devId, Port port, boolean remove) {
alshabib79e52872015-12-07 16:01:01 -0800234
alshabib03adb492016-02-01 17:25:00 -0800235 //TODO migrate to packet requests when packet service uses filtering objectives
236 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
237
238 builder = remove ? builder.deny() : builder.permit();
239
240 FilteringObjective igmp = builder
241 .withKey(Criteria.matchInPort(port.number()))
242 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
243 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
244 .withMeta(DefaultTrafficTreatment.builder()
245 .setOutput(PortNumber.CONTROLLER).build())
246 .fromApp(appId)
247 .withPriority(1000)
248 .add(new ObjectiveContext() {
249 @Override
250 public void onSuccess(Objective objective) {
251 log.info("Igmp filter for {} on {} installed.",
252 devId, port);
253 }
254
255 @Override
256 public void onError(Objective objective, ObjectiveError error) {
257 log.info("Igmp filter for {} on {} failed because {}.",
258 devId, port, error);
259 }
260 });
261
262 flowObjectiveService.filter(devId, igmp);
263 }
264
Jonathan Hart6ccfc5a2016-02-12 19:26:02 -0800265 private void processMembership(IGMP pkt, ConnectPoint location) {
266 pkt.getGroups().forEach(group -> {
267
268 if (!(group instanceof IGMPMembership)) {
269 log.warn("Wrong group type in IGMP membership");
270 return;
271 }
272
273 IGMPMembership membership = (IGMPMembership) group;
274
Jonathan Hart5e8689c2016-02-16 13:06:26 -0800275 // TODO allow pulling source from IGMP packet
276 IpAddress source = IpAddress.valueOf("0.0.0.0");
277 if (ssmTranslateTable.containsKey(group.getGaddr())) {
278 source = ssmTranslateTable.get(group.getGaddr());
279 }
280
281 McastRoute route = new McastRoute(source,
282 group.getGaddr(),
283 McastRoute.Type.IGMP);
Jonathan Hart6ccfc5a2016-02-12 19:26:02 -0800284
285 if (membership.getRecordType() == IGMPMembership.MODE_IS_INCLUDE ||
286 membership.getRecordType() == IGMPMembership.CHANGE_TO_INCLUDE_MODE) {
287
288
289 multicastService.add(route);
290 multicastService.addSink(route, location);
291
292 } else if (membership.getRecordType() == IGMPMembership.MODE_IS_EXCLUDE ||
293 membership.getRecordType() == IGMPMembership.CHANGE_TO_EXCLUDE_MODE) {
294 multicastService.removeSink(route, location);
295 // TODO remove route if all sinks are gone
296 }
297
298 });
299 }
300
alshabib42d32eb2016-02-14 19:53:42 -0800301 private ByteBuffer buildQueryPacket() {
302 IGMP igmp = new IGMP();
303 igmp.setIgmpType(IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY);
304 igmp.setMaxRespCode(maxRespCode);
305
306 IGMPQuery query = new IGMPQuery(IpAddress.valueOf("0.0.0.0"), 0);
307 igmp.addGroup(query);
308
309 IPv4 ip = new IPv4();
310 ip.setDestinationAddress(DEST_IP);
311 ip.setProtocol(IPv4.PROTOCOL_IGMP);
312 ip.setSourceAddress("192.168.1.1");
313 ip.setTtl((byte) 1);
314 ip.setPayload(igmp);
315
316 Ethernet eth = new Ethernet();
317 eth.setDestinationMACAddress(DEST_MAC);
318 eth.setSourceMACAddress("DE:AD:BE:EF:BA:11");
319 eth.setEtherType(Ethernet.TYPE_IPV4);
320
321 eth.setPayload(ip);
322
323 return ByteBuffer.wrap(eth.serialize());
324 }
325
326 private void querySubscribers() {
327 oltData.keySet().stream()
328 .flatMap(did -> deviceService.getPorts(did).stream())
329 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
330 .filter(p -> p.isEnabled())
331 .forEach(p -> {
332 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
333 .setOutput(p.number()).build();
334 packetService.emit(new DefaultOutboundPacket((DeviceId) p.element().id(),
335 treatment, queryPacket));
336 });
337 }
338
alshabibeff00542015-09-23 13:22:33 -0700339 /**
340 * Packet processor responsible for handling IGMP packets.
341 */
alshabib79e52872015-12-07 16:01:01 -0800342 private class IgmpPacketProcessor implements PacketProcessor {
alshabibeff00542015-09-23 13:22:33 -0700343
344 @Override
345 public void process(PacketContext context) {
346 // Stop processing if the packet has been handled, since we
347 // can't do any more to it.
348 if (context.isHandled()) {
349 return;
350 }
351
352 InboundPacket pkt = context.inPacket();
353 Ethernet ethPkt = pkt.parsed();
354 if (ethPkt == null) {
355 return;
356 }
357
358 /*
359 * IPv6 MLD packets are handled by ICMP6. We'll only deal
360 * with IPv4.
361 */
362 if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
363 return;
364 }
365
366 IPv4 ip = (IPv4) ethPkt.getPayload();
367 IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
368 IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
alshabib79e52872015-12-07 16:01:01 -0800369 log.debug("Packet ({}, {}) -> ingress port: {}", saddr, gaddr,
370 context.inPacket().receivedFrom());
371
alshabibeff00542015-09-23 13:22:33 -0700372
373 if (ip.getProtocol() != IPv4.PROTOCOL_IGMP) {
Rusty Eddy158d5d82015-10-12 16:59:04 -0700374 log.debug("IGMP Picked up a non IGMP packet.");
alshabibeff00542015-09-23 13:22:33 -0700375 return;
376 }
377
alshabib79e52872015-12-07 16:01:01 -0800378 IpPrefix mcast = IpPrefix.valueOf(DEFAULT_MCAST_ADDR);
alshabibeff00542015-09-23 13:22:33 -0700379 if (!mcast.contains(gaddr)) {
Rusty Eddy158d5d82015-10-12 16:59:04 -0700380 log.debug("IGMP Picked up a non multicast packet.");
alshabibeff00542015-09-23 13:22:33 -0700381 return;
382 }
383
384 if (mcast.contains(saddr)) {
Rusty Eddy158d5d82015-10-12 16:59:04 -0700385 log.debug("IGMP Picked up a packet with a multicast source address.");
alshabibeff00542015-09-23 13:22:33 -0700386 return;
387 }
alshabibeff00542015-09-23 13:22:33 -0700388
389 IGMP igmp = (IGMP) ip.getPayload();
390 switch (igmp.getIgmpType()) {
391
392 case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT:
Jonathan Hart6ccfc5a2016-02-12 19:26:02 -0800393 processMembership(igmp, pkt.receivedFrom());
alshabibeff00542015-09-23 13:22:33 -0700394 break;
395
396 case IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY:
alshabib42d32eb2016-02-14 19:53:42 -0800397 log.debug("Received a membership query {} from {}",
398 igmp, pkt.receivedFrom());
alshabibeff00542015-09-23 13:22:33 -0700399 break;
400
401 case IGMP.TYPE_IGMPV1_MEMBERSHIP_REPORT:
402 case IGMP.TYPE_IGMPV2_MEMBERSHIP_REPORT:
403 case IGMP.TYPE_IGMPV2_LEAVE_GROUP:
Jonathan Hart6ccfc5a2016-02-12 19:26:02 -0800404 log.debug("IGMP version 1 & 2 message types are not currently supported. Message type: {}",
alshabib42d32eb2016-02-14 19:53:42 -0800405 igmp.getIgmpType());
alshabibeff00542015-09-23 13:22:33 -0700406 break;
alshabibeff00542015-09-23 13:22:33 -0700407 default:
Jonathan Hart6ccfc5a2016-02-12 19:26:02 -0800408 log.debug("Unknown IGMP message type: {}", igmp.getIgmpType());
alshabibeff00542015-09-23 13:22:33 -0700409 break;
410 }
411 }
412 }
alshabib79e52872015-12-07 16:01:01 -0800413
alshabib79e52872015-12-07 16:01:01 -0800414
alshabib03adb492016-02-01 17:25:00 -0800415 private class InternalDeviceListener implements DeviceListener {
416 @Override
417 public void event(DeviceEvent event) {
418 switch (event.type()) {
419
420 case DEVICE_ADDED:
421 case DEVICE_UPDATED:
422 case DEVICE_REMOVED:
423 case DEVICE_SUSPENDED:
424 case DEVICE_AVAILABILITY_CHANGED:
425 case PORT_STATS_UPDATED:
426 break;
427 case PORT_ADDED:
428 if (event.port().isEnabled()) {
429 processFilterObjective(event.subject().id(), event.port(), false);
430 }
431 break;
432 case PORT_UPDATED:
433 if (event.port().isEnabled()) {
434 processFilterObjective(event.subject().id(), event.port(), false);
435 } else {
436 processFilterObjective(event.subject().id(), event.port(), true);
437 }
438 break;
439 case PORT_REMOVED:
alshabibfe69e9a2016-02-11 17:31:36 -0800440 processFilterObjective(event.subject().id(), event.port(), true);
alshabib03adb492016-02-01 17:25:00 -0800441 break;
442 default:
443 log.warn("Unknown device event {}", event.type());
444 break;
445 }
alshabib03adb492016-02-01 17:25:00 -0800446 }
447
448 @Override
449 public boolean isRelevant(DeviceEvent event) {
450 return oltData.containsKey(event.subject().id());
451 }
alshabib79e52872015-12-07 16:01:01 -0800452 }
alshabibfe69e9a2016-02-11 17:31:36 -0800453
454 private class InternalNetworkConfigListener implements NetworkConfigListener {
455 @Override
456 public void event(NetworkConfigEvent event) {
457 switch (event.type()) {
458
459 case CONFIG_ADDED:
460 case CONFIG_UPDATED:
461 if (event.configClass().equals(CONFIG_CLASS)) {
462 AccessDeviceConfig config =
463 networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
464 if (config != null) {
465 oltData.put(config.getOlt().deviceId(), config.getOlt());
466 provisionDefaultFlows((DeviceId) event.subject());
467 }
468 }
469 break;
470 case CONFIG_UNREGISTERED:
471 case CONFIG_REMOVED:
472 default:
473 break;
474 }
475 }
476 }
477
478 private void provisionDefaultFlows(DeviceId deviceId) {
479 List<Port> ports = deviceService.getPorts(deviceId);
480
481 ports.stream()
482 .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
483 .filter(p -> p.isEnabled())
484 .forEach(p -> processFilterObjective((DeviceId) p.element().id(), p, false));
485
486 }
alshabibeff00542015-09-23 13:22:33 -0700487}