blob: fea282499e2c52b9982b0e64a70b24f9b00c4829 [file] [log] [blame]
sangho80f11cb2015-04-01 13:05:26 -07001/*
Brian O'Connor43b53542016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sangho80f11cb2015-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 Chand7844e52016-10-20 17:02:44 -070018import com.google.common.collect.Maps;
sangho80f11cb2015-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;
sangho27462c62015-05-14 00:39:53 -070024import org.apache.felix.scr.annotations.Service;
sangho80f11cb2015-04-01 13:05:26 -070025import org.onlab.packet.Ethernet;
Charles Chan77277672015-10-20 16:24:19 -070026import org.onlab.packet.IPv4;
Charles Chan77277672015-10-20 16:24:19 -070027import org.onlab.packet.Ip4Prefix;
Charles Chan77277672015-10-20 16:24:19 -070028import org.onlab.packet.IpPrefix;
Jonathan Hart54541d12016-04-12 15:39:44 -070029import org.onlab.packet.VlanId;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070030import org.onlab.util.KryoNamespace;
Saurav Dasc3604f12016-03-23 11:22:49 -070031import org.onosproject.cfg.ComponentConfigService;
sangho80f11cb2015-04-01 13:05:26 -070032import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreService;
34import org.onosproject.event.Event;
Charles Chanc91c8782016-03-30 17:54:24 -070035import org.onosproject.incubator.net.config.basics.McastConfig;
Charles Chan46fdfaf2016-11-09 20:51:44 -080036import org.onosproject.incubator.net.intf.InterfaceService;
Charles Chandebfea32016-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 Hart54541d12016-04-12 15:39:44 -070040import org.onosproject.mastership.MastershipService;
Jonathan Hart54541d12016-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 Chanf4586112015-11-09 16:37:23 -080045import org.onosproject.net.PortNumber;
Charles Chan72f556a2015-10-05 17:50:33 -070046import org.onosproject.net.config.ConfigFactory;
47import org.onosproject.net.config.NetworkConfigEvent;
Charles Chan72f556a2015-10-05 17:50:33 -070048import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hart54541d12016-04-12 15:39:44 -070049import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chan72f556a2015-10-05 17:50:33 -070050import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hart54541d12016-04-12 15:39:44 -070051import org.onosproject.net.device.DeviceEvent;
52import org.onosproject.net.device.DeviceListener;
53import org.onosproject.net.device.DeviceService;
Charles Chanf4586112015-11-09 16:37:23 -080054import org.onosproject.net.flow.TrafficSelector;
55import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart54541d12016-04-12 15:39:44 -070056import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chanf4586112015-11-09 16:37:23 -080057import org.onosproject.net.host.HostEvent;
58import org.onosproject.net.host.HostListener;
Charles Chanc91c8782016-03-30 17:54:24 -070059import org.onosproject.net.mcast.McastEvent;
60import org.onosproject.net.mcast.McastListener;
61import org.onosproject.net.mcast.MulticastRouteService;
Charles Chanc91c8782016-03-30 17:54:24 -070062import org.onosproject.net.topology.TopologyService;
63import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
64import org.onosproject.segmentrouting.config.DeviceConfiguration;
65import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
66import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Charles Chan82f19972016-05-17 13:13:55 -070067import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chanc91c8782016-03-30 17:54:24 -070068import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
69import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Charles Chan1eaf4802016-04-18 13:44:03 -070070import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
71import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
sangho80f11cb2015-04-01 13:05:26 -070072import org.onosproject.net.host.HostService;
sangho80f11cb2015-04-01 13:05:26 -070073import org.onosproject.net.link.LinkEvent;
74import org.onosproject.net.link.LinkListener;
75import org.onosproject.net.link.LinkService;
76import org.onosproject.net.packet.InboundPacket;
77import org.onosproject.net.packet.PacketContext;
78import org.onosproject.net.packet.PacketProcessor;
79import org.onosproject.net.packet.PacketService;
Charles Chan1eaf4802016-04-18 13:44:03 -070080import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
81import org.onosproject.segmentrouting.storekey.SubnetNextObjectiveStoreKey;
Charles Chan82f19972016-05-17 13:13:55 -070082import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Jonathan Hart54541d12016-04-12 15:39:44 -070083import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070084import org.onosproject.store.service.EventuallyConsistentMap;
85import org.onosproject.store.service.EventuallyConsistentMapBuilder;
86import org.onosproject.store.service.StorageService;
87import org.onosproject.store.service.WallClockTimestamp;
Charles Chan41f5ec02016-06-13 18:54:31 -070088import org.opencord.cordconfig.CordConfigEvent;
89import org.opencord.cordconfig.CordConfigListener;
90import org.opencord.cordconfig.CordConfigService;
sangho80f11cb2015-04-01 13:05:26 -070091import org.slf4j.Logger;
92import org.slf4j.LoggerFactory;
93
Saurav Das7c305372015-10-28 12:39:42 -070094import java.util.Collections;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070095import java.util.HashSet;
sangho27462c62015-05-14 00:39:53 -070096import java.util.List;
sangho80f11cb2015-04-01 13:05:26 -070097import java.util.Map;
Saurav Das7c305372015-10-28 12:39:42 -070098import java.util.Set;
sangho80f11cb2015-04-01 13:05:26 -070099import java.util.concurrent.ConcurrentHashMap;
100import java.util.concurrent.ConcurrentLinkedQueue;
101import java.util.concurrent.Executors;
102import java.util.concurrent.ScheduledExecutorService;
103import java.util.concurrent.ScheduledFuture;
104import java.util.concurrent.TimeUnit;
105
Charles Chand6d25332016-02-26 22:19:52 -0800106import static com.google.common.base.Preconditions.checkState;
Pier Ventreadb4ae62016-11-23 09:57:42 -0800107import static org.onlab.packet.Ethernet.TYPE_ARP;
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700108import static org.onlab.util.Tools.groupedThreads;
Charles Chand6d25332016-02-26 22:19:52 -0800109
Charles Chanb7f75ac2016-01-11 18:28:54 -0800110/**
111 * Segment routing manager.
112 */
Jonathan Hart54541d12016-04-12 15:39:44 -0700113@Service
114@Component(immediate = true)
sangho27462c62015-05-14 00:39:53 -0700115public class SegmentRoutingManager implements SegmentRoutingService {
sangho80f11cb2015-04-01 13:05:26 -0700116
Charles Chan46fdfaf2016-11-09 20:51:44 -0800117 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
sangho80f11cb2015-04-01 13:05:26 -0700118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700120 private ComponentConfigService compCfgService;
sangho80f11cb2015-04-01 13:05:26 -0700121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700123 CoreService coreService;
sangho80f11cb2015-04-01 13:05:26 -0700124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700126 PacketService packetService;
sangho80f11cb2015-04-01 13:05:26 -0700127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700129 HostService hostService;
sangho80f11cb2015-04-01 13:05:26 -0700130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700132 DeviceService deviceService;
sangho80f11cb2015-04-01 13:05:26 -0700133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700135 FlowObjectiveService flowObjectiveService;
sangho80f11cb2015-04-01 13:05:26 -0700136
137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700138 LinkService linkService;
sangho27462c62015-05-14 00:39:53 -0700139
Charles Chan82ab1932016-01-30 23:22:37 -0800140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700141 MastershipService mastershipService;
142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
144 StorageService storageService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 MulticastRouteService multicastRouteService;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 TopologyService topologyService;
151
152 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
153 CordConfigService cordConfigService;
154
155 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
156 RouteService routeService;
Charles Chan82ab1932016-01-30 23:22:37 -0800157
158 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan46fdfaf2016-11-09 20:51:44 -0800159 public NetworkConfigRegistry cfgService;
Charles Chan82ab1932016-01-30 23:22:37 -0800160
Saurav Dasc3604f12016-03-23 11:22:49 -0700161 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan46fdfaf2016-11-09 20:51:44 -0800162 public InterfaceService interfaceService;
163
Charles Chandebfea32016-10-24 14:52:01 -0700164 ArpHandler arpHandler = null;
165 IcmpHandler icmpHandler = null;
166 IpHandler ipHandler = null;
167 RoutingRulePopulator routingRulePopulator = null;
Charles Chan46fdfaf2016-11-09 20:51:44 -0800168 public ApplicationId appId;
sangho9b169e32015-04-14 16:27:13 -0700169 protected DeviceConfiguration deviceConfiguration = null;
sangho80f11cb2015-04-01 13:05:26 -0700170
Charles Chandebfea32016-10-24 14:52:01 -0700171 DefaultRoutingHandler defaultRoutingHandler = null;
sangho27462c62015-05-14 00:39:53 -0700172 private TunnelHandler tunnelHandler = null;
173 private PolicyHandler policyHandler = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700174 private InternalPacketProcessor processor = null;
175 private InternalLinkListener linkListener = null;
176 private InternalDeviceListener deviceListener = null;
Charles Chan82f19972016-05-17 13:13:55 -0700177 private AppConfigHandler appCfgHandler = null;
Charles Chandebfea32016-10-24 14:52:01 -0700178 XConnectHandler xConnectHandler = null;
Charles Chan1eaf4802016-04-18 13:44:03 -0700179 private McastHandler mcastHandler = null;
Charles Chandebfea32016-10-24 14:52:01 -0700180 HostHandler hostHandler = null;
Charles Chan41f5ec02016-06-13 18:54:31 -0700181 private CordConfigHandler cordConfigHandler = null;
Charles Chandebfea32016-10-24 14:52:01 -0700182 RouteHandler routeHandler = null;
sangho80f11cb2015-04-01 13:05:26 -0700183 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan82ab1932016-01-30 23:22:37 -0800184 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chanc91c8782016-03-30 17:54:24 -0700185 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
186 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan41f5ec02016-06-13 18:54:31 -0700187 private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
Charles Chandebfea32016-10-24 14:52:01 -0700188 private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
sangho80f11cb2015-04-01 13:05:26 -0700189
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700190 private ScheduledExecutorService executorService = Executors
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700191 .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
sangho80f11cb2015-04-01 13:05:26 -0700192
Saurav Das2d94d312015-11-24 23:21:05 -0800193 @SuppressWarnings("unused")
sangho80f11cb2015-04-01 13:05:26 -0700194 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das2d94d312015-11-24 23:21:05 -0800195 @SuppressWarnings("rawtypes")
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700196 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
Charles Chanf4586112015-11-09 16:37:23 -0800197 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chanb7f75ac2016-01-11 18:28:54 -0800198 new ConcurrentHashMap<>();
199 /**
200 * Per device next objective ID store with (device id + neighbor set) as key.
201 */
202 public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
Charles Chanf4586112015-11-09 16:37:23 -0800203 nsNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800204 /**
205 * Per device next objective ID store with (device id + subnet) as key.
206 */
207 public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
Charles Chanf4586112015-11-09 16:37:23 -0800208 subnetNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800209 /**
210 * Per device next objective ID store with (device id + port) as key.
211 */
212 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das2d94d312015-11-24 23:21:05 -0800213 portNextObjStore = null;
Saurav Das7c305372015-10-28 12:39:42 -0700214 // Per device, per-subnet assigned-vlans store, with (device id + subnet
215 // IPv4 prefix) as key
216 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
Charles Chanb7f75ac2016-01-11 18:28:54 -0800217 subnetVidStore = null;
Saurav Das2d94d312015-11-24 23:21:05 -0800218 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
219 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho4a5c42a2015-05-20 22:16:38 -0700220
Charles Chanc91c8782016-03-30 17:54:24 -0700221 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700222 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
223 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700224 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chan72f556a2015-10-05 17:50:33 -0700225 @Override
Charles Chan82ab1932016-01-30 23:22:37 -0800226 public SegmentRoutingDeviceConfig createConfig() {
227 return new SegmentRoutingDeviceConfig();
Charles Chan72f556a2015-10-05 17:50:33 -0700228 }
229 };
Charles Chanc91c8782016-03-30 17:54:24 -0700230 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700231 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
232 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700233 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan82ab1932016-01-30 23:22:37 -0800234 @Override
235 public SegmentRoutingAppConfig createConfig() {
236 return new SegmentRoutingAppConfig();
237 }
238 };
Charles Chan82f19972016-05-17 13:13:55 -0700239 private final ConfigFactory<ApplicationId, XConnectConfig> xConnectConfigFactory =
240 new ConfigFactory<ApplicationId, XConnectConfig>(
241 SubjectFactories.APP_SUBJECT_FACTORY,
242 XConnectConfig.class, "xconnect") {
243 @Override
244 public XConnectConfig createConfig() {
245 return new XConnectConfig();
246 }
247 };
Charles Chanc91c8782016-03-30 17:54:24 -0700248 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700249 new ConfigFactory<ApplicationId, McastConfig>(
250 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700251 McastConfig.class, "multicast") {
252 @Override
253 public McastConfig createConfig() {
254 return new McastConfig();
255 }
256 };
257
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700258 private Object threadSchedulerLock = new Object();
259 private static int numOfEventsQueued = 0;
260 private static int numOfEventsExecuted = 0;
sangho80f11cb2015-04-01 13:05:26 -0700261 private static int numOfHandlerExecution = 0;
262 private static int numOfHandlerScheduled = 0;
263
Charles Chan1963f4f2016-02-18 14:22:42 -0800264 /**
265 * Segment Routing App ID.
266 */
Charles Chan46fdfaf2016-11-09 20:51:44 -0800267 public static final String APP_NAME = "org.onosproject.segmentrouting";
Charles Chanb7f75ac2016-01-11 18:28:54 -0800268 /**
269 * The starting value of per-subnet VLAN ID assignment.
270 */
Saurav Das7c305372015-10-28 12:39:42 -0700271 private static final short ASSIGNED_VLAN_START = 4093;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800272 /**
273 * The default VLAN ID assigned to the interfaces without subnet config.
274 */
Saurav Das7c305372015-10-28 12:39:42 -0700275 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
276
sangho80f11cb2015-04-01 13:05:26 -0700277 @Activate
278 protected void activate() {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800279 appId = coreService.registerApplication(APP_NAME);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700280
281 log.debug("Creating EC map nsnextobjectivestore");
282 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
283 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700284 nsNextObjStore = nsNextObjMapBuilder
285 .withName("nsnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700286 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700287 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700288 .build();
289 log.trace("Current size {}", nsNextObjStore.size());
290
Charles Chan77277672015-10-20 16:24:19 -0700291 log.debug("Creating EC map subnetnextobjectivestore");
292 EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
293 subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Charles Chan77277672015-10-20 16:24:19 -0700294 subnetNextObjStore = subnetNextObjMapBuilder
295 .withName("subnetnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700296 .withSerializer(createSerializer())
Charles Chan77277672015-10-20 16:24:19 -0700297 .withTimestampProvider((k, v) -> new WallClockTimestamp())
298 .build();
299
Saurav Das2d94d312015-11-24 23:21:05 -0800300 log.debug("Creating EC map subnetnextobjectivestore");
301 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
302 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
303 portNextObjStore = portNextObjMapBuilder
304 .withName("portnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700305 .withSerializer(createSerializer())
Saurav Das2d94d312015-11-24 23:21:05 -0800306 .withTimestampProvider((k, v) -> new WallClockTimestamp())
307 .build();
308
sangho4a5c42a2015-05-20 22:16:38 -0700309 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
310 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700311 tunnelStore = tunnelMapBuilder
312 .withName("tunnelstore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700313 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700314 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700315 .build();
316
317 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
318 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700319 policyStore = policyMapBuilder
320 .withName("policystore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700321 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700322 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700323 .build();
324
Saurav Das7c305372015-10-28 12:39:42 -0700325 EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
326 subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
Saurav Das7c305372015-10-28 12:39:42 -0700327 subnetVidStore = subnetVidStoreMapBuilder
328 .withName("subnetvidstore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700329 .withSerializer(createSerializer())
Saurav Das7c305372015-10-28 12:39:42 -0700330 .withTimestampProvider((k, v) -> new WallClockTimestamp())
331 .build();
332
Saurav Dasc3604f12016-03-23 11:22:49 -0700333 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
Pier Luigib9632ba2017-01-12 18:14:58 -0800334 "purgeOnDisconnection", "true");
Saurav Dasc3604f12016-03-23 11:22:49 -0700335 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
Pier Luigib9632ba2017-01-12 18:14:58 -0800336 "purgeOnDisconnection", "true");
Charles Chandebfea32016-10-24 14:52:01 -0700337 compCfgService.preSetProperty("org.onosproject.vrouter.Vrouter",
Charles Chan5c7bf022017-01-18 20:00:13 -0800338 "fibInstallerEnabled", "false");
Pier Luigib9632ba2017-01-12 18:14:58 -0800339 compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
340 "requestInterceptsEnabled", "false");
Pier Luigibc976df2017-01-12 22:46:39 -0800341 compCfgService.preSetProperty("org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager",
342 "requestInterceptsEnabled", "false");
343 compCfgService.preSetProperty("org.onosproject.dhcprelay.DhcpRelay",
344 "arpEnabled", "false");
Saurav Dasc3604f12016-03-23 11:22:49 -0700345
Charles Chan2b078ae2015-10-14 11:24:40 -0700346 processor = new InternalPacketProcessor();
347 linkListener = new InternalLinkListener();
348 deviceListener = new InternalDeviceListener();
Charles Chan82f19972016-05-17 13:13:55 -0700349 appCfgHandler = new AppConfigHandler(this);
350 xConnectHandler = new XConnectHandler(this);
Charles Chan1eaf4802016-04-18 13:44:03 -0700351 mcastHandler = new McastHandler(this);
352 hostHandler = new HostHandler(this);
Charles Chan41f5ec02016-06-13 18:54:31 -0700353 cordConfigHandler = new CordConfigHandler(this);
Charles Chandebfea32016-10-24 14:52:01 -0700354 routeHandler = new RouteHandler(this);
Charles Chan2b078ae2015-10-14 11:24:40 -0700355
Charles Chand6d25332016-02-26 22:19:52 -0800356 cfgService.addListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700357 cfgService.registerConfigFactory(deviceConfigFactory);
358 cfgService.registerConfigFactory(appConfigFactory);
Charles Chan82f19972016-05-17 13:13:55 -0700359 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chanc91c8782016-03-30 17:54:24 -0700360 cfgService.registerConfigFactory(mcastConfigFactory);
Charles Chan82ab1932016-01-30 23:22:37 -0800361 hostService.addListener(hostListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700362 packetService.addProcessor(processor, PacketProcessor.director(2));
363 linkService.addListener(linkListener);
364 deviceService.addListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700365 multicastRouteService.addListener(mcastListener);
Charles Chan41f5ec02016-06-13 18:54:31 -0700366 cordConfigService.addListener(cordConfigListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700367
368 cfgListener.configureNetwork();
369
Charles Chandebfea32016-10-24 14:52:01 -0700370 routeService.addListener(routeListener);
371
sangho80f11cb2015-04-01 13:05:26 -0700372 log.info("Started");
373 }
374
Jonathan Hart54541d12016-04-12 15:39:44 -0700375 private KryoNamespace.Builder createSerializer() {
376 return new KryoNamespace.Builder()
377 .register(KryoNamespaces.API)
378 .register(NeighborSetNextObjectiveStoreKey.class,
379 SubnetNextObjectiveStoreKey.class,
380 SubnetAssignedVidStoreKey.class,
381 NeighborSet.class,
382 Tunnel.class,
383 DefaultTunnel.class,
384 Policy.class,
385 TunnelPolicy.class,
386 Policy.Type.class,
387 PortNextObjectiveStoreKey.class,
Charles Chan82f19972016-05-17 13:13:55 -0700388 XConnectStoreKey.class
Jonathan Hart54541d12016-04-12 15:39:44 -0700389 );
390 }
391
sangho80f11cb2015-04-01 13:05:26 -0700392 @Deactivate
393 protected void deactivate() {
Charles Chan72f556a2015-10-05 17:50:33 -0700394 cfgService.removeListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700395 cfgService.unregisterConfigFactory(deviceConfigFactory);
396 cfgService.unregisterConfigFactory(appConfigFactory);
Charles Chandebfea32016-10-24 14:52:01 -0700397 cfgService.unregisterConfigFactory(xConnectConfigFactory);
Charles Chanc91c8782016-03-30 17:54:24 -0700398 cfgService.unregisterConfigFactory(mcastConfigFactory);
Charles Chan72f556a2015-10-05 17:50:33 -0700399
sangho80f11cb2015-04-01 13:05:26 -0700400 packetService.removeProcessor(processor);
Charles Chan2b078ae2015-10-14 11:24:40 -0700401 linkService.removeListener(linkListener);
402 deviceService.removeListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700403 multicastRouteService.removeListener(mcastListener);
Charles Chan41f5ec02016-06-13 18:54:31 -0700404 cordConfigService.removeListener(cordConfigListener);
Charles Chandebfea32016-10-24 14:52:01 -0700405 routeService.removeListener(routeListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700406
sangho80f11cb2015-04-01 13:05:26 -0700407 processor = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700408 linkListener = null;
Charles Chanc91c8782016-03-30 17:54:24 -0700409 deviceListener = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700410 groupHandlerMap.clear();
411
Charles Chanc91c8782016-03-30 17:54:24 -0700412 nsNextObjStore.destroy();
413 subnetNextObjStore.destroy();
414 portNextObjStore.destroy();
Charles Chanc91c8782016-03-30 17:54:24 -0700415 tunnelStore.destroy();
416 policyStore.destroy();
417 subnetVidStore.destroy();
sangho80f11cb2015-04-01 13:05:26 -0700418 log.info("Stopped");
419 }
420
sangho27462c62015-05-14 00:39:53 -0700421 @Override
422 public List<Tunnel> getTunnels() {
423 return tunnelHandler.getTunnels();
424 }
425
426 @Override
sanghobd812f82015-06-29 14:58:47 -0700427 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
428 return tunnelHandler.createTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700429 }
430
431 @Override
sanghobd812f82015-06-29 14:58:47 -0700432 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho27462c62015-05-14 00:39:53 -0700433 for (Policy policy: policyHandler.getPolicies()) {
434 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
435 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
436 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
437 log.warn("Cannot remove the tunnel used by a policy");
sanghobd812f82015-06-29 14:58:47 -0700438 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho27462c62015-05-14 00:39:53 -0700439 }
440 }
441 }
sanghobd812f82015-06-29 14:58:47 -0700442 return tunnelHandler.removeTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700443 }
444
445 @Override
sanghobd812f82015-06-29 14:58:47 -0700446 public PolicyHandler.Result removePolicy(Policy policy) {
447 return policyHandler.removePolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700448 }
449
450 @Override
sanghobd812f82015-06-29 14:58:47 -0700451 public PolicyHandler.Result createPolicy(Policy policy) {
452 return policyHandler.createPolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700453 }
454
455 @Override
456 public List<Policy> getPolicies() {
457 return policyHandler.getPolicies();
458 }
459
Saurav Das07c74602016-04-27 18:35:50 -0700460 @Override
461 public void rerouteNetwork() {
462 cfgListener.configureNetwork();
463 for (Device device : deviceService.getDevices()) {
464 defaultRoutingHandler.populatePortAddressingRules(device.id());
465 }
466 defaultRoutingHandler.startPopulationProcess();
467 }
468
Charles Chand7844e52016-10-20 17:02:44 -0700469 @Override
470 public Map<DeviceId, Set<Ip4Prefix>> getDeviceSubnetMap() {
471 Map<DeviceId, Set<Ip4Prefix>> deviceSubnetMap = Maps.newHashMap();
472 deviceService.getAvailableDevices().forEach(device -> {
473 deviceSubnetMap.put(device.id(), deviceConfiguration.getSubnets(device.id()));
474 });
475 return deviceSubnetMap;
476 }
477
sangho80f1f892015-05-19 11:57:42 -0700478 /**
Pier Ventre7a78de22016-10-31 15:00:01 -0700479 * Returns the MPLS-ECMP configuration.
480 *
481 * @return MPLS-ECMP value
482 */
483 public boolean getMplsEcmp() {
484 SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
485 .getConfig(this.appId, SegmentRoutingAppConfig.class);
486 return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
487 }
488
489 /**
sangho80f1f892015-05-19 11:57:42 -0700490 * Returns the tunnel object with the tunnel ID.
491 *
492 * @param tunnelId Tunnel ID
493 * @return Tunnel reference
494 */
sangho27462c62015-05-14 00:39:53 -0700495 public Tunnel getTunnel(String tunnelId) {
496 return tunnelHandler.getTunnel(tunnelId);
497 }
498
sangho80f11cb2015-04-01 13:05:26 -0700499 /**
Saurav Das7c305372015-10-28 12:39:42 -0700500 * Returns the vlan-id assigned to the subnet configured for a device.
501 * If no vlan-id has been assigned, a new one is assigned out of a pool of ids,
502 * if and only if this controller instance is the master for the device.
503 * <p>
504 * USAGE: The assigned vlans are meant to be applied to untagged packets on those
505 * switches/pipelines that need this functionality. These vids are meant
506 * to be used internally within a switch, and thus need to be unique only
507 * on a switch level. Note that packets never go out on the wire with these
508 * vlans. Currently, vlan ids are assigned from value 4093 down.
509 * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
510 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
511 * per subnet.
sangho80f11cb2015-04-01 13:05:26 -0700512 *
Saurav Das7c305372015-10-28 12:39:42 -0700513 * @param deviceId switch dpid
514 * @param subnet IPv4 prefix for which assigned vlan is desired
515 * @return VlanId assigned for the subnet on the device, or
516 * null if no vlan assignment was found and this instance is not
517 * the master for the device.
sangho80f11cb2015-04-01 13:05:26 -0700518 */
Charles Chanb7f75ac2016-01-11 18:28:54 -0800519 // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
Saurav Das7c305372015-10-28 12:39:42 -0700520 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
521 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
522 deviceId, subnet));
523 if (assignedVid != null) {
524 log.debug("Query for subnet:{} on device:{} returned assigned-vlan "
525 + "{}", subnet, deviceId, assignedVid);
526 return assignedVid;
527 }
528 //check mastership for the right to assign a vlan
529 if (!mastershipService.isLocalMaster(deviceId)) {
530 log.warn("This controller instance is not the master for device {}. "
531 + "Cannot assign vlan-id for subnet {}", deviceId, subnet);
532 return null;
533 }
534 // vlan assignment is expensive but done only once
Charles Chanc6ad7752015-10-29 14:58:10 -0700535 Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId);
Saurav Das7c305372015-10-28 12:39:42 -0700536 Set<Short> assignedVlans = new HashSet<>();
537 Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
538 for (Ip4Prefix sub : configuredSubnets) {
539 VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId,
540 sub));
541 if (v != null) {
542 assignedVlans.add(v.toShort());
543 } else {
544 unassignedSubnets.add(sub);
545 }
546 }
547 short nextAssignedVlan = ASSIGNED_VLAN_START;
548 if (!assignedVlans.isEmpty()) {
549 nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1);
550 }
551 for (Ip4Prefix unsub : unassignedSubnets) {
Charles Chan82ab1932016-01-30 23:22:37 -0800552 // Special case for default route. Assign default VLAN ID to /32 and /0 subnets
553 if (unsub.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
554 unsub.prefixLength() == 0) {
555 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
556 VlanId.vlanId(ASSIGNED_VLAN_NO_SUBNET));
557 } else {
558 subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
559 VlanId.vlanId(nextAssignedVlan--));
560 log.info("Assigned vlan: {} to subnet: {} on device: {}",
561 nextAssignedVlan + 1, unsub, deviceId);
562 }
sangho80f11cb2015-04-01 13:05:26 -0700563 }
564
Saurav Das7c305372015-10-28 12:39:42 -0700565 return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
sangho80f11cb2015-04-01 13:05:26 -0700566 }
567
sangho27462c62015-05-14 00:39:53 -0700568 /**
Saurav Das7c305372015-10-28 12:39:42 -0700569 * Returns the next objective ID for the given NeighborSet.
Saurav Das4c35fc42015-11-20 15:27:53 -0800570 * If the nextObjective does not exist, a new one is created and
Saurav Das2d94d312015-11-24 23:21:05 -0800571 * its id is returned.
sangho27462c62015-05-14 00:39:53 -0700572 *
sangho80f1f892015-05-19 11:57:42 -0700573 * @param deviceId Device ID
574 * @param ns NegighborSet
Saurav Das4c35fc42015-11-20 15:27:53 -0800575 * @param meta metadata passed into the creation of a Next Objective
576 * @return next objective ID or -1 if an error was encountered during the
577 * creation of the nextObjective
sangho27462c62015-05-14 00:39:53 -0700578 */
Saurav Das4c35fc42015-11-20 15:27:53 -0800579 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
580 TrafficSelector meta) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700581 if (groupHandlerMap.get(deviceId) != null) {
582 log.trace("getNextObjectiveId query in device {}", deviceId);
583 return groupHandlerMap
Saurav Das4c35fc42015-11-20 15:27:53 -0800584 .get(deviceId).getNextObjectiveId(ns, meta);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700585 } else {
Saurav Das2d94d312015-11-24 23:21:05 -0800586 log.warn("getNextObjectiveId query - groupHandler for device {} "
587 + "not found", deviceId);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700588 return -1;
589 }
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700590 }
591
Charles Chan77277672015-10-20 16:24:19 -0700592 /**
Saurav Das2d94d312015-11-24 23:21:05 -0800593 * Returns the next objective ID for the given subnet prefix. It is expected
594 * that the next-objective has been pre-created from configuration.
Charles Chan77277672015-10-20 16:24:19 -0700595 *
596 * @param deviceId Device ID
597 * @param prefix Subnet
Saurav Das2d94d312015-11-24 23:21:05 -0800598 * @return next objective ID or -1 if it was not found
Charles Chan77277672015-10-20 16:24:19 -0700599 */
600 public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
601 if (groupHandlerMap.get(deviceId) != null) {
602 log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
603 return groupHandlerMap
604 .get(deviceId).getSubnetNextObjectiveId(prefix);
605 } else {
Saurav Das2d94d312015-11-24 23:21:05 -0800606 log.warn("getSubnetNextObjectiveId query - groupHandler for "
607 + "device {} not found", deviceId);
608 return -1;
609 }
610 }
611
612 /**
613 * Returns the next objective ID for the given portNumber, given the treatment.
614 * There could be multiple different treatments to the same outport, which
615 * would result in different objectives. If the next object
616 * does not exist, a new one is created and its id is returned.
617 *
618 * @param deviceId Device ID
619 * @param portNum port number on device for which NextObjective is queried
620 * @param treatment the actions to apply on the packets (should include outport)
621 * @param meta metadata passed into the creation of a Next Objective if necessary
Saurav Das07c74602016-04-27 18:35:50 -0700622 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das2d94d312015-11-24 23:21:05 -0800623 */
624 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
625 TrafficTreatment treatment,
626 TrafficSelector meta) {
627 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
628 if (ghdlr != null) {
629 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
630 } else {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800631 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
632 + " not found", deviceId);
633 return -1;
634 }
635 }
636
sangho80f11cb2015-04-01 13:05:26 -0700637 private class InternalPacketProcessor implements PacketProcessor {
sangho80f11cb2015-04-01 13:05:26 -0700638 @Override
639 public void process(PacketContext context) {
640
641 if (context.isHandled()) {
642 return;
643 }
644
645 InboundPacket pkt = context.inPacket();
646 Ethernet ethernet = pkt.parsed();
Saurav Das2d94d312015-11-24 23:21:05 -0800647 log.trace("Rcvd pktin: {}", ethernet);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800648 if (ethernet.getEtherType() == TYPE_ARP) {
sangho80f11cb2015-04-01 13:05:26 -0700649 arpHandler.processPacketIn(pkt);
650 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
651 IPv4 ipPacket = (IPv4) ethernet.getPayload();
Charles Chand041ad82017-01-13 17:20:44 -0800652 // ipHandler.addToPacketBuffer(ipPacket);
sangho80f11cb2015-04-01 13:05:26 -0700653 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
654 icmpHandler.processPacketIn(pkt);
655 } else {
Charles Chand041ad82017-01-13 17:20:44 -0800656 // NOTE: We don't support IP learning at this moment so this
657 // is not necessary. Also it causes duplication of DHCP packets.
658 // ipHandler.processPacketIn(pkt);
sangho80f11cb2015-04-01 13:05:26 -0700659 }
660 }
661 }
662 }
663
664 private class InternalLinkListener implements LinkListener {
665 @Override
666 public void event(LinkEvent event) {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700667 if (event.type() == LinkEvent.Type.LINK_ADDED
668 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700669 log.debug("Event {} received from Link Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700670 scheduleEventHandlerIfNotScheduled(event);
671 }
672 }
673 }
674
675 private class InternalDeviceListener implements DeviceListener {
sangho80f11cb2015-04-01 13:05:26 -0700676 @Override
677 public void event(DeviceEvent event) {
sangho80f11cb2015-04-01 13:05:26 -0700678 switch (event.type()) {
679 case DEVICE_ADDED:
Saurav Dasf0f592d2016-11-18 15:21:57 -0800680 case PORT_UPDATED:
681 case PORT_ADDED:
sanghofb7c7292015-04-13 15:15:58 -0700682 case DEVICE_UPDATED:
683 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700684 log.debug("Event {} received from Device Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700685 scheduleEventHandlerIfNotScheduled(event);
686 break;
687 default:
688 }
689 }
690 }
691
Saurav Das2d94d312015-11-24 23:21:05 -0800692 @SuppressWarnings("rawtypes")
sangho80f11cb2015-04-01 13:05:26 -0700693 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700694 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700695 eventQueue.add(event);
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700696 numOfEventsQueued++;
697
698 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
699 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700700 eventHandlerFuture = executorService
701 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
702 numOfHandlerScheduled++;
703 }
Jonathan Hart54541d12016-04-12 15:39:44 -0700704 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700705 numOfEventsQueued,
706 numOfHandlerScheduled);
sangho80f11cb2015-04-01 13:05:26 -0700707 }
sangho80f11cb2015-04-01 13:05:26 -0700708 }
709
710 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700711 @Override
sangho80f11cb2015-04-01 13:05:26 -0700712 public void run() {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700713 try {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700714 while (true) {
Saurav Das2d94d312015-11-24 23:21:05 -0800715 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700716 Event event = null;
717 synchronized (threadSchedulerLock) {
718 if (!eventQueue.isEmpty()) {
719 event = eventQueue.poll();
720 numOfEventsExecuted++;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700721 } else {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700722 numOfHandlerExecution++;
723 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
724 numOfHandlerExecution, numOfEventsExecuted);
725 break;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700726 }
sanghofb7c7292015-04-13 15:15:58 -0700727 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700728 if (event.type() == LinkEvent.Type.LINK_ADDED) {
729 processLinkAdded((Link) event.subject());
730 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
Pier Ventre6d593892016-09-13 21:33:40 -0700731 Link linkRemoved = (Link) event.subject();
732 if (linkRemoved.src().elementId() instanceof DeviceId &&
733 !deviceService.isAvailable(linkRemoved.src().deviceId())) {
734 continue;
735 }
736 if (linkRemoved.dst().elementId() instanceof DeviceId &&
737 !deviceService.isAvailable(linkRemoved.dst().deviceId())) {
738 continue;
739 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700740 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700741 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
742 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
743 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das62af8802015-12-04 10:52:59 -0800744 DeviceId deviceId = ((Device) event.subject()).id();
745 if (deviceService.isAvailable(deviceId)) {
Saurav Dasc28b3432015-10-30 17:45:38 -0700746 log.info("Processing device event {} for available device {}",
747 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700748 processDeviceAdded((Device) event.subject());
Saurav Dasc3604f12016-03-23 11:22:49 -0700749 } else {
750 log.info("Processing device event {} for unavailable device {}",
751 event.type(), ((Device) event.subject()).id());
752 processDeviceRemoved((Device) event.subject());
753 }
Saurav Dasf0f592d2016-11-18 15:21:57 -0800754 } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
Saurav Dasd1872b02016-12-02 15:43:47 -0800755 // typically these calls come when device is added first time
756 // so port filtering rules are handled at the device_added event.
757 // port added calls represent all ports on the device,
758 // enabled or not.
Saurav Dasf0f592d2016-11-18 15:21:57 -0800759 log.debug("** PORT ADDED {}/{} -> {}",
Saurav Dasd1872b02016-12-02 15:43:47 -0800760 ((DeviceEvent) event).subject().id(),
761 ((DeviceEvent) event).port().number(),
762 event.type());
Saurav Dasf0f592d2016-11-18 15:21:57 -0800763 } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
Saurav Dasd1872b02016-12-02 15:43:47 -0800764 // these calls happen for every subsequent event
765 // ports enabled, disabled, switch goes away, comes back
Saurav Dasf0f592d2016-11-18 15:21:57 -0800766 log.info("** PORT UPDATED {}/{} -> {}",
767 event.subject(),
768 ((DeviceEvent) event).port(),
769 event.type());
770 processPortUpdated(((Device) event.subject()),
771 ((DeviceEvent) event).port());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700772 } else {
773 log.warn("Unhandled event type: {}", event.type());
774 }
sangho80f11cb2015-04-01 13:05:26 -0700775 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700776 } catch (Exception e) {
777 log.error("SegmentRouting event handler "
778 + "thread thrown an exception: {}", e);
sangho80f11cb2015-04-01 13:05:26 -0700779 }
sangho80f11cb2015-04-01 13:05:26 -0700780 }
781 }
782
sangho80f11cb2015-04-01 13:05:26 -0700783 private void processLinkAdded(Link link) {
Saurav Dasb149be12016-06-07 10:08:06 -0700784 log.info("** LINK ADDED {}", link.toString());
Charles Chan319d1a22015-11-03 10:42:14 -0800785 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
786 log.warn("Source device of this link is not configured.");
787 return;
788 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700789 //Irrespective whether the local is a MASTER or not for this device,
790 //create group handler instance and push default TTP flow rules.
791 //Because in a multi-instance setup, instances can initiate
792 //groups for any devices. Also the default TTP rules are needed
793 //to be pushed before inserting any IP table entries for any device
794 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
795 .deviceId());
796 if (groupHandler != null) {
Saurav Das4c35fc42015-11-20 15:27:53 -0800797 groupHandler.linkUp(link, mastershipService.isLocalMaster(
798 link.src().deviceId()));
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700799 } else {
800 Device device = deviceService.getDevice(link.src().deviceId());
801 if (device != null) {
802 log.warn("processLinkAdded: Link Added "
803 + "Notification without Device Added "
804 + "event, still handling it");
805 processDeviceAdded(device);
806 groupHandler = groupHandlerMap.get(link.src()
807 .deviceId());
Saurav Das4c35fc42015-11-20 15:27:53 -0800808 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sangho80f11cb2015-04-01 13:05:26 -0700809 }
810 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700811
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700812 log.trace("Starting optimized route population process");
813 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
814 //log.trace("processLinkAdded: re-starting route population process");
815 //defaultRoutingHandler.startPopulationProcess();
Charles Chan72779502016-04-23 17:36:10 -0700816
817 mcastHandler.init();
sangho80f11cb2015-04-01 13:05:26 -0700818 }
819
820 private void processLinkRemoved(Link link) {
Saurav Dasb149be12016-06-07 10:08:06 -0700821 log.info("** LINK REMOVED {}", link.toString());
sangho2165d222015-05-01 09:38:25 -0700822 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
823 if (groupHandler != null) {
Saurav Das62af8802015-12-04 10:52:59 -0800824 groupHandler.portDown(link.src().port(),
825 mastershipService.isLocalMaster(link.src().deviceId()));
sangho2165d222015-05-01 09:38:25 -0700826 }
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700827 log.trace("Starting optimized route population process");
828 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
829 //log.trace("processLinkRemoved: re-starting route population process");
830 //defaultRoutingHandler.startPopulationProcess();
Charles Chan72779502016-04-23 17:36:10 -0700831
832 mcastHandler.processLinkDown(link);
sangho80f11cb2015-04-01 13:05:26 -0700833 }
834
835 private void processDeviceAdded(Device device) {
Saurav Dasb149be12016-06-07 10:08:06 -0700836 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan319d1a22015-11-03 10:42:14 -0800837 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das8ec0ec42015-11-03 14:39:27 -0800838 log.warn("Device configuration uploading. Device {} will be "
839 + "processed after config completes.", device.id());
840 return;
841 }
Charles Chan72779502016-04-23 17:36:10 -0700842 processDeviceAddedInternal(device.id());
843 }
844
845 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Dasc28b3432015-10-30 17:45:38 -0700846 // Irrespective of whether the local is a MASTER or not for this device,
847 // we need to create a SR-group-handler instance. This is because in a
848 // multi-instance setup, any instance can initiate forwarding/next-objectives
849 // for any switch (even if this instance is a SLAVE or not even connected
850 // to the switch). To handle this, a default-group-handler instance is necessary
851 // per switch.
Charles Chan72779502016-04-23 17:36:10 -0700852 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
853 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan319d1a22015-11-03 10:42:14 -0800854 DefaultGroupHandler groupHandler;
855 try {
856 groupHandler = DefaultGroupHandler.
Charles Chan72779502016-04-23 17:36:10 -0700857 createGroupHandler(deviceId,
858 appId,
859 deviceConfiguration,
860 linkService,
861 flowObjectiveService,
862 this);
Charles Chan319d1a22015-11-03 10:42:14 -0800863 } catch (DeviceConfigNotFoundException e) {
864 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
865 return;
866 }
Charles Chan72779502016-04-23 17:36:10 -0700867 log.debug("updating groupHandlerMap with new config for device: {}",
868 deviceId);
869 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das8ec0ec42015-11-03 14:39:27 -0800870 }
Saurav Dasb149be12016-06-07 10:08:06 -0700871 // Also, in some cases, drivers may need extra
872 // information to process rules (eg. Router IP/MAC); and so, we send
873 // port addressing rules to the driver as well irrespective of whether
874 // this instance is the master or not.
875 defaultRoutingHandler.populatePortAddressingRules(deviceId);
876
Charles Chan72779502016-04-23 17:36:10 -0700877 if (mastershipService.isLocalMaster(deviceId)) {
Charles Chandebfea32016-10-24 14:52:01 -0700878 hostHandler.init(deviceId);
Charles Chan82f19972016-05-17 13:13:55 -0700879 xConnectHandler.init(deviceId);
Charles Chan41f5ec02016-06-13 18:54:31 -0700880 cordConfigHandler.init(deviceId);
Charles Chan72779502016-04-23 17:36:10 -0700881 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chan77277672015-10-20 16:24:19 -0700882 groupHandler.createGroupsFromSubnetConfig();
Charles Chan72779502016-04-23 17:36:10 -0700883 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chan77277672015-10-20 16:24:19 -0700884 }
Charles Chan82ab1932016-01-30 23:22:37 -0800885
Charles Chandebfea32016-10-24 14:52:01 -0700886 appCfgHandler.init(deviceId);
887 routeHandler.init(deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700888 }
889
Saurav Dasc3604f12016-03-23 11:22:49 -0700890 private void processDeviceRemoved(Device device) {
891 nsNextObjStore.entrySet().stream()
892 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
893 .forEach(entry -> {
894 nsNextObjStore.remove(entry.getKey());
895 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700896 subnetNextObjStore.entrySet().stream()
897 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
898 .forEach(entry -> {
899 subnetNextObjStore.remove(entry.getKey());
900 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700901 portNextObjStore.entrySet().stream()
902 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
903 .forEach(entry -> {
904 portNextObjStore.remove(entry.getKey());
905 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700906 subnetVidStore.entrySet().stream()
907 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
908 .forEach(entry -> {
909 subnetVidStore.remove(entry.getKey());
910 });
Saurav Dasc3604f12016-03-23 11:22:49 -0700911 groupHandlerMap.remove(device.id());
Saurav Dasc3604f12016-03-23 11:22:49 -0700912 defaultRoutingHandler.purgeEcmpGraph(device.id());
Charles Chan72779502016-04-23 17:36:10 -0700913 mcastHandler.removeDevice(device.id());
Charles Chan82f19972016-05-17 13:13:55 -0700914 xConnectHandler.removeDevice(device.id());
Saurav Dasc3604f12016-03-23 11:22:49 -0700915 }
916
Saurav Dasf0f592d2016-11-18 15:21:57 -0800917 private void processPortUpdated(Device device, Port port) {
918 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
919 log.warn("Device configuration uploading. Not handling port event for"
920 + "dev: {} port: {}", device.id(), port.number());
921 return;
922 }
923 /* XXX create method for single port filtering rules which are needed
924 for both switch-to-switch ports and edge ports
925 if (defaultRoutingHandler != null) {
926 defaultRoutingHandler.populatePortAddressingRules(
927 ((Device) event.subject()).id());
928 }*/
929
930 // portUpdated calls are for ports that have gone down or up. For switch
931 // to switch ports, link-events should take care of any re-routing or
932 // group editing necessary for port up/down. Here we only process edge ports
933 // that are already configured.
934 Ip4Prefix configuredSubnet = deviceConfiguration.getPortSubnet(device.id(),
935 port.number());
936 if (configuredSubnet == null) {
937 log.debug("Not handling port updated event for unconfigured port "
938 + "dev/port: {}/{}", device.id(), port.number());
939 return;
940 }
941 processEdgePort(device, port, configuredSubnet);
942 }
943
944 private void processEdgePort(Device device, Port port, Ip4Prefix subnet) {
945 boolean portUp = port.isEnabled();
946 if (portUp) {
947 log.info("Device:EdgePort {}:{} is enabled in subnet: {}", device.id(),
948 port.number(), subnet);
949 } else {
950 log.info("Device:EdgePort {}:{} is disabled in subnet: {}", device.id(),
951 port.number(), subnet);
952 }
953
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700954 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sangho80f11cb2015-04-01 13:05:26 -0700955 if (groupHandler != null) {
Saurav Dasf0f592d2016-11-18 15:21:57 -0800956 groupHandler.processEdgePort(port.number(), subnet, portUp,
Saurav Das62af8802015-12-04 10:52:59 -0800957 mastershipService.isLocalMaster(device.id()));
Saurav Dasf0f592d2016-11-18 15:21:57 -0800958 } else {
959 log.warn("Group handler not found for dev:{}. Not handling edge port"
960 + " {} event for port:{}", device.id(),
961 (portUp) ? "UP" : "DOWN", port.number());
sangho80f11cb2015-04-01 13:05:26 -0700962 }
963 }
sangho27462c62015-05-14 00:39:53 -0700964
Charles Chan72f556a2015-10-05 17:50:33 -0700965 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800966 SegmentRoutingManager srManager;
Charles Chane7c61022015-10-07 14:21:45 -0700967
Charles Chanb7f75ac2016-01-11 18:28:54 -0800968 /**
969 * Constructs the internal network config listener.
970 *
Charles Chan46fdfaf2016-11-09 20:51:44 -0800971 * @param srManager segment routing manager
Charles Chanb7f75ac2016-01-11 18:28:54 -0800972 */
Charles Chan46fdfaf2016-11-09 20:51:44 -0800973 public InternalConfigListener(SegmentRoutingManager srManager) {
974 this.srManager = srManager;
Charles Chane7c61022015-10-07 14:21:45 -0700975 }
976
Charles Chanb7f75ac2016-01-11 18:28:54 -0800977 /**
978 * Reads network config and initializes related data structure accordingly.
979 */
Charles Chane7c61022015-10-07 14:21:45 -0700980 public void configureNetwork() {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800981 deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chane7c61022015-10-07 14:21:45 -0700982
Charles Chan46fdfaf2016-11-09 20:51:44 -0800983 arpHandler = new ArpHandler(srManager);
984 icmpHandler = new IcmpHandler(srManager);
985 ipHandler = new IpHandler(srManager);
986 routingRulePopulator = new RoutingRulePopulator(srManager);
987 defaultRoutingHandler = new DefaultRoutingHandler(srManager);
Charles Chane7c61022015-10-07 14:21:45 -0700988
989 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
990 groupHandlerMap, tunnelStore);
991 policyHandler = new PolicyHandler(appId, deviceConfiguration,
992 flowObjectiveService,
993 tunnelHandler, policyStore);
994
Charles Chane7c61022015-10-07 14:21:45 -0700995 for (Device device : deviceService.getDevices()) {
Charles Chan72779502016-04-23 17:36:10 -0700996 processDeviceAddedInternal(device.id());
Charles Chane7c61022015-10-07 14:21:45 -0700997 }
998
999 defaultRoutingHandler.startPopulationProcess();
Charles Chan72779502016-04-23 17:36:10 -07001000 mcastHandler.init();
Charles Chane7c61022015-10-07 14:21:45 -07001001 }
1002
Charles Chan72f556a2015-10-05 17:50:33 -07001003 @Override
1004 public void event(NetworkConfigEvent event) {
Charles Chan82ab1932016-01-30 23:22:37 -08001005 // TODO move this part to NetworkConfigEventHandler
1006 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
1007 switch (event.type()) {
1008 case CONFIG_ADDED:
1009 log.info("Segment Routing Config added.");
1010 configureNetwork();
1011 break;
1012 case CONFIG_UPDATED:
1013 log.info("Segment Routing Config updated.");
1014 // TODO support dynamic configuration
1015 break;
1016 default:
1017 break;
Charles Chan2b078ae2015-10-14 11:24:40 -07001018 }
Charles Chan82ab1932016-01-30 23:22:37 -08001019 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chan82f19972016-05-17 13:13:55 -07001020 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan82ab1932016-01-30 23:22:37 -08001021 switch (event.type()) {
1022 case CONFIG_ADDED:
Charles Chan82f19972016-05-17 13:13:55 -07001023 appCfgHandler.processAppConfigAdded(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001024 break;
1025 case CONFIG_UPDATED:
Charles Chan82f19972016-05-17 13:13:55 -07001026 appCfgHandler.processAppConfigUpdated(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001027 break;
1028 case CONFIG_REMOVED:
Charles Chan82f19972016-05-17 13:13:55 -07001029 appCfgHandler.processAppConfigRemoved(event);
1030 break;
1031 default:
1032 break;
1033 }
Charles Chandebfea32016-10-24 14:52:01 -07001034 configureNetwork();
Charles Chan82f19972016-05-17 13:13:55 -07001035 } else if (event.configClass().equals(XConnectConfig.class)) {
1036 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
1037 switch (event.type()) {
1038 case CONFIG_ADDED:
1039 xConnectHandler.processXConnectConfigAdded(event);
1040 break;
1041 case CONFIG_UPDATED:
1042 xConnectHandler.processXConnectConfigUpdated(event);
1043 break;
1044 case CONFIG_REMOVED:
1045 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001046 break;
1047 default:
1048 break;
Charles Chan2b078ae2015-10-14 11:24:40 -07001049 }
Charles Chan72f556a2015-10-05 17:50:33 -07001050 }
1051 }
1052 }
Charles Chanf4586112015-11-09 16:37:23 -08001053
1054 private class InternalHostListener implements HostListener {
Charles Chanf4586112015-11-09 16:37:23 -08001055 @Override
1056 public void event(HostEvent event) {
1057 // Do not proceed without mastership
1058 DeviceId deviceId = event.subject().location().deviceId();
1059 if (!mastershipService.isLocalMaster(deviceId)) {
1060 return;
1061 }
1062
1063 switch (event.type()) {
1064 case HOST_ADDED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001065 hostHandler.processHostAddedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001066 break;
1067 case HOST_MOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001068 hostHandler.processHostMovedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001069 break;
1070 case HOST_REMOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001071 hostHandler.processHostRemoveEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001072 break;
1073 case HOST_UPDATED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001074 hostHandler.processHostUpdatedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001075 break;
1076 default:
1077 log.warn("Unsupported host event type: {}", event.type());
1078 break;
1079 }
1080 }
1081 }
1082
Charles Chanc91c8782016-03-30 17:54:24 -07001083 private class InternalMcastListener implements McastListener {
1084 @Override
1085 public void event(McastEvent event) {
1086 switch (event.type()) {
1087 case SOURCE_ADDED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001088 mcastHandler.processSourceAdded(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001089 break;
1090 case SINK_ADDED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001091 mcastHandler.processSinkAdded(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001092 break;
1093 case SINK_REMOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001094 mcastHandler.processSinkRemoved(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001095 break;
1096 case ROUTE_ADDED:
1097 case ROUTE_REMOVED:
1098 default:
1099 break;
1100 }
1101 }
1102 }
Charles Chan41f5ec02016-06-13 18:54:31 -07001103
1104 private class InternalCordConfigListener implements CordConfigListener {
1105 @Override
1106 public void event(CordConfigEvent event) {
1107 switch (event.type()) {
1108 case ACCESS_AGENT_ADDED:
1109 cordConfigHandler.processAccessAgentAddedEvent(event);
1110 break;
1111 case ACCESS_AGENT_UPDATED:
1112 cordConfigHandler.processAccessAgentUpdatedEvent(event);
1113 break;
1114 case ACCESS_AGENT_REMOVED:
1115 cordConfigHandler.processAccessAgentRemovedEvent(event);
1116 break;
1117 case ACCESS_DEVICE_ADDED:
1118 case ACCESS_DEVICE_UPDATED:
1119 case ACCESS_DEVICE_REMOVED:
1120 default:
1121 break;
1122 }
1123 }
1124 }
Charles Chandebfea32016-10-24 14:52:01 -07001125
1126 private class InternalRouteEventListener implements RouteListener {
1127 @Override
1128 public void event(RouteEvent event) {
1129 switch (event.type()) {
1130 case ROUTE_ADDED:
1131 routeHandler.processRouteAdded(event);
1132 break;
1133 case ROUTE_UPDATED:
1134 routeHandler.processRouteUpdated(event);
1135 break;
1136 case ROUTE_REMOVED:
1137 routeHandler.processRouteRemoved(event);
1138 break;
1139 default:
1140 break;
1141 }
1142 }
1143 }
sangho80f11cb2015-04-01 13:05:26 -07001144}