blob: 23eb66840be1915d282f982ab80f5c854bcbb860 [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -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 */
16package org.onosproject.segmentrouting;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
sangho1e575652015-05-14 00:39:53 -070023import org.apache.felix.scr.annotations.Service;
sanghob35a6192015-04-01 13:05:26 -070024import org.onlab.packet.Ethernet;
25import org.onlab.packet.IPv4;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070026import org.onlab.util.KryoNamespace;
sanghob35a6192015-04-01 13:05:26 -070027import org.onosproject.core.ApplicationId;
28import org.onosproject.core.CoreService;
29import org.onosproject.event.Event;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070030import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
31import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070032import org.onosproject.segmentrouting.grouphandler.NeighborSetNextObjectiveStoreKey;
sanghob35a6192015-04-01 13:05:26 -070033import org.onosproject.mastership.MastershipService;
34import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.Link;
sanghob35a6192015-04-01 13:05:26 -070037import org.onosproject.net.Port;
38import org.onosproject.net.device.DeviceEvent;
39import org.onosproject.net.device.DeviceListener;
40import org.onosproject.net.device.DeviceService;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070041import org.onosproject.net.flowobjective.FlowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -070042import org.onosproject.net.group.GroupKey;
sanghob35a6192015-04-01 13:05:26 -070043import org.onosproject.net.host.HostService;
44import org.onosproject.net.intent.IntentService;
45import org.onosproject.net.link.LinkEvent;
46import org.onosproject.net.link.LinkListener;
47import org.onosproject.net.link.LinkService;
48import org.onosproject.net.packet.InboundPacket;
49import org.onosproject.net.packet.PacketContext;
50import org.onosproject.net.packet.PacketProcessor;
51import org.onosproject.net.packet.PacketService;
52import org.onosproject.net.topology.TopologyService;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070053import org.onosproject.segmentrouting.config.NetworkConfigManager;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070054import org.onosproject.store.service.EventuallyConsistentMap;
55import org.onosproject.store.service.EventuallyConsistentMapBuilder;
56import org.onosproject.store.service.StorageService;
57import org.onosproject.store.service.WallClockTimestamp;
58import org.onosproject.store.service.WallclockClockManager;
sanghob35a6192015-04-01 13:05:26 -070059import org.slf4j.Logger;
60import org.slf4j.LoggerFactory;
61
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070062import java.net.URI;
63import java.util.HashSet;
sangho1e575652015-05-14 00:39:53 -070064import java.util.List;
sanghob35a6192015-04-01 13:05:26 -070065import java.util.Map;
66import java.util.concurrent.ConcurrentHashMap;
67import java.util.concurrent.ConcurrentLinkedQueue;
68import java.util.concurrent.Executors;
69import java.util.concurrent.ScheduledExecutorService;
70import java.util.concurrent.ScheduledFuture;
71import java.util.concurrent.TimeUnit;
72
73@SuppressWarnings("ALL")
sangho1e575652015-05-14 00:39:53 -070074@Service
sanghob35a6192015-04-01 13:05:26 -070075@Component(immediate = true)
sangho1e575652015-05-14 00:39:53 -070076public class SegmentRoutingManager implements SegmentRoutingService {
sanghob35a6192015-04-01 13:05:26 -070077
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070078 private static Logger log = LoggerFactory
79 .getLogger(SegmentRoutingManager.class);
sanghob35a6192015-04-01 13:05:26 -070080
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected CoreService coreService;
83
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected TopologyService topologyService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected PacketService packetService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected IntentService intentService;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected HostService hostService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected DeviceService deviceService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700100 protected FlowObjectiveService flowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -0700101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected LinkService linkService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghob35a6192015-04-01 13:05:26 -0700106 protected MastershipService mastershipService;
sangho1e575652015-05-14 00:39:53 -0700107
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700108 protected ArpHandler arpHandler = null;
109 protected IcmpHandler icmpHandler = null;
110 protected IpHandler ipHandler = null;
111 protected RoutingRulePopulator routingRulePopulator = null;
sanghob35a6192015-04-01 13:05:26 -0700112 protected ApplicationId appId;
sangho666cd6d2015-04-14 16:27:13 -0700113 protected DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700114
sangho1e575652015-05-14 00:39:53 -0700115
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700116 private DefaultRoutingHandler defaultRoutingHandler = null;
sangho1e575652015-05-14 00:39:53 -0700117 private TunnelHandler tunnelHandler = null;
118 private PolicyHandler policyHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700119 private InternalPacketProcessor processor = new InternalPacketProcessor();
120 private InternalEventHandler eventHandler = new InternalEventHandler();
121
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700122 private ScheduledExecutorService executorService = Executors
123 .newScheduledThreadPool(1);
sanghob35a6192015-04-01 13:05:26 -0700124
125 private static ScheduledFuture<?> eventHandlerFuture = null;
126 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700127 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700128 // Per device next objective ID store with (device id + neighbor set) as key
129 private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
130 Integer> nsNextObjStore = null;
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
132 protected StorageService storageService;
sanghob35a6192015-04-01 13:05:26 -0700133
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700134 private NetworkConfigManager networkConfigService = new NetworkConfigManager();;
135
sanghob35a6192015-04-01 13:05:26 -0700136 private static int numOfEvents = 0;
137 private static int numOfHandlerExecution = 0;
138 private static int numOfHandlerScheduled = 0;
139
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700140 private KryoNamespace.Builder kryoBuilder = null;
141
sanghob35a6192015-04-01 13:05:26 -0700142 @Activate
143 protected void activate() {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700144 appId = coreService
145 .registerApplication("org.onosproject.segmentrouting");
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700146
147 kryoBuilder = new KryoNamespace.Builder()
148 .register(NeighborSetNextObjectiveStoreKey.class,
149 NeighborSet.class,
150 DeviceId.class,
151 URI.class,
152 WallClockTimestamp.class,
153 org.onosproject.cluster.NodeId.class,
154 HashSet.class
155 );
156
157 log.debug("Creating EC map nsnextobjectivestore");
158 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
159 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
160
161 nsNextObjStore = nsNextObjMapBuilder
162 .withName("nsnextobjectivestore")
163 .withSerializer(kryoBuilder)
164 .withClockService(new WallclockClockManager<>())
165 .build();
166 log.trace("Current size {}", nsNextObjStore.size());
167
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700168 networkConfigService.init();
169 deviceConfiguration = new DeviceConfiguration(networkConfigService);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700170 arpHandler = new ArpHandler(this);
171 icmpHandler = new IcmpHandler(this);
172 ipHandler = new IpHandler(this);
173 routingRulePopulator = new RoutingRulePopulator(this);
174 defaultRoutingHandler = new DefaultRoutingHandler(this);
sangho1e575652015-05-14 00:39:53 -0700175 tunnelHandler = new TunnelHandler();
176 policyHandler = new PolicyHandler();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700177
sanghob35a6192015-04-01 13:05:26 -0700178 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
179 linkService.addListener(new InternalLinkListener());
sanghob35a6192015-04-01 13:05:26 -0700180 deviceService.addListener(new InternalDeviceListener());
181
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700182 for (Device device : deviceService.getDevices()) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700183 //Irrespective whether the local is a MASTER or not for this device,
184 //create group handler instance and push default TTP flow rules.
185 //Because in a multi-instance setup, instances can initiate
186 //groups for any devices. Also the default TTP rules are needed
187 //to be pushed before inserting any IP table entries for any device
188 DefaultGroupHandler groupHandler = DefaultGroupHandler
189 .createGroupHandler(device.id(), appId,
190 deviceConfiguration, linkService,
191 flowObjectiveService,
192 nsNextObjStore);
193 groupHandlerMap.put(device.id(), groupHandler);
194 defaultRoutingHandler.populateTtpRules(device.id());
sanghob35a6192015-04-01 13:05:26 -0700195 }
196
sangho20eff1d2015-04-13 15:15:58 -0700197 defaultRoutingHandler.startPopulationProcess();
sanghob35a6192015-04-01 13:05:26 -0700198 log.info("Started");
sangho1e575652015-05-14 00:39:53 -0700199
sanghob35a6192015-04-01 13:05:26 -0700200 }
201
202 @Deactivate
203 protected void deactivate() {
204 packetService.removeProcessor(processor);
205 processor = null;
206 log.info("Stopped");
207 }
208
sangho1e575652015-05-14 00:39:53 -0700209
210 @Override
211 public List<Tunnel> getTunnels() {
212 return tunnelHandler.getTunnels();
213 }
214
215 @Override
216 public void createTunnel(Tunnel tunnel) {
217 tunnelHandler.createTunnel(tunnel);
218 }
219
220 @Override
221 public void removeTunnel(Tunnel tunnel) {
222 for (Policy policy: policyHandler.getPolicies()) {
223 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
224 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
225 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
226 log.warn("Cannot remove the tunnel used by a policy");
227 return;
228 }
229 }
230 }
231 tunnelHandler.removeTunnel(tunnel);
232 }
233
234 @Override
235 public void removePolicy(Policy policy) {
236 policyHandler.removePolicy(policy);
237
238 }
239
240 @Override
241 public void createPolicy(Policy policy) {
242 policyHandler.createPolicy(policy);
243 }
244
245 @Override
246 public List<Policy> getPolicies() {
247 return policyHandler.getPolicies();
248 }
249
250 public Tunnel getTunnel(String tunnelId) {
251 return tunnelHandler.getTunnel(tunnelId);
252 }
253
sanghob35a6192015-04-01 13:05:26 -0700254 /**
255 * Returns the GrouopKey object for the device and the NighborSet given.
256 *
257 * @param ns NeightborSet object for the GroupKey
258 * @return GroupKey object for the NeighborSet
259 */
260 public GroupKey getGroupKey(NeighborSet ns) {
261
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700262 for (DefaultGroupHandler groupHandler : groupHandlerMap.values()) {
sanghob35a6192015-04-01 13:05:26 -0700263 return groupHandler.getGroupKey(ns);
264 }
265
266 return null;
267 }
268
sangho1e575652015-05-14 00:39:53 -0700269 /**
270 *
271 * @param deviceId
272 * @param ns
273 * @return
274 */
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700275 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) {
276
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700277 if (groupHandlerMap.get(deviceId) != null) {
278 log.trace("getNextObjectiveId query in device {}", deviceId);
279 return groupHandlerMap
280 .get(deviceId).getNextObjectiveId(ns);
281 } else {
282 log.warn("getNextObjectiveId query in device {} not found", deviceId);
283 return -1;
284 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700285 }
286
sangho1e575652015-05-14 00:39:53 -0700287 /**
288 *
289 * @param deviceId
290 * @param objectiveId
291 * @return
292 */
293 public boolean removeNextObjective(DeviceId deviceId, int objectiveId) {
294 return groupHandlerMap.get(deviceId).removeGroup(objectiveId);
295 }
296
sanghob35a6192015-04-01 13:05:26 -0700297 private class InternalPacketProcessor implements PacketProcessor {
298
299 @Override
300 public void process(PacketContext context) {
301
302 if (context.isHandled()) {
303 return;
304 }
305
306 InboundPacket pkt = context.inPacket();
307 Ethernet ethernet = pkt.parsed();
308
309 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
310 arpHandler.processPacketIn(pkt);
311 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
312 IPv4 ipPacket = (IPv4) ethernet.getPayload();
313 ipHandler.addToPacketBuffer(ipPacket);
314 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
315 icmpHandler.processPacketIn(pkt);
316 } else {
317 ipHandler.processPacketIn(pkt);
318 }
319 }
320 }
321 }
322
323 private class InternalLinkListener implements LinkListener {
324 @Override
325 public void event(LinkEvent event) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700326 if (event.type() == LinkEvent.Type.LINK_ADDED
327 || event.type() == LinkEvent.Type.LINK_REMOVED) {
sanghob35a6192015-04-01 13:05:26 -0700328 scheduleEventHandlerIfNotScheduled(event);
329 }
330 }
331 }
332
333 private class InternalDeviceListener implements DeviceListener {
334
335 @Override
336 public void event(DeviceEvent event) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700337 /*if (mastershipService.getLocalRole(event.subject().id()) != MastershipRole.MASTER) {
sanghob35a6192015-04-01 13:05:26 -0700338 log.debug("Local role {} is not MASTER for device {}",
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700339 mastershipService.getLocalRole(event.subject().id()),
340 event.subject().id());
sanghob35a6192015-04-01 13:05:26 -0700341 return;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700342 }*/
sanghob35a6192015-04-01 13:05:26 -0700343
344 switch (event.type()) {
345 case DEVICE_ADDED:
346 case PORT_REMOVED:
sangho20eff1d2015-04-13 15:15:58 -0700347 case DEVICE_UPDATED:
348 case DEVICE_AVAILABILITY_CHANGED:
sanghob35a6192015-04-01 13:05:26 -0700349 scheduleEventHandlerIfNotScheduled(event);
350 break;
351 default:
352 }
353 }
354 }
355
sanghob35a6192015-04-01 13:05:26 -0700356 private void scheduleEventHandlerIfNotScheduled(Event event) {
357
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700358 synchronized (eventQueue) {
359 eventQueue.add(event);
360 numOfEvents++;
361 if (eventHandlerFuture == null || eventHandlerFuture.isDone()) {
362 eventHandlerFuture = executorService
363 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
364 numOfHandlerScheduled++;
365 }
sanghob35a6192015-04-01 13:05:26 -0700366 }
367
368 log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
sangho1e575652015-05-14 00:39:53 -0700369 numOfHandlerScheduled);
sanghob35a6192015-04-01 13:05:26 -0700370
371 }
372
373 private class InternalEventHandler implements Runnable {
374
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700375 @Override
sanghob35a6192015-04-01 13:05:26 -0700376 public void run() {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700377 try {
378 synchronized (eventQueue) {
379 numOfHandlerExecution++;
380 while (!eventQueue.isEmpty()) {
381 Event event = eventQueue.poll();
382 if (event.type() == LinkEvent.Type.LINK_ADDED) {
383 processLinkAdded((Link) event.subject());
384 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
385 processLinkRemoved((Link) event.subject());
386 //} else if (event.type() == GroupEvent.Type.GROUP_ADDED) {
387 // processGroupAdded((Group) event.subject());
388 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
389 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
390 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
391 if (deviceService.isAvailable(((Device) event.subject()).id())) {
392 processDeviceAdded((Device) event.subject());
393 }
394 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
395 processPortRemoved((Device) event.subject(),
396 ((DeviceEvent) event).port());
397 } else {
398 log.warn("Unhandled event type: {}", event.type());
399 }
sangho20eff1d2015-04-13 15:15:58 -0700400 }
sanghob35a6192015-04-01 13:05:26 -0700401 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700402 log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}",
403 numOfHandlerExecution, numOfHandlerScheduled, numOfEvents);
404 } catch (Exception e) {
405 log.error("SegmentRouting event handler "
406 + "thread thrown an exception: {}", e);
sanghob35a6192015-04-01 13:05:26 -0700407 }
sanghob35a6192015-04-01 13:05:26 -0700408 }
409 }
410
sanghob35a6192015-04-01 13:05:26 -0700411 private void processLinkAdded(Link link) {
412 log.debug("A new link {} was added", link.toString());
413
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700414 //Irrespective whether the local is a MASTER or not for this device,
415 //create group handler instance and push default TTP flow rules.
416 //Because in a multi-instance setup, instances can initiate
417 //groups for any devices. Also the default TTP rules are needed
418 //to be pushed before inserting any IP table entries for any device
419 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
420 .deviceId());
421 if (groupHandler != null) {
422 groupHandler.linkUp(link);
423 } else {
424 Device device = deviceService.getDevice(link.src().deviceId());
425 if (device != null) {
426 log.warn("processLinkAdded: Link Added "
427 + "Notification without Device Added "
428 + "event, still handling it");
429 processDeviceAdded(device);
430 groupHandler = groupHandlerMap.get(link.src()
431 .deviceId());
sanghob35a6192015-04-01 13:05:26 -0700432 groupHandler.linkUp(link);
433 }
434 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700435
436 //defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
437 log.trace("processLinkAdded: re-starting route population process");
438 defaultRoutingHandler.startPopulationProcess();
sanghob35a6192015-04-01 13:05:26 -0700439 }
440
441 private void processLinkRemoved(Link link) {
442 log.debug("A link {} was removed", link.toString());
sangho834e4b02015-05-01 09:38:25 -0700443 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
444 if (groupHandler != null) {
445 groupHandler.portDown(link.src().port());
446 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700447 //defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
448 log.trace("processLinkRemoved: re-starting route population process");
449 defaultRoutingHandler.startPopulationProcess();
sanghob35a6192015-04-01 13:05:26 -0700450 }
451
452 private void processDeviceAdded(Device device) {
453 log.debug("A new device with ID {} was added", device.id());
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700454 //Irrespective whether the local is a MASTER or not for this device,
455 //create group handler instance and push default TTP flow rules.
456 //Because in a multi-instance setup, instances can initiate
457 //groups for any devices. Also the default TTP rules are needed
458 //to be pushed before inserting any IP table entries for any device
459 DefaultGroupHandler dgh = DefaultGroupHandler.
460 createGroupHandler(device.id(),
461 appId,
462 deviceConfiguration,
463 linkService,
464 flowObjectiveService,
465 nsNextObjStore);
sanghob35a6192015-04-01 13:05:26 -0700466 groupHandlerMap.put(device.id(), dgh);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700467 defaultRoutingHandler.populateTtpRules(device.id());
sanghob35a6192015-04-01 13:05:26 -0700468 }
469
470 private void processPortRemoved(Device device, Port port) {
471 log.debug("Port {} was removed", port.toString());
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700472 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -0700473 if (groupHandler != null) {
474 groupHandler.portDown(port.number());
475 }
476 }
sangho1e575652015-05-14 00:39:53 -0700477
478
479
sanghob35a6192015-04-01 13:05:26 -0700480}