blob: b548492635e63775d93feaf707a1f48314c52c2a [file] [log] [blame]
Jonathan Hartdf207092015-12-10 11:19:25 -08001/*
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 */
16
Jonathan Hartc22e8472015-11-17 18:25:45 -080017package org.onosproject.routing.impl;
Jonathan Hartdf207092015-12-10 11:19:25 -080018
19import com.google.common.collect.ConcurrentHashMultiset;
20import com.google.common.collect.HashMultimap;
21import com.google.common.collect.Maps;
22import com.google.common.collect.Multimap;
23import com.google.common.collect.Multiset;
24import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
Jonathan Hartb9401902016-02-02 18:46:01 -080027import org.apache.felix.scr.annotations.Modified;
28import org.apache.felix.scr.annotations.Property;
Jonathan Hartdf207092015-12-10 11:19:25 -080029import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
31import org.onlab.packet.Ethernet;
32import org.onlab.packet.IpAddress;
33import org.onlab.packet.IpPrefix;
Jonathan Hartca47cd72015-12-13 12:31:09 -080034import org.onlab.packet.VlanId;
Jonathan Hartb9401902016-02-02 18:46:01 -080035import org.onlab.util.Tools;
36import org.onosproject.cfg.ComponentConfigService;
Jonathan Hartdf207092015-12-10 11:19:25 -080037import org.onosproject.core.ApplicationId;
38import org.onosproject.core.CoreService;
39import org.onosproject.incubator.net.intf.Interface;
gaurav164cf6d2016-03-25 21:43:04 +053040import org.onosproject.incubator.net.intf.InterfaceEvent;
41import org.onosproject.incubator.net.intf.InterfaceListener;
Jonathan Hartdf207092015-12-10 11:19:25 -080042import org.onosproject.incubator.net.intf.InterfaceService;
Saurav Das49cb5a12016-01-16 22:54:07 -080043import org.onosproject.net.ConnectPoint;
Jonathan Hartdf207092015-12-10 11:19:25 -080044import org.onosproject.net.DeviceId;
Jonathan Hartb3fa42c2016-01-13 09:50:43 -080045import org.onosproject.net.config.NetworkConfigEvent;
46import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hartdf207092015-12-10 11:19:25 -080047import org.onosproject.net.config.NetworkConfigService;
48import org.onosproject.net.device.DeviceEvent;
49import org.onosproject.net.device.DeviceListener;
50import org.onosproject.net.device.DeviceService;
51import org.onosproject.net.flow.DefaultTrafficSelector;
52import org.onosproject.net.flow.DefaultTrafficTreatment;
53import org.onosproject.net.flow.TrafficSelector;
54import org.onosproject.net.flow.TrafficTreatment;
55import org.onosproject.net.flow.criteria.Criteria;
56import org.onosproject.net.flowobjective.DefaultFilteringObjective;
57import org.onosproject.net.flowobjective.DefaultForwardingObjective;
58import org.onosproject.net.flowobjective.DefaultNextObjective;
59import org.onosproject.net.flowobjective.FilteringObjective;
60import org.onosproject.net.flowobjective.FlowObjectiveService;
61import org.onosproject.net.flowobjective.ForwardingObjective;
62import org.onosproject.net.flowobjective.NextObjective;
63import org.onosproject.net.flowobjective.Objective;
64import org.onosproject.net.flowobjective.ObjectiveContext;
65import org.onosproject.net.flowobjective.ObjectiveError;
66import org.onosproject.routing.FibEntry;
67import org.onosproject.routing.FibListener;
68import org.onosproject.routing.FibUpdate;
69import org.onosproject.routing.RoutingService;
Jonathan Hartb3fa42c2016-01-13 09:50:43 -080070import org.onosproject.routing.config.RouterConfig;
Jonathan Hartb9401902016-02-02 18:46:01 -080071import org.osgi.service.component.ComponentContext;
Jonathan Hartdf207092015-12-10 11:19:25 -080072import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74
75import java.util.Collection;
Jonathan Hartb9401902016-02-02 18:46:01 -080076import java.util.Dictionary;
Jonathan Hartdf207092015-12-10 11:19:25 -080077import java.util.HashMap;
Jonathan Hart883fd372016-02-10 14:36:15 -080078import java.util.List;
Jonathan Hartdf207092015-12-10 11:19:25 -080079import java.util.Map;
Jonathan Hartdf207092015-12-10 11:19:25 -080080import java.util.Set;
Jonathan Hart883fd372016-02-10 14:36:15 -080081import java.util.stream.Collectors;
Jonathan Hartdf207092015-12-10 11:19:25 -080082
83/**
84 * Programs routes to a single OpenFlow switch.
85 */
Jonathan Hartc22e8472015-11-17 18:25:45 -080086@Component(immediate = true, enabled = false)
87public class SingleSwitchFibInstaller {
Jonathan Hartdf207092015-12-10 11:19:25 -080088
89 private final Logger log = LoggerFactory.getLogger(getClass());
90
91 private static final int PRIORITY_OFFSET = 100;
92 private static final int PRIORITY_MULTIPLIER = 5;
93
Saurav Das49cb5a12016-01-16 22:54:07 -080094 public static final short ASSIGNED_VLAN = 4094;
95
Jonathan Hartdf207092015-12-10 11:19:25 -080096 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected CoreService coreService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected RoutingService routingService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected InterfaceService interfaceService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected NetworkConfigService networkConfigService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartb9401902016-02-02 18:46:01 -0800109 protected ComponentConfigService componentConfigService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartdf207092015-12-10 11:19:25 -0800112 protected FlowObjectiveService flowObjectiveService;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected DeviceService deviceService;
116
Jonathan Hartb9401902016-02-02 18:46:01 -0800117 @Property(name = "routeToNextHop", boolValue = false,
118 label = "Install a /32 route to each next hop")
119 private boolean routeToNextHop = false;
120
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800121 private InternalDeviceListener deviceListener;
Jonathan Hartdf207092015-12-10 11:19:25 -0800122
123 // Device id of data-plane switch - should be learned from config
124 private DeviceId deviceId;
125
Saurav Das49cb5a12016-01-16 22:54:07 -0800126 private ConnectPoint controlPlaneConnectPoint;
127
Jonathan Hart883fd372016-02-10 14:36:15 -0800128 private List<String> interfaces;
129
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800130 private ApplicationId routerAppId;
Jonathan Hartdf207092015-12-10 11:19:25 -0800131
132 // Reference count for how many times a next hop is used by a route
133 private final Multiset<IpAddress> nextHopsCount = ConcurrentHashMultiset.create();
134
135 // Mapping from prefix to its current next hop
136 private final Map<IpPrefix, IpAddress> prefixToNextHop = Maps.newHashMap();
137
138 // Mapping from next hop IP to next hop object containing group info
139 private final Map<IpAddress, Integer> nextHops = Maps.newHashMap();
140
141 // Stores FIB updates that are waiting for groups to be set up
142 private final Multimap<NextHopGroupKey, FibEntry> pendingUpdates = HashMultimap.create();
143
gaurav164cf6d2016-03-25 21:43:04 +0530144 //interface object for event
145 private InternalInterfaceListener internalInterfaceList = new InternalInterfaceListener();
Jonathan Hartdf207092015-12-10 11:19:25 -0800146
147 @Activate
Jonathan Hartb9401902016-02-02 18:46:01 -0800148 protected void activate(ComponentContext context) {
Jonathan Hartb9401902016-02-02 18:46:01 -0800149 componentConfigService.registerProperties(getClass());
Jonathan Hart9ad777f2016-02-19 12:44:36 -0800150 modified(context);
151
152 routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID);
Jonathan Hartb9401902016-02-02 18:46:01 -0800153
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800154 deviceListener = new InternalDeviceListener();
Jonathan Hartdf207092015-12-10 11:19:25 -0800155 deviceService.addListener(deviceListener);
156
gaurav164cf6d2016-03-25 21:43:04 +0530157 interfaceService.addListener(internalInterfaceList);
158
Jonathan Hartdf207092015-12-10 11:19:25 -0800159 routingService.addFibListener(new InternalFibListener());
160 routingService.start();
161
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800162 updateConfig();
Jonathan Hartdf207092015-12-10 11:19:25 -0800163
164 log.info("Started");
165 }
166
167 @Deactivate
168 protected void deactivate() {
169 routingService.stop();
170
171 deviceService.removeListener(deviceListener);
172
gaurav164cf6d2016-03-25 21:43:04 +0530173 interfaceService.removeListener(internalInterfaceList);
174
Jonathan Hartdf207092015-12-10 11:19:25 -0800175 //processIntfFilters(false, configService.getInterfaces()); //TODO necessary?
176
Jonathan Hartb9401902016-02-02 18:46:01 -0800177 componentConfigService.unregisterProperties(getClass(), false);
178
Jonathan Hartdf207092015-12-10 11:19:25 -0800179 log.info("Stopped");
180 }
181
Jonathan Hartb9401902016-02-02 18:46:01 -0800182 @Modified
183 protected void modified(ComponentContext context) {
184 Dictionary<?, ?> properties = context.getProperties();
185 if (properties == null) {
186 return;
187 }
188
189 String strRouteToNextHop = Tools.get(properties, "routeToNextHop");
190 routeToNextHop = Boolean.parseBoolean(strRouteToNextHop);
191
192 log.info("routeToNextHop set to {}", routeToNextHop);
193 }
194
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800195 private void updateConfig() {
196 RouterConfig routerConfig =
197 networkConfigService.getConfig(routerAppId, RoutingService.ROUTER_CONFIG_CLASS);
Jonathan Hartdf207092015-12-10 11:19:25 -0800198
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800199 if (routerConfig == null) {
200 log.info("Router config not available");
Jonathan Hartdf207092015-12-10 11:19:25 -0800201 return;
202 }
Saurav Das49cb5a12016-01-16 22:54:07 -0800203 controlPlaneConnectPoint = routerConfig.getControlPlaneConnectPoint();
204 log.info("Control Plane Connect Point: {}", controlPlaneConnectPoint);
Jonathan Hartdf207092015-12-10 11:19:25 -0800205
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800206 deviceId = routerConfig.getControlPlaneConnectPoint().deviceId();
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800207 log.info("Router device ID is {}", deviceId);
208
Jonathan Hart883fd372016-02-10 14:36:15 -0800209 interfaces = routerConfig.getInterfaces();
210 log.info("Using interfaces: {}", interfaces.isEmpty() ? "all" : interfaces);
211
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800212 updateDevice();
213 }
214
215 private void updateDevice() {
216 if (deviceId != null && deviceService.isAvailable(deviceId)) {
Jonathan Hart883fd372016-02-10 14:36:15 -0800217
218 Set<Interface> intfs;
219 if (interfaces.isEmpty()) {
220 intfs = interfaceService.getInterfaces();
221 } else {
222 // TODO need to fix by making interface names globally unique
223 intfs = interfaceService.getInterfaces().stream()
224 .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
225 .filter(intf -> interfaces.contains(intf.name()))
226 .collect(Collectors.toSet());
227 }
228
229 processIntfFilters(true, intfs);
Jonathan Hartdf207092015-12-10 11:19:25 -0800230 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800231 }
232
233 private void updateFibEntry(Collection<FibUpdate> updates) {
234 Map<FibEntry, Integer> toInstall = new HashMap<>(updates.size());
235
236 for (FibUpdate update : updates) {
237 FibEntry entry = update.entry();
238
239 addNextHop(entry);
240
241 Integer nextId;
242 synchronized (pendingUpdates) {
243 nextId = nextHops.get(entry.nextHopIp());
244 }
245
246 toInstall.put(update.entry(), nextId);
247 }
248
249 installFlows(toInstall);
250 }
251
252 private void installFlows(Map<FibEntry, Integer> entriesToInstall) {
253
254 for (Map.Entry<FibEntry, Integer> entry : entriesToInstall.entrySet()) {
255 FibEntry fibEntry = entry.getKey();
256 Integer nextId = entry.getValue();
257
258 flowObjectiveService.forward(deviceId,
259 generateRibForwardingObj(fibEntry.prefix(), nextId).add());
260 log.trace("Sending forwarding objective {} -> nextId:{}", fibEntry, nextId);
261 }
262
263 }
264
265 private synchronized void deleteFibEntry(Collection<FibUpdate> withdraws) {
266
267 for (FibUpdate update : withdraws) {
268 FibEntry entry = update.entry();
269 //Integer nextId = nextHops.get(entry.nextHopIp());
270
271 /* Group group = deleteNextHop(entry.prefix());
272 if (group == null) {
273 log.warn("Group not found when deleting {}", entry);
274 return;
275 }*/
276
277 flowObjectiveService.forward(deviceId,
278 generateRibForwardingObj(entry.prefix(), null).remove());
279
280 }
281
282 }
283
284 private ForwardingObjective.Builder generateRibForwardingObj(IpPrefix prefix,
285 Integer nextId) {
286 TrafficSelector selector = DefaultTrafficSelector.builder()
287 .matchEthType(Ethernet.TYPE_IPV4)
288 .matchIPDst(prefix)
289 .build();
290
291 int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
292
293 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder()
Saurav Das49cb5a12016-01-16 22:54:07 -0800294 .fromApp(routerAppId)
Jonathan Hartdf207092015-12-10 11:19:25 -0800295 .makePermanent()
296 .withSelector(selector)
297 .withPriority(priority)
298 .withFlag(ForwardingObjective.Flag.SPECIFIC);
299
300 if (nextId == null) {
301 // Route withdraws are not specified with next hops. Generating
302 // dummy treatment as there is no equivalent nextId info.
303 fwdBuilder.withTreatment(DefaultTrafficTreatment.builder().build());
304 } else {
305 fwdBuilder.nextStep(nextId);
306 }
307 return fwdBuilder;
308 }
309
310 private synchronized void addNextHop(FibEntry entry) {
311 prefixToNextHop.put(entry.prefix(), entry.nextHopIp());
312 if (nextHopsCount.count(entry.nextHopIp()) == 0) {
313 // There was no next hop in the multiset
314
315 Interface egressIntf = interfaceService.getMatchingInterface(entry.nextHopIp());
316 if (egressIntf == null) {
317 log.warn("no egress interface found for {}", entry);
318 return;
319 }
320
321 NextHopGroupKey groupKey = new NextHopGroupKey(entry.nextHopIp());
322
323 NextHop nextHop = new NextHop(entry.nextHopIp(), entry.nextHopMac(), groupKey);
324
Jonathan Hartca47cd72015-12-13 12:31:09 -0800325 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
Jonathan Hartdf207092015-12-10 11:19:25 -0800326 .setEthSrc(egressIntf.mac())
Jonathan Hartca47cd72015-12-13 12:31:09 -0800327 .setEthDst(nextHop.mac());
328
Saurav Das49cb5a12016-01-16 22:54:07 -0800329 TrafficSelector.Builder metabuilder = null;
Jonathan Hartca47cd72015-12-13 12:31:09 -0800330 if (!egressIntf.vlan().equals(VlanId.NONE)) {
331 treatment.pushVlan()
332 .setVlanId(egressIntf.vlan())
333 .setVlanPcp((byte) 0);
Saurav Das49cb5a12016-01-16 22:54:07 -0800334 } else {
335 // untagged outgoing port may require internal vlan in some pipelines
336 metabuilder = DefaultTrafficSelector.builder();
337 metabuilder.matchVlanId(VlanId.vlanId(ASSIGNED_VLAN));
Jonathan Hartca47cd72015-12-13 12:31:09 -0800338 }
339
340 treatment.setOutput(egressIntf.connectPoint().port());
Jonathan Hartdf207092015-12-10 11:19:25 -0800341
342 int nextId = flowObjectiveService.allocateNextId();
Saurav Das49cb5a12016-01-16 22:54:07 -0800343 NextObjective.Builder nextBuilder = DefaultNextObjective.builder()
Jonathan Hartdf207092015-12-10 11:19:25 -0800344 .withId(nextId)
Jonathan Hartca47cd72015-12-13 12:31:09 -0800345 .addTreatment(treatment.build())
Jonathan Hartdf207092015-12-10 11:19:25 -0800346 .withType(NextObjective.Type.SIMPLE)
Saurav Das49cb5a12016-01-16 22:54:07 -0800347 .fromApp(routerAppId);
348 if (metabuilder != null) {
349 nextBuilder.withMeta(metabuilder.build());
350 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800351
Saurav Das49cb5a12016-01-16 22:54:07 -0800352 NextObjective nextObjective = nextBuilder.add(); // TODO add callbacks
Jonathan Hartdf207092015-12-10 11:19:25 -0800353 flowObjectiveService.next(deviceId, nextObjective);
354
355 nextHops.put(nextHop.ip(), nextId);
356
Jonathan Hartb9401902016-02-02 18:46:01 -0800357 if (routeToNextHop) {
358 // Install route to next hop
359 ForwardingObjective fob =
360 generateRibForwardingObj(IpPrefix.valueOf(entry.nextHopIp(), 32), nextId).add();
361 flowObjectiveService.forward(deviceId, fob);
362 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800363 }
364
365 nextHopsCount.add(entry.nextHopIp());
366 }
367
368 /*private synchronized Group deleteNextHop(IpPrefix prefix) {
369 IpAddress nextHopIp = prefixToNextHop.remove(prefix);
370 NextHop nextHop = nextHops.get(nextHopIp);
371 if (nextHop == null) {
372 log.warn("No next hop found when removing prefix {}", prefix);
373 return null;
374 }
375
376 Group group = groupService.getGroup(deviceId,
377 new DefaultGroupKey(appKryo.
378 serialize(nextHop.group())));
379
380 // FIXME disabling group deletes for now until we verify the logic is OK
381 if (nextHopsCount.remove(nextHopIp, 1) <= 1) {
382 // There was one or less next hops, so there are now none
383
384 log.debug("removing group for next hop {}", nextHop);
385
386 nextHops.remove(nextHopIp);
387
388 groupService.removeGroup(deviceId,
389 new DefaultGroupKey(appKryo.build().serialize(nextHop.group())),
390 appId);
391 }
392
393 return group;
394 }*/
395
396 private void processIntfFilters(boolean install, Set<Interface> intfs) {
397 log.info("Processing {} router interfaces", intfs.size());
398 for (Interface intf : intfs) {
399 if (!intf.connectPoint().deviceId().equals(deviceId)) {
400 // Ignore interfaces if they are not on the router switch
401 continue;
402 }
403
gaurav164cf6d2016-03-25 21:43:04 +0530404 createFilteringObjective(install, intf);
405 }
406 }
Jonathan Hart6344f572015-12-15 08:26:25 -0800407
gaurav164cf6d2016-03-25 21:43:04 +0530408 //process filtering objective for interface add/remove.
409 private void processIntfFilter(boolean install, Interface intf) {
410
411 if (!intf.connectPoint().deviceId().equals(deviceId)) {
412 // Ignore interfaces if they are not on the router switch
413 return;
414 }
415
416 createFilteringObjective(install, intf);
417 }
418
419 //create filtering objective for interface
420 private void createFilteringObjective(boolean install, Interface intf) {
421
422 FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
423 // first add filter for the interface
424 fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
425 .addCondition(Criteria.matchEthDst(intf.mac()))
426 .addCondition(Criteria.matchVlanId(intf.vlan()));
427 fob.withPriority(PRIORITY_OFFSET);
428 if (intf.vlan() == VlanId.NONE) {
429 TrafficTreatment tt = DefaultTrafficTreatment.builder()
430 .pushVlan().setVlanId(VlanId.vlanId(ASSIGNED_VLAN)).build();
431 fob.withMeta(tt);
432 }
433
434 fob.permit().fromApp(routerAppId);
435 sendFilteringObjective(install, fob, intf);
436 if (controlPlaneConnectPoint != null) {
437 // then add the same mac/vlan filters for control-plane connect point
438 fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port()));
Saurav Das49cb5a12016-01-16 22:54:07 -0800439 sendFilteringObjective(install, fob, intf);
Jonathan Hartdf207092015-12-10 11:19:25 -0800440 }
441 }
442
Saurav Das49cb5a12016-01-16 22:54:07 -0800443 private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob,
444 Interface intf) {
gaurav164cf6d2016-03-25 21:43:04 +0530445 if (install) {
446 flowObjectiveService.filter(
447 deviceId,
448 fob.add(new ObjectiveContext() {
449 @Override
450 public void onSuccess(Objective objective) {
451 log.info("Successfully installed interface based "
452 + "filtering objectives for intf {}", intf);
453 }
Saurav Das49cb5a12016-01-16 22:54:07 -0800454
gaurav164cf6d2016-03-25 21:43:04 +0530455 @Override
456 public void onError(Objective objective,
457 ObjectiveError error) {
458 log.error("Failed to install interface filters for intf {}: {}",
459 intf, error);
460 // TODO something more than just logging
461 }
Saurav Das49cb5a12016-01-16 22:54:07 -0800462 }));
gaurav164cf6d2016-03-25 21:43:04 +0530463 } else {
464 flowObjectiveService.filter(
465 deviceId,
466 fob.remove(new ObjectiveContext() {
467 @Override
468 public void onSuccess(Objective objective) {
469 log.info("Successfully removed interface based "
470 + "filtering objectives for intf {}", intf);
471 }
472
473 @Override
474 public void onError(Objective objective,
475 ObjectiveError error) {
476 log.error("Failed to install interface filters for intf {}: {}",
477 intf, error);
478 // TODO something more than just logging
479 }
480 }));
481 }
Saurav Das49cb5a12016-01-16 22:54:07 -0800482 }
483
Jonathan Hartdf207092015-12-10 11:19:25 -0800484 private class InternalFibListener implements FibListener {
485
486 @Override
487 public void update(Collection<FibUpdate> updates,
488 Collection<FibUpdate> withdraws) {
Jonathan Hartc22e8472015-11-17 18:25:45 -0800489 SingleSwitchFibInstaller.this.deleteFibEntry(withdraws);
490 SingleSwitchFibInstaller.this.updateFibEntry(updates);
Jonathan Hartdf207092015-12-10 11:19:25 -0800491 }
492 }
493
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800494 /**
495 * Listener for device events used to trigger driver setup when a device is
496 * (re)detected.
497 */
498 private class InternalDeviceListener implements DeviceListener {
Jonathan Hartdf207092015-12-10 11:19:25 -0800499 @Override
500 public void event(DeviceEvent event) {
501 switch (event.type()) {
502 case DEVICE_ADDED:
503 case DEVICE_AVAILABILITY_CHANGED:
504 if (deviceService.isAvailable(event.subject().id())) {
505 log.info("Device connected {}", event.subject().id());
506 if (event.subject().id().equals(deviceId)) {
Charles Chanf555a732016-02-15 15:37:15 -0800507 updateDevice();
Jonathan Hartdf207092015-12-10 11:19:25 -0800508 }
509 }
510 break;
511 // TODO other cases
512 case DEVICE_UPDATED:
513 case DEVICE_REMOVED:
514 case DEVICE_SUSPENDED:
515 case PORT_ADDED:
516 case PORT_UPDATED:
517 case PORT_REMOVED:
518 default:
519 break;
520 }
521 }
522 }
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800523
524 /**
525 * Listener for network config events.
526 */
527 private class InternalNetworkConfigListener implements NetworkConfigListener {
528 @Override
529 public void event(NetworkConfigEvent event) {
530 if (event.subject().equals(RoutingService.ROUTER_CONFIG_CLASS)) {
531 switch (event.type()) {
532 case CONFIG_ADDED:
533 case CONFIG_UPDATED:
534 updateConfig();
535 break;
536 case CONFIG_REGISTERED:
537 case CONFIG_UNREGISTERED:
538 case CONFIG_REMOVED:
539 default:
540 break;
541 }
542 }
543 }
544 }
gaurav164cf6d2016-03-25 21:43:04 +0530545
546 private class InternalInterfaceListener implements InterfaceListener {
547
548 @Override
549 public void event(InterfaceEvent event) {
550 Interface intf = event.subject();
551 switch (event.type()) {
552 case INTERFACE_ADDED:
553 if (intf != null) {
554 processIntfFilter(true, intf);
555 }
556 break;
557 case INTERFACE_UPDATED:
558 break;
559 case INTERFACE_REMOVED:
560 if (intf != null) {
561 processIntfFilter(false, intf);
562 }
563 break;
564 default:
565 break;
566 }
567 }
568 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800569}