blob: 84889249c07932a7673fb9013122045a43d665df [file] [log] [blame]
Jonathan Hart9a426f82015-09-03 15:43:13 +02001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Jonathan Hart9a426f82015-09-03 15:43:13 +02003 *
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
17package org.onosproject.sdnip;
18
19import com.google.common.collect.ImmutableList;
Jonathan Hartb14221c2016-03-07 09:55:50 -080020import com.google.common.collect.Sets;
Jonathan Hart365335e2015-12-10 11:09:53 -080021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart9a426f82015-09-03 15:43:13 +020026import org.onlab.packet.Ethernet;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
29import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
31import org.onosproject.core.ApplicationId;
Jonathan Hart365335e2015-12-10 11:09:53 -080032import org.onosproject.core.CoreService;
Ray Milkeyfacf2862017-08-03 11:58:29 -070033import org.onosproject.net.intf.Interface;
34import org.onosproject.net.intf.InterfaceEvent;
35import org.onosproject.net.intf.InterfaceListener;
36import org.onosproject.net.intf.InterfaceService;
Jonathan Harta2eb9ff2016-04-13 21:27:06 -070037import org.onosproject.incubator.net.routing.ResolvedRoute;
38import org.onosproject.incubator.net.routing.RouteEvent;
39import org.onosproject.incubator.net.routing.RouteListener;
40import org.onosproject.incubator.net.routing.RouteService;
Jonathan Hart9a426f82015-09-03 15:43:13 +020041import org.onosproject.net.ConnectPoint;
Luca Prete83bac342016-12-06 19:42:05 -080042import org.onosproject.net.EncapsulationType;
Luca Pretee4a5e1a2016-09-07 17:01:22 -070043import org.onosproject.net.FilteredConnectPoint;
Luca Prete83bac342016-12-06 19:42:05 -080044import org.onosproject.net.config.NetworkConfigEvent;
45import org.onosproject.net.config.NetworkConfigListener;
46import org.onosproject.net.config.NetworkConfigService;
Jonathan Hart9a426f82015-09-03 15:43:13 +020047import org.onosproject.net.flow.DefaultTrafficSelector;
48import org.onosproject.net.flow.DefaultTrafficTreatment;
49import org.onosproject.net.flow.TrafficSelector;
50import org.onosproject.net.flow.TrafficTreatment;
Luca Prete83bac342016-12-06 19:42:05 -080051import org.onosproject.net.intent.ConnectivityIntent;
Jonathan Hart9a426f82015-09-03 15:43:13 +020052import org.onosproject.net.intent.Constraint;
53import org.onosproject.net.intent.Key;
54import org.onosproject.net.intent.MultiPointToSinglePointIntent;
Luca Prete83bac342016-12-06 19:42:05 -080055import org.onosproject.net.intent.constraint.EncapsulationConstraint;
Jonathan Hart9a426f82015-09-03 15:43:13 +020056import org.onosproject.net.intent.constraint.PartialFailureConstraint;
Jonathan Hart470ed4f2017-01-31 16:52:28 -080057import org.onosproject.intentsync.IntentSynchronizationService;
Luca Prete83bac342016-12-06 19:42:05 -080058import org.onosproject.sdnip.config.SdnIpConfig;
Jonathan Hart9a426f82015-09-03 15:43:13 +020059import org.slf4j.Logger;
60import org.slf4j.LoggerFactory;
61
Luca Prete83bac342016-12-06 19:42:05 -080062import java.util.ArrayList;
63import java.util.List;
Jonathan Hart9a426f82015-09-03 15:43:13 +020064import java.util.Map;
65import java.util.Set;
66import java.util.concurrent.ConcurrentHashMap;
67
Luca Prete83bac342016-12-06 19:42:05 -080068import static org.onosproject.net.EncapsulationType.NONE;
69
Jonathan Hart9a426f82015-09-03 15:43:13 +020070/**
71 * FIB component of SDN-IP.
72 */
Jonathan Hartc22e8472015-11-17 18:25:45 -080073@Component(immediate = true, enabled = false)
Jonathan Hart365335e2015-12-10 11:09:53 -080074public class SdnIpFib {
Jonathan Hart9a426f82015-09-03 15:43:13 +020075 private Logger log = LoggerFactory.getLogger(getClass());
76
Jonathan Hart365335e2015-12-10 11:09:53 -080077 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 protected InterfaceService interfaceService;
79
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected IntentSynchronizationService intentSynchronizer;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected CoreService coreService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Luca Prete83bac342016-12-06 19:42:05 -080087 protected NetworkConfigService networkConfigService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Harta2eb9ff2016-04-13 21:27:06 -070090 protected RouteService routeService;
Jonathan Hart365335e2015-12-10 11:09:53 -080091
Jonathan Harta2eb9ff2016-04-13 21:27:06 -070092 private final InternalRouteListener routeListener = new InternalRouteListener();
Jonathan Hartb14221c2016-03-07 09:55:50 -080093 private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
Luca Prete83bac342016-12-06 19:42:05 -080094 private final InternalNetworkConfigListener networkConfigListener =
95 new InternalNetworkConfigListener();
Jonathan Hart365335e2015-12-10 11:09:53 -080096
Jonathan Hart9a426f82015-09-03 15:43:13 +020097 private static final int PRIORITY_OFFSET = 100;
98 private static final int PRIORITY_MULTIPLIER = 5;
99 protected static final ImmutableList<Constraint> CONSTRAINTS
100 = ImmutableList.of(new PartialFailureConstraint());
101
Jonathan Hart365335e2015-12-10 11:09:53 -0800102 private final Map<IpPrefix, MultiPointToSinglePointIntent> routeIntents
103 = new ConcurrentHashMap<>();
Jonathan Hart9a426f82015-09-03 15:43:13 +0200104
Jonathan Hart365335e2015-12-10 11:09:53 -0800105 private ApplicationId appId;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200106
Jonathan Hart365335e2015-12-10 11:09:53 -0800107 @Activate
108 public void activate() {
109 appId = coreService.getAppId(SdnIp.SDN_IP_APP);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800110 interfaceService.addListener(interfaceListener);
Luca Prete83bac342016-12-06 19:42:05 -0800111 networkConfigService.addListener(networkConfigListener);
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700112 routeService.addListener(routeListener);
Jonathan Hart9a426f82015-09-03 15:43:13 +0200113 }
114
Jonathan Hart365335e2015-12-10 11:09:53 -0800115 @Deactivate
116 public void deactivate() {
Jonathan Hartb14221c2016-03-07 09:55:50 -0800117 interfaceService.removeListener(interfaceListener);
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700118 routeService.removeListener(routeListener);
Jonathan Hart365335e2015-12-10 11:09:53 -0800119 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200120
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700121 private void update(ResolvedRoute route) {
Jonathan Hart9a426f82015-09-03 15:43:13 +0200122 synchronized (this) {
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700123 IpPrefix prefix = route.prefix();
Luca Prete83bac342016-12-06 19:42:05 -0800124 EncapsulationType encap = encap();
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700125 MultiPointToSinglePointIntent intent =
Luca Prete83bac342016-12-06 19:42:05 -0800126 generateRouteIntent(prefix,
127 route.nextHop(),
128 route.nextHopMac(),
129 encap);
Jonathan Hart9a426f82015-09-03 15:43:13 +0200130
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700131 if (intent == null) {
Luca Prete83bac342016-12-06 19:42:05 -0800132 log.debug("No interface found for route {}", route);
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700133 return;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200134 }
135
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700136 routeIntents.put(prefix, intent);
137 intentSynchronizer.submit(intent);
138 }
139 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200140
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700141 private void withdraw(ResolvedRoute route) {
142 synchronized (this) {
143 IpPrefix prefix = route.prefix();
144 MultiPointToSinglePointIntent intent = routeIntents.remove(prefix);
145 if (intent == null) {
Luca Prete83bac342016-12-06 19:42:05 -0800146 log.trace("No intent in routeIntents to delete for prefix: {}",
147 prefix);
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700148 return;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200149 }
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700150 intentSynchronizer.withdraw(intent);
Jonathan Hart9a426f82015-09-03 15:43:13 +0200151 }
152 }
153
154 /**
155 * Generates a route intent for a prefix, the next hop IP address, and
156 * the next hop MAC address.
157 * <p/>
158 * This method will find the egress interface for the intent.
159 * Intent will match dst IP prefix and rewrite dst MAC address at all other
160 * border switches, then forward packets according to dst MAC address.
161 *
Luca Prete83bac342016-12-06 19:42:05 -0800162 * @param prefix the IP prefix of the route to add
163 * @param nextHopIpAddress the IP address of the next hop
164 * @param nextHopMacAddress the MAC address of the next hop
165 * @param encap the encapsulation type in use
Jonathan Hart9a426f82015-09-03 15:43:13 +0200166 * @return the generated intent, or null if no intent should be submitted
167 */
168 private MultiPointToSinglePointIntent generateRouteIntent(
169 IpPrefix prefix,
170 IpAddress nextHopIpAddress,
Luca Prete83bac342016-12-06 19:42:05 -0800171 MacAddress nextHopMacAddress,
172 EncapsulationType encap) {
Jonathan Hart9a426f82015-09-03 15:43:13 +0200173
174 // Find the attachment point (egress interface) of the next hop
Pingping Lin92ca4912015-11-19 16:41:54 -0800175 Interface egressInterface =
176 interfaceService.getMatchingInterface(nextHopIpAddress);
Jonathan Hart9a426f82015-09-03 15:43:13 +0200177 if (egressInterface == null) {
178 log.warn("No outgoing interface found for {}",
179 nextHopIpAddress);
180 return null;
181 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200182 ConnectPoint egressPort = egressInterface.connectPoint();
Luca Pretee9511512016-05-13 10:30:19 -0700183
Jonathan Hart9a426f82015-09-03 15:43:13 +0200184 log.debug("Generating intent for prefix {}, next hop mac {}",
185 prefix, nextHopMacAddress);
186
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700187 Set<FilteredConnectPoint> ingressFilteredCPs = Sets.newHashSet();
Luca Pretee9511512016-05-13 10:30:19 -0700188
Luca Pretee9511512016-05-13 10:30:19 -0700189 // TODO this should be only peering interfaces
Sho SHIMIZU8ebb04a2016-10-06 15:58:29 -0700190 interfaceService.getInterfaces().forEach(intf -> {
191 // Get ony ingress interfaces with IPs configured
192 if (validIngressIntf(intf, egressInterface)) {
193 TrafficSelector.Builder selector =
194 buildIngressTrafficSelector(intf, prefix);
195 FilteredConnectPoint ingressFilteredCP =
196 new FilteredConnectPoint(intf.connectPoint(), selector.build());
197 ingressFilteredCPs.add(ingressFilteredCP);
198 }
199 });
Luca Pretee9511512016-05-13 10:30:19 -0700200
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700201 // Build treatment: rewrite the destination MAC address
202 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
203 .setEthDst(nextHopMacAddress);
Luca Pretee9511512016-05-13 10:30:19 -0700204
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700205 // Build the egress selector for VLAN Id
206 TrafficSelector.Builder selector =
207 buildTrafficSelector(egressInterface);
208 FilteredConnectPoint egressFilteredCP =
209 new FilteredConnectPoint(egressPort, selector.build());
210
211 // Set priority
212 int priority =
213 prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
214
215 // Set key
216 Key key = Key.of(prefix.toString(), appId);
217
Luca Prete83bac342016-12-06 19:42:05 -0800218 MultiPointToSinglePointIntent.Builder intentBuilder =
219 MultiPointToSinglePointIntent.builder()
220 .appId(appId)
221 .key(key)
222 .filteredIngressPoints(ingressFilteredCPs)
223 .filteredEgressPoint(egressFilteredCP)
224 .treatment(treatment.build())
225 .priority(priority)
226 .constraints(CONSTRAINTS);
227
228 setEncap(intentBuilder, CONSTRAINTS, encap);
229
230 return intentBuilder.build();
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700231 }
232
233 private void addInterface(Interface intf) {
234 synchronized (this) {
235 for (Map.Entry<IpPrefix, MultiPointToSinglePointIntent> entry : routeIntents.entrySet()) {
236 // Retrieve the IP prefix and affected intent
237 IpPrefix prefix = entry.getKey();
238 MultiPointToSinglePointIntent intent = entry.getValue();
239
240 // Add new ingress FilteredConnectPoint
241 Set<FilteredConnectPoint> ingressFilteredCPs =
242 Sets.newHashSet(intent.filteredIngressPoints());
243
244 // Create the new traffic selector
245 TrafficSelector.Builder selector =
246 buildIngressTrafficSelector(intf, prefix);
247
248 // Create the Filtered ConnectPoint and add it to the existing set
249 FilteredConnectPoint newIngressFilteredCP =
250 new FilteredConnectPoint(intf.connectPoint(), selector.build());
251 ingressFilteredCPs.add(newIngressFilteredCP);
252
253 // Create new intent
254 MultiPointToSinglePointIntent newIntent =
255 MultiPointToSinglePointIntent.builder(intent)
256 .filteredIngressPoints(ingressFilteredCPs)
257 .build();
258
259 routeIntents.put(entry.getKey(), newIntent);
260 intentSynchronizer.submit(newIntent);
Jonathan Hart9a426f82015-09-03 15:43:13 +0200261 }
262 }
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700263 }
264
265 /*
266 * Handles the case in which an existing interface gets removed.
267 */
268 private void removeInterface(Interface intf) {
269 synchronized (this) {
270 for (Map.Entry<IpPrefix, MultiPointToSinglePointIntent> entry : routeIntents.entrySet()) {
271 // Retrieve the IP prefix and intent possibly affected
272 IpPrefix prefix = entry.getKey();
273 MultiPointToSinglePointIntent intent = entry.getValue();
274
275 // The interface removed might be an ingress interface, so the
276 // selector needs to match on the interface tagging params and
277 // on the prefix
278 TrafficSelector.Builder ingressSelector =
279 buildIngressTrafficSelector(intf, prefix);
280 FilteredConnectPoint removedIngressFilteredCP =
281 new FilteredConnectPoint(intf.connectPoint(),
282 ingressSelector.build());
283
284 // The interface removed might be an egress interface, so the
285 // selector needs to match only on the interface tagging params
286 TrafficSelector.Builder selector = buildTrafficSelector(intf);
287 FilteredConnectPoint removedEgressFilteredCP =
288 new FilteredConnectPoint(intf.connectPoint(), selector.build());
289
290 if (intent.filteredEgressPoint().equals(removedEgressFilteredCP)) {
291 // The interface is an egress interface for the intent.
292 // This intent just lost its head. Remove it and let higher
293 // layer routing reroute
294 intentSynchronizer.withdraw(routeIntents.remove(entry.getKey()));
295 } else {
296 if (intent.filteredIngressPoints().contains(removedIngressFilteredCP)) {
297 // The FilteredConnectPoint is an ingress
298 // FilteredConnectPoint for the intent
299 Set<FilteredConnectPoint> ingressFilteredCPs =
300 Sets.newHashSet(intent.filteredIngressPoints());
301
302 // Remove FilteredConnectPoint from the existing set
303 ingressFilteredCPs.remove(removedIngressFilteredCP);
304
305 if (!ingressFilteredCPs.isEmpty()) {
306 // There are still ingress points. Create a new
307 // intent and resubmit
308 MultiPointToSinglePointIntent newIntent =
309 MultiPointToSinglePointIntent.builder(intent)
310 .filteredIngressPoints(ingressFilteredCPs)
311 .build();
312
313 routeIntents.put(entry.getKey(), newIntent);
314 intentSynchronizer.submit(newIntent);
315 } else {
316 // No more ingress FilteredConnectPoint. Withdraw
317 //the intent
318 intentSynchronizer.withdraw(routeIntents.remove(entry.getKey()));
319 }
320 }
321 }
322 }
323 }
324 }
325
326 /*
327 * Builds an ingress traffic selector builder given an ingress interface and
328 * the IP prefix to be reached.
329 */
330 private TrafficSelector.Builder buildIngressTrafficSelector(Interface intf, IpPrefix prefix) {
331 TrafficSelector.Builder selector = buildTrafficSelector(intf);
Jonathan Hart9a426f82015-09-03 15:43:13 +0200332
333 // Match the destination IP prefix at the first hop
Jonathan Hart9a426f82015-09-03 15:43:13 +0200334 if (prefix.isIp4()) {
335 selector.matchEthType(Ethernet.TYPE_IPV4);
Pingping Lin92ca4912015-11-19 16:41:54 -0800336 // if it is default route, then we do not need match destination
337 // IP address
338 if (prefix.prefixLength() != 0) {
339 selector.matchIPDst(prefix);
340 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200341 } else {
342 selector.matchEthType(Ethernet.TYPE_IPV6);
Pingping Lin92ca4912015-11-19 16:41:54 -0800343 // if it is default route, then we do not need match destination
344 // IP address
345 if (prefix.prefixLength() != 0) {
346 selector.matchIPv6Dst(prefix);
347 }
Jonathan Hart9a426f82015-09-03 15:43:13 +0200348 }
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700349 return selector;
Jonathan Hart9a426f82015-09-03 15:43:13 +0200350 }
351
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700352 /*
353 * Builds a traffic selector builder based on interface tagging settings.
354 */
355 private TrafficSelector.Builder buildTrafficSelector(Interface intf) {
356 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Jonathan Hartb14221c2016-03-07 09:55:50 -0800357
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700358 // TODO: Consider other tag types
359 // Match the VlanId if specified in the network interface configuration
360 VlanId vlanId = intf.vlan();
361 if (!vlanId.equals(VlanId.NONE)) {
362 selector.matchVlanId(vlanId);
Jonathan Hartb14221c2016-03-07 09:55:50 -0800363 }
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700364 return selector;
Jonathan Hartb14221c2016-03-07 09:55:50 -0800365 }
366
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700367 // Check if the interface is an ingress interface with IPs configured
368 private boolean validIngressIntf(Interface intf, Interface egressInterface) {
369 if (!intf.equals(egressInterface) &&
370 !intf.ipAddressesList().isEmpty() &&
371 // TODO: An egress point might have two routers connected on different interfaces
372 !intf.connectPoint().equals(egressInterface.connectPoint())) {
373 return true;
Jonathan Hartb14221c2016-03-07 09:55:50 -0800374 }
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700375 return false;
Jonathan Hartb14221c2016-03-07 09:55:50 -0800376 }
377
Luca Prete83bac342016-12-06 19:42:05 -0800378 /*
379 * Triggered when the network configuration configuration is modified.
380 * It checks if the encapsulation type has changed from last time, and in
381 * case modifies all intents.
382 */
383 private void encapUpdate() {
384 synchronized (this) {
385 // Get the encapsulation type just set from the configuration
386 EncapsulationType encap = encap();
387
388
389 for (Map.Entry<IpPrefix, MultiPointToSinglePointIntent> entry : routeIntents.entrySet()) {
390 // Get each intent currently registered by SDN-IP
391 MultiPointToSinglePointIntent intent = entry.getValue();
392
393 // Make sure the same constraint is not already part of the
394 // intent constraints
395 List<Constraint> constraints = intent.constraints();
396 if (!constraints.stream()
397 .filter(c -> c instanceof EncapsulationConstraint &&
398 new EncapsulationConstraint(encap).equals(c))
399 .findAny()
400 .isPresent()) {
401 MultiPointToSinglePointIntent.Builder intentBuilder =
402 MultiPointToSinglePointIntent.builder(intent);
403
404 // Set the new encapsulation constraint
405 setEncap(intentBuilder, constraints, encap);
406
407 // Build and submit the new intent
408 MultiPointToSinglePointIntent newIntent =
409 intentBuilder.build();
410
411 routeIntents.put(entry.getKey(), newIntent);
412 intentSynchronizer.submit(newIntent);
413 }
414 }
415 }
416 }
417
418 /**
419 * Sets an encapsulation constraint to the intent builder given.
420 *
421 * @param builder the intent builder
422 * @param constraints the existing intent constraints
423 * @param encap the encapsulation type to be set
424 */
425 private static void setEncap(ConnectivityIntent.Builder builder,
426 List<Constraint> constraints,
427 EncapsulationType encap) {
428 // Constraints might be an immutable list, so a new modifiable list
429 // is created
430 List<Constraint> newConstraints = new ArrayList<>(constraints);
431
432 // Remove any encapsulation constraint if already in the list
433 constraints.stream()
434 .filter(c -> c instanceof EncapsulationConstraint)
435 .forEach(c -> newConstraints.remove(c));
436
437 // if the new encapsulation is different from NONE, a new encapsulation
438 // constraint should be added to the list
439 if (!encap.equals(NONE)) {
440 newConstraints.add(new EncapsulationConstraint(encap));
441 }
442
443 // Submit new constraint list as immutable list
444 builder.constraints(ImmutableList.copyOf(newConstraints));
445 }
446
447 private EncapsulationType encap() {
448 SdnIpConfig sdnIpConfig =
449 networkConfigService.getConfig(appId, SdnIpConfig.class);
450
451 if (sdnIpConfig == null) {
452 log.debug("No SDN-IP config available");
453 return EncapsulationType.NONE;
454 } else {
455 return sdnIpConfig.encap();
456 }
457 }
458
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700459 private class InternalRouteListener implements RouteListener {
Jonathan Hart365335e2015-12-10 11:09:53 -0800460 @Override
Jonathan Harta2eb9ff2016-04-13 21:27:06 -0700461 public void event(RouteEvent event) {
462 switch (event.type()) {
463 case ROUTE_ADDED:
464 case ROUTE_UPDATED:
465 update(event.subject());
466 break;
467 case ROUTE_REMOVED:
468 withdraw(event.subject());
469 break;
470 default:
471 break;
472 }
Jonathan Hart365335e2015-12-10 11:09:53 -0800473 }
474 }
475
Luca Prete83bac342016-12-06 19:42:05 -0800476 private class InternalNetworkConfigListener implements NetworkConfigListener {
477 @Override
478 public void event(NetworkConfigEvent event) {
479 switch (event.type()) {
480 case CONFIG_REGISTERED:
481 break;
482 case CONFIG_UNREGISTERED:
483 break;
484 case CONFIG_ADDED:
485 case CONFIG_UPDATED:
486 case CONFIG_REMOVED:
487 if (event.configClass() == SdnIpConfig.class) {
488 encapUpdate();
489 }
490 break;
491 default:
492 break;
493 }
494 }
495 }
Jonathan Hartb14221c2016-03-07 09:55:50 -0800496
Luca Prete83bac342016-12-06 19:42:05 -0800497 private class InternalInterfaceListener implements InterfaceListener {
Jonathan Hartb14221c2016-03-07 09:55:50 -0800498 @Override
499 public void event(InterfaceEvent event) {
500 switch (event.type()) {
501 case INTERFACE_ADDED:
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700502 addInterface(event.subject());
Jonathan Hartb14221c2016-03-07 09:55:50 -0800503 break;
504 case INTERFACE_UPDATED:
Luca Pretee4a5e1a2016-09-07 17:01:22 -0700505 removeInterface(event.prevSubject());
506 addInterface(event.subject());
Jonathan Hartb14221c2016-03-07 09:55:50 -0800507 break;
508 case INTERFACE_REMOVED:
509 removeInterface(event.subject());
510 break;
511 default:
512 break;
513 }
514 }
515 }
516
Jonathan Hart9a426f82015-09-03 15:43:13 +0200517}