blob: 473450d59424e81c6190a30956d9555faff25d80 [file] [log] [blame]
Jonathan Hartdf207092015-12-10 11:19:25 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Jonathan Hartdf207092015-12-10 11:19:25 -08003 *
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;
Jonathan Hartdf207092015-12-10 11:19:25 -080020import com.google.common.collect.Maps;
Jonathan Hartdf207092015-12-10 11:19:25 -080021import com.google.common.collect.Multiset;
22import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
Jonathan Hartb9401902016-02-02 18:46:01 -080025import org.apache.felix.scr.annotations.Modified;
26import org.apache.felix.scr.annotations.Property;
Jonathan Hartdf207092015-12-10 11:19:25 -080027import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.onlab.packet.Ethernet;
30import org.onlab.packet.IpAddress;
31import org.onlab.packet.IpPrefix;
Jonathan Hartca47cd72015-12-13 12:31:09 -080032import org.onlab.packet.VlanId;
Jonathan Hartb9401902016-02-02 18:46:01 -080033import org.onlab.util.Tools;
34import org.onosproject.cfg.ComponentConfigService;
Jonathan Hartdf207092015-12-10 11:19:25 -080035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
37import org.onosproject.incubator.net.intf.Interface;
gaurav164cf6d2016-03-25 21:43:04 +053038import org.onosproject.incubator.net.intf.InterfaceEvent;
39import org.onosproject.incubator.net.intf.InterfaceListener;
Jonathan Hartdf207092015-12-10 11:19:25 -080040import org.onosproject.incubator.net.intf.InterfaceService;
Jonathan Harta2eb9ff2016-04-13 21:27:06 -070041import org.onosproject.incubator.net.routing.ResolvedRoute;
42import org.onosproject.incubator.net.routing.RouteEvent;
43import org.onosproject.incubator.net.routing.RouteListener;
44import org.onosproject.incubator.net.routing.RouteService;
Saurav Das49cb5a12016-01-16 22:54:07 -080045import org.onosproject.net.ConnectPoint;
Jonathan Hartdf207092015-12-10 11:19:25 -080046import org.onosproject.net.DeviceId;
Jonathan Hartb3fa42c2016-01-13 09:50:43 -080047import org.onosproject.net.config.NetworkConfigEvent;
48import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hartdf207092015-12-10 11:19:25 -080049import org.onosproject.net.config.NetworkConfigService;
50import org.onosproject.net.device.DeviceEvent;
51import org.onosproject.net.device.DeviceListener;
52import org.onosproject.net.device.DeviceService;
53import org.onosproject.net.flow.DefaultTrafficSelector;
54import org.onosproject.net.flow.DefaultTrafficTreatment;
55import org.onosproject.net.flow.TrafficSelector;
56import org.onosproject.net.flow.TrafficTreatment;
57import org.onosproject.net.flow.criteria.Criteria;
58import org.onosproject.net.flowobjective.DefaultFilteringObjective;
59import org.onosproject.net.flowobjective.DefaultForwardingObjective;
60import org.onosproject.net.flowobjective.DefaultNextObjective;
Jonathan Harta2eb9ff2016-04-13 21:27:06 -070061import org.onosproject.net.flowobjective.DefaultObjectiveContext;
Jonathan Hartdf207092015-12-10 11:19:25 -080062import org.onosproject.net.flowobjective.FilteringObjective;
63import org.onosproject.net.flowobjective.FlowObjectiveService;
64import org.onosproject.net.flowobjective.ForwardingObjective;
65import org.onosproject.net.flowobjective.NextObjective;
Jonathan Hartdf207092015-12-10 11:19:25 -080066import org.onosproject.net.flowobjective.ObjectiveContext;
Jonathan Hartdf207092015-12-10 11:19:25 -080067import org.onosproject.routing.RoutingService;
Jonathan Hartb3fa42c2016-01-13 09:50:43 -080068import org.onosproject.routing.config.RouterConfig;
Jonathan Hartb9401902016-02-02 18:46:01 -080069import org.osgi.service.component.ComponentContext;
Jonathan Hartdf207092015-12-10 11:19:25 -080070import org.slf4j.Logger;
71import org.slf4j.LoggerFactory;
72
Jonathan Hartb9401902016-02-02 18:46:01 -080073import java.util.Dictionary;
Jonathan Hart883fd372016-02-10 14:36:15 -080074import java.util.List;
Jonathan Hartdf207092015-12-10 11:19:25 -080075import java.util.Map;
Jonathan Hartdf207092015-12-10 11:19:25 -080076import java.util.Set;
Jonathan Hart883fd372016-02-10 14:36:15 -080077import java.util.stream.Collectors;
Jonathan Hartdf207092015-12-10 11:19:25 -080078
79/**
80 * Programs routes to a single OpenFlow switch.
81 */
Jonathan Hartc22e8472015-11-17 18:25:45 -080082@Component(immediate = true, enabled = false)
83public class SingleSwitchFibInstaller {
Jonathan Hartdf207092015-12-10 11:19:25 -080084
85 private final Logger log = LoggerFactory.getLogger(getClass());
86
87 private static final int PRIORITY_OFFSET = 100;
88 private static final int PRIORITY_MULTIPLIER = 5;
89
Saurav Das49cb5a12016-01-16 22:54:07 -080090 public static final short ASSIGNED_VLAN = 4094;
91
Jonathan Hartdf207092015-12-10 11:19:25 -080092 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected CoreService coreService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Harta2eb9ff2016-04-13 21:27:06 -070096 protected RouteService routeService;
Jonathan Hartdf207092015-12-10 11:19:25 -080097
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected InterfaceService interfaceService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected NetworkConfigService networkConfigService;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartb9401902016-02-02 18:46:01 -0800105 protected ComponentConfigService componentConfigService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartdf207092015-12-10 11:19:25 -0800108 protected FlowObjectiveService flowObjectiveService;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected DeviceService deviceService;
112
Jonathan Hartb9401902016-02-02 18:46:01 -0800113 @Property(name = "routeToNextHop", boolValue = false,
114 label = "Install a /32 route to each next hop")
115 private boolean routeToNextHop = false;
116
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800117 private InternalDeviceListener deviceListener;
Jonathan Hartdf207092015-12-10 11:19:25 -0800118
119 // Device id of data-plane switch - should be learned from config
120 private DeviceId deviceId;
121
Saurav Das49cb5a12016-01-16 22:54:07 -0800122 private ConnectPoint controlPlaneConnectPoint;
123
Jonathan Hart883fd372016-02-10 14:36:15 -0800124 private List<String> interfaces;
125
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800126 private ApplicationId routerAppId;
Jonathan Hartdf207092015-12-10 11:19:25 -0800127
128 // Reference count for how many times a next hop is used by a route
129 private final Multiset<IpAddress> nextHopsCount = ConcurrentHashMultiset.create();
130
131 // Mapping from prefix to its current next hop
132 private final Map<IpPrefix, IpAddress> prefixToNextHop = Maps.newHashMap();
133
134 // Mapping from next hop IP to next hop object containing group info
135 private final Map<IpAddress, Integer> nextHops = Maps.newHashMap();
136
gaurav164cf6d2016-03-25 21:43:04 +0530137 //interface object for event
138 private InternalInterfaceListener internalInterfaceList = new InternalInterfaceListener();
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700139 private InternalRouteListener routeListener = new InternalRouteListener();
Jonathan Hartdf207092015-12-10 11:19:25 -0800140
141 @Activate
Jonathan Hartb9401902016-02-02 18:46:01 -0800142 protected void activate(ComponentContext context) {
Jonathan Hartb9401902016-02-02 18:46:01 -0800143 componentConfigService.registerProperties(getClass());
Jonathan Hart9ad777f2016-02-19 12:44:36 -0800144 modified(context);
145
146 routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID);
Jonathan Hartb9401902016-02-02 18:46:01 -0800147
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800148 deviceListener = new InternalDeviceListener();
Jonathan Hartdf207092015-12-10 11:19:25 -0800149 deviceService.addListener(deviceListener);
150
gaurav164cf6d2016-03-25 21:43:04 +0530151 interfaceService.addListener(internalInterfaceList);
152
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800153 updateConfig();
Jonathan Hartdf207092015-12-10 11:19:25 -0800154
155 log.info("Started");
156 }
157
158 @Deactivate
159 protected void deactivate() {
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700160 routeService.removeListener(routeListener);
Jonathan Hartdf207092015-12-10 11:19:25 -0800161 deviceService.removeListener(deviceListener);
gaurav164cf6d2016-03-25 21:43:04 +0530162 interfaceService.removeListener(internalInterfaceList);
163
Jonathan Hartdf207092015-12-10 11:19:25 -0800164 //processIntfFilters(false, configService.getInterfaces()); //TODO necessary?
165
Jonathan Hartb9401902016-02-02 18:46:01 -0800166 componentConfigService.unregisterProperties(getClass(), false);
167
Jonathan Hartdf207092015-12-10 11:19:25 -0800168 log.info("Stopped");
169 }
170
Jonathan Hartb9401902016-02-02 18:46:01 -0800171 @Modified
172 protected void modified(ComponentContext context) {
173 Dictionary<?, ?> properties = context.getProperties();
174 if (properties == null) {
175 return;
176 }
177
178 String strRouteToNextHop = Tools.get(properties, "routeToNextHop");
179 routeToNextHop = Boolean.parseBoolean(strRouteToNextHop);
180
181 log.info("routeToNextHop set to {}", routeToNextHop);
182 }
183
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800184 private void updateConfig() {
185 RouterConfig routerConfig =
186 networkConfigService.getConfig(routerAppId, RoutingService.ROUTER_CONFIG_CLASS);
Jonathan Hartdf207092015-12-10 11:19:25 -0800187
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800188 if (routerConfig == null) {
189 log.info("Router config not available");
Jonathan Hartdf207092015-12-10 11:19:25 -0800190 return;
191 }
Saurav Das49cb5a12016-01-16 22:54:07 -0800192 controlPlaneConnectPoint = routerConfig.getControlPlaneConnectPoint();
193 log.info("Control Plane Connect Point: {}", controlPlaneConnectPoint);
Jonathan Hartdf207092015-12-10 11:19:25 -0800194
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800195 deviceId = routerConfig.getControlPlaneConnectPoint().deviceId();
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800196 log.info("Router device ID is {}", deviceId);
197
Jonathan Hart883fd372016-02-10 14:36:15 -0800198 interfaces = routerConfig.getInterfaces();
199 log.info("Using interfaces: {}", interfaces.isEmpty() ? "all" : interfaces);
200
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700201 routeService.addListener(routeListener);
202
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800203 updateDevice();
204 }
205
206 private void updateDevice() {
207 if (deviceId != null && deviceService.isAvailable(deviceId)) {
Jonathan Hart883fd372016-02-10 14:36:15 -0800208
209 Set<Interface> intfs;
210 if (interfaces.isEmpty()) {
211 intfs = interfaceService.getInterfaces();
212 } else {
213 // TODO need to fix by making interface names globally unique
214 intfs = interfaceService.getInterfaces().stream()
215 .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
216 .filter(intf -> interfaces.contains(intf.name()))
217 .collect(Collectors.toSet());
218 }
219
220 processIntfFilters(true, intfs);
Jonathan Hartdf207092015-12-10 11:19:25 -0800221 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800222 }
223
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700224 private void updateRoute(ResolvedRoute route) {
225 addNextHop(route);
Jonathan Hartdf207092015-12-10 11:19:25 -0800226
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700227 Integer nextId;
228 synchronized (this) {
229 nextId = nextHops.get(route.nextHop());
Jonathan Hartdf207092015-12-10 11:19:25 -0800230 }
231
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700232 flowObjectiveService.forward(deviceId,
233 generateRibForwardingObj(route.prefix(), nextId).add());
234 log.trace("Sending forwarding objective {} -> nextId:{}", route, nextId);
Jonathan Hartdf207092015-12-10 11:19:25 -0800235 }
236
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700237 private synchronized void deleteRoute(ResolvedRoute route) {
238 //Integer nextId = nextHops.get(route.nextHop());
Jonathan Hartdf207092015-12-10 11:19:25 -0800239
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700240 /* Group group = deleteNextHop(route.prefix());
241 if (group == null) {
242 log.warn("Group not found when deleting {}", route);
243 return;
244 }*/
Jonathan Hartdf207092015-12-10 11:19:25 -0800245
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700246 flowObjectiveService.forward(deviceId,
247 generateRibForwardingObj(route.prefix(), null).remove());
Jonathan Hartdf207092015-12-10 11:19:25 -0800248 }
249
250 private ForwardingObjective.Builder generateRibForwardingObj(IpPrefix prefix,
251 Integer nextId) {
252 TrafficSelector selector = DefaultTrafficSelector.builder()
253 .matchEthType(Ethernet.TYPE_IPV4)
254 .matchIPDst(prefix)
255 .build();
256
257 int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
258
259 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder()
Saurav Das49cb5a12016-01-16 22:54:07 -0800260 .fromApp(routerAppId)
Jonathan Hartdf207092015-12-10 11:19:25 -0800261 .makePermanent()
262 .withSelector(selector)
263 .withPriority(priority)
264 .withFlag(ForwardingObjective.Flag.SPECIFIC);
265
266 if (nextId == null) {
267 // Route withdraws are not specified with next hops. Generating
268 // dummy treatment as there is no equivalent nextId info.
269 fwdBuilder.withTreatment(DefaultTrafficTreatment.builder().build());
270 } else {
271 fwdBuilder.nextStep(nextId);
272 }
273 return fwdBuilder;
274 }
275
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700276 private synchronized void addNextHop(ResolvedRoute route) {
277 prefixToNextHop.put(route.prefix(), route.nextHop());
278 if (nextHopsCount.count(route.nextHop()) == 0) {
Jonathan Hartdf207092015-12-10 11:19:25 -0800279 // There was no next hop in the multiset
280
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700281 Interface egressIntf = interfaceService.getMatchingInterface(route.nextHop());
Jonathan Hartdf207092015-12-10 11:19:25 -0800282 if (egressIntf == null) {
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700283 log.warn("no egress interface found for {}", route);
Jonathan Hartdf207092015-12-10 11:19:25 -0800284 return;
285 }
286
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700287 NextHopGroupKey groupKey = new NextHopGroupKey(route.nextHop());
Jonathan Hartdf207092015-12-10 11:19:25 -0800288
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700289 NextHop nextHop = new NextHop(route.nextHop(), route.nextHopMac(), groupKey);
Jonathan Hartdf207092015-12-10 11:19:25 -0800290
Jonathan Hartca47cd72015-12-13 12:31:09 -0800291 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
Jonathan Hartdf207092015-12-10 11:19:25 -0800292 .setEthSrc(egressIntf.mac())
Jonathan Hartca47cd72015-12-13 12:31:09 -0800293 .setEthDst(nextHop.mac());
294
Saurav Das49cb5a12016-01-16 22:54:07 -0800295 TrafficSelector.Builder metabuilder = null;
Jonathan Hartca47cd72015-12-13 12:31:09 -0800296 if (!egressIntf.vlan().equals(VlanId.NONE)) {
297 treatment.pushVlan()
298 .setVlanId(egressIntf.vlan())
299 .setVlanPcp((byte) 0);
Saurav Das49cb5a12016-01-16 22:54:07 -0800300 } else {
301 // untagged outgoing port may require internal vlan in some pipelines
302 metabuilder = DefaultTrafficSelector.builder();
303 metabuilder.matchVlanId(VlanId.vlanId(ASSIGNED_VLAN));
Jonathan Hartca47cd72015-12-13 12:31:09 -0800304 }
305
306 treatment.setOutput(egressIntf.connectPoint().port());
Jonathan Hartdf207092015-12-10 11:19:25 -0800307
308 int nextId = flowObjectiveService.allocateNextId();
Saurav Das49cb5a12016-01-16 22:54:07 -0800309 NextObjective.Builder nextBuilder = DefaultNextObjective.builder()
Jonathan Hartdf207092015-12-10 11:19:25 -0800310 .withId(nextId)
Jonathan Hartca47cd72015-12-13 12:31:09 -0800311 .addTreatment(treatment.build())
Jonathan Hartdf207092015-12-10 11:19:25 -0800312 .withType(NextObjective.Type.SIMPLE)
Saurav Das49cb5a12016-01-16 22:54:07 -0800313 .fromApp(routerAppId);
314 if (metabuilder != null) {
315 nextBuilder.withMeta(metabuilder.build());
316 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800317
Saurav Das49cb5a12016-01-16 22:54:07 -0800318 NextObjective nextObjective = nextBuilder.add(); // TODO add callbacks
Jonathan Hartdf207092015-12-10 11:19:25 -0800319 flowObjectiveService.next(deviceId, nextObjective);
320
321 nextHops.put(nextHop.ip(), nextId);
322
Jonathan Hartb9401902016-02-02 18:46:01 -0800323 if (routeToNextHop) {
324 // Install route to next hop
325 ForwardingObjective fob =
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700326 generateRibForwardingObj(IpPrefix.valueOf(route.nextHop(), 32), nextId).add();
Jonathan Hartb9401902016-02-02 18:46:01 -0800327 flowObjectiveService.forward(deviceId, fob);
328 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800329 }
330
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700331 nextHopsCount.add(route.nextHop());
Jonathan Hartdf207092015-12-10 11:19:25 -0800332 }
333
334 /*private synchronized Group deleteNextHop(IpPrefix prefix) {
335 IpAddress nextHopIp = prefixToNextHop.remove(prefix);
336 NextHop nextHop = nextHops.get(nextHopIp);
337 if (nextHop == null) {
338 log.warn("No next hop found when removing prefix {}", prefix);
339 return null;
340 }
341
342 Group group = groupService.getGroup(deviceId,
343 new DefaultGroupKey(appKryo.
344 serialize(nextHop.group())));
345
346 // FIXME disabling group deletes for now until we verify the logic is OK
347 if (nextHopsCount.remove(nextHopIp, 1) <= 1) {
348 // There was one or less next hops, so there are now none
349
350 log.debug("removing group for next hop {}", nextHop);
351
352 nextHops.remove(nextHopIp);
353
354 groupService.removeGroup(deviceId,
355 new DefaultGroupKey(appKryo.build().serialize(nextHop.group())),
356 appId);
357 }
358
359 return group;
360 }*/
361
362 private void processIntfFilters(boolean install, Set<Interface> intfs) {
363 log.info("Processing {} router interfaces", intfs.size());
364 for (Interface intf : intfs) {
365 if (!intf.connectPoint().deviceId().equals(deviceId)) {
366 // Ignore interfaces if they are not on the router switch
367 continue;
368 }
369
gaurav164cf6d2016-03-25 21:43:04 +0530370 createFilteringObjective(install, intf);
371 }
372 }
Jonathan Hart6344f572015-12-15 08:26:25 -0800373
gaurav164cf6d2016-03-25 21:43:04 +0530374 //process filtering objective for interface add/remove.
375 private void processIntfFilter(boolean install, Interface intf) {
376
377 if (!intf.connectPoint().deviceId().equals(deviceId)) {
378 // Ignore interfaces if they are not on the router switch
379 return;
380 }
381
382 createFilteringObjective(install, intf);
383 }
384
385 //create filtering objective for interface
386 private void createFilteringObjective(boolean install, Interface intf) {
387
388 FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
389 // first add filter for the interface
390 fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
391 .addCondition(Criteria.matchEthDst(intf.mac()))
392 .addCondition(Criteria.matchVlanId(intf.vlan()));
393 fob.withPriority(PRIORITY_OFFSET);
394 if (intf.vlan() == VlanId.NONE) {
395 TrafficTreatment tt = DefaultTrafficTreatment.builder()
396 .pushVlan().setVlanId(VlanId.vlanId(ASSIGNED_VLAN)).build();
397 fob.withMeta(tt);
398 }
399
400 fob.permit().fromApp(routerAppId);
401 sendFilteringObjective(install, fob, intf);
402 if (controlPlaneConnectPoint != null) {
403 // then add the same mac/vlan filters for control-plane connect point
404 fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port()));
Saurav Das49cb5a12016-01-16 22:54:07 -0800405 sendFilteringObjective(install, fob, intf);
Jonathan Hartdf207092015-12-10 11:19:25 -0800406 }
407 }
408
Saurav Das49cb5a12016-01-16 22:54:07 -0800409 private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob,
410 Interface intf) {
Saurav Das49cb5a12016-01-16 22:54:07 -0800411
Jonathan Hartf04b7d92016-03-29 09:39:11 -0700412 ObjectiveContext context = new DefaultObjectiveContext(
413 (objective) -> log.info("Installed filter for interface {}", intf),
414 (objective, error) ->
415 log.error("Failed to install filter for interface {}: {}", intf, error));
gaurav164cf6d2016-03-25 21:43:04 +0530416
Jonathan Hartf04b7d92016-03-29 09:39:11 -0700417 FilteringObjective filter = install ? fob.add(context) : fob.remove(context);
418
419 flowObjectiveService.filter(deviceId, filter);
Saurav Das49cb5a12016-01-16 22:54:07 -0800420 }
421
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700422 private class InternalRouteListener implements RouteListener {
Jonathan Hartdf207092015-12-10 11:19:25 -0800423 @Override
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700424 public void event(RouteEvent event) {
425 ResolvedRoute route = event.subject();
426 switch (event.type()) {
427 case ROUTE_ADDED:
428 case ROUTE_UPDATED:
429 updateRoute(route);
430 break;
431 case ROUTE_REMOVED:
432 deleteRoute(route);
433 break;
434 default:
435 break;
436 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800437 }
438 }
439
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800440 /**
441 * Listener for device events used to trigger driver setup when a device is
442 * (re)detected.
443 */
444 private class InternalDeviceListener implements DeviceListener {
Jonathan Hartdf207092015-12-10 11:19:25 -0800445 @Override
446 public void event(DeviceEvent event) {
447 switch (event.type()) {
448 case DEVICE_ADDED:
449 case DEVICE_AVAILABILITY_CHANGED:
450 if (deviceService.isAvailable(event.subject().id())) {
451 log.info("Device connected {}", event.subject().id());
452 if (event.subject().id().equals(deviceId)) {
Charles Chanf555a732016-02-15 15:37:15 -0800453 updateDevice();
Jonathan Hartdf207092015-12-10 11:19:25 -0800454 }
455 }
456 break;
457 // TODO other cases
458 case DEVICE_UPDATED:
459 case DEVICE_REMOVED:
460 case DEVICE_SUSPENDED:
461 case PORT_ADDED:
462 case PORT_UPDATED:
463 case PORT_REMOVED:
464 default:
465 break;
466 }
467 }
468 }
Jonathan Hartb3fa42c2016-01-13 09:50:43 -0800469
470 /**
471 * Listener for network config events.
472 */
473 private class InternalNetworkConfigListener implements NetworkConfigListener {
474 @Override
475 public void event(NetworkConfigEvent event) {
476 if (event.subject().equals(RoutingService.ROUTER_CONFIG_CLASS)) {
477 switch (event.type()) {
478 case CONFIG_ADDED:
479 case CONFIG_UPDATED:
480 updateConfig();
481 break;
482 case CONFIG_REGISTERED:
483 case CONFIG_UNREGISTERED:
484 case CONFIG_REMOVED:
485 default:
486 break;
487 }
488 }
489 }
490 }
gaurav164cf6d2016-03-25 21:43:04 +0530491
492 private class InternalInterfaceListener implements InterfaceListener {
493
494 @Override
495 public void event(InterfaceEvent event) {
496 Interface intf = event.subject();
497 switch (event.type()) {
498 case INTERFACE_ADDED:
499 if (intf != null) {
500 processIntfFilter(true, intf);
501 }
502 break;
503 case INTERFACE_UPDATED:
504 break;
505 case INTERFACE_REMOVED:
506 if (intf != null) {
507 processIntfFilter(false, intf);
508 }
509 break;
510 default:
511 break;
512 }
513 }
514 }
Jonathan Hartdf207092015-12-10 11:19:25 -0800515}