blob: 1a540ef31b8909df5ca14764e85f0001e5350866 [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sanghob35a6192015-04-01 13:05:26 -07003 *
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
Charles Chanc81c45b2016-10-20 17:02:44 -070018import com.google.common.collect.Maps;
sanghob35a6192015-04-01 13:05:26 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
sangho1e575652015-05-14 00:39:53 -070024import org.apache.felix.scr.annotations.Service;
sanghob35a6192015-04-01 13:05:26 -070025import org.onlab.packet.Ethernet;
Charles Chanc42e84e2015-10-20 16:24:19 -070026import org.onlab.packet.IPv4;
Charles Chanc42e84e2015-10-20 16:24:19 -070027import org.onlab.packet.Ip4Prefix;
Charles Chanc42e84e2015-10-20 16:24:19 -070028import org.onlab.packet.IpPrefix;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070029import org.onlab.packet.VlanId;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070030import org.onlab.util.KryoNamespace;
Saurav Das80980c72016-03-23 11:22:49 -070031import org.onosproject.cfg.ComponentConfigService;
sanghob35a6192015-04-01 13:05:26 -070032import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreService;
34import org.onosproject.event.Event;
Charles Chand55e84d2016-03-30 17:54:24 -070035import org.onosproject.incubator.net.config.basics.McastConfig;
Charles Chan2c15aca2016-11-09 20:51:44 -080036import org.onosproject.incubator.net.intf.InterfaceService;
Charles Chan03a73e02016-10-24 14:52:01 -070037import org.onosproject.incubator.net.routing.RouteEvent;
38import org.onosproject.incubator.net.routing.RouteListener;
39import org.onosproject.incubator.net.routing.RouteService;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070040import org.onosproject.mastership.MastershipService;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070041import org.onosproject.net.Device;
42import org.onosproject.net.DeviceId;
43import org.onosproject.net.Link;
44import org.onosproject.net.Port;
Charles Chan68aa62d2015-11-09 16:37:23 -080045import org.onosproject.net.PortNumber;
Charles Chand6832882015-10-05 17:50:33 -070046import org.onosproject.net.config.ConfigFactory;
47import org.onosproject.net.config.NetworkConfigEvent;
Charles Chand6832882015-10-05 17:50:33 -070048import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070049import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chand6832882015-10-05 17:50:33 -070050import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070051import org.onosproject.net.device.DeviceEvent;
52import org.onosproject.net.device.DeviceListener;
53import org.onosproject.net.device.DeviceService;
Charles Chan68aa62d2015-11-09 16:37:23 -080054import org.onosproject.net.flow.DefaultTrafficSelector;
Charles Chan68aa62d2015-11-09 16:37:23 -080055import org.onosproject.net.flow.TrafficSelector;
56import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070057import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chan68aa62d2015-11-09 16:37:23 -080058import org.onosproject.net.host.HostEvent;
59import org.onosproject.net.host.HostListener;
Charles Chand55e84d2016-03-30 17:54:24 -070060import org.onosproject.net.mcast.McastEvent;
61import org.onosproject.net.mcast.McastListener;
62import org.onosproject.net.mcast.MulticastRouteService;
63import org.onosproject.net.packet.PacketPriority;
64import org.onosproject.net.topology.TopologyService;
65import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
66import org.onosproject.segmentrouting.config.DeviceConfiguration;
67import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
68import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Charles Chanfc5c7802016-05-17 13:13:55 -070069import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chand55e84d2016-03-30 17:54:24 -070070import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
71import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Charles Chand2990362016-04-18 13:44:03 -070072import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
73import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
sanghob35a6192015-04-01 13:05:26 -070074import org.onosproject.net.host.HostService;
sanghob35a6192015-04-01 13:05:26 -070075import org.onosproject.net.link.LinkEvent;
76import org.onosproject.net.link.LinkListener;
77import org.onosproject.net.link.LinkService;
78import org.onosproject.net.packet.InboundPacket;
79import org.onosproject.net.packet.PacketContext;
80import org.onosproject.net.packet.PacketProcessor;
81import org.onosproject.net.packet.PacketService;
Charles Chand2990362016-04-18 13:44:03 -070082import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
83import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
Charles Chanfc5c7802016-05-17 13:13:55 -070084import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070085import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070086import org.onosproject.store.service.EventuallyConsistentMap;
87import org.onosproject.store.service.EventuallyConsistentMapBuilder;
88import org.onosproject.store.service.StorageService;
89import org.onosproject.store.service.WallClockTimestamp;
Charles Chan35fd1a72016-06-13 18:54:31 -070090import org.opencord.cordconfig.CordConfigEvent;
91import org.opencord.cordconfig.CordConfigListener;
92import org.opencord.cordconfig.CordConfigService;
sanghob35a6192015-04-01 13:05:26 -070093import org.slf4j.Logger;
94import org.slf4j.LoggerFactory;
95
Saurav Das0e99e2b2015-10-28 12:39:42 -070096import java.util.Collections;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070097import java.util.HashSet;
sangho1e575652015-05-14 00:39:53 -070098import java.util.List;
sanghob35a6192015-04-01 13:05:26 -070099import java.util.Map;
Charles Chan188ebf52015-12-23 00:15:11 -0800100import java.util.Optional;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700101import java.util.Set;
sanghob35a6192015-04-01 13:05:26 -0700102import java.util.concurrent.ConcurrentHashMap;
103import java.util.concurrent.ConcurrentLinkedQueue;
104import java.util.concurrent.Executors;
105import java.util.concurrent.ScheduledExecutorService;
106import java.util.concurrent.ScheduledFuture;
107import java.util.concurrent.TimeUnit;
108
Charles Chan3e783d02016-02-26 22:19:52 -0800109import static com.google.common.base.Preconditions.checkState;
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700110import static org.onlab.util.Tools.groupedThreads;
Charles Chan3e783d02016-02-26 22:19:52 -0800111
Charles Chane849c192016-01-11 18:28:54 -0800112/**
113 * Segment routing manager.
114 */
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700115@Service
116@Component(immediate = true)
sangho1e575652015-05-14 00:39:53 -0700117public class SegmentRoutingManager implements SegmentRoutingService {
sanghob35a6192015-04-01 13:05:26 -0700118
Charles Chan2c15aca2016-11-09 20:51:44 -0800119 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
sanghob35a6192015-04-01 13:05:26 -0700120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700122 private ComponentConfigService compCfgService;
sanghob35a6192015-04-01 13:05:26 -0700123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700125 CoreService coreService;
sanghob35a6192015-04-01 13:05:26 -0700126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700128 PacketService packetService;
sanghob35a6192015-04-01 13:05:26 -0700129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700131 HostService hostService;
sanghob35a6192015-04-01 13:05:26 -0700132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700134 DeviceService deviceService;
sanghob35a6192015-04-01 13:05:26 -0700135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700137 FlowObjectiveService flowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -0700138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700140 LinkService linkService;
sangho1e575652015-05-14 00:39:53 -0700141
Charles Chan5270ed02016-01-30 23:22:37 -0800142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700143 MastershipService mastershipService;
144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
146 StorageService storageService;
147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
149 MulticastRouteService multicastRouteService;
150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
152 TopologyService topologyService;
153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
155 CordConfigService cordConfigService;
156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
158 RouteService routeService;
Charles Chan5270ed02016-01-30 23:22:37 -0800159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan2c15aca2016-11-09 20:51:44 -0800161 public NetworkConfigRegistry cfgService;
Charles Chan5270ed02016-01-30 23:22:37 -0800162
Saurav Das80980c72016-03-23 11:22:49 -0700163 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan2c15aca2016-11-09 20:51:44 -0800164 public InterfaceService interfaceService;
165
Charles Chan03a73e02016-10-24 14:52:01 -0700166 ArpHandler arpHandler = null;
167 IcmpHandler icmpHandler = null;
168 IpHandler ipHandler = null;
169 RoutingRulePopulator routingRulePopulator = null;
Charles Chan2c15aca2016-11-09 20:51:44 -0800170 public ApplicationId appId;
sangho666cd6d2015-04-14 16:27:13 -0700171 protected DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700172
Charles Chan03a73e02016-10-24 14:52:01 -0700173 DefaultRoutingHandler defaultRoutingHandler = null;
sangho1e575652015-05-14 00:39:53 -0700174 private TunnelHandler tunnelHandler = null;
175 private PolicyHandler policyHandler = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700176 private InternalPacketProcessor processor = null;
177 private InternalLinkListener linkListener = null;
178 private InternalDeviceListener deviceListener = null;
Charles Chanfc5c7802016-05-17 13:13:55 -0700179 private AppConfigHandler appCfgHandler = null;
Charles Chan03a73e02016-10-24 14:52:01 -0700180 XConnectHandler xConnectHandler = null;
Charles Chand2990362016-04-18 13:44:03 -0700181 private McastHandler mcastHandler = null;
Charles Chan03a73e02016-10-24 14:52:01 -0700182 HostHandler hostHandler = null;
Charles Chan35fd1a72016-06-13 18:54:31 -0700183 private CordConfigHandler cordConfigHandler = null;
Charles Chan03a73e02016-10-24 14:52:01 -0700184 RouteHandler routeHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700185 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan5270ed02016-01-30 23:22:37 -0800186 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chand55e84d2016-03-30 17:54:24 -0700187 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
188 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan35fd1a72016-06-13 18:54:31 -0700189 private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
Charles Chan03a73e02016-10-24 14:52:01 -0700190 private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
sanghob35a6192015-04-01 13:05:26 -0700191
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700192 private ScheduledExecutorService executorService = Executors
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700193 .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
sanghob35a6192015-04-01 13:05:26 -0700194
Saurav Das4ce45962015-11-24 23:21:05 -0800195 @SuppressWarnings("unused")
sanghob35a6192015-04-01 13:05:26 -0700196 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das4ce45962015-11-24 23:21:05 -0800197 @SuppressWarnings("rawtypes")
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700198 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
Charles Chan68aa62d2015-11-09 16:37:23 -0800199 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chane849c192016-01-11 18:28:54 -0800200 new ConcurrentHashMap<>();
201 /**
202 * Per device next objective ID store with (device id + neighbor set) as key.
203 */
204 public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
Charles Chan68aa62d2015-11-09 16:37:23 -0800205 nsNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800206 /**
207 * Per device next objective ID store with (device id + subnet) as key.
208 */
209 public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
Charles Chan68aa62d2015-11-09 16:37:23 -0800210 subnetNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800211 /**
212 * Per device next objective ID store with (device id + port) as key.
213 */
214 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das4ce45962015-11-24 23:21:05 -0800215 portNextObjStore = null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700216 // Per device, per-subnet assigned-vlans store, with (device id + subnet
217 // IPv4 prefix) as key
218 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
Charles Chane849c192016-01-11 18:28:54 -0800219 subnetVidStore = null;
Saurav Das4ce45962015-11-24 23:21:05 -0800220 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
221 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho0b2b6d12015-05-20 22:16:38 -0700222
Charles Chand55e84d2016-03-30 17:54:24 -0700223 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700224 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
225 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700226 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chand6832882015-10-05 17:50:33 -0700227 @Override
Charles Chan5270ed02016-01-30 23:22:37 -0800228 public SegmentRoutingDeviceConfig createConfig() {
229 return new SegmentRoutingDeviceConfig();
Charles Chand6832882015-10-05 17:50:33 -0700230 }
231 };
Charles Chand55e84d2016-03-30 17:54:24 -0700232 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700233 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
234 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700235 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan5270ed02016-01-30 23:22:37 -0800236 @Override
237 public SegmentRoutingAppConfig createConfig() {
238 return new SegmentRoutingAppConfig();
239 }
240 };
Charles Chanfc5c7802016-05-17 13:13:55 -0700241 private final ConfigFactory<ApplicationId, XConnectConfig> xConnectConfigFactory =
242 new ConfigFactory<ApplicationId, XConnectConfig>(
243 SubjectFactories.APP_SUBJECT_FACTORY,
244 XConnectConfig.class, "xconnect") {
245 @Override
246 public XConnectConfig createConfig() {
247 return new XConnectConfig();
248 }
249 };
Charles Chand55e84d2016-03-30 17:54:24 -0700250 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700251 new ConfigFactory<ApplicationId, McastConfig>(
252 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700253 McastConfig.class, "multicast") {
254 @Override
255 public McastConfig createConfig() {
256 return new McastConfig();
257 }
258 };
259
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700260 private Object threadSchedulerLock = new Object();
261 private static int numOfEventsQueued = 0;
262 private static int numOfEventsExecuted = 0;
sanghob35a6192015-04-01 13:05:26 -0700263 private static int numOfHandlerExecution = 0;
264 private static int numOfHandlerScheduled = 0;
265
Charles Chan116188d2016-02-18 14:22:42 -0800266 /**
267 * Segment Routing App ID.
268 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800269 public static final String APP_NAME = "org.onosproject.segmentrouting";
Charles Chane849c192016-01-11 18:28:54 -0800270 /**
271 * The starting value of per-subnet VLAN ID assignment.
272 */
Saurav Das0e99e2b2015-10-28 12:39:42 -0700273 private static final short ASSIGNED_VLAN_START = 4093;
Charles Chane849c192016-01-11 18:28:54 -0800274 /**
275 * The default VLAN ID assigned to the interfaces without subnet config.
276 */
Saurav Das0e99e2b2015-10-28 12:39:42 -0700277 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
278
sanghob35a6192015-04-01 13:05:26 -0700279 @Activate
280 protected void activate() {
Charles Chan2c15aca2016-11-09 20:51:44 -0800281 appId = coreService.registerApplication(APP_NAME);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700282
283 log.debug("Creating EC map nsnextobjectivestore");
284 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
285 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700286 nsNextObjStore = nsNextObjMapBuilder
287 .withName("nsnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700288 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700289 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700290 .build();
291 log.trace("Current size {}", nsNextObjStore.size());
292
Charles Chanc42e84e2015-10-20 16:24:19 -0700293 log.debug("Creating EC map subnetnextobjectivestore");
294 EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
295 subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Charles Chanc42e84e2015-10-20 16:24:19 -0700296 subnetNextObjStore = subnetNextObjMapBuilder
297 .withName("subnetnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700298 .withSerializer(createSerializer())
Charles Chanc42e84e2015-10-20 16:24:19 -0700299 .withTimestampProvider((k, v) -> new WallClockTimestamp())
300 .build();
301
Saurav Das4ce45962015-11-24 23:21:05 -0800302 log.debug("Creating EC map subnetnextobjectivestore");
303 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
304 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
305 portNextObjStore = portNextObjMapBuilder
306 .withName("portnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700307 .withSerializer(createSerializer())
Saurav Das4ce45962015-11-24 23:21:05 -0800308 .withTimestampProvider((k, v) -> new WallClockTimestamp())
309 .build();
310
sangho0b2b6d12015-05-20 22:16:38 -0700311 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
312 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700313 tunnelStore = tunnelMapBuilder
314 .withName("tunnelstore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700315 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700316 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700317 .build();
318
319 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
320 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700321 policyStore = policyMapBuilder
322 .withName("policystore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700323 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700324 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700325 .build();
326
Saurav Das0e99e2b2015-10-28 12:39:42 -0700327 EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
328 subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
Saurav Das0e99e2b2015-10-28 12:39:42 -0700329 subnetVidStore = subnetVidStoreMapBuilder
330 .withName("subnetvidstore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700331 .withSerializer(createSerializer())
Saurav Das0e99e2b2015-10-28 12:39:42 -0700332 .withTimestampProvider((k, v) -> new WallClockTimestamp())
333 .build();
334
Saurav Das80980c72016-03-23 11:22:49 -0700335 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
336 "purgeOnDisconnection", "true");
337 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
338 "purgeOnDisconnection", "true");
Charles Chan03a73e02016-10-24 14:52:01 -0700339 compCfgService.preSetProperty("org.onosproject.vrouter.Vrouter",
340 "fibInstalledEnabled", "false");
Saurav Das80980c72016-03-23 11:22:49 -0700341
Charles Chanb8e10c82015-10-14 11:24:40 -0700342 processor = new InternalPacketProcessor();
343 linkListener = new InternalLinkListener();
344 deviceListener = new InternalDeviceListener();
Charles Chanfc5c7802016-05-17 13:13:55 -0700345 appCfgHandler = new AppConfigHandler(this);
346 xConnectHandler = new XConnectHandler(this);
Charles Chand2990362016-04-18 13:44:03 -0700347 mcastHandler = new McastHandler(this);
348 hostHandler = new HostHandler(this);
Charles Chan35fd1a72016-06-13 18:54:31 -0700349 cordConfigHandler = new CordConfigHandler(this);
Charles Chan03a73e02016-10-24 14:52:01 -0700350 routeHandler = new RouteHandler(this);
Charles Chanb8e10c82015-10-14 11:24:40 -0700351
Charles Chan3e783d02016-02-26 22:19:52 -0800352 cfgService.addListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700353 cfgService.registerConfigFactory(deviceConfigFactory);
354 cfgService.registerConfigFactory(appConfigFactory);
Charles Chanfc5c7802016-05-17 13:13:55 -0700355 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700356 cfgService.registerConfigFactory(mcastConfigFactory);
Charles Chan5270ed02016-01-30 23:22:37 -0800357 hostService.addListener(hostListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700358 packetService.addProcessor(processor, PacketProcessor.director(2));
359 linkService.addListener(linkListener);
360 deviceService.addListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700361 multicastRouteService.addListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700362 cordConfigService.addListener(cordConfigListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700363
Charles Chan2df0e8a2017-01-09 11:45:08 -0800364 /* Request ARP packet-in.
365 * Copy flag set to true since in cross-connect case we still want to
366 * forward ARP packet to the flood group.
367 */
Charles Chan188ebf52015-12-23 00:15:11 -0800368 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
369 selector.matchEthType(Ethernet.TYPE_ARP);
Charles Chan2df0e8a2017-01-09 11:45:08 -0800370 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId, true);
Charles Chan188ebf52015-12-23 00:15:11 -0800371
Charles Chanb8e10c82015-10-14 11:24:40 -0700372 cfgListener.configureNetwork();
373
Charles Chan03a73e02016-10-24 14:52:01 -0700374 routeService.addListener(routeListener);
375
sanghob35a6192015-04-01 13:05:26 -0700376 log.info("Started");
377 }
378
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700379 private KryoNamespace.Builder createSerializer() {
380 return new KryoNamespace.Builder()
381 .register(KryoNamespaces.API)
382 .register(NeighborSetNextObjectiveStoreKey.class,
383 SubnetNextObjectiveStoreKey.class,
384 SubnetAssignedVidStoreKey.class,
385 NeighborSet.class,
386 Tunnel.class,
387 DefaultTunnel.class,
388 Policy.class,
389 TunnelPolicy.class,
390 Policy.Type.class,
391 PortNextObjectiveStoreKey.class,
Charles Chanfc5c7802016-05-17 13:13:55 -0700392 XConnectStoreKey.class
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700393 );
394 }
395
sanghob35a6192015-04-01 13:05:26 -0700396 @Deactivate
397 protected void deactivate() {
Charles Chand6832882015-10-05 17:50:33 -0700398 cfgService.removeListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700399 cfgService.unregisterConfigFactory(deviceConfigFactory);
400 cfgService.unregisterConfigFactory(appConfigFactory);
Charles Chan03a73e02016-10-24 14:52:01 -0700401 cfgService.unregisterConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700402 cfgService.unregisterConfigFactory(mcastConfigFactory);
Charles Chand6832882015-10-05 17:50:33 -0700403
Charles Chan188ebf52015-12-23 00:15:11 -0800404 // Withdraw ARP packet-in
405 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
406 selector.matchEthType(Ethernet.TYPE_ARP);
407 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId, Optional.empty());
408
sanghob35a6192015-04-01 13:05:26 -0700409 packetService.removeProcessor(processor);
Charles Chanb8e10c82015-10-14 11:24:40 -0700410 linkService.removeListener(linkListener);
411 deviceService.removeListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700412 multicastRouteService.removeListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700413 cordConfigService.removeListener(cordConfigListener);
Charles Chan03a73e02016-10-24 14:52:01 -0700414 routeService.removeListener(routeListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700415
sanghob35a6192015-04-01 13:05:26 -0700416 processor = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700417 linkListener = null;
Charles Chand55e84d2016-03-30 17:54:24 -0700418 deviceListener = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700419 groupHandlerMap.clear();
420
Charles Chand55e84d2016-03-30 17:54:24 -0700421 nsNextObjStore.destroy();
422 subnetNextObjStore.destroy();
423 portNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700424 tunnelStore.destroy();
425 policyStore.destroy();
426 subnetVidStore.destroy();
sanghob35a6192015-04-01 13:05:26 -0700427 log.info("Stopped");
428 }
429
sangho1e575652015-05-14 00:39:53 -0700430 @Override
431 public List<Tunnel> getTunnels() {
432 return tunnelHandler.getTunnels();
433 }
434
435 @Override
sangho71abe1b2015-06-29 14:58:47 -0700436 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
437 return tunnelHandler.createTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700438 }
439
440 @Override
sangho71abe1b2015-06-29 14:58:47 -0700441 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho1e575652015-05-14 00:39:53 -0700442 for (Policy policy: policyHandler.getPolicies()) {
443 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
444 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
445 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
446 log.warn("Cannot remove the tunnel used by a policy");
sangho71abe1b2015-06-29 14:58:47 -0700447 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho1e575652015-05-14 00:39:53 -0700448 }
449 }
450 }
sangho71abe1b2015-06-29 14:58:47 -0700451 return tunnelHandler.removeTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700452 }
453
454 @Override
sangho71abe1b2015-06-29 14:58:47 -0700455 public PolicyHandler.Result removePolicy(Policy policy) {
456 return policyHandler.removePolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700457 }
458
459 @Override
sangho71abe1b2015-06-29 14:58:47 -0700460 public PolicyHandler.Result createPolicy(Policy policy) {
461 return policyHandler.createPolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700462 }
463
464 @Override
465 public List<Policy> getPolicies() {
466 return policyHandler.getPolicies();
467 }
468
Saurav Das59232cf2016-04-27 18:35:50 -0700469 @Override
470 public void rerouteNetwork() {
471 cfgListener.configureNetwork();
472 for (Device device : deviceService.getDevices()) {
473 defaultRoutingHandler.populatePortAddressingRules(device.id());
474 }
475 defaultRoutingHandler.startPopulationProcess();
476 }
477
Charles Chanc81c45b2016-10-20 17:02:44 -0700478 @Override
479 public Map<DeviceId, Set<Ip4Prefix>> getDeviceSubnetMap() {
480 Map<DeviceId, Set<Ip4Prefix>> deviceSubnetMap = Maps.newHashMap();
481 deviceService.getAvailableDevices().forEach(device -> {
482 deviceSubnetMap.put(device.id(), deviceConfiguration.getSubnets(device.id()));
483 });
484 return deviceSubnetMap;
485 }
486
sanghof9d0bf12015-05-19 11:57:42 -0700487 /**
Pier Ventre98161782016-10-31 15:00:01 -0700488 * Returns the MPLS-ECMP configuration.
489 *
490 * @return MPLS-ECMP value
491 */
492 public boolean getMplsEcmp() {
493 SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
494 .getConfig(this.appId, SegmentRoutingAppConfig.class);
495 return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
496 }
497
498 /**
sanghof9d0bf12015-05-19 11:57:42 -0700499 * Returns the tunnel object with the tunnel ID.
500 *
501 * @param tunnelId Tunnel ID
502 * @return Tunnel reference
503 */
sangho1e575652015-05-14 00:39:53 -0700504 public Tunnel getTunnel(String tunnelId) {
505 return tunnelHandler.getTunnel(tunnelId);
506 }
507
sanghob35a6192015-04-01 13:05:26 -0700508 /**
Saurav Das0e99e2b2015-10-28 12:39:42 -0700509 * Returns the vlan-id assigned to the subnet configured for a device.
510 * If no vlan-id has been assigned, a new one is assigned out of a pool of ids,
511 * if and only if this controller instance is the master for the device.
512 * <p>
513 * USAGE: The assigned vlans are meant to be applied to untagged packets on those
514 * switches/pipelines that need this functionality. These vids are meant
515 * to be used internally within a switch, and thus need to be unique only
516 * on a switch level. Note that packets never go out on the wire with these
517 * vlans. Currently, vlan ids are assigned from value 4093 down.
518 * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
519 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
520 * per subnet.
sanghob35a6192015-04-01 13:05:26 -0700521 *
Saurav Das0e99e2b2015-10-28 12:39:42 -0700522 * @param deviceId switch dpid
523 * @param subnet IPv4 prefix for which assigned vlan is desired
524 * @return VlanId assigned for the subnet on the device, or
525 * null if no vlan assignment was found and this instance is not
526 * the master for the device.
sanghob35a6192015-04-01 13:05:26 -0700527 */
Charles Chane849c192016-01-11 18:28:54 -0800528 // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700529 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
530 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
531 deviceId, subnet));
532 if (assignedVid != null) {
533 log.debug("Query for subnet:{} on device:{} returned assigned-vlan "
534 + "{}", subnet, deviceId, assignedVid);
535 return assignedVid;
536 }
537 //check mastership for the right to assign a vlan
538 if (!mastershipService.isLocalMaster(deviceId)) {
539 log.warn("This controller instance is not the master for device {}. "
540 + "Cannot assign vlan-id for subnet {}", deviceId, subnet);
541 return null;
542 }
543 // vlan assignment is expensive but done only once
Charles Chan9f676b62015-10-29 14:58:10 -0700544 Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId);
Saurav Das0e99e2b2015-10-28 12:39:42 -0700545 Set<Short> assignedVlans = new HashSet<>();
546 Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
547 for (Ip4Prefix sub : configuredSubnets) {
548 VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId,
549 sub));
550 if (v != null) {
551 assignedVlans.add(v.toShort());
552 } else {
553 unassignedSubnets.add(sub);
554 }
555 }
556 short nextAssignedVlan = ASSIGNED_VLAN_START;
557 if (!assignedVlans.isEmpty()) {
558 nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1);
559 }
560 for (Ip4Prefix unsub : unassignedSubnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800561 // Special case for default route. Assign default VLAN ID to /32 and /0 subnets
562 if (unsub.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
563 unsub.prefixLength() == 0) {
564 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
565 VlanId.vlanId(ASSIGNED_VLAN_NO_SUBNET));
566 } else {
567 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
568 VlanId.vlanId(nextAssignedVlan--));
569 log.info("Assigned vlan: {} to subnet: {} on device: {}",
570 nextAssignedVlan + 1, unsub, deviceId);
571 }
sanghob35a6192015-04-01 13:05:26 -0700572 }
573
Saurav Das0e99e2b2015-10-28 12:39:42 -0700574 return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
sanghob35a6192015-04-01 13:05:26 -0700575 }
576
sangho1e575652015-05-14 00:39:53 -0700577 /**
Saurav Das0e99e2b2015-10-28 12:39:42 -0700578 * Returns the next objective ID for the given NeighborSet.
Saurav Das8a0732e2015-11-20 15:27:53 -0800579 * If the nextObjective does not exist, a new one is created and
Saurav Das4ce45962015-11-24 23:21:05 -0800580 * its id is returned.
sangho1e575652015-05-14 00:39:53 -0700581 *
sanghof9d0bf12015-05-19 11:57:42 -0700582 * @param deviceId Device ID
583 * @param ns NegighborSet
Saurav Das8a0732e2015-11-20 15:27:53 -0800584 * @param meta metadata passed into the creation of a Next Objective
585 * @return next objective ID or -1 if an error was encountered during the
586 * creation of the nextObjective
sangho1e575652015-05-14 00:39:53 -0700587 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800588 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
589 TrafficSelector meta) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700590 if (groupHandlerMap.get(deviceId) != null) {
591 log.trace("getNextObjectiveId query in device {}", deviceId);
592 return groupHandlerMap
Saurav Das8a0732e2015-11-20 15:27:53 -0800593 .get(deviceId).getNextObjectiveId(ns, meta);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700594 } else {
Saurav Das4ce45962015-11-24 23:21:05 -0800595 log.warn("getNextObjectiveId query - groupHandler for device {} "
596 + "not found", deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700597 return -1;
598 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700599 }
600
Charles Chanc42e84e2015-10-20 16:24:19 -0700601 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800602 * Returns the next objective ID for the given subnet prefix. It is expected
603 * that the next-objective has been pre-created from configuration.
Charles Chanc42e84e2015-10-20 16:24:19 -0700604 *
605 * @param deviceId Device ID
606 * @param prefix Subnet
Saurav Das4ce45962015-11-24 23:21:05 -0800607 * @return next objective ID or -1 if it was not found
Charles Chanc42e84e2015-10-20 16:24:19 -0700608 */
609 public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
610 if (groupHandlerMap.get(deviceId) != null) {
611 log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
612 return groupHandlerMap
613 .get(deviceId).getSubnetNextObjectiveId(prefix);
614 } else {
Saurav Das4ce45962015-11-24 23:21:05 -0800615 log.warn("getSubnetNextObjectiveId query - groupHandler for "
616 + "device {} not found", deviceId);
617 return -1;
618 }
619 }
620
621 /**
622 * Returns the next objective ID for the given portNumber, given the treatment.
623 * There could be multiple different treatments to the same outport, which
624 * would result in different objectives. If the next object
625 * does not exist, a new one is created and its id is returned.
626 *
627 * @param deviceId Device ID
628 * @param portNum port number on device for which NextObjective is queried
629 * @param treatment the actions to apply on the packets (should include outport)
630 * @param meta metadata passed into the creation of a Next Objective if necessary
Saurav Das59232cf2016-04-27 18:35:50 -0700631 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das4ce45962015-11-24 23:21:05 -0800632 */
633 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
634 TrafficTreatment treatment,
635 TrafficSelector meta) {
636 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
637 if (ghdlr != null) {
638 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
639 } else {
Charles Chane849c192016-01-11 18:28:54 -0800640 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
641 + " not found", deviceId);
642 return -1;
643 }
644 }
645
sanghob35a6192015-04-01 13:05:26 -0700646 private class InternalPacketProcessor implements PacketProcessor {
sanghob35a6192015-04-01 13:05:26 -0700647 @Override
648 public void process(PacketContext context) {
649
650 if (context.isHandled()) {
651 return;
652 }
653
654 InboundPacket pkt = context.inPacket();
655 Ethernet ethernet = pkt.parsed();
Saurav Das4ce45962015-11-24 23:21:05 -0800656 log.trace("Rcvd pktin: {}", ethernet);
sanghob35a6192015-04-01 13:05:26 -0700657 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
658 arpHandler.processPacketIn(pkt);
659 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
660 IPv4 ipPacket = (IPv4) ethernet.getPayload();
661 ipHandler.addToPacketBuffer(ipPacket);
662 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
663 icmpHandler.processPacketIn(pkt);
664 } else {
665 ipHandler.processPacketIn(pkt);
666 }
667 }
668 }
669 }
670
671 private class InternalLinkListener implements LinkListener {
672 @Override
673 public void event(LinkEvent event) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700674 if (event.type() == LinkEvent.Type.LINK_ADDED
675 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700676 log.debug("Event {} received from Link Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700677 scheduleEventHandlerIfNotScheduled(event);
678 }
679 }
680 }
681
682 private class InternalDeviceListener implements DeviceListener {
sanghob35a6192015-04-01 13:05:26 -0700683 @Override
684 public void event(DeviceEvent event) {
sanghob35a6192015-04-01 13:05:26 -0700685 switch (event.type()) {
686 case DEVICE_ADDED:
Saurav Das1a129a02016-11-18 15:21:57 -0800687 case PORT_UPDATED:
688 case PORT_ADDED:
sangho20eff1d2015-04-13 15:15:58 -0700689 case DEVICE_UPDATED:
690 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700691 log.debug("Event {} received from Device Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700692 scheduleEventHandlerIfNotScheduled(event);
693 break;
694 default:
695 }
696 }
697 }
698
Saurav Das4ce45962015-11-24 23:21:05 -0800699 @SuppressWarnings("rawtypes")
sanghob35a6192015-04-01 13:05:26 -0700700 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700701 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700702 eventQueue.add(event);
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700703 numOfEventsQueued++;
704
705 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
706 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700707 eventHandlerFuture = executorService
708 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
709 numOfHandlerScheduled++;
710 }
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700711 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700712 numOfEventsQueued,
713 numOfHandlerScheduled);
sanghob35a6192015-04-01 13:05:26 -0700714 }
sanghob35a6192015-04-01 13:05:26 -0700715 }
716
717 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700718 @Override
sanghob35a6192015-04-01 13:05:26 -0700719 public void run() {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700720 try {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700721 while (true) {
Saurav Das4ce45962015-11-24 23:21:05 -0800722 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700723 Event event = null;
724 synchronized (threadSchedulerLock) {
725 if (!eventQueue.isEmpty()) {
726 event = eventQueue.poll();
727 numOfEventsExecuted++;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700728 } else {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700729 numOfHandlerExecution++;
730 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
731 numOfHandlerExecution, numOfEventsExecuted);
732 break;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700733 }
sangho20eff1d2015-04-13 15:15:58 -0700734 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700735 if (event.type() == LinkEvent.Type.LINK_ADDED) {
736 processLinkAdded((Link) event.subject());
737 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
Pier Ventre2c515312016-09-13 21:33:40 -0700738 Link linkRemoved = (Link) event.subject();
739 if (linkRemoved.src().elementId() instanceof DeviceId &&
740 !deviceService.isAvailable(linkRemoved.src().deviceId())) {
741 continue;
742 }
743 if (linkRemoved.dst().elementId() instanceof DeviceId &&
744 !deviceService.isAvailable(linkRemoved.dst().deviceId())) {
745 continue;
746 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700747 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700748 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
749 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
750 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800751 DeviceId deviceId = ((Device) event.subject()).id();
752 if (deviceService.isAvailable(deviceId)) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700753 log.info("Processing device event {} for available device {}",
754 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700755 processDeviceAdded((Device) event.subject());
Saurav Das80980c72016-03-23 11:22:49 -0700756 } else {
757 log.info("Processing device event {} for unavailable device {}",
758 event.type(), ((Device) event.subject()).id());
759 processDeviceRemoved((Device) event.subject());
760 }
Saurav Das1a129a02016-11-18 15:21:57 -0800761 } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
Saurav Dasd2fded02016-12-02 15:43:47 -0800762 // typically these calls come when device is added first time
763 // so port filtering rules are handled at the device_added event.
764 // port added calls represent all ports on the device,
765 // enabled or not.
Saurav Das1a129a02016-11-18 15:21:57 -0800766 log.debug("** PORT ADDED {}/{} -> {}",
Saurav Dasd2fded02016-12-02 15:43:47 -0800767 ((DeviceEvent) event).subject().id(),
768 ((DeviceEvent) event).port().number(),
769 event.type());
Saurav Das1a129a02016-11-18 15:21:57 -0800770 } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
Saurav Dasd2fded02016-12-02 15:43:47 -0800771 // these calls happen for every subsequent event
772 // ports enabled, disabled, switch goes away, comes back
Saurav Das1a129a02016-11-18 15:21:57 -0800773 log.info("** PORT UPDATED {}/{} -> {}",
774 event.subject(),
775 ((DeviceEvent) event).port(),
776 event.type());
777 processPortUpdated(((Device) event.subject()),
778 ((DeviceEvent) event).port());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700779 } else {
780 log.warn("Unhandled event type: {}", event.type());
781 }
sanghob35a6192015-04-01 13:05:26 -0700782 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700783 } catch (Exception e) {
784 log.error("SegmentRouting event handler "
785 + "thread thrown an exception: {}", e);
sanghob35a6192015-04-01 13:05:26 -0700786 }
sanghob35a6192015-04-01 13:05:26 -0700787 }
788 }
789
sanghob35a6192015-04-01 13:05:26 -0700790 private void processLinkAdded(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700791 log.info("** LINK ADDED {}", link.toString());
Charles Chan0b4e6182015-11-03 10:42:14 -0800792 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
793 log.warn("Source device of this link is not configured.");
794 return;
795 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700796 //Irrespective whether the local is a MASTER or not for this device,
797 //create group handler instance and push default TTP flow rules.
798 //Because in a multi-instance setup, instances can initiate
799 //groups for any devices. Also the default TTP rules are needed
800 //to be pushed before inserting any IP table entries for any device
801 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
802 .deviceId());
803 if (groupHandler != null) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800804 groupHandler.linkUp(link, mastershipService.isLocalMaster(
805 link.src().deviceId()));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700806 } else {
807 Device device = deviceService.getDevice(link.src().deviceId());
808 if (device != null) {
809 log.warn("processLinkAdded: Link Added "
810 + "Notification without Device Added "
811 + "event, still handling it");
812 processDeviceAdded(device);
813 groupHandler = groupHandlerMap.get(link.src()
814 .deviceId());
Saurav Das8a0732e2015-11-20 15:27:53 -0800815 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sanghob35a6192015-04-01 13:05:26 -0700816 }
817 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700818
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700819 log.trace("Starting optimized route population process");
820 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
821 //log.trace("processLinkAdded: re-starting route population process");
822 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700823
824 mcastHandler.init();
sanghob35a6192015-04-01 13:05:26 -0700825 }
826
827 private void processLinkRemoved(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700828 log.info("** LINK REMOVED {}", link.toString());
sangho834e4b02015-05-01 09:38:25 -0700829 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
830 if (groupHandler != null) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800831 groupHandler.portDown(link.src().port(),
832 mastershipService.isLocalMaster(link.src().deviceId()));
sangho834e4b02015-05-01 09:38:25 -0700833 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700834 log.trace("Starting optimized route population process");
835 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
836 //log.trace("processLinkRemoved: re-starting route population process");
837 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700838
839 mcastHandler.processLinkDown(link);
sanghob35a6192015-04-01 13:05:26 -0700840 }
841
842 private void processDeviceAdded(Device device) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700843 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan0b4e6182015-11-03 10:42:14 -0800844 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das2857f382015-11-03 14:39:27 -0800845 log.warn("Device configuration uploading. Device {} will be "
846 + "processed after config completes.", device.id());
847 return;
848 }
Charles Chan2199c302016-04-23 17:36:10 -0700849 processDeviceAddedInternal(device.id());
850 }
851
852 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700853 // Irrespective of whether the local is a MASTER or not for this device,
854 // we need to create a SR-group-handler instance. This is because in a
855 // multi-instance setup, any instance can initiate forwarding/next-objectives
856 // for any switch (even if this instance is a SLAVE or not even connected
857 // to the switch). To handle this, a default-group-handler instance is necessary
858 // per switch.
Charles Chan2199c302016-04-23 17:36:10 -0700859 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
860 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan0b4e6182015-11-03 10:42:14 -0800861 DefaultGroupHandler groupHandler;
862 try {
863 groupHandler = DefaultGroupHandler.
Charles Chan2199c302016-04-23 17:36:10 -0700864 createGroupHandler(deviceId,
865 appId,
866 deviceConfiguration,
867 linkService,
868 flowObjectiveService,
869 this);
Charles Chan0b4e6182015-11-03 10:42:14 -0800870 } catch (DeviceConfigNotFoundException e) {
871 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
872 return;
873 }
Charles Chan2199c302016-04-23 17:36:10 -0700874 log.debug("updating groupHandlerMap with new config for device: {}",
875 deviceId);
876 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das2857f382015-11-03 14:39:27 -0800877 }
Saurav Dasb5c236e2016-06-07 10:08:06 -0700878 // Also, in some cases, drivers may need extra
879 // information to process rules (eg. Router IP/MAC); and so, we send
880 // port addressing rules to the driver as well irrespective of whether
881 // this instance is the master or not.
882 defaultRoutingHandler.populatePortAddressingRules(deviceId);
883
Charles Chan2199c302016-04-23 17:36:10 -0700884 if (mastershipService.isLocalMaster(deviceId)) {
Charles Chan03a73e02016-10-24 14:52:01 -0700885 hostHandler.init(deviceId);
Charles Chanfc5c7802016-05-17 13:13:55 -0700886 xConnectHandler.init(deviceId);
Charles Chan35fd1a72016-06-13 18:54:31 -0700887 cordConfigHandler.init(deviceId);
Charles Chan2199c302016-04-23 17:36:10 -0700888 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700889 groupHandler.createGroupsFromSubnetConfig();
Charles Chan2199c302016-04-23 17:36:10 -0700890 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700891 }
Charles Chan5270ed02016-01-30 23:22:37 -0800892
Charles Chan03a73e02016-10-24 14:52:01 -0700893 appCfgHandler.init(deviceId);
894 routeHandler.init(deviceId);
sanghob35a6192015-04-01 13:05:26 -0700895 }
896
Saurav Das80980c72016-03-23 11:22:49 -0700897 private void processDeviceRemoved(Device device) {
898 nsNextObjStore.entrySet().stream()
899 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
900 .forEach(entry -> {
901 nsNextObjStore.remove(entry.getKey());
902 });
Saurav Das80980c72016-03-23 11:22:49 -0700903 subnetNextObjStore.entrySet().stream()
904 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
905 .forEach(entry -> {
906 subnetNextObjStore.remove(entry.getKey());
907 });
Saurav Das80980c72016-03-23 11:22:49 -0700908 portNextObjStore.entrySet().stream()
909 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
910 .forEach(entry -> {
911 portNextObjStore.remove(entry.getKey());
912 });
Saurav Das80980c72016-03-23 11:22:49 -0700913 subnetVidStore.entrySet().stream()
914 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
915 .forEach(entry -> {
916 subnetVidStore.remove(entry.getKey());
917 });
Saurav Das80980c72016-03-23 11:22:49 -0700918 groupHandlerMap.remove(device.id());
Saurav Das80980c72016-03-23 11:22:49 -0700919 defaultRoutingHandler.purgeEcmpGraph(device.id());
Charles Chan2199c302016-04-23 17:36:10 -0700920 mcastHandler.removeDevice(device.id());
Charles Chanfc5c7802016-05-17 13:13:55 -0700921 xConnectHandler.removeDevice(device.id());
Saurav Das80980c72016-03-23 11:22:49 -0700922 }
923
Saurav Das1a129a02016-11-18 15:21:57 -0800924 private void processPortUpdated(Device device, Port port) {
925 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
926 log.warn("Device configuration uploading. Not handling port event for"
927 + "dev: {} port: {}", device.id(), port.number());
928 return;
929 }
930 /* XXX create method for single port filtering rules which are needed
931 for both switch-to-switch ports and edge ports
932 if (defaultRoutingHandler != null) {
933 defaultRoutingHandler.populatePortAddressingRules(
934 ((Device) event.subject()).id());
935 }*/
936
937 // portUpdated calls are for ports that have gone down or up. For switch
938 // to switch ports, link-events should take care of any re-routing or
939 // group editing necessary for port up/down. Here we only process edge ports
940 // that are already configured.
941 Ip4Prefix configuredSubnet = deviceConfiguration.getPortSubnet(device.id(),
942 port.number());
943 if (configuredSubnet == null) {
944 log.debug("Not handling port updated event for unconfigured port "
945 + "dev/port: {}/{}", device.id(), port.number());
946 return;
947 }
948 processEdgePort(device, port, configuredSubnet);
949 }
950
951 private void processEdgePort(Device device, Port port, Ip4Prefix subnet) {
952 boolean portUp = port.isEnabled();
953 if (portUp) {
954 log.info("Device:EdgePort {}:{} is enabled in subnet: {}", device.id(),
955 port.number(), subnet);
956 } else {
957 log.info("Device:EdgePort {}:{} is disabled in subnet: {}", device.id(),
958 port.number(), subnet);
959 }
960
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700961 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -0700962 if (groupHandler != null) {
Saurav Das1a129a02016-11-18 15:21:57 -0800963 groupHandler.processEdgePort(port.number(), subnet, portUp,
Saurav Das423fe2b2015-12-04 10:52:59 -0800964 mastershipService.isLocalMaster(device.id()));
Saurav Das1a129a02016-11-18 15:21:57 -0800965 } else {
966 log.warn("Group handler not found for dev:{}. Not handling edge port"
967 + " {} event for port:{}", device.id(),
968 (portUp) ? "UP" : "DOWN", port.number());
sanghob35a6192015-04-01 13:05:26 -0700969 }
970 }
sangho1e575652015-05-14 00:39:53 -0700971
Charles Chand6832882015-10-05 17:50:33 -0700972 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan2c15aca2016-11-09 20:51:44 -0800973 SegmentRoutingManager srManager;
Charles Chan4636be02015-10-07 14:21:45 -0700974
Charles Chane849c192016-01-11 18:28:54 -0800975 /**
976 * Constructs the internal network config listener.
977 *
Charles Chan2c15aca2016-11-09 20:51:44 -0800978 * @param srManager segment routing manager
Charles Chane849c192016-01-11 18:28:54 -0800979 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800980 public InternalConfigListener(SegmentRoutingManager srManager) {
981 this.srManager = srManager;
Charles Chan4636be02015-10-07 14:21:45 -0700982 }
983
Charles Chane849c192016-01-11 18:28:54 -0800984 /**
985 * Reads network config and initializes related data structure accordingly.
986 */
Charles Chan4636be02015-10-07 14:21:45 -0700987 public void configureNetwork() {
Charles Chan2c15aca2016-11-09 20:51:44 -0800988 deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan4636be02015-10-07 14:21:45 -0700989
Charles Chan2c15aca2016-11-09 20:51:44 -0800990 arpHandler = new ArpHandler(srManager);
991 icmpHandler = new IcmpHandler(srManager);
992 ipHandler = new IpHandler(srManager);
993 routingRulePopulator = new RoutingRulePopulator(srManager);
994 defaultRoutingHandler = new DefaultRoutingHandler(srManager);
Charles Chan4636be02015-10-07 14:21:45 -0700995
996 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
997 groupHandlerMap, tunnelStore);
998 policyHandler = new PolicyHandler(appId, deviceConfiguration,
999 flowObjectiveService,
1000 tunnelHandler, policyStore);
1001
Charles Chan4636be02015-10-07 14:21:45 -07001002 for (Device device : deviceService.getDevices()) {
Charles Chan2199c302016-04-23 17:36:10 -07001003 processDeviceAddedInternal(device.id());
Charles Chan4636be02015-10-07 14:21:45 -07001004 }
1005
1006 defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -07001007 mcastHandler.init();
Charles Chan4636be02015-10-07 14:21:45 -07001008 }
1009
Charles Chand6832882015-10-05 17:50:33 -07001010 @Override
1011 public void event(NetworkConfigEvent event) {
Charles Chan5270ed02016-01-30 23:22:37 -08001012 // TODO move this part to NetworkConfigEventHandler
1013 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
1014 switch (event.type()) {
1015 case CONFIG_ADDED:
1016 log.info("Segment Routing Config added.");
1017 configureNetwork();
1018 break;
1019 case CONFIG_UPDATED:
1020 log.info("Segment Routing Config updated.");
1021 // TODO support dynamic configuration
1022 break;
1023 default:
1024 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001025 }
Charles Chan5270ed02016-01-30 23:22:37 -08001026 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chanfc5c7802016-05-17 13:13:55 -07001027 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan5270ed02016-01-30 23:22:37 -08001028 switch (event.type()) {
1029 case CONFIG_ADDED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001030 appCfgHandler.processAppConfigAdded(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001031 break;
1032 case CONFIG_UPDATED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001033 appCfgHandler.processAppConfigUpdated(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001034 break;
1035 case CONFIG_REMOVED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001036 appCfgHandler.processAppConfigRemoved(event);
1037 break;
1038 default:
1039 break;
1040 }
Charles Chan03a73e02016-10-24 14:52:01 -07001041 configureNetwork();
Charles Chanfc5c7802016-05-17 13:13:55 -07001042 } else if (event.configClass().equals(XConnectConfig.class)) {
1043 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
1044 switch (event.type()) {
1045 case CONFIG_ADDED:
1046 xConnectHandler.processXConnectConfigAdded(event);
1047 break;
1048 case CONFIG_UPDATED:
1049 xConnectHandler.processXConnectConfigUpdated(event);
1050 break;
1051 case CONFIG_REMOVED:
1052 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001053 break;
1054 default:
1055 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001056 }
Charles Chand6832882015-10-05 17:50:33 -07001057 }
1058 }
1059 }
Charles Chan68aa62d2015-11-09 16:37:23 -08001060
1061 private class InternalHostListener implements HostListener {
Charles Chan68aa62d2015-11-09 16:37:23 -08001062 @Override
1063 public void event(HostEvent event) {
1064 // Do not proceed without mastership
1065 DeviceId deviceId = event.subject().location().deviceId();
1066 if (!mastershipService.isLocalMaster(deviceId)) {
1067 return;
1068 }
1069
1070 switch (event.type()) {
1071 case HOST_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001072 hostHandler.processHostAddedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001073 break;
1074 case HOST_MOVED:
Charles Chand2990362016-04-18 13:44:03 -07001075 hostHandler.processHostMovedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001076 break;
1077 case HOST_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001078 hostHandler.processHostRemoveEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001079 break;
1080 case HOST_UPDATED:
Charles Chand2990362016-04-18 13:44:03 -07001081 hostHandler.processHostUpdatedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001082 break;
1083 default:
1084 log.warn("Unsupported host event type: {}", event.type());
1085 break;
1086 }
1087 }
1088 }
1089
Charles Chand55e84d2016-03-30 17:54:24 -07001090 private class InternalMcastListener implements McastListener {
1091 @Override
1092 public void event(McastEvent event) {
1093 switch (event.type()) {
1094 case SOURCE_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001095 mcastHandler.processSourceAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001096 break;
1097 case SINK_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001098 mcastHandler.processSinkAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001099 break;
1100 case SINK_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001101 mcastHandler.processSinkRemoved(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001102 break;
1103 case ROUTE_ADDED:
1104 case ROUTE_REMOVED:
1105 default:
1106 break;
1107 }
1108 }
1109 }
Charles Chan35fd1a72016-06-13 18:54:31 -07001110
1111 private class InternalCordConfigListener implements CordConfigListener {
1112 @Override
1113 public void event(CordConfigEvent event) {
1114 switch (event.type()) {
1115 case ACCESS_AGENT_ADDED:
1116 cordConfigHandler.processAccessAgentAddedEvent(event);
1117 break;
1118 case ACCESS_AGENT_UPDATED:
1119 cordConfigHandler.processAccessAgentUpdatedEvent(event);
1120 break;
1121 case ACCESS_AGENT_REMOVED:
1122 cordConfigHandler.processAccessAgentRemovedEvent(event);
1123 break;
1124 case ACCESS_DEVICE_ADDED:
1125 case ACCESS_DEVICE_UPDATED:
1126 case ACCESS_DEVICE_REMOVED:
1127 default:
1128 break;
1129 }
1130 }
1131 }
Charles Chan03a73e02016-10-24 14:52:01 -07001132
1133 private class InternalRouteEventListener implements RouteListener {
1134 @Override
1135 public void event(RouteEvent event) {
1136 switch (event.type()) {
1137 case ROUTE_ADDED:
1138 routeHandler.processRouteAdded(event);
1139 break;
1140 case ROUTE_UPDATED:
1141 routeHandler.processRouteUpdated(event);
1142 break;
1143 case ROUTE_REMOVED:
1144 routeHandler.processRouteRemoved(event);
1145 break;
1146 default:
1147 break;
1148 }
1149 }
1150 }
sanghob35a6192015-04-01 13:05:26 -07001151}