blob: 39b901bf1060334973a6964fd161094f339f2fcd [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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
Ray Milkey6c1f0f02017-08-15 11:02:29 -070018import java.util.List;
19import java.util.Map;
20import java.util.Map.Entry;
21import java.util.Optional;
22import java.util.Set;
23import java.util.concurrent.ConcurrentHashMap;
24import java.util.concurrent.ConcurrentLinkedQueue;
25import java.util.concurrent.Executors;
26import java.util.concurrent.ScheduledExecutorService;
27import java.util.concurrent.ScheduledFuture;
28import java.util.concurrent.TimeUnit;
29import java.util.concurrent.atomic.AtomicBoolean;
30import java.util.stream.Collectors;
31
sanghob35a6192015-04-01 13:05:26 -070032import org.apache.felix.scr.annotations.Activate;
33import org.apache.felix.scr.annotations.Component;
34import org.apache.felix.scr.annotations.Deactivate;
35import org.apache.felix.scr.annotations.Reference;
36import org.apache.felix.scr.annotations.ReferenceCardinality;
sangho1e575652015-05-14 00:39:53 -070037import org.apache.felix.scr.annotations.Service;
sanghob35a6192015-04-01 13:05:26 -070038import org.onlab.packet.Ethernet;
Pier Ventre735b8c82016-12-02 08:16:05 -080039import org.onlab.packet.ICMP6;
Charles Chanc42e84e2015-10-20 16:24:19 -070040import org.onlab.packet.IPv4;
Pier Ventre10bd8d12016-11-26 21:05:22 -080041import org.onlab.packet.IPv6;
Charles Chanc42e84e2015-10-20 16:24:19 -070042import org.onlab.packet.IpPrefix;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070043import org.onlab.packet.VlanId;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070044import org.onlab.util.KryoNamespace;
Saurav Das80980c72016-03-23 11:22:49 -070045import org.onosproject.cfg.ComponentConfigService;
sanghob35a6192015-04-01 13:05:26 -070046import org.onosproject.core.ApplicationId;
47import org.onosproject.core.CoreService;
48import org.onosproject.event.Event;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070049import org.onosproject.mastership.MastershipService;
Pier Ventre10bd8d12016-11-26 21:05:22 -080050import org.onosproject.net.ConnectPoint;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070051import org.onosproject.net.Device;
52import org.onosproject.net.DeviceId;
53import org.onosproject.net.Link;
54import org.onosproject.net.Port;
Charles Chan68aa62d2015-11-09 16:37:23 -080055import org.onosproject.net.PortNumber;
Charles Chand6832882015-10-05 17:50:33 -070056import org.onosproject.net.config.ConfigFactory;
57import org.onosproject.net.config.NetworkConfigEvent;
Charles Chand6832882015-10-05 17:50:33 -070058import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070059import org.onosproject.net.config.NetworkConfigRegistry;
Ray Milkey6c1f0f02017-08-15 11:02:29 -070060import org.onosproject.net.config.basics.InterfaceConfig;
61import org.onosproject.net.config.basics.McastConfig;
Charles Chand6832882015-10-05 17:50:33 -070062import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070063import org.onosproject.net.device.DeviceEvent;
64import org.onosproject.net.device.DeviceListener;
65import org.onosproject.net.device.DeviceService;
Charles Chan68aa62d2015-11-09 16:37:23 -080066import org.onosproject.net.flow.TrafficSelector;
67import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070068import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chan68aa62d2015-11-09 16:37:23 -080069import org.onosproject.net.host.HostEvent;
70import org.onosproject.net.host.HostListener;
Pier Ventre10bd8d12016-11-26 21:05:22 -080071import org.onosproject.net.host.HostService;
Ray Milkey6c1f0f02017-08-15 11:02:29 -070072import org.onosproject.net.intf.Interface;
73import org.onosproject.net.intf.InterfaceService;
Pier Ventre10bd8d12016-11-26 21:05:22 -080074import org.onosproject.net.link.LinkEvent;
75import org.onosproject.net.link.LinkListener;
76import org.onosproject.net.link.LinkService;
Charles Chand55e84d2016-03-30 17:54:24 -070077import org.onosproject.net.mcast.McastEvent;
78import org.onosproject.net.mcast.McastListener;
79import org.onosproject.net.mcast.MulticastRouteService;
Ray Milkey6c1f0f02017-08-15 11:02:29 -070080import org.onosproject.net.neighbour.NeighbourResolutionService;
Pier Ventre10bd8d12016-11-26 21:05:22 -080081import org.onosproject.net.packet.InboundPacket;
82import org.onosproject.net.packet.PacketContext;
83import org.onosproject.net.packet.PacketProcessor;
84import org.onosproject.net.packet.PacketService;
Pier Ventre42287df2016-11-09 14:17:26 -080085import org.onosproject.net.topology.PathService;
Charles Chand55e84d2016-03-30 17:54:24 -070086import org.onosproject.net.topology.TopologyService;
Ray Milkey6c1f0f02017-08-15 11:02:29 -070087import org.onosproject.routeservice.RouteEvent;
88import org.onosproject.routeservice.RouteListener;
89import org.onosproject.routeservice.RouteService;
Charles Chand55e84d2016-03-30 17:54:24 -070090import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
91import org.onosproject.segmentrouting.config.DeviceConfiguration;
Pier Ventref34966c2016-11-07 16:21:04 -080092import org.onosproject.segmentrouting.config.PwaasConfig;
Pier Ventref34966c2016-11-07 16:21:04 -080093import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Ray Milkey6c1f0f02017-08-15 11:02:29 -070094import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chanfc5c7802016-05-17 13:13:55 -070095import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chand55e84d2016-03-30 17:54:24 -070096import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
Saurav Das7bcbe702017-06-13 15:35:54 -070097import org.onosproject.segmentrouting.grouphandler.DestinationSet;
98import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
Ray Milkey6c1f0f02017-08-15 11:02:29 -070099import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
Saurav Das7bcbe702017-06-13 15:35:54 -0700100import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
Charles Chand2990362016-04-18 13:44:03 -0700101import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
Charles Chan59cc16d2017-02-02 16:20:42 -0800102import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
Charles Chanfc5c7802016-05-17 13:13:55 -0700103import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700104import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700105import org.onosproject.store.service.EventuallyConsistentMap;
106import org.onosproject.store.service.EventuallyConsistentMapBuilder;
107import org.onosproject.store.service.StorageService;
108import org.onosproject.store.service.WallClockTimestamp;
sanghob35a6192015-04-01 13:05:26 -0700109import org.slf4j.Logger;
110import org.slf4j.LoggerFactory;
111
Ray Milkey6c1f0f02017-08-15 11:02:29 -0700112import com.google.common.collect.HashMultimap;
113import com.google.common.collect.ImmutableMap;
114import com.google.common.collect.Maps;
115import com.google.common.collect.Multimap;
sanghob35a6192015-04-01 13:05:26 -0700116
Charles Chan3e783d02016-02-26 22:19:52 -0800117import static com.google.common.base.Preconditions.checkState;
Pier Ventree0ae7a32016-11-23 09:57:42 -0800118import static org.onlab.packet.Ethernet.TYPE_ARP;
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700119import static org.onlab.util.Tools.groupedThreads;
Charles Chan3e783d02016-02-26 22:19:52 -0800120
Charles Chane849c192016-01-11 18:28:54 -0800121/**
122 * Segment routing manager.
123 */
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700124@Service
125@Component(immediate = true)
sangho1e575652015-05-14 00:39:53 -0700126public class SegmentRoutingManager implements SegmentRoutingService {
sanghob35a6192015-04-01 13:05:26 -0700127
Charles Chan2c15aca2016-11-09 20:51:44 -0800128 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
sanghob35a6192015-04-01 13:05:26 -0700129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700131 private ComponentConfigService compCfgService;
sanghob35a6192015-04-01 13:05:26 -0700132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre10bd8d12016-11-26 21:05:22 -0800134 private NeighbourResolutionService neighbourResolutionService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800137 public PathService pathService;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700140 CoreService coreService;
sanghob35a6192015-04-01 13:05:26 -0700141
142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700143 PacketService packetService;
sanghob35a6192015-04-01 13:05:26 -0700144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700146 HostService hostService;
sanghob35a6192015-04-01 13:05:26 -0700147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700149 DeviceService deviceService;
sanghob35a6192015-04-01 13:05:26 -0700150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800152 public FlowObjectiveService flowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -0700153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700155 LinkService linkService;
sangho1e575652015-05-14 00:39:53 -0700156
Charles Chan5270ed02016-01-30 23:22:37 -0800157 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800158 public MastershipService mastershipService;
Charles Chan03a73e02016-10-24 14:52:01 -0700159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800161 public StorageService storageService;
Charles Chan03a73e02016-10-24 14:52:01 -0700162
163 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
164 MulticastRouteService multicastRouteService;
165
166 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
167 TopologyService topologyService;
168
169 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700170 RouteService routeService;
Charles Chan5270ed02016-01-30 23:22:37 -0800171
172 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan2c15aca2016-11-09 20:51:44 -0800173 public NetworkConfigRegistry cfgService;
Charles Chan5270ed02016-01-30 23:22:37 -0800174
Saurav Das80980c72016-03-23 11:22:49 -0700175 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan2c15aca2016-11-09 20:51:44 -0800176 public InterfaceService interfaceService;
177
Charles Chan03a73e02016-10-24 14:52:01 -0700178 ArpHandler arpHandler = null;
179 IcmpHandler icmpHandler = null;
180 IpHandler ipHandler = null;
181 RoutingRulePopulator routingRulePopulator = null;
Ray Milkeye4afdb52017-04-05 09:42:04 -0700182 ApplicationId appId;
183 DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700184
Charles Chan03a73e02016-10-24 14:52:01 -0700185 DefaultRoutingHandler defaultRoutingHandler = null;
sangho1e575652015-05-14 00:39:53 -0700186 private TunnelHandler tunnelHandler = null;
187 private PolicyHandler policyHandler = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700188 private InternalPacketProcessor processor = null;
189 private InternalLinkListener linkListener = null;
190 private InternalDeviceListener deviceListener = null;
Charles Chanfc5c7802016-05-17 13:13:55 -0700191 private AppConfigHandler appCfgHandler = null;
Charles Chan03a73e02016-10-24 14:52:01 -0700192 XConnectHandler xConnectHandler = null;
Charles Chand2990362016-04-18 13:44:03 -0700193 private McastHandler mcastHandler = null;
Charles Chan65238242017-06-22 18:03:14 -0700194 private HostHandler hostHandler = null;
Pier Ventre10bd8d12016-11-26 21:05:22 -0800195 private RouteHandler routeHandler = null;
Pier Ventre735b8c82016-12-02 08:16:05 -0800196 private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
Pier Ventref34966c2016-11-07 16:21:04 -0800197 private L2TunnelHandler l2TunnelHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700198 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan5270ed02016-01-30 23:22:37 -0800199 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chand55e84d2016-03-30 17:54:24 -0700200 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
201 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan03a73e02016-10-24 14:52:01 -0700202 private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
sanghob35a6192015-04-01 13:05:26 -0700203
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700204 private ScheduledExecutorService executorService = Executors
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700205 .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
sanghob35a6192015-04-01 13:05:26 -0700206
Saurav Das4ce45962015-11-24 23:21:05 -0800207 @SuppressWarnings("unused")
sanghob35a6192015-04-01 13:05:26 -0700208 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das4ce45962015-11-24 23:21:05 -0800209 @SuppressWarnings("rawtypes")
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700210 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
Charles Chan68aa62d2015-11-09 16:37:23 -0800211 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chane849c192016-01-11 18:28:54 -0800212 new ConcurrentHashMap<>();
213 /**
Saurav Das7bcbe702017-06-13 15:35:54 -0700214 * Per device next objective ID store with (device id + destination set) as key.
Charles Chan5bc32632017-08-22 15:07:34 -0700215 * Used to keep track on MPLS group information.
Charles Chane849c192016-01-11 18:28:54 -0800216 */
Saurav Das7bcbe702017-06-13 15:35:54 -0700217 EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
218 dsNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800219 /**
Charles Chan5bc32632017-08-22 15:07:34 -0700220 * Per device next objective ID store with (device id + vlanid) as key.
221 * Used to keep track on L2 flood group information.
Charles Chane849c192016-01-11 18:28:54 -0800222 */
Ray Milkeye4afdb52017-04-05 09:42:04 -0700223 EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
Charles Chan59cc16d2017-02-02 16:20:42 -0800224 vlanNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800225 /**
Charles Chan5bc32632017-08-22 15:07:34 -0700226 * Per device next objective ID store with (device id + port + treatment + meta) as key.
227 * Used to keep track on L2 interface group and L3 unicast group information.
Charles Chane849c192016-01-11 18:28:54 -0800228 */
Ray Milkeye4afdb52017-04-05 09:42:04 -0700229 EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das4ce45962015-11-24 23:21:05 -0800230 portNextObjStore = null;
Charles Chan59cc16d2017-02-02 16:20:42 -0800231
Saurav Dasc88d4662017-05-15 15:34:25 -0700232 // Local store for all links seen and their present status, used for
233 // optimized routing. The existence of the link in the keys is enough to know
234 // if the link has been "seen-before" by this instance of the controller.
235 // The boolean value indicates if the link is currently up or not.
236 // XXX Currently the optimized routing logic depends on "forgetting" a link
237 // when a switch goes down, but "remembering" it when only the link goes down.
238 // Consider changing this logic so we can use the Link Service instead of
239 // a local cache.
240 private Map<Link, Boolean> seenLinks = new ConcurrentHashMap<>();
241
Saurav Das4ce45962015-11-24 23:21:05 -0800242 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
243 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho0b2b6d12015-05-20 22:16:38 -0700244
Saurav Das7bcbe702017-06-13 15:35:54 -0700245 private AtomicBoolean programmingScheduled = new AtomicBoolean();
246
Charles Chand55e84d2016-03-30 17:54:24 -0700247 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700248 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
249 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700250 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chand6832882015-10-05 17:50:33 -0700251 @Override
Charles Chan5270ed02016-01-30 23:22:37 -0800252 public SegmentRoutingDeviceConfig createConfig() {
253 return new SegmentRoutingDeviceConfig();
Charles Chand6832882015-10-05 17:50:33 -0700254 }
255 };
Pier Ventref34966c2016-11-07 16:21:04 -0800256
Charles Chand55e84d2016-03-30 17:54:24 -0700257 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700258 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
259 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700260 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan5270ed02016-01-30 23:22:37 -0800261 @Override
262 public SegmentRoutingAppConfig createConfig() {
263 return new SegmentRoutingAppConfig();
264 }
265 };
Pier Ventref34966c2016-11-07 16:21:04 -0800266
Charles Chanfc5c7802016-05-17 13:13:55 -0700267 private final ConfigFactory<ApplicationId, XConnectConfig> xConnectConfigFactory =
268 new ConfigFactory<ApplicationId, XConnectConfig>(
269 SubjectFactories.APP_SUBJECT_FACTORY,
270 XConnectConfig.class, "xconnect") {
271 @Override
272 public XConnectConfig createConfig() {
273 return new XConnectConfig();
274 }
275 };
Pier Ventref34966c2016-11-07 16:21:04 -0800276
Charles Chand55e84d2016-03-30 17:54:24 -0700277 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700278 new ConfigFactory<ApplicationId, McastConfig>(
279 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700280 McastConfig.class, "multicast") {
281 @Override
282 public McastConfig createConfig() {
283 return new McastConfig();
284 }
285 };
286
Pier Ventref34966c2016-11-07 16:21:04 -0800287 private final ConfigFactory<ApplicationId, PwaasConfig> pwaasConfigFactory =
288 new ConfigFactory<ApplicationId, PwaasConfig>(
289 SubjectFactories.APP_SUBJECT_FACTORY,
290 PwaasConfig.class, "pwaas") {
291 @Override
292 public PwaasConfig createConfig() {
293 return new PwaasConfig();
294 }
295 };
296
Charles Chan65238242017-06-22 18:03:14 -0700297 private static final Object THREAD_SCHED_LOCK = new Object();
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700298 private static int numOfEventsQueued = 0;
299 private static int numOfEventsExecuted = 0;
sanghob35a6192015-04-01 13:05:26 -0700300 private static int numOfHandlerExecution = 0;
301 private static int numOfHandlerScheduled = 0;
302
Charles Chan116188d2016-02-18 14:22:42 -0800303 /**
304 * Segment Routing App ID.
305 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800306 public static final String APP_NAME = "org.onosproject.segmentrouting";
Charles Chan59cc16d2017-02-02 16:20:42 -0800307
Charles Chane849c192016-01-11 18:28:54 -0800308 /**
309 * The default VLAN ID assigned to the interfaces without subnet config.
310 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800311 public static final VlanId INTERNAL_VLAN = VlanId.vlanId((short) 4094);
Saurav Das0e99e2b2015-10-28 12:39:42 -0700312
sanghob35a6192015-04-01 13:05:26 -0700313 @Activate
314 protected void activate() {
Charles Chan2c15aca2016-11-09 20:51:44 -0800315 appId = coreService.registerApplication(APP_NAME);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700316
317 log.debug("Creating EC map nsnextobjectivestore");
Saurav Das7bcbe702017-06-13 15:35:54 -0700318 EventuallyConsistentMapBuilder<DestinationSetNextObjectiveStoreKey, NextNeighbors>
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700319 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Saurav Das7bcbe702017-06-13 15:35:54 -0700320 dsNextObjStore = nsNextObjMapBuilder
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700321 .withName("nsnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700322 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700323 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700324 .build();
Saurav Das7bcbe702017-06-13 15:35:54 -0700325 log.trace("Current size {}", dsNextObjStore.size());
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700326
Charles Chan59cc16d2017-02-02 16:20:42 -0800327 log.debug("Creating EC map vlannextobjectivestore");
328 EventuallyConsistentMapBuilder<VlanNextObjectiveStoreKey, Integer>
329 vlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
330 vlanNextObjStore = vlanNextObjMapBuilder
331 .withName("vlannextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700332 .withSerializer(createSerializer())
Charles Chanc42e84e2015-10-20 16:24:19 -0700333 .withTimestampProvider((k, v) -> new WallClockTimestamp())
334 .build();
335
Saurav Das4ce45962015-11-24 23:21:05 -0800336 log.debug("Creating EC map subnetnextobjectivestore");
337 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
338 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
339 portNextObjStore = portNextObjMapBuilder
340 .withName("portnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700341 .withSerializer(createSerializer())
Saurav Das4ce45962015-11-24 23:21:05 -0800342 .withTimestampProvider((k, v) -> new WallClockTimestamp())
343 .build();
344
sangho0b2b6d12015-05-20 22:16:38 -0700345 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
346 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700347 tunnelStore = tunnelMapBuilder
348 .withName("tunnelstore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700349 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700350 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700351 .build();
352
353 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
354 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700355 policyStore = policyMapBuilder
356 .withName("policystore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700357 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700358 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700359 .build();
360
Saurav Das80980c72016-03-23 11:22:49 -0700361 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800362 "purgeOnDisconnection", "true");
Saurav Das80980c72016-03-23 11:22:49 -0700363 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800364 "purgeOnDisconnection", "true");
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800365 compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
366 "requestInterceptsEnabled", "false");
Charles Chand3baaba2017-08-08 15:13:37 -0700367 compCfgService.preSetProperty("org.onosproject.net.neighbour.impl.NeighbourResolutionManager",
Pier Luigi7e415132017-01-12 22:46:39 -0800368 "requestInterceptsEnabled", "false");
Charles Chanc760f382017-07-24 15:56:10 -0700369 compCfgService.preSetProperty("org.onosproject.dhcprelay.DhcpRelayManager",
Pier Luigi7e415132017-01-12 22:46:39 -0800370 "arpEnabled", "false");
Pier Luigi9b1d6262017-02-02 22:31:34 -0800371 compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
372 "greedyLearningIpv6", "true");
Charles Chanc6d227e2017-02-28 15:15:17 -0800373 compCfgService.preSetProperty("org.onosproject.routing.cpr.ControlPlaneRedirectManager",
374 "forceUnprovision", "true");
Charles Chanef624ed2017-08-10 16:57:28 -0700375 compCfgService.preSetProperty("org.onosproject.routeservice.store.RouteStoreImpl",
Charles Chan73316522017-07-20 16:16:25 -0700376 "distributed", "true");
Charles Chan35a32322017-08-14 11:42:11 -0700377 compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
378 "multihomingEnabled", "true");
Saurav Das80980c72016-03-23 11:22:49 -0700379
Charles Chanb8e10c82015-10-14 11:24:40 -0700380 processor = new InternalPacketProcessor();
381 linkListener = new InternalLinkListener();
382 deviceListener = new InternalDeviceListener();
Charles Chanfc5c7802016-05-17 13:13:55 -0700383 appCfgHandler = new AppConfigHandler(this);
384 xConnectHandler = new XConnectHandler(this);
Charles Chand2990362016-04-18 13:44:03 -0700385 mcastHandler = new McastHandler(this);
386 hostHandler = new HostHandler(this);
Charles Chan03a73e02016-10-24 14:52:01 -0700387 routeHandler = new RouteHandler(this);
Pier Ventre735b8c82016-12-02 08:16:05 -0800388 neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
Pier Ventref34966c2016-11-07 16:21:04 -0800389 l2TunnelHandler = new L2TunnelHandler(this);
Charles Chanb8e10c82015-10-14 11:24:40 -0700390
Charles Chan3e783d02016-02-26 22:19:52 -0800391 cfgService.addListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700392 cfgService.registerConfigFactory(deviceConfigFactory);
393 cfgService.registerConfigFactory(appConfigFactory);
Charles Chanfc5c7802016-05-17 13:13:55 -0700394 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700395 cfgService.registerConfigFactory(mcastConfigFactory);
Pier Ventref34966c2016-11-07 16:21:04 -0800396 cfgService.registerConfigFactory(pwaasConfigFactory);
Charles Chan5270ed02016-01-30 23:22:37 -0800397 hostService.addListener(hostListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700398 packetService.addProcessor(processor, PacketProcessor.director(2));
399 linkService.addListener(linkListener);
400 deviceService.addListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700401 multicastRouteService.addListener(mcastListener);
Charles Chanc7a8a682017-06-19 00:43:31 -0700402 routeService.addListener(routeListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700403
404 cfgListener.configureNetwork();
405
sanghob35a6192015-04-01 13:05:26 -0700406 log.info("Started");
407 }
408
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700409 private KryoNamespace.Builder createSerializer() {
410 return new KryoNamespace.Builder()
411 .register(KryoNamespaces.API)
Saurav Das7bcbe702017-06-13 15:35:54 -0700412 .register(DestinationSetNextObjectiveStoreKey.class,
Charles Chan59cc16d2017-02-02 16:20:42 -0800413 VlanNextObjectiveStoreKey.class,
Saurav Das7bcbe702017-06-13 15:35:54 -0700414 DestinationSet.class,
415 NextNeighbors.class,
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700416 Tunnel.class,
417 DefaultTunnel.class,
418 Policy.class,
419 TunnelPolicy.class,
420 Policy.Type.class,
421 PortNextObjectiveStoreKey.class,
Charles Chanfc5c7802016-05-17 13:13:55 -0700422 XConnectStoreKey.class
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700423 );
424 }
425
sanghob35a6192015-04-01 13:05:26 -0700426 @Deactivate
427 protected void deactivate() {
Charles Chand6832882015-10-05 17:50:33 -0700428 cfgService.removeListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700429 cfgService.unregisterConfigFactory(deviceConfigFactory);
430 cfgService.unregisterConfigFactory(appConfigFactory);
Charles Chan03a73e02016-10-24 14:52:01 -0700431 cfgService.unregisterConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700432 cfgService.unregisterConfigFactory(mcastConfigFactory);
Pier Ventref34966c2016-11-07 16:21:04 -0800433 cfgService.unregisterConfigFactory(pwaasConfigFactory);
Charles Chand6832882015-10-05 17:50:33 -0700434
Charles Chanc7a8a682017-06-19 00:43:31 -0700435 hostService.removeListener(hostListener);
sanghob35a6192015-04-01 13:05:26 -0700436 packetService.removeProcessor(processor);
Charles Chanb8e10c82015-10-14 11:24:40 -0700437 linkService.removeListener(linkListener);
438 deviceService.removeListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700439 multicastRouteService.removeListener(mcastListener);
Charles Chan03a73e02016-10-24 14:52:01 -0700440 routeService.removeListener(routeListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700441
Charles Chan0aa674e2017-02-23 15:44:08 -0800442 neighbourResolutionService.unregisterNeighbourHandlers(appId);
443
sanghob35a6192015-04-01 13:05:26 -0700444 processor = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700445 linkListener = null;
Charles Chand55e84d2016-03-30 17:54:24 -0700446 deviceListener = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700447 groupHandlerMap.clear();
448
Saurav Das7bcbe702017-06-13 15:35:54 -0700449 dsNextObjStore.destroy();
Charles Chan59cc16d2017-02-02 16:20:42 -0800450 vlanNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700451 portNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700452 tunnelStore.destroy();
453 policyStore.destroy();
sanghob35a6192015-04-01 13:05:26 -0700454 log.info("Stopped");
455 }
456
sangho1e575652015-05-14 00:39:53 -0700457 @Override
458 public List<Tunnel> getTunnels() {
459 return tunnelHandler.getTunnels();
460 }
461
462 @Override
sangho71abe1b2015-06-29 14:58:47 -0700463 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
464 return tunnelHandler.createTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700465 }
466
467 @Override
sangho71abe1b2015-06-29 14:58:47 -0700468 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho1e575652015-05-14 00:39:53 -0700469 for (Policy policy: policyHandler.getPolicies()) {
470 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
471 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
472 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
473 log.warn("Cannot remove the tunnel used by a policy");
sangho71abe1b2015-06-29 14:58:47 -0700474 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho1e575652015-05-14 00:39:53 -0700475 }
476 }
477 }
sangho71abe1b2015-06-29 14:58:47 -0700478 return tunnelHandler.removeTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700479 }
480
481 @Override
sangho71abe1b2015-06-29 14:58:47 -0700482 public PolicyHandler.Result removePolicy(Policy policy) {
483 return policyHandler.removePolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700484 }
485
486 @Override
sangho71abe1b2015-06-29 14:58:47 -0700487 public PolicyHandler.Result createPolicy(Policy policy) {
488 return policyHandler.createPolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700489 }
490
491 @Override
492 public List<Policy> getPolicies() {
493 return policyHandler.getPolicies();
494 }
495
Saurav Das59232cf2016-04-27 18:35:50 -0700496 @Override
497 public void rerouteNetwork() {
498 cfgListener.configureNetwork();
Saurav Das59232cf2016-04-27 18:35:50 -0700499 }
500
Charles Chanc81c45b2016-10-20 17:02:44 -0700501 @Override
Pier Ventre10bd8d12016-11-26 21:05:22 -0800502 public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
503 Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
Charles Chanc81c45b2016-10-20 17:02:44 -0700504 deviceService.getAvailableDevices().forEach(device -> {
505 deviceSubnetMap.put(device.id(), deviceConfiguration.getSubnets(device.id()));
506 });
507 return deviceSubnetMap;
508 }
509
Saurav Dasc88d4662017-05-15 15:34:25 -0700510
511 @Override
512 public ImmutableMap<DeviceId, EcmpShortestPathGraph> getCurrentEcmpSpg() {
513 if (defaultRoutingHandler != null) {
514 return defaultRoutingHandler.getCurrentEmcpSpgMap();
515 } else {
516 return null;
517 }
518 }
519
520 @Override
Saurav Das7bcbe702017-06-13 15:35:54 -0700521 public ImmutableMap<DestinationSetNextObjectiveStoreKey, NextNeighbors> getDestinationSet() {
522 if (dsNextObjStore != null) {
523 return ImmutableMap.copyOf(dsNextObjStore.entrySet());
Saurav Dasc88d4662017-05-15 15:34:25 -0700524 } else {
525 return ImmutableMap.of();
526 }
527 }
528
Saurav Dasceccf242017-08-03 18:30:35 -0700529 @Override
530 public void verifyGroups(DeviceId id) {
531 DefaultGroupHandler gh = groupHandlerMap.get(id);
532 if (gh != null) {
533 gh.triggerBucketCorrector();
534 }
535 }
536
sanghof9d0bf12015-05-19 11:57:42 -0700537 /**
Ray Milkeye4afdb52017-04-05 09:42:04 -0700538 * Extracts the application ID from the manager.
539 *
540 * @return application ID
541 */
542 public ApplicationId appId() {
543 return appId;
544 }
545
546 /**
547 * Returns the device configuration.
548 *
549 * @return device configuration
550 */
551 public DeviceConfiguration deviceConfiguration() {
552 return deviceConfiguration;
553 }
554
555 /**
Saurav Das7bcbe702017-06-13 15:35:54 -0700556 * Per device next objective ID store with (device id + destination set) as key.
Charles Chan5bc32632017-08-22 15:07:34 -0700557 * Used to keep track on MPLS group information.
Ray Milkeye4afdb52017-04-05 09:42:04 -0700558 *
559 * @return next objective ID store
560 */
Saurav Das7bcbe702017-06-13 15:35:54 -0700561 public EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
562 dsNextObjStore() {
563 return dsNextObjStore;
Ray Milkeye4afdb52017-04-05 09:42:04 -0700564 }
565
566 /**
Charles Chan5bc32632017-08-22 15:07:34 -0700567 * Per device next objective ID store with (device id + vlanid) as key.
568 * Used to keep track on L2 flood group information.
Ray Milkeye4afdb52017-04-05 09:42:04 -0700569 *
570 * @return vlan next object store
571 */
572 public EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer> vlanNextObjStore() {
573 return vlanNextObjStore;
574 }
575
576 /**
Charles Chan5bc32632017-08-22 15:07:34 -0700577 * Per device next objective ID store with (device id + port + treatment + meta) as key.
578 * Used to keep track on L2 interface group and L3 unicast group information.
Ray Milkeye4afdb52017-04-05 09:42:04 -0700579 *
580 * @return port next object store.
581 */
582 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer> portNextObjStore() {
583 return portNextObjStore;
584 }
585
586 /**
Saurav Das7bcbe702017-06-13 15:35:54 -0700587 * Returns the MPLS-ECMP configuration which indicates whether ECMP on
588 * labeled packets should be programmed or not.
Pier Ventre98161782016-10-31 15:00:01 -0700589 *
590 * @return MPLS-ECMP value
591 */
592 public boolean getMplsEcmp() {
593 SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
594 .getConfig(this.appId, SegmentRoutingAppConfig.class);
595 return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
596 }
597
598 /**
sanghof9d0bf12015-05-19 11:57:42 -0700599 * Returns the tunnel object with the tunnel ID.
600 *
601 * @param tunnelId Tunnel ID
602 * @return Tunnel reference
603 */
sangho1e575652015-05-14 00:39:53 -0700604 public Tunnel getTunnel(String tunnelId) {
605 return tunnelHandler.getTunnel(tunnelId);
606 }
607
Charles Chan7ffd81f2017-02-08 15:52:08 -0800608 // TODO Consider moving these to InterfaceService
sanghob35a6192015-04-01 13:05:26 -0700609 /**
Charles Chan59cc16d2017-02-02 16:20:42 -0800610 * Returns untagged VLAN configured on given connect point.
Charles Chan7ffd81f2017-02-08 15:52:08 -0800611 * <p>
612 * Only returns the first match if there are multiple untagged VLAN configured
613 * on the connect point.
sanghob35a6192015-04-01 13:05:26 -0700614 *
Charles Chan59cc16d2017-02-02 16:20:42 -0800615 * @param connectPoint connect point
616 * @return untagged VLAN or null if not configured
sanghob35a6192015-04-01 13:05:26 -0700617 */
Charles Chan65238242017-06-22 18:03:14 -0700618 VlanId getUntaggedVlanId(ConnectPoint connectPoint) {
Charles Chan59cc16d2017-02-02 16:20:42 -0800619 return interfaceService.getInterfacesByPort(connectPoint).stream()
620 .filter(intf -> !intf.vlanUntagged().equals(VlanId.NONE))
621 .map(Interface::vlanUntagged)
622 .findFirst().orElse(null);
sanghob35a6192015-04-01 13:05:26 -0700623 }
624
sangho1e575652015-05-14 00:39:53 -0700625 /**
Charles Chan7ffd81f2017-02-08 15:52:08 -0800626 * Returns tagged VLAN configured on given connect point.
627 * <p>
628 * Returns all matches if there are multiple tagged VLAN configured
629 * on the connect point.
630 *
631 * @param connectPoint connect point
632 * @return tagged VLAN or empty set if not configured
633 */
Charles Chan65238242017-06-22 18:03:14 -0700634 Set<VlanId> getTaggedVlanId(ConnectPoint connectPoint) {
Charles Chan7ffd81f2017-02-08 15:52:08 -0800635 Set<Interface> interfaces = interfaceService.getInterfacesByPort(connectPoint);
636 return interfaces.stream()
637 .map(Interface::vlanTagged)
Charles Chan65238242017-06-22 18:03:14 -0700638 .flatMap(Set::stream)
Charles Chan7ffd81f2017-02-08 15:52:08 -0800639 .collect(Collectors.toSet());
640 }
641
642 /**
643 * Returns native VLAN configured on given connect point.
644 * <p>
645 * Only returns the first match if there are multiple native VLAN configured
646 * on the connect point.
647 *
648 * @param connectPoint connect point
649 * @return native VLAN or null if not configured
650 */
Charles Chan65238242017-06-22 18:03:14 -0700651 VlanId getNativeVlanId(ConnectPoint connectPoint) {
Charles Chan7ffd81f2017-02-08 15:52:08 -0800652 Set<Interface> interfaces = interfaceService.getInterfacesByPort(connectPoint);
653 return interfaces.stream()
654 .filter(intf -> !intf.vlanNative().equals(VlanId.NONE))
655 .map(Interface::vlanNative)
656 .findFirst()
657 .orElse(null);
658 }
659
660 /**
Charles Chanf9a52702017-06-16 15:19:24 -0700661 * Returns internal VLAN for untagged hosts on given connect point.
662 * <p>
663 * The internal VLAN is either vlan-untagged for an access port,
664 * or vlan-native for a trunk port.
665 *
666 * @param connectPoint connect point
667 * @return internal VLAN or null if both vlan-untagged and vlan-native are undefined
668 */
Charles Chan65238242017-06-22 18:03:14 -0700669 VlanId getInternalVlanId(ConnectPoint connectPoint) {
Charles Chanf9a52702017-06-16 15:19:24 -0700670 VlanId untaggedVlanId = getUntaggedVlanId(connectPoint);
671 VlanId nativeVlanId = getNativeVlanId(connectPoint);
672 return untaggedVlanId != null ? untaggedVlanId : nativeVlanId;
673 }
674
675 /**
Charles Chan65238242017-06-22 18:03:14 -0700676 * Returns optional pair device ID of given device.
677 *
678 * @param deviceId device ID
679 * @return optional pair device ID. Might be empty if pair device is not configured
680 */
681 Optional<DeviceId> getPairDeviceId(DeviceId deviceId) {
682 SegmentRoutingDeviceConfig deviceConfig =
683 cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
684 return Optional.ofNullable(deviceConfig).map(SegmentRoutingDeviceConfig::pairDeviceId);
685 }
686 /**
687 * Returns optional pair device local port of given device.
688 *
689 * @param deviceId device ID
690 * @return optional pair device ID. Might be empty if pair device is not configured
691 */
692 Optional<PortNumber> getPairLocalPorts(DeviceId deviceId) {
693 SegmentRoutingDeviceConfig deviceConfig =
694 cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
695 return Optional.ofNullable(deviceConfig).map(SegmentRoutingDeviceConfig::pairLocalPort);
696 }
697
698 /**
Charles Chan7ffd81f2017-02-08 15:52:08 -0800699 * Returns vlan port map of given device.
700 *
701 * @param deviceId device id
702 * @return vlan-port multimap
703 */
704 public Multimap<VlanId, PortNumber> getVlanPortMap(DeviceId deviceId) {
705 HashMultimap<VlanId, PortNumber> vlanPortMap = HashMultimap.create();
706
707 interfaceService.getInterfaces().stream()
708 .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
709 .forEach(intf -> {
710 vlanPortMap.put(intf.vlanUntagged(), intf.connectPoint().port());
Charles Chan65238242017-06-22 18:03:14 -0700711 intf.vlanTagged().forEach(vlanTagged ->
712 vlanPortMap.put(vlanTagged, intf.connectPoint().port())
713 );
Charles Chan7ffd81f2017-02-08 15:52:08 -0800714 vlanPortMap.put(intf.vlanNative(), intf.connectPoint().port());
715 });
716 vlanPortMap.removeAll(VlanId.NONE);
717
718 return vlanPortMap;
719 }
720
721 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800722 * Returns the next objective ID for the given subnet prefix. It is expected
Charles Chan59cc16d2017-02-02 16:20:42 -0800723 * Returns the next objective ID for the given vlan id. It is expected
Saurav Das4ce45962015-11-24 23:21:05 -0800724 * that the next-objective has been pre-created from configuration.
Charles Chanc42e84e2015-10-20 16:24:19 -0700725 *
726 * @param deviceId Device ID
Charles Chan59cc16d2017-02-02 16:20:42 -0800727 * @param vlanId VLAN ID
Saurav Das4ce45962015-11-24 23:21:05 -0800728 * @return next objective ID or -1 if it was not found
Charles Chanc42e84e2015-10-20 16:24:19 -0700729 */
Charles Chan65238242017-06-22 18:03:14 -0700730 int getVlanNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
Charles Chanc42e84e2015-10-20 16:24:19 -0700731 if (groupHandlerMap.get(deviceId) != null) {
Charles Chan59cc16d2017-02-02 16:20:42 -0800732 log.trace("getVlanNextObjectiveId query in device {}", deviceId);
733 return groupHandlerMap.get(deviceId).getVlanNextObjectiveId(vlanId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700734 } else {
Charles Chan59cc16d2017-02-02 16:20:42 -0800735 log.warn("getVlanNextObjectiveId query - groupHandler for "
Saurav Das4ce45962015-11-24 23:21:05 -0800736 + "device {} not found", deviceId);
737 return -1;
738 }
739 }
740
741 /**
742 * Returns the next objective ID for the given portNumber, given the treatment.
743 * There could be multiple different treatments to the same outport, which
Saurav Das961beb22017-03-29 19:09:17 -0700744 * would result in different objectives. If the next object does not exist,
745 * and should be created, a new one is created and its id is returned.
Saurav Das4ce45962015-11-24 23:21:05 -0800746 *
747 * @param deviceId Device ID
748 * @param portNum port number on device for which NextObjective is queried
749 * @param treatment the actions to apply on the packets (should include outport)
750 * @param meta metadata passed into the creation of a Next Objective if necessary
Saurav Das961beb22017-03-29 19:09:17 -0700751 * @param createIfMissing true if a next object should be created if not found
Saurav Das59232cf2016-04-27 18:35:50 -0700752 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das4ce45962015-11-24 23:21:05 -0800753 */
754 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
755 TrafficTreatment treatment,
Saurav Das961beb22017-03-29 19:09:17 -0700756 TrafficSelector meta,
757 boolean createIfMissing) {
Saurav Das4ce45962015-11-24 23:21:05 -0800758 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
759 if (ghdlr != null) {
Saurav Das961beb22017-03-29 19:09:17 -0700760 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta, createIfMissing);
Saurav Das4ce45962015-11-24 23:21:05 -0800761 } else {
Charles Chane849c192016-01-11 18:28:54 -0800762 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
763 + " not found", deviceId);
764 return -1;
765 }
766 }
767
Saurav Dasc88d4662017-05-15 15:34:25 -0700768 /**
769 * Returns the group handler object for the specified device id.
770 *
771 * @param devId the device identifier
772 * @return the groupHandler object for the device id, or null if not found
773 */
Charles Chan65238242017-06-22 18:03:14 -0700774 DefaultGroupHandler getGroupHandler(DeviceId devId) {
Saurav Dasc88d4662017-05-15 15:34:25 -0700775 return groupHandlerMap.get(devId);
776 }
777
778 /**
Saurav Dasceccf242017-08-03 18:30:35 -0700779 * Returns the default routing handler object.
780 *
781 * @return the default routing handler object
782 */
783 public DefaultRoutingHandler getRoutingHandler() {
784 return defaultRoutingHandler;
785 }
786
787 /**
Saurav Dasc88d4662017-05-15 15:34:25 -0700788 * Returns true if this controller instance has seen this link before. The
789 * link may not be currently up, but as long as the link had been seen before
790 * this method will return true. The one exception is when the link was
791 * indeed seen before, but this controller instance was forced to forget it
792 * by a call to purgeSeenLink method.
793 *
794 * @param link the infrastructure link being queried
795 * @return true if this controller instance has seen this link before
796 */
Charles Chan65238242017-06-22 18:03:14 -0700797 boolean isSeenLink(Link link) {
Saurav Dasc88d4662017-05-15 15:34:25 -0700798 return seenLinks.containsKey(link);
799 }
800
801 /**
802 * Updates the seen link store. Updates can be for links that are currently
803 * available or not.
804 *
805 * @param link the link to update in the seen-link local store
806 * @param up the status of the link, true if up, false if down
807 */
Charles Chan65238242017-06-22 18:03:14 -0700808 void updateSeenLink(Link link, boolean up) {
Saurav Dasc88d4662017-05-15 15:34:25 -0700809 seenLinks.put(link, up);
810 }
811
812 /**
813 * Returns the status of a seen-link (up or down). If the link has not
814 * been seen-before, a null object is returned.
815 *
816 * @param link the infrastructure link being queried
817 * @return null if the link was not seen-before;
818 * true if the seen-link is up;
819 * false if the seen-link is down
820 */
Charles Chan65238242017-06-22 18:03:14 -0700821 Boolean isSeenLinkUp(Link link) {
Saurav Dasc88d4662017-05-15 15:34:25 -0700822 return seenLinks.get(link);
823 }
824
825 /**
826 * Makes this controller instance forget a previously seen before link.
827 *
828 * @param link the infrastructure link to purge
829 */
Charles Chan65238242017-06-22 18:03:14 -0700830 private void purgeSeenLink(Link link) {
Saurav Dasc88d4662017-05-15 15:34:25 -0700831 seenLinks.remove(link);
832 }
833
834 /**
835 * Returns the status of a link as parallel link. A parallel link
836 * is defined as a link which has common src and dst switches as another
837 * seen-link that is currently enabled. It is not necessary for the link being
838 * queried to be a seen-link.
839 *
840 * @param link the infrastructure link being queried
841 * @return true if a seen-link exists that is up, and shares the
842 * same src and dst switches as the link being queried
843 */
Charles Chan65238242017-06-22 18:03:14 -0700844 private boolean isParallelLink(Link link) {
Saurav Dasc88d4662017-05-15 15:34:25 -0700845 for (Entry<Link, Boolean> seen : seenLinks.entrySet()) {
846 Link seenLink = seen.getKey();
847 if (seenLink.equals(link)) {
848 continue;
849 }
850 if (seenLink.src().deviceId().equals(link.src().deviceId()) &&
851 seenLink.dst().deviceId().equals(link.dst().deviceId()) &&
852 seen.getValue()) {
853 return true;
854 }
855 }
856 return false;
857 }
858
Saurav Das7bcbe702017-06-13 15:35:54 -0700859 /**
860 * Returns true if the link being queried is a bidirectional link. A bidi
861 * link is defined as a link, whose reverse link - ie. the link in the reverse
862 * direction - has been seen-before and is up. It is not necessary for the link
863 * being queried to be a seen-link.
864 *
865 * @param link the infrastructure link being queried
866 * @return true if another unidirectional link exists in the reverse direction,
867 * has been seen-before and is up
868 */
869 public boolean isBidirectional(Link link) {
870 Link reverseLink = linkService.getLink(link.dst(), link.src());
871 if (reverseLink == null) {
872 return false;
873 }
874 Boolean result = isSeenLinkUp(reverseLink);
875 if (result == null) {
876 return false;
877 }
878 return result.booleanValue();
879 }
880
881 /**
882 * Determines if the given link should be avoided in routing calculations
883 * by policy or design.
884 *
885 * @param link the infrastructure link being queried
886 * @return true if link should be avoided
887 */
888 public boolean avoidLink(Link link) {
889 // XXX currently only avoids all pair-links. In the future can be
890 // extended to avoid any generic link
891 DeviceId src = link.src().deviceId();
892 PortNumber srcPort = link.src().port();
893 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(src)) {
894 log.warn("Device {} not configured..cannot avoid link {}", src, link);
895 return false;
896 }
897 DeviceId pairDev;
898 PortNumber pairLocalPort, pairRemotePort = null;
899 try {
900 pairDev = deviceConfiguration.getPairDeviceId(src);
901 pairLocalPort = deviceConfiguration.getPairLocalPort(src);
902 if (pairDev != null) {
903 pairRemotePort = deviceConfiguration.getPairLocalPort(pairDev);
904 }
905 } catch (DeviceConfigNotFoundException e) {
906 log.warn("Pair dev for dev {} not configured..cannot avoid link {}",
907 src, link);
908 return false;
909 }
910
911 if (srcPort.equals(pairLocalPort) &&
912 link.dst().deviceId().equals(pairDev) &&
913 link.dst().port().equals(pairRemotePort)) {
914 return true;
915 }
916 return false;
917 }
918
sanghob35a6192015-04-01 13:05:26 -0700919 private class InternalPacketProcessor implements PacketProcessor {
sanghob35a6192015-04-01 13:05:26 -0700920 @Override
921 public void process(PacketContext context) {
922
923 if (context.isHandled()) {
924 return;
925 }
926
927 InboundPacket pkt = context.inPacket();
928 Ethernet ethernet = pkt.parsed();
Pier Luigi7dad71c2017-02-01 13:50:04 -0800929
930 if (ethernet == null) {
931 return;
932 }
933
Saurav Das7bcbe702017-06-13 15:35:54 -0700934 log.trace("Rcvd pktin from {}: {}", context.inPacket().receivedFrom(),
935 ethernet);
Pier Ventree0ae7a32016-11-23 09:57:42 -0800936 if (ethernet.getEtherType() == TYPE_ARP) {
Saurav Dasc88d4662017-05-15 15:34:25 -0700937 log.warn("Received unexpected ARP packet on {}",
938 context.inPacket().receivedFrom());
Saurav Das76ae6812017-03-15 15:15:14 -0700939 log.trace("{}", ethernet);
Pier Ventre968da122016-12-09 17:26:04 -0800940 return;
sanghob35a6192015-04-01 13:05:26 -0700941 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
Pier Ventre735b8c82016-12-02 08:16:05 -0800942 IPv4 ipv4Packet = (IPv4) ethernet.getPayload();
943 //ipHandler.addToPacketBuffer(ipv4Packet);
944 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) {
945 icmpHandler.processIcmp(ethernet, pkt.receivedFrom());
sanghob35a6192015-04-01 13:05:26 -0700946 } else {
Charles Chan50035632017-01-13 17:20:44 -0800947 // NOTE: We don't support IP learning at this moment so this
948 // is not necessary. Also it causes duplication of DHCP packets.
Pier Ventre968da122016-12-09 17:26:04 -0800949 // ipHandler.processPacketIn(ipv4Packet, pkt.receivedFrom());
sanghob35a6192015-04-01 13:05:26 -0700950 }
Pier Ventre10bd8d12016-11-26 21:05:22 -0800951 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
952 IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
Pier Ventre735b8c82016-12-02 08:16:05 -0800953 //ipHandler.addToPacketBuffer(ipv6Packet);
Pier Luigi7dad71c2017-02-01 13:50:04 -0800954 // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
Pier Ventre735b8c82016-12-02 08:16:05 -0800955 if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
956 ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
957 if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST ||
958 icmp6Packet.getIcmpType() == ICMP6.ECHO_REPLY) {
959 icmpHandler.processIcmpv6(ethernet, pkt.receivedFrom());
960 } else {
Saurav Dasc88d4662017-05-15 15:34:25 -0700961 log.trace("Received ICMPv6 0x{} - not handled",
Charles Chan0ed44fb2017-03-13 13:10:30 -0700962 Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
Pier Ventre735b8c82016-12-02 08:16:05 -0800963 }
964 } else {
965 // NOTE: We don't support IP learning at this moment so this
966 // is not necessary. Also it causes duplication of DHCPv6 packets.
967 // ipHandler.processPacketIn(ipv6Packet, pkt.receivedFrom());
968 }
sanghob35a6192015-04-01 13:05:26 -0700969 }
970 }
971 }
972
973 private class InternalLinkListener implements LinkListener {
974 @Override
975 public void event(LinkEvent event) {
Charles Chanb1f8c762017-03-29 16:39:05 -0700976 if (event.type() == LinkEvent.Type.LINK_ADDED ||
977 event.type() == LinkEvent.Type.LINK_UPDATED ||
978 event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700979 log.debug("Event {} received from Link Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700980 scheduleEventHandlerIfNotScheduled(event);
981 }
982 }
983 }
984
985 private class InternalDeviceListener implements DeviceListener {
sanghob35a6192015-04-01 13:05:26 -0700986 @Override
987 public void event(DeviceEvent event) {
sanghob35a6192015-04-01 13:05:26 -0700988 switch (event.type()) {
989 case DEVICE_ADDED:
Saurav Das1a129a02016-11-18 15:21:57 -0800990 case PORT_UPDATED:
991 case PORT_ADDED:
sangho20eff1d2015-04-13 15:15:58 -0700992 case DEVICE_UPDATED:
993 case DEVICE_AVAILABILITY_CHANGED:
Saurav Dasc88d4662017-05-15 15:34:25 -0700994 log.trace("Event {} received from Device Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700995 scheduleEventHandlerIfNotScheduled(event);
996 break;
997 default:
998 }
999 }
1000 }
1001
Saurav Das4ce45962015-11-24 23:21:05 -08001002 @SuppressWarnings("rawtypes")
sanghob35a6192015-04-01 13:05:26 -07001003 private void scheduleEventHandlerIfNotScheduled(Event event) {
Charles Chan65238242017-06-22 18:03:14 -07001004 synchronized (THREAD_SCHED_LOCK) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001005 eventQueue.add(event);
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001006 numOfEventsQueued++;
1007
1008 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
1009 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001010 eventHandlerFuture = executorService
1011 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
1012 numOfHandlerScheduled++;
1013 }
Jonathan Hartc19f7c12016-04-12 15:39:44 -07001014 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001015 numOfEventsQueued,
1016 numOfHandlerScheduled);
sanghob35a6192015-04-01 13:05:26 -07001017 }
sanghob35a6192015-04-01 13:05:26 -07001018 }
1019
1020 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -07001021 @Override
sanghob35a6192015-04-01 13:05:26 -07001022 public void run() {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001023 try {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001024 while (true) {
Saurav Das4ce45962015-11-24 23:21:05 -08001025 @SuppressWarnings("rawtypes")
Charles Chan65238242017-06-22 18:03:14 -07001026 Event event;
1027 synchronized (THREAD_SCHED_LOCK) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001028 if (!eventQueue.isEmpty()) {
1029 event = eventQueue.poll();
1030 numOfEventsExecuted++;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001031 } else {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001032 numOfHandlerExecution++;
1033 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
1034 numOfHandlerExecution, numOfEventsExecuted);
1035 break;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001036 }
sangho20eff1d2015-04-13 15:15:58 -07001037 }
Charles Chanb1f8c762017-03-29 16:39:05 -07001038 if (event.type() == LinkEvent.Type.LINK_ADDED ||
1039 event.type() == LinkEvent.Type.LINK_UPDATED) {
Saurav Dasc88d4662017-05-15 15:34:25 -07001040 // Note: do not update seenLinks here, otherwise every
1041 // link, even one seen for the first time, will be appear
1042 // to be a previously seen link
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001043 processLinkAdded((Link) event.subject());
1044 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
Pier Ventre2c515312016-09-13 21:33:40 -07001045 Link linkRemoved = (Link) event.subject();
Saurav Dasc88d4662017-05-15 15:34:25 -07001046 if (linkRemoved.type() == Link.Type.DIRECT) {
1047 updateSeenLink(linkRemoved, false);
1048 }
1049 // device availability check helps to ensure that
1050 // multiple link-removed events are actually treated as a
1051 // single switch removed event. purgeSeenLink is necessary
1052 // so we do rerouting (instead of rehashing) when switch
1053 // comes back.
Pier Ventre2c515312016-09-13 21:33:40 -07001054 if (linkRemoved.src().elementId() instanceof DeviceId &&
1055 !deviceService.isAvailable(linkRemoved.src().deviceId())) {
Saurav Dasc88d4662017-05-15 15:34:25 -07001056 purgeSeenLink(linkRemoved);
Pier Ventre2c515312016-09-13 21:33:40 -07001057 continue;
1058 }
1059 if (linkRemoved.dst().elementId() instanceof DeviceId &&
1060 !deviceService.isAvailable(linkRemoved.dst().deviceId())) {
Saurav Dasc88d4662017-05-15 15:34:25 -07001061 purgeSeenLink(linkRemoved);
Pier Ventre2c515312016-09-13 21:33:40 -07001062 continue;
1063 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001064 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001065 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
1066 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
1067 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das423fe2b2015-12-04 10:52:59 -08001068 DeviceId deviceId = ((Device) event.subject()).id();
1069 if (deviceService.isAvailable(deviceId)) {
Saurav Das837e0bb2015-10-30 17:45:38 -07001070 log.info("Processing device event {} for available device {}",
1071 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001072 processDeviceAdded((Device) event.subject());
Saurav Das80980c72016-03-23 11:22:49 -07001073 } else {
1074 log.info("Processing device event {} for unavailable device {}",
1075 event.type(), ((Device) event.subject()).id());
1076 processDeviceRemoved((Device) event.subject());
1077 }
Saurav Das1a129a02016-11-18 15:21:57 -08001078 } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
Saurav Dasd2fded02016-12-02 15:43:47 -08001079 // typically these calls come when device is added first time
1080 // so port filtering rules are handled at the device_added event.
1081 // port added calls represent all ports on the device,
1082 // enabled or not.
Saurav Dasc88d4662017-05-15 15:34:25 -07001083 log.trace("** PORT ADDED {}/{} -> {}",
Saurav Dasd2fded02016-12-02 15:43:47 -08001084 ((DeviceEvent) event).subject().id(),
1085 ((DeviceEvent) event).port().number(),
1086 event.type());
Saurav Das1a129a02016-11-18 15:21:57 -08001087 } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
Saurav Dasd2fded02016-12-02 15:43:47 -08001088 // these calls happen for every subsequent event
1089 // ports enabled, disabled, switch goes away, comes back
Saurav Das1a129a02016-11-18 15:21:57 -08001090 log.info("** PORT UPDATED {}/{} -> {}",
1091 event.subject(),
1092 ((DeviceEvent) event).port(),
1093 event.type());
1094 processPortUpdated(((Device) event.subject()),
1095 ((DeviceEvent) event).port());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -07001096 } else {
1097 log.warn("Unhandled event type: {}", event.type());
1098 }
sanghob35a6192015-04-01 13:05:26 -07001099 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001100 } catch (Exception e) {
1101 log.error("SegmentRouting event handler "
1102 + "thread thrown an exception: {}", e);
sanghob35a6192015-04-01 13:05:26 -07001103 }
sanghob35a6192015-04-01 13:05:26 -07001104 }
1105 }
1106
sanghob35a6192015-04-01 13:05:26 -07001107 private void processLinkAdded(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -07001108 log.info("** LINK ADDED {}", link.toString());
Saurav Dasc88d4662017-05-15 15:34:25 -07001109 if (link.type() != Link.Type.DIRECT) {
1110 // NOTE: A DIRECT link might be transiently marked as INDIRECT
1111 // if BDDP is received before LLDP. We can safely ignore that
1112 // until the LLDP is received and the link is marked as DIRECT.
1113 log.info("Ignore link {}->{}. Link type is {} instead of DIRECT.",
1114 link.src(), link.dst(), link.type());
1115 return;
1116 }
Saurav Das9df5b7c2017-08-14 16:44:43 -07001117 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
1118 updateSeenLink(link, true);
1119 // XXX revisit - what about devicePortMap
1120 log.warn("Source device of this link is not configured.. "
1121 + "not processing further");
1122 return;
1123 }
Saurav Dasc88d4662017-05-15 15:34:25 -07001124
1125 //Irrespective of whether the local is a MASTER or not for this device,
1126 //create group handler instance and push default TTP flow rules if needed,
1127 //as in a multi-instance setup, instances can initiate groups for any device.
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001128 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
1129 .deviceId());
1130 if (groupHandler != null) {
Saurav Dasc88d4662017-05-15 15:34:25 -07001131 groupHandler.portUpForLink(link);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001132 } else {
Saurav Das9df5b7c2017-08-14 16:44:43 -07001133 // XXX revisit/cleanup
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001134 Device device = deviceService.getDevice(link.src().deviceId());
1135 if (device != null) {
1136 log.warn("processLinkAdded: Link Added "
1137 + "Notification without Device Added "
1138 + "event, still handling it");
1139 processDeviceAdded(device);
1140 groupHandler = groupHandlerMap.get(link.src()
1141 .deviceId());
Saurav Dasc88d4662017-05-15 15:34:25 -07001142 groupHandler.portUpForLink(link);
sanghob35a6192015-04-01 13:05:26 -07001143 }
1144 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -07001145
Saurav Das7bcbe702017-06-13 15:35:54 -07001146 /*// process link only if it is bidirectional
1147 if (!isBidirectional(link)) {
1148 log.debug("Link not bidirectional.. waiting for other direction "
1149 + "src {} --> dst {} ", link.dst(), link.src());
1150 // note that if we are not processing for routing, it should at least
1151 // be considered a seen-link
1152 updateSeenLink(link, true);
1153 return;
1154 }
1155 TO DO this ensure that rehash is still done correctly even if link is
1156 not processed for rerouting - perhaps rehash in both directions when
1157 it ultimately becomes bidi?
1158 */
1159
1160 log.debug("Starting optimized route population process for link "
1161 + "{} --> {}", link.src(), link.dst());
Saurav Dasc88d4662017-05-15 15:34:25 -07001162 boolean seenBefore = isSeenLink(link);
1163 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null, link, null);
Saurav Das7bcbe702017-06-13 15:35:54 -07001164
1165 // It's possible that linkUp causes no route-path change as ECMP graph does
1166 // not change if the link is a parallel link (same src-dst as another link.
1167 // However we still need to update ECMP hash groups to include new buckets
1168 // for the link that has come up.
Saurav Dasc88d4662017-05-15 15:34:25 -07001169 if (mastershipService.isLocalMaster(link.src().deviceId())) {
Saurav Das7bcbe702017-06-13 15:35:54 -07001170 if (!seenBefore && isParallelLink(link)) {
Saurav Dasc88d4662017-05-15 15:34:25 -07001171 // if link seen first time, we need to ensure hash-groups have all ports
Saurav Das7bcbe702017-06-13 15:35:54 -07001172 log.debug("Attempting retryHash for paralled first-time link {}", link);
Saurav Dasc88d4662017-05-15 15:34:25 -07001173 groupHandler.retryHash(link, false, true);
1174 } else {
1175 //seen before-link
1176 if (isParallelLink(link)) {
Saurav Das7bcbe702017-06-13 15:35:54 -07001177 log.debug("Attempting retryHash for paralled seen-before "
1178 + "link {}", link);
Saurav Dasc88d4662017-05-15 15:34:25 -07001179 groupHandler.retryHash(link, false, false);
1180 }
1181 }
1182 }
Charles Chan2199c302016-04-23 17:36:10 -07001183
1184 mcastHandler.init();
sanghob35a6192015-04-01 13:05:26 -07001185 }
1186
1187 private void processLinkRemoved(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -07001188 log.info("** LINK REMOVED {}", link.toString());
Saurav Dasc88d4662017-05-15 15:34:25 -07001189 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link, null, null);
1190
1191 // update local groupHandler stores
sangho834e4b02015-05-01 09:38:25 -07001192 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
1193 if (groupHandler != null) {
Saurav Dasc88d4662017-05-15 15:34:25 -07001194 if (mastershipService.isLocalMaster(link.src().deviceId()) &&
1195 isParallelLink(link)) {
Saurav Das9df5b7c2017-08-14 16:44:43 -07001196 log.debug("* retrying hash for parallel link removed:{}", link);
Saurav Dasc88d4662017-05-15 15:34:25 -07001197 groupHandler.retryHash(link, true, false);
Saurav Das9df5b7c2017-08-14 16:44:43 -07001198 } else {
1199 log.debug("Not attempting retry-hash for link removed: {} .. {}", link,
1200 (mastershipService.isLocalMaster(link.src().deviceId()))
1201 ? "not parallel" : "not master");
Saurav Dasc88d4662017-05-15 15:34:25 -07001202 }
1203 // ensure local stores are updated
1204 groupHandler.portDown(link.src().port());
1205 } else {
1206 log.warn("group handler not found for dev:{} when removing link: {}",
1207 link.src().deviceId(), link);
sangho834e4b02015-05-01 09:38:25 -07001208 }
Charles Chan2199c302016-04-23 17:36:10 -07001209
1210 mcastHandler.processLinkDown(link);
sanghob35a6192015-04-01 13:05:26 -07001211 }
1212
1213 private void processDeviceAdded(Device device) {
Saurav Dasb5c236e2016-06-07 10:08:06 -07001214 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan91ccbf72017-06-27 18:48:32 -07001215
1216 // NOTE: Punt ARP/NDP even when the device is not configured.
1217 // Host learning without network config is required for CORD config generator.
1218 routingRulePopulator.populateIpPunts(device.id());
1219 routingRulePopulator.populateArpNdpPunts(device.id());
1220
Charles Chan0b4e6182015-11-03 10:42:14 -08001221 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das7bcbe702017-06-13 15:35:54 -07001222 log.warn("Device configuration unavailable. Device {} will be "
1223 + "processed after configuration.", device.id());
Saurav Das2857f382015-11-03 14:39:27 -08001224 return;
1225 }
Charles Chan2199c302016-04-23 17:36:10 -07001226 processDeviceAddedInternal(device.id());
1227 }
1228
1229 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Das837e0bb2015-10-30 17:45:38 -07001230 // Irrespective of whether the local is a MASTER or not for this device,
1231 // we need to create a SR-group-handler instance. This is because in a
1232 // multi-instance setup, any instance can initiate forwarding/next-objectives
1233 // for any switch (even if this instance is a SLAVE or not even connected
1234 // to the switch). To handle this, a default-group-handler instance is necessary
1235 // per switch.
Charles Chan2199c302016-04-23 17:36:10 -07001236 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
1237 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan0b4e6182015-11-03 10:42:14 -08001238 DefaultGroupHandler groupHandler;
1239 try {
1240 groupHandler = DefaultGroupHandler.
Charles Chan2199c302016-04-23 17:36:10 -07001241 createGroupHandler(deviceId,
1242 appId,
1243 deviceConfiguration,
1244 linkService,
1245 flowObjectiveService,
1246 this);
Charles Chan0b4e6182015-11-03 10:42:14 -08001247 } catch (DeviceConfigNotFoundException e) {
1248 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
1249 return;
1250 }
Charles Chan2199c302016-04-23 17:36:10 -07001251 log.debug("updating groupHandlerMap with new config for device: {}",
1252 deviceId);
1253 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das2857f382015-11-03 14:39:27 -08001254 }
Saurav Dasb5c236e2016-06-07 10:08:06 -07001255
Charles Chan2199c302016-04-23 17:36:10 -07001256 if (mastershipService.isLocalMaster(deviceId)) {
Saurav Das018605f2017-02-18 14:05:44 -08001257 defaultRoutingHandler.populatePortAddressingRules(deviceId);
Charles Chan03a73e02016-10-24 14:52:01 -07001258 hostHandler.init(deviceId);
Charles Chanfc5c7802016-05-17 13:13:55 -07001259 xConnectHandler.init(deviceId);
Charles Chan2199c302016-04-23 17:36:10 -07001260 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chan59cc16d2017-02-02 16:20:42 -08001261 groupHandler.createGroupsFromVlanConfig();
Charles Chan2199c302016-04-23 17:36:10 -07001262 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chanc42e84e2015-10-20 16:24:19 -07001263 }
Charles Chan5270ed02016-01-30 23:22:37 -08001264
Charles Chan03a73e02016-10-24 14:52:01 -07001265 appCfgHandler.init(deviceId);
1266 routeHandler.init(deviceId);
sanghob35a6192015-04-01 13:05:26 -07001267 }
1268
Saurav Das80980c72016-03-23 11:22:49 -07001269 private void processDeviceRemoved(Device device) {
Saurav Das7bcbe702017-06-13 15:35:54 -07001270 dsNextObjStore.entrySet().stream()
Saurav Das80980c72016-03-23 11:22:49 -07001271 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
1272 .forEach(entry -> {
Saurav Das7bcbe702017-06-13 15:35:54 -07001273 dsNextObjStore.remove(entry.getKey());
Saurav Das80980c72016-03-23 11:22:49 -07001274 });
Charles Chan59cc16d2017-02-02 16:20:42 -08001275 vlanNextObjStore.entrySet().stream()
Saurav Das80980c72016-03-23 11:22:49 -07001276 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
Charles Chan65238242017-06-22 18:03:14 -07001277 .forEach(entry -> vlanNextObjStore.remove(entry.getKey()));
Saurav Das80980c72016-03-23 11:22:49 -07001278 portNextObjStore.entrySet().stream()
1279 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
Charles Chan65238242017-06-22 18:03:14 -07001280 .forEach(entry -> portNextObjStore.remove(entry.getKey()));
Charles Chaned3742352017-06-15 00:44:51 -07001281
1282 seenLinks.keySet().removeIf(key -> key.src().deviceId().equals(device.id()) ||
1283 key.dst().deviceId().equals(device.id()));
1284
Saurav Dasceccf242017-08-03 18:30:35 -07001285 DefaultGroupHandler gh = groupHandlerMap.remove(device.id());
1286 if (gh != null) {
1287 gh.shutdown();
1288 }
Saurav Das80980c72016-03-23 11:22:49 -07001289 defaultRoutingHandler.purgeEcmpGraph(device.id());
Saurav Dasc88d4662017-05-15 15:34:25 -07001290 // Note that a switch going down is associated with all of its links
1291 // going down as well, but it is treated as a single switch down event
1292 // while the link-downs are ignored.
1293 defaultRoutingHandler
1294 .populateRoutingRulesForLinkStatusChange(null, null, device.id());
Charles Chan2199c302016-04-23 17:36:10 -07001295 mcastHandler.removeDevice(device.id());
Charles Chanfc5c7802016-05-17 13:13:55 -07001296 xConnectHandler.removeDevice(device.id());
Saurav Das80980c72016-03-23 11:22:49 -07001297 }
1298
Saurav Das1a129a02016-11-18 15:21:57 -08001299 private void processPortUpdated(Device device, Port port) {
1300 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
1301 log.warn("Device configuration uploading. Not handling port event for"
1302 + "dev: {} port: {}", device.id(), port.number());
1303 return;
1304 }
Saurav Das018605f2017-02-18 14:05:44 -08001305
1306 if (!mastershipService.isLocalMaster(device.id())) {
1307 log.debug("Not master for dev:{} .. not handling port updated event"
1308 + "for port {}", device.id(), port.number());
1309 return;
1310 }
1311
1312 // first we handle filtering rules associated with the port
1313 if (port.isEnabled()) {
1314 log.info("Switchport {}/{} enabled..programming filters",
1315 device.id(), port.number());
Charles Chan7e4f8192017-02-26 22:59:35 -08001316 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), true);
Saurav Das018605f2017-02-18 14:05:44 -08001317 } else {
1318 log.info("Switchport {}/{} disabled..removing filters",
1319 device.id(), port.number());
Charles Chan7e4f8192017-02-26 22:59:35 -08001320 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), false);
Saurav Das018605f2017-02-18 14:05:44 -08001321 }
Saurav Das1a129a02016-11-18 15:21:57 -08001322
1323 // portUpdated calls are for ports that have gone down or up. For switch
1324 // to switch ports, link-events should take care of any re-routing or
1325 // group editing necessary for port up/down. Here we only process edge ports
1326 // that are already configured.
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001327 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
1328 VlanId untaggedVlan = getUntaggedVlanId(cp);
1329 VlanId nativeVlan = getNativeVlanId(cp);
1330 Set<VlanId> taggedVlans = getTaggedVlanId(cp);
Charles Chan59cc16d2017-02-02 16:20:42 -08001331
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001332 if (untaggedVlan == null && nativeVlan == null && taggedVlans.isEmpty()) {
Saurav Dasc88d4662017-05-15 15:34:25 -07001333 log.debug("Not handling port updated event for non-edge port (unconfigured) "
Saurav Das1a129a02016-11-18 15:21:57 -08001334 + "dev/port: {}/{}", device.id(), port.number());
1335 return;
1336 }
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001337 if (untaggedVlan != null) {
1338 processEdgePort(device, port, untaggedVlan, true);
1339 }
1340 if (nativeVlan != null) {
1341 processEdgePort(device, port, nativeVlan, true);
1342 }
1343 if (!taggedVlans.isEmpty()) {
1344 taggedVlans.forEach(tag -> processEdgePort(device, port, tag, false));
1345 }
Saurav Das1a129a02016-11-18 15:21:57 -08001346 }
1347
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001348 private void processEdgePort(Device device, Port port, VlanId vlanId,
1349 boolean popVlan) {
Saurav Das1a129a02016-11-18 15:21:57 -08001350 boolean portUp = port.isEnabled();
1351 if (portUp) {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001352 log.info("Device:EdgePort {}:{} is enabled in vlan: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001353 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001354 } else {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001355 log.info("Device:EdgePort {}:{} is disabled in vlan: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001356 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001357 }
1358
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -07001359 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -07001360 if (groupHandler != null) {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001361 groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
Saurav Das1a129a02016-11-18 15:21:57 -08001362 } else {
1363 log.warn("Group handler not found for dev:{}. Not handling edge port"
1364 + " {} event for port:{}", device.id(),
1365 (portUp) ? "UP" : "DOWN", port.number());
sanghob35a6192015-04-01 13:05:26 -07001366 }
1367 }
sangho1e575652015-05-14 00:39:53 -07001368
Pier Ventre10bd8d12016-11-26 21:05:22 -08001369 /**
1370 * Registers the given connect point with the NRS, this is necessary
1371 * to receive the NDP and ARP packets from the NRS.
1372 *
1373 * @param portToRegister connect point to register
1374 */
1375 public void registerConnectPoint(ConnectPoint portToRegister) {
Charles Chan0aa674e2017-02-23 15:44:08 -08001376 neighbourResolutionService.registerNeighbourHandler(
Pier Ventre10bd8d12016-11-26 21:05:22 -08001377 portToRegister,
1378 neighbourHandler,
1379 appId
1380 );
1381 }
1382
Charles Chand6832882015-10-05 17:50:33 -07001383 private class InternalConfigListener implements NetworkConfigListener {
Saurav Das7bcbe702017-06-13 15:35:54 -07001384 private static final long PROGRAM_DELAY = 2;
Charles Chan2c15aca2016-11-09 20:51:44 -08001385 SegmentRoutingManager srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001386
Charles Chane849c192016-01-11 18:28:54 -08001387 /**
1388 * Constructs the internal network config listener.
1389 *
Charles Chan2c15aca2016-11-09 20:51:44 -08001390 * @param srManager segment routing manager
Charles Chane849c192016-01-11 18:28:54 -08001391 */
Charles Chan65238242017-06-22 18:03:14 -07001392 InternalConfigListener(SegmentRoutingManager srManager) {
Charles Chan2c15aca2016-11-09 20:51:44 -08001393 this.srManager = srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001394 }
1395
Charles Chane849c192016-01-11 18:28:54 -08001396 /**
1397 * Reads network config and initializes related data structure accordingly.
1398 */
Charles Chan4636be02015-10-07 14:21:45 -07001399 public void configureNetwork() {
Saurav Das7bcbe702017-06-13 15:35:54 -07001400 if (deviceConfiguration == null) {
1401 deviceConfiguration = new DeviceConfiguration(srManager);
1402 } else {
1403 deviceConfiguration.updateConfig();
1404 }
Charles Chan4636be02015-10-07 14:21:45 -07001405
Charles Chan2c15aca2016-11-09 20:51:44 -08001406 arpHandler = new ArpHandler(srManager);
1407 icmpHandler = new IcmpHandler(srManager);
1408 ipHandler = new IpHandler(srManager);
1409 routingRulePopulator = new RoutingRulePopulator(srManager);
1410 defaultRoutingHandler = new DefaultRoutingHandler(srManager);
Charles Chan4636be02015-10-07 14:21:45 -07001411
1412 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
1413 groupHandlerMap, tunnelStore);
1414 policyHandler = new PolicyHandler(appId, deviceConfiguration,
1415 flowObjectiveService,
1416 tunnelHandler, policyStore);
Saurav Das7bcbe702017-06-13 15:35:54 -07001417 // add a small delay to absorb multiple network config added notifications
1418 if (!programmingScheduled.get()) {
1419 programmingScheduled.set(true);
1420 executorService.schedule(new ConfigChange(), PROGRAM_DELAY,
1421 TimeUnit.SECONDS);
Charles Chan4636be02015-10-07 14:21:45 -07001422 }
Charles Chan2199c302016-04-23 17:36:10 -07001423 mcastHandler.init();
Charles Chan4636be02015-10-07 14:21:45 -07001424 }
1425
Charles Chand6832882015-10-05 17:50:33 -07001426 @Override
1427 public void event(NetworkConfigEvent event) {
Charles Chan5270ed02016-01-30 23:22:37 -08001428 // TODO move this part to NetworkConfigEventHandler
1429 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
1430 switch (event.type()) {
1431 case CONFIG_ADDED:
Charles Chan278ce832017-06-26 15:25:09 -07001432 log.info("Segment Routing Device Config added for {}", event.subject());
Charles Chan5270ed02016-01-30 23:22:37 -08001433 configureNetwork();
1434 break;
1435 case CONFIG_UPDATED:
Charles Chan278ce832017-06-26 15:25:09 -07001436 log.info("Segment Routing Config updated for {}", event.subject());
1437 // TODO support dynamic configuration
1438 break;
1439 default:
1440 break;
1441 }
1442 } else if (event.configClass().equals(InterfaceConfig.class)) {
1443 switch (event.type()) {
1444 case CONFIG_ADDED:
1445 log.info("Interface Config added for {}", event.subject());
1446 configureNetwork();
1447 break;
1448 case CONFIG_UPDATED:
1449 log.info("Interface Config updated for {}", event.subject());
Charles Chan5270ed02016-01-30 23:22:37 -08001450 // TODO support dynamic configuration
1451 break;
1452 default:
1453 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001454 }
Charles Chan5270ed02016-01-30 23:22:37 -08001455 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chanfc5c7802016-05-17 13:13:55 -07001456 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan5270ed02016-01-30 23:22:37 -08001457 switch (event.type()) {
1458 case CONFIG_ADDED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001459 appCfgHandler.processAppConfigAdded(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001460 break;
1461 case CONFIG_UPDATED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001462 appCfgHandler.processAppConfigUpdated(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001463 break;
1464 case CONFIG_REMOVED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001465 appCfgHandler.processAppConfigRemoved(event);
1466 break;
1467 default:
1468 break;
1469 }
Charles Chan03a73e02016-10-24 14:52:01 -07001470 configureNetwork();
Charles Chanfc5c7802016-05-17 13:13:55 -07001471 } else if (event.configClass().equals(XConnectConfig.class)) {
1472 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
1473 switch (event.type()) {
1474 case CONFIG_ADDED:
1475 xConnectHandler.processXConnectConfigAdded(event);
1476 break;
1477 case CONFIG_UPDATED:
1478 xConnectHandler.processXConnectConfigUpdated(event);
1479 break;
1480 case CONFIG_REMOVED:
1481 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001482 break;
1483 default:
1484 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001485 }
Pier Ventref34966c2016-11-07 16:21:04 -08001486 } else if (event.configClass().equals(PwaasConfig.class)) {
1487 checkState(l2TunnelHandler != null, "L2TunnelHandler is not initialized");
1488 switch (event.type()) {
1489 case CONFIG_ADDED:
1490 l2TunnelHandler.processPwaasConfigAdded(event);
1491 break;
1492 case CONFIG_UPDATED:
1493 l2TunnelHandler.processPwaasConfigUpdated(event);
1494 break;
1495 case CONFIG_REMOVED:
1496 l2TunnelHandler.processPwaasConfigRemoved(event);
1497 break;
1498 default:
1499 break;
1500 }
Charles Chand6832882015-10-05 17:50:33 -07001501 }
1502 }
Saurav Das7bcbe702017-06-13 15:35:54 -07001503
1504 private final class ConfigChange implements Runnable {
1505 @Override
1506 public void run() {
1507 programmingScheduled.set(false);
1508 for (Device device : deviceService.getDevices()) {
1509 processDeviceAdded(device);
1510 }
1511 defaultRoutingHandler.startPopulationProcess();
1512 }
1513 }
Charles Chand6832882015-10-05 17:50:33 -07001514 }
Charles Chan68aa62d2015-11-09 16:37:23 -08001515
1516 private class InternalHostListener implements HostListener {
Charles Chan68aa62d2015-11-09 16:37:23 -08001517 @Override
1518 public void event(HostEvent event) {
Charles Chan68aa62d2015-11-09 16:37:23 -08001519 switch (event.type()) {
1520 case HOST_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001521 hostHandler.processHostAddedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001522 break;
1523 case HOST_MOVED:
Charles Chand2990362016-04-18 13:44:03 -07001524 hostHandler.processHostMovedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001525 break;
1526 case HOST_REMOVED:
Charles Chanf9a52702017-06-16 15:19:24 -07001527 hostHandler.processHostRemovedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001528 break;
1529 case HOST_UPDATED:
Charles Chand2990362016-04-18 13:44:03 -07001530 hostHandler.processHostUpdatedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001531 break;
1532 default:
1533 log.warn("Unsupported host event type: {}", event.type());
1534 break;
1535 }
1536 }
1537 }
1538
Charles Chand55e84d2016-03-30 17:54:24 -07001539 private class InternalMcastListener implements McastListener {
1540 @Override
1541 public void event(McastEvent event) {
1542 switch (event.type()) {
1543 case SOURCE_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001544 mcastHandler.processSourceAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001545 break;
1546 case SINK_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001547 mcastHandler.processSinkAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001548 break;
1549 case SINK_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001550 mcastHandler.processSinkRemoved(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001551 break;
1552 case ROUTE_ADDED:
1553 case ROUTE_REMOVED:
1554 default:
1555 break;
1556 }
1557 }
1558 }
Charles Chan35fd1a72016-06-13 18:54:31 -07001559
Charles Chan03a73e02016-10-24 14:52:01 -07001560 private class InternalRouteEventListener implements RouteListener {
1561 @Override
1562 public void event(RouteEvent event) {
1563 switch (event.type()) {
1564 case ROUTE_ADDED:
1565 routeHandler.processRouteAdded(event);
1566 break;
1567 case ROUTE_UPDATED:
1568 routeHandler.processRouteUpdated(event);
1569 break;
1570 case ROUTE_REMOVED:
1571 routeHandler.processRouteRemoved(event);
1572 break;
1573 default:
1574 break;
1575 }
1576 }
1577 }
Saurav Dasc88d4662017-05-15 15:34:25 -07001578
sanghob35a6192015-04-01 13:05:26 -07001579}