blob: 01a09e423454985fda96544afbfc6199a3e26ea1 [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sanghob35a6192015-04-01 13:05:26 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.segmentrouting;
17
Charles Chan7ffd81f2017-02-08 15:52:08 -080018import com.google.common.collect.HashMultimap;
Charles Chanc81c45b2016-10-20 17:02:44 -070019import com.google.common.collect.Maps;
Charles Chan7ffd81f2017-02-08 15:52:08 -080020import com.google.common.collect.Multimap;
sanghob35a6192015-04-01 13:05:26 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
sangho1e575652015-05-14 00:39:53 -070026import org.apache.felix.scr.annotations.Service;
sanghob35a6192015-04-01 13:05:26 -070027import org.onlab.packet.Ethernet;
Pier Ventre735b8c82016-12-02 08:16:05 -080028import org.onlab.packet.ICMP6;
Charles Chanc42e84e2015-10-20 16:24:19 -070029import org.onlab.packet.IPv4;
Pier Ventre10bd8d12016-11-26 21:05:22 -080030import org.onlab.packet.IPv6;
Charles Chanc42e84e2015-10-20 16:24:19 -070031import org.onlab.packet.IpPrefix;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070032import org.onlab.packet.VlanId;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070033import org.onlab.util.KryoNamespace;
Saurav Das80980c72016-03-23 11:22:49 -070034import org.onosproject.cfg.ComponentConfigService;
sanghob35a6192015-04-01 13:05:26 -070035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
37import org.onosproject.event.Event;
Charles Chand55e84d2016-03-30 17:54:24 -070038import org.onosproject.incubator.net.config.basics.McastConfig;
Pier Luigi721b6622017-02-03 13:34:21 -080039import org.onosproject.incubator.net.intf.Interface;
Charles Chan2c15aca2016-11-09 20:51:44 -080040import org.onosproject.incubator.net.intf.InterfaceService;
Charles Chan03a73e02016-10-24 14:52:01 -070041import org.onosproject.incubator.net.routing.RouteEvent;
42import org.onosproject.incubator.net.routing.RouteListener;
43import org.onosproject.incubator.net.routing.RouteService;
Pier Ventre735b8c82016-12-02 08:16:05 -080044import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070045import org.onosproject.mastership.MastershipService;
Pier Ventre10bd8d12016-11-26 21:05:22 -080046import org.onosproject.net.ConnectPoint;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070047import org.onosproject.net.Device;
48import org.onosproject.net.DeviceId;
49import org.onosproject.net.Link;
50import org.onosproject.net.Port;
Charles Chan68aa62d2015-11-09 16:37:23 -080051import org.onosproject.net.PortNumber;
Charles Chand6832882015-10-05 17:50:33 -070052import org.onosproject.net.config.ConfigFactory;
53import org.onosproject.net.config.NetworkConfigEvent;
Charles Chand6832882015-10-05 17:50:33 -070054import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070055import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chand6832882015-10-05 17:50:33 -070056import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070057import org.onosproject.net.device.DeviceEvent;
58import org.onosproject.net.device.DeviceListener;
59import org.onosproject.net.device.DeviceService;
Charles Chan68aa62d2015-11-09 16:37:23 -080060import org.onosproject.net.flow.TrafficSelector;
61import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070062import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chan68aa62d2015-11-09 16:37:23 -080063import org.onosproject.net.host.HostEvent;
64import org.onosproject.net.host.HostListener;
Pier Ventre10bd8d12016-11-26 21:05:22 -080065import org.onosproject.net.host.HostService;
66import org.onosproject.net.link.LinkEvent;
67import org.onosproject.net.link.LinkListener;
68import org.onosproject.net.link.LinkService;
Charles Chand55e84d2016-03-30 17:54:24 -070069import org.onosproject.net.mcast.McastEvent;
70import org.onosproject.net.mcast.McastListener;
71import org.onosproject.net.mcast.MulticastRouteService;
Pier Ventre10bd8d12016-11-26 21:05:22 -080072import org.onosproject.net.packet.InboundPacket;
73import org.onosproject.net.packet.PacketContext;
74import org.onosproject.net.packet.PacketProcessor;
75import org.onosproject.net.packet.PacketService;
Pier Ventre42287df2016-11-09 14:17:26 -080076import org.onosproject.net.topology.PathService;
Charles Chand55e84d2016-03-30 17:54:24 -070077import org.onosproject.net.topology.TopologyService;
78import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
79import org.onosproject.segmentrouting.config.DeviceConfiguration;
Pier Ventref34966c2016-11-07 16:21:04 -080080import org.onosproject.segmentrouting.config.PwaasConfig;
Pier Ventre10bd8d12016-11-26 21:05:22 -080081import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Pier Ventref34966c2016-11-07 16:21:04 -080082import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Charles Chanfc5c7802016-05-17 13:13:55 -070083import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chand55e84d2016-03-30 17:54:24 -070084import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
85import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Charles Chand2990362016-04-18 13:44:03 -070086import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
87import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
Charles Chand2990362016-04-18 13:44:03 -070088import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
Charles Chan59cc16d2017-02-02 16:20:42 -080089import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
Charles Chanfc5c7802016-05-17 13:13:55 -070090import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Pier Ventref34966c2016-11-07 16:21:04 -080091import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070092import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070093import org.onosproject.store.service.EventuallyConsistentMap;
94import org.onosproject.store.service.EventuallyConsistentMapBuilder;
95import org.onosproject.store.service.StorageService;
96import org.onosproject.store.service.WallClockTimestamp;
Charles Chan35fd1a72016-06-13 18:54:31 -070097import org.opencord.cordconfig.CordConfigEvent;
98import org.opencord.cordconfig.CordConfigListener;
99import org.opencord.cordconfig.CordConfigService;
sanghob35a6192015-04-01 13:05:26 -0700100import org.slf4j.Logger;
101import org.slf4j.LoggerFactory;
102
sangho1e575652015-05-14 00:39:53 -0700103import java.util.List;
sanghob35a6192015-04-01 13:05:26 -0700104import java.util.Map;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700105import java.util.Set;
sanghob35a6192015-04-01 13:05:26 -0700106import java.util.concurrent.ConcurrentHashMap;
107import java.util.concurrent.ConcurrentLinkedQueue;
108import java.util.concurrent.Executors;
109import java.util.concurrent.ScheduledExecutorService;
110import java.util.concurrent.ScheduledFuture;
111import java.util.concurrent.TimeUnit;
Charles Chan7ffd81f2017-02-08 15:52:08 -0800112import java.util.stream.Collectors;
sanghob35a6192015-04-01 13:05:26 -0700113
Charles Chan3e783d02016-02-26 22:19:52 -0800114import static com.google.common.base.Preconditions.checkState;
Pier Ventree0ae7a32016-11-23 09:57:42 -0800115import static org.onlab.packet.Ethernet.TYPE_ARP;
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700116import static org.onlab.util.Tools.groupedThreads;
Charles Chan3e783d02016-02-26 22:19:52 -0800117
Charles Chane849c192016-01-11 18:28:54 -0800118/**
119 * Segment routing manager.
120 */
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700121@Service
122@Component(immediate = true)
sangho1e575652015-05-14 00:39:53 -0700123public class SegmentRoutingManager implements SegmentRoutingService {
sanghob35a6192015-04-01 13:05:26 -0700124
Charles Chan2c15aca2016-11-09 20:51:44 -0800125 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
sanghob35a6192015-04-01 13:05:26 -0700126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700128 private ComponentConfigService compCfgService;
sanghob35a6192015-04-01 13:05:26 -0700129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre10bd8d12016-11-26 21:05:22 -0800131 private NeighbourResolutionService neighbourResolutionService;
132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800134 public PathService pathService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700137 CoreService coreService;
sanghob35a6192015-04-01 13:05:26 -0700138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700140 PacketService packetService;
sanghob35a6192015-04-01 13:05:26 -0700141
142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700143 HostService hostService;
sanghob35a6192015-04-01 13:05:26 -0700144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700146 DeviceService deviceService;
sanghob35a6192015-04-01 13:05:26 -0700147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800149 public FlowObjectiveService flowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -0700150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan03a73e02016-10-24 14:52:01 -0700152 LinkService linkService;
sangho1e575652015-05-14 00:39:53 -0700153
Charles Chan5270ed02016-01-30 23:22:37 -0800154 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800155 public MastershipService mastershipService;
Charles Chan03a73e02016-10-24 14:52:01 -0700156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventre42287df2016-11-09 14:17:26 -0800158 public StorageService storageService;
Charles Chan03a73e02016-10-24 14:52:01 -0700159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
161 MulticastRouteService multicastRouteService;
162
163 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
164 TopologyService topologyService;
165
166 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
167 CordConfigService cordConfigService;
168
169 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
170 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 Chan03a73e02016-10-24 14:52:01 -0700194 HostHandler hostHandler = null;
Charles Chan35fd1a72016-06-13 18:54:31 -0700195 private CordConfigHandler cordConfigHandler = null;
Pier Ventre10bd8d12016-11-26 21:05:22 -0800196 private RouteHandler routeHandler = null;
Pier Ventre735b8c82016-12-02 08:16:05 -0800197 private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
Pier Ventref34966c2016-11-07 16:21:04 -0800198 private L2TunnelHandler l2TunnelHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700199 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan5270ed02016-01-30 23:22:37 -0800200 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chand55e84d2016-03-30 17:54:24 -0700201 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
202 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan35fd1a72016-06-13 18:54:31 -0700203 private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
Charles Chan03a73e02016-10-24 14:52:01 -0700204 private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
sanghob35a6192015-04-01 13:05:26 -0700205
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700206 private ScheduledExecutorService executorService = Executors
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700207 .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
sanghob35a6192015-04-01 13:05:26 -0700208
Saurav Das4ce45962015-11-24 23:21:05 -0800209 @SuppressWarnings("unused")
sanghob35a6192015-04-01 13:05:26 -0700210 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das4ce45962015-11-24 23:21:05 -0800211 @SuppressWarnings("rawtypes")
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700212 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
Charles Chan68aa62d2015-11-09 16:37:23 -0800213 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chane849c192016-01-11 18:28:54 -0800214 new ConcurrentHashMap<>();
215 /**
216 * Per device next objective ID store with (device id + neighbor set) as key.
217 */
Ray Milkeye4afdb52017-04-05 09:42:04 -0700218 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
Charles Chan68aa62d2015-11-09 16:37:23 -0800219 nsNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800220 /**
221 * Per device next objective ID store with (device id + subnet) as key.
222 */
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 /**
226 * Per device next objective ID store with (device id + port) as key.
227 */
Ray Milkeye4afdb52017-04-05 09:42:04 -0700228 EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das4ce45962015-11-24 23:21:05 -0800229 portNextObjStore = null;
Charles Chan59cc16d2017-02-02 16:20:42 -0800230
Saurav Das4ce45962015-11-24 23:21:05 -0800231 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
232 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho0b2b6d12015-05-20 22:16:38 -0700233
Charles Chand55e84d2016-03-30 17:54:24 -0700234 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700235 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
236 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700237 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chand6832882015-10-05 17:50:33 -0700238 @Override
Charles Chan5270ed02016-01-30 23:22:37 -0800239 public SegmentRoutingDeviceConfig createConfig() {
240 return new SegmentRoutingDeviceConfig();
Charles Chand6832882015-10-05 17:50:33 -0700241 }
242 };
Pier Ventref34966c2016-11-07 16:21:04 -0800243
Charles Chand55e84d2016-03-30 17:54:24 -0700244 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700245 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
246 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700247 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan5270ed02016-01-30 23:22:37 -0800248 @Override
249 public SegmentRoutingAppConfig createConfig() {
250 return new SegmentRoutingAppConfig();
251 }
252 };
Pier Ventref34966c2016-11-07 16:21:04 -0800253
Charles Chanfc5c7802016-05-17 13:13:55 -0700254 private final ConfigFactory<ApplicationId, XConnectConfig> xConnectConfigFactory =
255 new ConfigFactory<ApplicationId, XConnectConfig>(
256 SubjectFactories.APP_SUBJECT_FACTORY,
257 XConnectConfig.class, "xconnect") {
258 @Override
259 public XConnectConfig createConfig() {
260 return new XConnectConfig();
261 }
262 };
Pier Ventref34966c2016-11-07 16:21:04 -0800263
Charles Chand55e84d2016-03-30 17:54:24 -0700264 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700265 new ConfigFactory<ApplicationId, McastConfig>(
266 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700267 McastConfig.class, "multicast") {
268 @Override
269 public McastConfig createConfig() {
270 return new McastConfig();
271 }
272 };
273
Pier Ventref34966c2016-11-07 16:21:04 -0800274 private final ConfigFactory<ApplicationId, PwaasConfig> pwaasConfigFactory =
275 new ConfigFactory<ApplicationId, PwaasConfig>(
276 SubjectFactories.APP_SUBJECT_FACTORY,
277 PwaasConfig.class, "pwaas") {
278 @Override
279 public PwaasConfig createConfig() {
280 return new PwaasConfig();
281 }
282 };
283
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700284 private Object threadSchedulerLock = new Object();
285 private static int numOfEventsQueued = 0;
286 private static int numOfEventsExecuted = 0;
sanghob35a6192015-04-01 13:05:26 -0700287 private static int numOfHandlerExecution = 0;
288 private static int numOfHandlerScheduled = 0;
289
Charles Chan116188d2016-02-18 14:22:42 -0800290 /**
291 * Segment Routing App ID.
292 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800293 public static final String APP_NAME = "org.onosproject.segmentrouting";
Charles Chan59cc16d2017-02-02 16:20:42 -0800294
Charles Chane849c192016-01-11 18:28:54 -0800295 /**
296 * The default VLAN ID assigned to the interfaces without subnet config.
297 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800298 public static final VlanId INTERNAL_VLAN = VlanId.vlanId((short) 4094);
Saurav Das0e99e2b2015-10-28 12:39:42 -0700299
sanghob35a6192015-04-01 13:05:26 -0700300 @Activate
301 protected void activate() {
Charles Chan2c15aca2016-11-09 20:51:44 -0800302 appId = coreService.registerApplication(APP_NAME);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700303
304 log.debug("Creating EC map nsnextobjectivestore");
305 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
306 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700307 nsNextObjStore = nsNextObjMapBuilder
308 .withName("nsnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700309 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700310 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700311 .build();
312 log.trace("Current size {}", nsNextObjStore.size());
313
Charles Chan59cc16d2017-02-02 16:20:42 -0800314 log.debug("Creating EC map vlannextobjectivestore");
315 EventuallyConsistentMapBuilder<VlanNextObjectiveStoreKey, Integer>
316 vlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
317 vlanNextObjStore = vlanNextObjMapBuilder
318 .withName("vlannextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700319 .withSerializer(createSerializer())
Charles Chanc42e84e2015-10-20 16:24:19 -0700320 .withTimestampProvider((k, v) -> new WallClockTimestamp())
321 .build();
322
Saurav Das4ce45962015-11-24 23:21:05 -0800323 log.debug("Creating EC map subnetnextobjectivestore");
324 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
325 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
326 portNextObjStore = portNextObjMapBuilder
327 .withName("portnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700328 .withSerializer(createSerializer())
Saurav Das4ce45962015-11-24 23:21:05 -0800329 .withTimestampProvider((k, v) -> new WallClockTimestamp())
330 .build();
331
sangho0b2b6d12015-05-20 22:16:38 -0700332 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
333 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700334 tunnelStore = tunnelMapBuilder
335 .withName("tunnelstore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700336 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700337 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700338 .build();
339
340 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
341 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700342 policyStore = policyMapBuilder
343 .withName("policystore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700344 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700345 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700346 .build();
347
Saurav Das80980c72016-03-23 11:22:49 -0700348 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800349 "purgeOnDisconnection", "true");
Saurav Das80980c72016-03-23 11:22:49 -0700350 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800351 "purgeOnDisconnection", "true");
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800352 compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
353 "requestInterceptsEnabled", "false");
Pier Luigi7e415132017-01-12 22:46:39 -0800354 compCfgService.preSetProperty("org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager",
355 "requestInterceptsEnabled", "false");
356 compCfgService.preSetProperty("org.onosproject.dhcprelay.DhcpRelay",
357 "arpEnabled", "false");
Pier Luigi9b1d6262017-02-02 22:31:34 -0800358 compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
359 "greedyLearningIpv6", "true");
Charles Chanc6d227e2017-02-28 15:15:17 -0800360 compCfgService.preSetProperty("org.onosproject.routing.cpr.ControlPlaneRedirectManager",
361 "forceUnprovision", "true");
Saurav Das80980c72016-03-23 11:22:49 -0700362
Charles Chanb8e10c82015-10-14 11:24:40 -0700363 processor = new InternalPacketProcessor();
364 linkListener = new InternalLinkListener();
365 deviceListener = new InternalDeviceListener();
Charles Chanfc5c7802016-05-17 13:13:55 -0700366 appCfgHandler = new AppConfigHandler(this);
367 xConnectHandler = new XConnectHandler(this);
Charles Chand2990362016-04-18 13:44:03 -0700368 mcastHandler = new McastHandler(this);
369 hostHandler = new HostHandler(this);
Charles Chan35fd1a72016-06-13 18:54:31 -0700370 cordConfigHandler = new CordConfigHandler(this);
Charles Chan03a73e02016-10-24 14:52:01 -0700371 routeHandler = new RouteHandler(this);
Pier Ventre735b8c82016-12-02 08:16:05 -0800372 neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
Pier Ventref34966c2016-11-07 16:21:04 -0800373 l2TunnelHandler = new L2TunnelHandler(this);
Charles Chanb8e10c82015-10-14 11:24:40 -0700374
Charles Chan3e783d02016-02-26 22:19:52 -0800375 cfgService.addListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700376 cfgService.registerConfigFactory(deviceConfigFactory);
377 cfgService.registerConfigFactory(appConfigFactory);
Charles Chanfc5c7802016-05-17 13:13:55 -0700378 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700379 cfgService.registerConfigFactory(mcastConfigFactory);
Pier Ventref34966c2016-11-07 16:21:04 -0800380 cfgService.registerConfigFactory(pwaasConfigFactory);
Charles Chan5270ed02016-01-30 23:22:37 -0800381 hostService.addListener(hostListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700382 packetService.addProcessor(processor, PacketProcessor.director(2));
383 linkService.addListener(linkListener);
384 deviceService.addListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700385 multicastRouteService.addListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700386 cordConfigService.addListener(cordConfigListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700387
388 cfgListener.configureNetwork();
389
Charles Chan03a73e02016-10-24 14:52:01 -0700390 routeService.addListener(routeListener);
391
sanghob35a6192015-04-01 13:05:26 -0700392 log.info("Started");
393 }
394
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700395 private KryoNamespace.Builder createSerializer() {
396 return new KryoNamespace.Builder()
397 .register(KryoNamespaces.API)
398 .register(NeighborSetNextObjectiveStoreKey.class,
Charles Chan59cc16d2017-02-02 16:20:42 -0800399 VlanNextObjectiveStoreKey.class,
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700400 SubnetAssignedVidStoreKey.class,
401 NeighborSet.class,
402 Tunnel.class,
403 DefaultTunnel.class,
404 Policy.class,
405 TunnelPolicy.class,
406 Policy.Type.class,
407 PortNextObjectiveStoreKey.class,
Charles Chanfc5c7802016-05-17 13:13:55 -0700408 XConnectStoreKey.class
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700409 );
410 }
411
sanghob35a6192015-04-01 13:05:26 -0700412 @Deactivate
413 protected void deactivate() {
Charles Chand6832882015-10-05 17:50:33 -0700414 cfgService.removeListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700415 cfgService.unregisterConfigFactory(deviceConfigFactory);
416 cfgService.unregisterConfigFactory(appConfigFactory);
Charles Chan03a73e02016-10-24 14:52:01 -0700417 cfgService.unregisterConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700418 cfgService.unregisterConfigFactory(mcastConfigFactory);
Pier Ventref34966c2016-11-07 16:21:04 -0800419 cfgService.unregisterConfigFactory(pwaasConfigFactory);
Charles Chand6832882015-10-05 17:50:33 -0700420
sanghob35a6192015-04-01 13:05:26 -0700421 packetService.removeProcessor(processor);
Charles Chanb8e10c82015-10-14 11:24:40 -0700422 linkService.removeListener(linkListener);
423 deviceService.removeListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700424 multicastRouteService.removeListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700425 cordConfigService.removeListener(cordConfigListener);
Charles Chan03a73e02016-10-24 14:52:01 -0700426 routeService.removeListener(routeListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700427
Charles Chan0aa674e2017-02-23 15:44:08 -0800428 neighbourResolutionService.unregisterNeighbourHandlers(appId);
429
sanghob35a6192015-04-01 13:05:26 -0700430 processor = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700431 linkListener = null;
Charles Chand55e84d2016-03-30 17:54:24 -0700432 deviceListener = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700433 groupHandlerMap.clear();
434
Charles Chand55e84d2016-03-30 17:54:24 -0700435 nsNextObjStore.destroy();
Charles Chan59cc16d2017-02-02 16:20:42 -0800436 vlanNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700437 portNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700438 tunnelStore.destroy();
439 policyStore.destroy();
sanghob35a6192015-04-01 13:05:26 -0700440 log.info("Stopped");
441 }
442
sangho1e575652015-05-14 00:39:53 -0700443 @Override
444 public List<Tunnel> getTunnels() {
445 return tunnelHandler.getTunnels();
446 }
447
448 @Override
sangho71abe1b2015-06-29 14:58:47 -0700449 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
450 return tunnelHandler.createTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700451 }
452
453 @Override
sangho71abe1b2015-06-29 14:58:47 -0700454 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho1e575652015-05-14 00:39:53 -0700455 for (Policy policy: policyHandler.getPolicies()) {
456 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
457 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
458 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
459 log.warn("Cannot remove the tunnel used by a policy");
sangho71abe1b2015-06-29 14:58:47 -0700460 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho1e575652015-05-14 00:39:53 -0700461 }
462 }
463 }
sangho71abe1b2015-06-29 14:58:47 -0700464 return tunnelHandler.removeTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700465 }
466
467 @Override
sangho71abe1b2015-06-29 14:58:47 -0700468 public PolicyHandler.Result removePolicy(Policy policy) {
469 return policyHandler.removePolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700470 }
471
472 @Override
sangho71abe1b2015-06-29 14:58:47 -0700473 public PolicyHandler.Result createPolicy(Policy policy) {
474 return policyHandler.createPolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700475 }
476
477 @Override
478 public List<Policy> getPolicies() {
479 return policyHandler.getPolicies();
480 }
481
Saurav Das59232cf2016-04-27 18:35:50 -0700482 @Override
483 public void rerouteNetwork() {
484 cfgListener.configureNetwork();
485 for (Device device : deviceService.getDevices()) {
Saurav Das018605f2017-02-18 14:05:44 -0800486 if (mastershipService.isLocalMaster(device.id())) {
487 defaultRoutingHandler.populatePortAddressingRules(device.id());
488 }
Saurav Das59232cf2016-04-27 18:35:50 -0700489 }
490 defaultRoutingHandler.startPopulationProcess();
491 }
492
Charles Chanc81c45b2016-10-20 17:02:44 -0700493 @Override
Pier Ventre10bd8d12016-11-26 21:05:22 -0800494 public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
495 Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
Charles Chanc81c45b2016-10-20 17:02:44 -0700496 deviceService.getAvailableDevices().forEach(device -> {
497 deviceSubnetMap.put(device.id(), deviceConfiguration.getSubnets(device.id()));
498 });
499 return deviceSubnetMap;
500 }
501
sanghof9d0bf12015-05-19 11:57:42 -0700502 /**
Ray Milkeye4afdb52017-04-05 09:42:04 -0700503 * Extracts the application ID from the manager.
504 *
505 * @return application ID
506 */
507 public ApplicationId appId() {
508 return appId;
509 }
510
511 /**
512 * Returns the device configuration.
513 *
514 * @return device configuration
515 */
516 public DeviceConfiguration deviceConfiguration() {
517 return deviceConfiguration;
518 }
519
520 /**
521 * Per device next objective ID store with (device id + neighbor set) as key.
522 *
523 * @return next objective ID store
524 */
525 public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore() {
526 return nsNextObjStore;
527 }
528
529 /**
530 * Per device next objective ID store with (device id + subnet) as key.
531 *
532 * @return vlan next object store
533 */
534 public EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer> vlanNextObjStore() {
535 return vlanNextObjStore;
536 }
537
538 /**
539 * Per device next objective ID store with (device id + port) as key.
540 *
541 * @return port next object store.
542 */
543 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer> portNextObjStore() {
544 return portNextObjStore;
545 }
546
547 /**
Pier Ventre98161782016-10-31 15:00:01 -0700548 * Returns the MPLS-ECMP configuration.
549 *
550 * @return MPLS-ECMP value
551 */
552 public boolean getMplsEcmp() {
553 SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
554 .getConfig(this.appId, SegmentRoutingAppConfig.class);
555 return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
556 }
557
558 /**
sanghof9d0bf12015-05-19 11:57:42 -0700559 * Returns the tunnel object with the tunnel ID.
560 *
561 * @param tunnelId Tunnel ID
562 * @return Tunnel reference
563 */
sangho1e575652015-05-14 00:39:53 -0700564 public Tunnel getTunnel(String tunnelId) {
565 return tunnelHandler.getTunnel(tunnelId);
566 }
567
Charles Chan7ffd81f2017-02-08 15:52:08 -0800568 // TODO Consider moving these to InterfaceService
sanghob35a6192015-04-01 13:05:26 -0700569 /**
Charles Chan59cc16d2017-02-02 16:20:42 -0800570 * Returns untagged VLAN configured on given connect point.
Charles Chan7ffd81f2017-02-08 15:52:08 -0800571 * <p>
572 * Only returns the first match if there are multiple untagged VLAN configured
573 * on the connect point.
sanghob35a6192015-04-01 13:05:26 -0700574 *
Charles Chan59cc16d2017-02-02 16:20:42 -0800575 * @param connectPoint connect point
576 * @return untagged VLAN or null if not configured
sanghob35a6192015-04-01 13:05:26 -0700577 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800578 public VlanId getUntaggedVlanId(ConnectPoint connectPoint) {
579 return interfaceService.getInterfacesByPort(connectPoint).stream()
580 .filter(intf -> !intf.vlanUntagged().equals(VlanId.NONE))
581 .map(Interface::vlanUntagged)
582 .findFirst().orElse(null);
sanghob35a6192015-04-01 13:05:26 -0700583 }
584
sangho1e575652015-05-14 00:39:53 -0700585 /**
Charles Chan7ffd81f2017-02-08 15:52:08 -0800586 * Returns tagged VLAN configured on given connect point.
587 * <p>
588 * Returns all matches if there are multiple tagged VLAN configured
589 * on the connect point.
590 *
591 * @param connectPoint connect point
592 * @return tagged VLAN or empty set if not configured
593 */
594 public Set<VlanId> getTaggedVlanId(ConnectPoint connectPoint) {
595 Set<Interface> interfaces = interfaceService.getInterfacesByPort(connectPoint);
596 return interfaces.stream()
597 .map(Interface::vlanTagged)
598 .flatMap(vlanIds -> vlanIds.stream())
599 .collect(Collectors.toSet());
600 }
601
602 /**
603 * Returns native VLAN configured on given connect point.
604 * <p>
605 * Only returns the first match if there are multiple native VLAN configured
606 * on the connect point.
607 *
608 * @param connectPoint connect point
609 * @return native VLAN or null if not configured
610 */
611 public VlanId getNativeVlanId(ConnectPoint connectPoint) {
612 Set<Interface> interfaces = interfaceService.getInterfacesByPort(connectPoint);
613 return interfaces.stream()
614 .filter(intf -> !intf.vlanNative().equals(VlanId.NONE))
615 .map(Interface::vlanNative)
616 .findFirst()
617 .orElse(null);
618 }
619
620 /**
621 * Returns vlan port map of given device.
622 *
623 * @param deviceId device id
624 * @return vlan-port multimap
625 */
626 public Multimap<VlanId, PortNumber> getVlanPortMap(DeviceId deviceId) {
627 HashMultimap<VlanId, PortNumber> vlanPortMap = HashMultimap.create();
628
629 interfaceService.getInterfaces().stream()
630 .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
631 .forEach(intf -> {
632 vlanPortMap.put(intf.vlanUntagged(), intf.connectPoint().port());
633 intf.vlanTagged().forEach(vlanTagged -> {
634 vlanPortMap.put(vlanTagged, intf.connectPoint().port());
635 });
636 vlanPortMap.put(intf.vlanNative(), intf.connectPoint().port());
637 });
638 vlanPortMap.removeAll(VlanId.NONE);
639
640 return vlanPortMap;
641 }
642
643 /**
Saurav Das0e99e2b2015-10-28 12:39:42 -0700644 * Returns the next objective ID for the given NeighborSet.
Saurav Das8a0732e2015-11-20 15:27:53 -0800645 * If the nextObjective does not exist, a new one is created and
Saurav Das4ce45962015-11-24 23:21:05 -0800646 * its id is returned.
sangho1e575652015-05-14 00:39:53 -0700647 *
sanghof9d0bf12015-05-19 11:57:42 -0700648 * @param deviceId Device ID
649 * @param ns NegighborSet
Saurav Das8a0732e2015-11-20 15:27:53 -0800650 * @param meta metadata passed into the creation of a Next Objective
Pier Ventre917127a2016-10-31 16:49:19 -0700651 * @param isBos indicates if it is BoS or not
Saurav Das8a0732e2015-11-20 15:27:53 -0800652 * @return next objective ID or -1 if an error was encountered during the
653 * creation of the nextObjective
sangho1e575652015-05-14 00:39:53 -0700654 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800655 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
Pier Ventre917127a2016-10-31 16:49:19 -0700656 TrafficSelector meta, boolean isBos) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700657 if (groupHandlerMap.get(deviceId) != null) {
658 log.trace("getNextObjectiveId query in device {}", deviceId);
659 return groupHandlerMap
Pier Ventre917127a2016-10-31 16:49:19 -0700660 .get(deviceId).getNextObjectiveId(ns, meta, isBos);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700661 } else {
Saurav Das4ce45962015-11-24 23:21:05 -0800662 log.warn("getNextObjectiveId query - groupHandler for device {} "
663 + "not found", deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700664 return -1;
665 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700666 }
667
Charles Chanc42e84e2015-10-20 16:24:19 -0700668 /**
Pier Ventre917127a2016-10-31 16:49:19 -0700669 * Returns the next objective ID for the given NeighborSet.
670 * If the nextObjective does not exist, a new one is created and
671 * its id is returned.
672 *
673 * @param deviceId Device ID
674 * @param ns NegighborSet
675 * @param meta metadata passed into the creation of a Next Objective
676 * @return next objective ID or -1 if an error was encountered during the
677 * creation of the nextObjective
678 */
679 public int getNextObjectiveId(DeviceId deviceId,
680 NeighborSet ns,
681 TrafficSelector meta) {
682 return this.getNextObjectiveId(deviceId, ns, meta, true);
683 }
684
685 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800686 * Returns the next objective ID for the given subnet prefix. It is expected
Charles Chan59cc16d2017-02-02 16:20:42 -0800687 * Returns the next objective ID for the given vlan id. It is expected
Saurav Das4ce45962015-11-24 23:21:05 -0800688 * that the next-objective has been pre-created from configuration.
Charles Chanc42e84e2015-10-20 16:24:19 -0700689 *
690 * @param deviceId Device ID
Charles Chan59cc16d2017-02-02 16:20:42 -0800691 * @param vlanId VLAN ID
Saurav Das4ce45962015-11-24 23:21:05 -0800692 * @return next objective ID or -1 if it was not found
Charles Chanc42e84e2015-10-20 16:24:19 -0700693 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800694 public int getVlanNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
Charles Chanc42e84e2015-10-20 16:24:19 -0700695 if (groupHandlerMap.get(deviceId) != null) {
Charles Chan59cc16d2017-02-02 16:20:42 -0800696 log.trace("getVlanNextObjectiveId query in device {}", deviceId);
697 return groupHandlerMap.get(deviceId).getVlanNextObjectiveId(vlanId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700698 } else {
Charles Chan59cc16d2017-02-02 16:20:42 -0800699 log.warn("getVlanNextObjectiveId query - groupHandler for "
Saurav Das4ce45962015-11-24 23:21:05 -0800700 + "device {} not found", deviceId);
701 return -1;
702 }
703 }
704
705 /**
706 * Returns the next objective ID for the given portNumber, given the treatment.
707 * There could be multiple different treatments to the same outport, which
708 * would result in different objectives. If the next object
709 * does not exist, a new one is created and its id is returned.
710 *
711 * @param deviceId Device ID
712 * @param portNum port number on device for which NextObjective is queried
713 * @param treatment the actions to apply on the packets (should include outport)
714 * @param meta metadata passed into the creation of a Next Objective if necessary
Saurav Das59232cf2016-04-27 18:35:50 -0700715 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das4ce45962015-11-24 23:21:05 -0800716 */
717 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
718 TrafficTreatment treatment,
719 TrafficSelector meta) {
720 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
721 if (ghdlr != null) {
722 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
723 } else {
Charles Chane849c192016-01-11 18:28:54 -0800724 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
725 + " not found", deviceId);
726 return -1;
727 }
728 }
729
sanghob35a6192015-04-01 13:05:26 -0700730 private class InternalPacketProcessor implements PacketProcessor {
sanghob35a6192015-04-01 13:05:26 -0700731 @Override
732 public void process(PacketContext context) {
733
734 if (context.isHandled()) {
735 return;
736 }
737
738 InboundPacket pkt = context.inPacket();
739 Ethernet ethernet = pkt.parsed();
Pier Luigi7dad71c2017-02-01 13:50:04 -0800740
741 if (ethernet == null) {
742 return;
743 }
744
Saurav Das4ce45962015-11-24 23:21:05 -0800745 log.trace("Rcvd pktin: {}", ethernet);
Pier Ventree0ae7a32016-11-23 09:57:42 -0800746 if (ethernet.getEtherType() == TYPE_ARP) {
Saurav Das76ae6812017-03-15 15:15:14 -0700747 log.warn("Received unexpected ARP packet on {}", context.inPacket().receivedFrom());
748 log.trace("{}", ethernet);
Pier Ventre968da122016-12-09 17:26:04 -0800749 return;
sanghob35a6192015-04-01 13:05:26 -0700750 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
Pier Ventre735b8c82016-12-02 08:16:05 -0800751 IPv4 ipv4Packet = (IPv4) ethernet.getPayload();
752 //ipHandler.addToPacketBuffer(ipv4Packet);
753 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) {
754 icmpHandler.processIcmp(ethernet, pkt.receivedFrom());
sanghob35a6192015-04-01 13:05:26 -0700755 } else {
Charles Chan50035632017-01-13 17:20:44 -0800756 // NOTE: We don't support IP learning at this moment so this
757 // is not necessary. Also it causes duplication of DHCP packets.
Pier Ventre968da122016-12-09 17:26:04 -0800758 // ipHandler.processPacketIn(ipv4Packet, pkt.receivedFrom());
sanghob35a6192015-04-01 13:05:26 -0700759 }
Pier Ventre10bd8d12016-11-26 21:05:22 -0800760 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
761 IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
Pier Ventre735b8c82016-12-02 08:16:05 -0800762 //ipHandler.addToPacketBuffer(ipv6Packet);
Pier Luigi7dad71c2017-02-01 13:50:04 -0800763 // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
Pier Ventre735b8c82016-12-02 08:16:05 -0800764 if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
765 ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
766 if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST ||
767 icmp6Packet.getIcmpType() == ICMP6.ECHO_REPLY) {
768 icmpHandler.processIcmpv6(ethernet, pkt.receivedFrom());
769 } else {
Charles Chan0ed44fb2017-03-13 13:10:30 -0700770 log.debug("Received ICMPv6 0x{} - not handled",
771 Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
Pier Ventre735b8c82016-12-02 08:16:05 -0800772 }
773 } else {
774 // NOTE: We don't support IP learning at this moment so this
775 // is not necessary. Also it causes duplication of DHCPv6 packets.
776 // ipHandler.processPacketIn(ipv6Packet, pkt.receivedFrom());
777 }
sanghob35a6192015-04-01 13:05:26 -0700778 }
779 }
780 }
781
782 private class InternalLinkListener implements LinkListener {
783 @Override
784 public void event(LinkEvent event) {
Charles Chanb1f8c762017-03-29 16:39:05 -0700785 if (event.type() == LinkEvent.Type.LINK_ADDED ||
786 event.type() == LinkEvent.Type.LINK_UPDATED ||
787 event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700788 log.debug("Event {} received from Link Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700789 scheduleEventHandlerIfNotScheduled(event);
790 }
791 }
792 }
793
794 private class InternalDeviceListener implements DeviceListener {
sanghob35a6192015-04-01 13:05:26 -0700795 @Override
796 public void event(DeviceEvent event) {
sanghob35a6192015-04-01 13:05:26 -0700797 switch (event.type()) {
798 case DEVICE_ADDED:
Saurav Das1a129a02016-11-18 15:21:57 -0800799 case PORT_UPDATED:
800 case PORT_ADDED:
sangho20eff1d2015-04-13 15:15:58 -0700801 case DEVICE_UPDATED:
802 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700803 log.debug("Event {} received from Device Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700804 scheduleEventHandlerIfNotScheduled(event);
805 break;
806 default:
807 }
808 }
809 }
810
Saurav Das4ce45962015-11-24 23:21:05 -0800811 @SuppressWarnings("rawtypes")
sanghob35a6192015-04-01 13:05:26 -0700812 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700813 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700814 eventQueue.add(event);
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700815 numOfEventsQueued++;
816
817 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
818 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700819 eventHandlerFuture = executorService
820 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
821 numOfHandlerScheduled++;
822 }
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700823 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700824 numOfEventsQueued,
825 numOfHandlerScheduled);
sanghob35a6192015-04-01 13:05:26 -0700826 }
sanghob35a6192015-04-01 13:05:26 -0700827 }
828
829 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700830 @Override
sanghob35a6192015-04-01 13:05:26 -0700831 public void run() {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700832 try {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700833 while (true) {
Saurav Das4ce45962015-11-24 23:21:05 -0800834 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700835 Event event = null;
836 synchronized (threadSchedulerLock) {
837 if (!eventQueue.isEmpty()) {
838 event = eventQueue.poll();
839 numOfEventsExecuted++;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700840 } else {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700841 numOfHandlerExecution++;
842 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
843 numOfHandlerExecution, numOfEventsExecuted);
844 break;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700845 }
sangho20eff1d2015-04-13 15:15:58 -0700846 }
Charles Chanb1f8c762017-03-29 16:39:05 -0700847 if (event.type() == LinkEvent.Type.LINK_ADDED ||
848 event.type() == LinkEvent.Type.LINK_UPDATED) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700849 processLinkAdded((Link) event.subject());
850 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
Pier Ventre2c515312016-09-13 21:33:40 -0700851 Link linkRemoved = (Link) event.subject();
852 if (linkRemoved.src().elementId() instanceof DeviceId &&
853 !deviceService.isAvailable(linkRemoved.src().deviceId())) {
854 continue;
855 }
856 if (linkRemoved.dst().elementId() instanceof DeviceId &&
857 !deviceService.isAvailable(linkRemoved.dst().deviceId())) {
858 continue;
859 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700860 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700861 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
862 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
863 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800864 DeviceId deviceId = ((Device) event.subject()).id();
865 if (deviceService.isAvailable(deviceId)) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700866 log.info("Processing device event {} for available device {}",
867 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700868 processDeviceAdded((Device) event.subject());
Saurav Das80980c72016-03-23 11:22:49 -0700869 } else {
870 log.info("Processing device event {} for unavailable device {}",
871 event.type(), ((Device) event.subject()).id());
872 processDeviceRemoved((Device) event.subject());
873 }
Saurav Das1a129a02016-11-18 15:21:57 -0800874 } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
Saurav Dasd2fded02016-12-02 15:43:47 -0800875 // typically these calls come when device is added first time
876 // so port filtering rules are handled at the device_added event.
877 // port added calls represent all ports on the device,
878 // enabled or not.
Saurav Das1a129a02016-11-18 15:21:57 -0800879 log.debug("** PORT ADDED {}/{} -> {}",
Saurav Dasd2fded02016-12-02 15:43:47 -0800880 ((DeviceEvent) event).subject().id(),
881 ((DeviceEvent) event).port().number(),
882 event.type());
Saurav Das1a129a02016-11-18 15:21:57 -0800883 } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
Saurav Dasd2fded02016-12-02 15:43:47 -0800884 // these calls happen for every subsequent event
885 // ports enabled, disabled, switch goes away, comes back
Saurav Das1a129a02016-11-18 15:21:57 -0800886 log.info("** PORT UPDATED {}/{} -> {}",
887 event.subject(),
888 ((DeviceEvent) event).port(),
889 event.type());
890 processPortUpdated(((Device) event.subject()),
891 ((DeviceEvent) event).port());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700892 } else {
893 log.warn("Unhandled event type: {}", event.type());
894 }
sanghob35a6192015-04-01 13:05:26 -0700895 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700896 } catch (Exception e) {
897 log.error("SegmentRouting event handler "
898 + "thread thrown an exception: {}", e);
sanghob35a6192015-04-01 13:05:26 -0700899 }
sanghob35a6192015-04-01 13:05:26 -0700900 }
901 }
902
sanghob35a6192015-04-01 13:05:26 -0700903 private void processLinkAdded(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700904 log.info("** LINK ADDED {}", link.toString());
Charles Chan0b4e6182015-11-03 10:42:14 -0800905 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
906 log.warn("Source device of this link is not configured.");
907 return;
908 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700909 //Irrespective whether the local is a MASTER or not for this device,
910 //create group handler instance and push default TTP flow rules.
911 //Because in a multi-instance setup, instances can initiate
912 //groups for any devices. Also the default TTP rules are needed
913 //to be pushed before inserting any IP table entries for any device
914 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
915 .deviceId());
916 if (groupHandler != null) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800917 groupHandler.linkUp(link, mastershipService.isLocalMaster(
918 link.src().deviceId()));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700919 } else {
920 Device device = deviceService.getDevice(link.src().deviceId());
921 if (device != null) {
922 log.warn("processLinkAdded: Link Added "
923 + "Notification without Device Added "
924 + "event, still handling it");
925 processDeviceAdded(device);
926 groupHandler = groupHandlerMap.get(link.src()
927 .deviceId());
Saurav Das8a0732e2015-11-20 15:27:53 -0800928 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sanghob35a6192015-04-01 13:05:26 -0700929 }
930 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700931
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700932 log.trace("Starting optimized route population process");
933 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
934 //log.trace("processLinkAdded: re-starting route population process");
935 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700936
937 mcastHandler.init();
sanghob35a6192015-04-01 13:05:26 -0700938 }
939
940 private void processLinkRemoved(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700941 log.info("** LINK REMOVED {}", link.toString());
sangho834e4b02015-05-01 09:38:25 -0700942 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
943 if (groupHandler != null) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800944 groupHandler.portDown(link.src().port(),
945 mastershipService.isLocalMaster(link.src().deviceId()));
sangho834e4b02015-05-01 09:38:25 -0700946 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700947 log.trace("Starting optimized route population process");
948 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
949 //log.trace("processLinkRemoved: re-starting route population process");
950 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700951
952 mcastHandler.processLinkDown(link);
sanghob35a6192015-04-01 13:05:26 -0700953 }
954
955 private void processDeviceAdded(Device device) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700956 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan0b4e6182015-11-03 10:42:14 -0800957 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das2857f382015-11-03 14:39:27 -0800958 log.warn("Device configuration uploading. Device {} will be "
959 + "processed after config completes.", device.id());
960 return;
961 }
Charles Chan2199c302016-04-23 17:36:10 -0700962 processDeviceAddedInternal(device.id());
963 }
964
965 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700966 // Irrespective of whether the local is a MASTER or not for this device,
967 // we need to create a SR-group-handler instance. This is because in a
968 // multi-instance setup, any instance can initiate forwarding/next-objectives
969 // for any switch (even if this instance is a SLAVE or not even connected
970 // to the switch). To handle this, a default-group-handler instance is necessary
971 // per switch.
Charles Chan2199c302016-04-23 17:36:10 -0700972 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
973 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan0b4e6182015-11-03 10:42:14 -0800974 DefaultGroupHandler groupHandler;
975 try {
976 groupHandler = DefaultGroupHandler.
Charles Chan2199c302016-04-23 17:36:10 -0700977 createGroupHandler(deviceId,
978 appId,
979 deviceConfiguration,
980 linkService,
981 flowObjectiveService,
982 this);
Charles Chan0b4e6182015-11-03 10:42:14 -0800983 } catch (DeviceConfigNotFoundException e) {
984 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
985 return;
986 }
Charles Chan2199c302016-04-23 17:36:10 -0700987 log.debug("updating groupHandlerMap with new config for device: {}",
988 deviceId);
989 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das2857f382015-11-03 14:39:27 -0800990 }
Saurav Dasb5c236e2016-06-07 10:08:06 -0700991
Charles Chan2199c302016-04-23 17:36:10 -0700992 if (mastershipService.isLocalMaster(deviceId)) {
Saurav Das018605f2017-02-18 14:05:44 -0800993 defaultRoutingHandler.populatePortAddressingRules(deviceId);
Charles Chan03a73e02016-10-24 14:52:01 -0700994 hostHandler.init(deviceId);
Charles Chanfc5c7802016-05-17 13:13:55 -0700995 xConnectHandler.init(deviceId);
Charles Chan35fd1a72016-06-13 18:54:31 -0700996 cordConfigHandler.init(deviceId);
Charles Chan2199c302016-04-23 17:36:10 -0700997 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chan59cc16d2017-02-02 16:20:42 -0800998 groupHandler.createGroupsFromVlanConfig();
Charles Chan2199c302016-04-23 17:36:10 -0700999 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chanc42e84e2015-10-20 16:24:19 -07001000 }
Charles Chan5270ed02016-01-30 23:22:37 -08001001
Charles Chan03a73e02016-10-24 14:52:01 -07001002 appCfgHandler.init(deviceId);
1003 routeHandler.init(deviceId);
sanghob35a6192015-04-01 13:05:26 -07001004 }
1005
Saurav Das80980c72016-03-23 11:22:49 -07001006 private void processDeviceRemoved(Device device) {
1007 nsNextObjStore.entrySet().stream()
1008 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
1009 .forEach(entry -> {
1010 nsNextObjStore.remove(entry.getKey());
1011 });
Charles Chan59cc16d2017-02-02 16:20:42 -08001012 vlanNextObjStore.entrySet().stream()
Saurav Das80980c72016-03-23 11:22:49 -07001013 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
1014 .forEach(entry -> {
Charles Chan59cc16d2017-02-02 16:20:42 -08001015 vlanNextObjStore.remove(entry.getKey());
Saurav Das80980c72016-03-23 11:22:49 -07001016 });
Saurav Das80980c72016-03-23 11:22:49 -07001017 portNextObjStore.entrySet().stream()
1018 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
1019 .forEach(entry -> {
1020 portNextObjStore.remove(entry.getKey());
1021 });
Saurav Das80980c72016-03-23 11:22:49 -07001022 groupHandlerMap.remove(device.id());
Saurav Das80980c72016-03-23 11:22:49 -07001023 defaultRoutingHandler.purgeEcmpGraph(device.id());
Charles Chan2199c302016-04-23 17:36:10 -07001024 mcastHandler.removeDevice(device.id());
Charles Chanfc5c7802016-05-17 13:13:55 -07001025 xConnectHandler.removeDevice(device.id());
Saurav Das80980c72016-03-23 11:22:49 -07001026 }
1027
Saurav Das1a129a02016-11-18 15:21:57 -08001028 private void processPortUpdated(Device device, Port port) {
1029 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
1030 log.warn("Device configuration uploading. Not handling port event for"
1031 + "dev: {} port: {}", device.id(), port.number());
1032 return;
1033 }
Saurav Das018605f2017-02-18 14:05:44 -08001034
1035 if (!mastershipService.isLocalMaster(device.id())) {
1036 log.debug("Not master for dev:{} .. not handling port updated event"
1037 + "for port {}", device.id(), port.number());
1038 return;
1039 }
1040
1041 // first we handle filtering rules associated with the port
1042 if (port.isEnabled()) {
1043 log.info("Switchport {}/{} enabled..programming filters",
1044 device.id(), port.number());
Charles Chan7e4f8192017-02-26 22:59:35 -08001045 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), true);
Saurav Das018605f2017-02-18 14:05:44 -08001046 } else {
1047 log.info("Switchport {}/{} disabled..removing filters",
1048 device.id(), port.number());
Charles Chan7e4f8192017-02-26 22:59:35 -08001049 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), false);
Saurav Das018605f2017-02-18 14:05:44 -08001050 }
Saurav Das1a129a02016-11-18 15:21:57 -08001051
1052 // portUpdated calls are for ports that have gone down or up. For switch
1053 // to switch ports, link-events should take care of any re-routing or
1054 // group editing necessary for port up/down. Here we only process edge ports
1055 // that are already configured.
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001056 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
1057 VlanId untaggedVlan = getUntaggedVlanId(cp);
1058 VlanId nativeVlan = getNativeVlanId(cp);
1059 Set<VlanId> taggedVlans = getTaggedVlanId(cp);
Charles Chan59cc16d2017-02-02 16:20:42 -08001060
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001061 if (untaggedVlan == null && nativeVlan == null && taggedVlans.isEmpty()) {
Saurav Das1a129a02016-11-18 15:21:57 -08001062 log.debug("Not handling port updated event for unconfigured port "
1063 + "dev/port: {}/{}", device.id(), port.number());
1064 return;
1065 }
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001066 if (untaggedVlan != null) {
1067 processEdgePort(device, port, untaggedVlan, true);
1068 }
1069 if (nativeVlan != null) {
1070 processEdgePort(device, port, nativeVlan, true);
1071 }
1072 if (!taggedVlans.isEmpty()) {
1073 taggedVlans.forEach(tag -> processEdgePort(device, port, tag, false));
1074 }
Saurav Das1a129a02016-11-18 15:21:57 -08001075 }
1076
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001077 private void processEdgePort(Device device, Port port, VlanId vlanId,
1078 boolean popVlan) {
Saurav Das1a129a02016-11-18 15:21:57 -08001079 boolean portUp = port.isEnabled();
1080 if (portUp) {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001081 log.info("Device:EdgePort {}:{} is enabled in vlan: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001082 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001083 } else {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001084 log.info("Device:EdgePort {}:{} is disabled in vlan: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001085 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001086 }
1087
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -07001088 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -07001089 if (groupHandler != null) {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001090 groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
Saurav Das1a129a02016-11-18 15:21:57 -08001091 } else {
1092 log.warn("Group handler not found for dev:{}. Not handling edge port"
1093 + " {} event for port:{}", device.id(),
1094 (portUp) ? "UP" : "DOWN", port.number());
sanghob35a6192015-04-01 13:05:26 -07001095 }
1096 }
sangho1e575652015-05-14 00:39:53 -07001097
Pier Ventre10bd8d12016-11-26 21:05:22 -08001098 /**
1099 * Registers the given connect point with the NRS, this is necessary
1100 * to receive the NDP and ARP packets from the NRS.
1101 *
1102 * @param portToRegister connect point to register
1103 */
1104 public void registerConnectPoint(ConnectPoint portToRegister) {
Charles Chan0aa674e2017-02-23 15:44:08 -08001105 neighbourResolutionService.registerNeighbourHandler(
Pier Ventre10bd8d12016-11-26 21:05:22 -08001106 portToRegister,
1107 neighbourHandler,
1108 appId
1109 );
1110 }
1111
Charles Chand6832882015-10-05 17:50:33 -07001112 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan2c15aca2016-11-09 20:51:44 -08001113 SegmentRoutingManager srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001114
Charles Chane849c192016-01-11 18:28:54 -08001115 /**
1116 * Constructs the internal network config listener.
1117 *
Charles Chan2c15aca2016-11-09 20:51:44 -08001118 * @param srManager segment routing manager
Charles Chane849c192016-01-11 18:28:54 -08001119 */
Charles Chan2c15aca2016-11-09 20:51:44 -08001120 public InternalConfigListener(SegmentRoutingManager srManager) {
1121 this.srManager = srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001122 }
1123
Charles Chane849c192016-01-11 18:28:54 -08001124 /**
1125 * Reads network config and initializes related data structure accordingly.
1126 */
Charles Chan4636be02015-10-07 14:21:45 -07001127 public void configureNetwork() {
Pier Ventre10bd8d12016-11-26 21:05:22 -08001128
Charles Chan2c15aca2016-11-09 20:51:44 -08001129 deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan4636be02015-10-07 14:21:45 -07001130
Charles Chan2c15aca2016-11-09 20:51:44 -08001131 arpHandler = new ArpHandler(srManager);
1132 icmpHandler = new IcmpHandler(srManager);
1133 ipHandler = new IpHandler(srManager);
1134 routingRulePopulator = new RoutingRulePopulator(srManager);
1135 defaultRoutingHandler = new DefaultRoutingHandler(srManager);
Charles Chan4636be02015-10-07 14:21:45 -07001136
1137 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
1138 groupHandlerMap, tunnelStore);
1139 policyHandler = new PolicyHandler(appId, deviceConfiguration,
1140 flowObjectiveService,
1141 tunnelHandler, policyStore);
1142
Charles Chan4636be02015-10-07 14:21:45 -07001143 for (Device device : deviceService.getDevices()) {
Charles Chan2199c302016-04-23 17:36:10 -07001144 processDeviceAddedInternal(device.id());
Charles Chan4636be02015-10-07 14:21:45 -07001145 }
1146
1147 defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -07001148 mcastHandler.init();
Charles Chan4636be02015-10-07 14:21:45 -07001149 }
1150
Charles Chand6832882015-10-05 17:50:33 -07001151 @Override
1152 public void event(NetworkConfigEvent event) {
Charles Chan5270ed02016-01-30 23:22:37 -08001153 // TODO move this part to NetworkConfigEventHandler
1154 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
1155 switch (event.type()) {
1156 case CONFIG_ADDED:
1157 log.info("Segment Routing Config added.");
1158 configureNetwork();
1159 break;
1160 case CONFIG_UPDATED:
1161 log.info("Segment Routing Config updated.");
1162 // TODO support dynamic configuration
1163 break;
1164 default:
1165 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001166 }
Charles Chan5270ed02016-01-30 23:22:37 -08001167 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chanfc5c7802016-05-17 13:13:55 -07001168 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan5270ed02016-01-30 23:22:37 -08001169 switch (event.type()) {
1170 case CONFIG_ADDED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001171 appCfgHandler.processAppConfigAdded(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001172 break;
1173 case CONFIG_UPDATED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001174 appCfgHandler.processAppConfigUpdated(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001175 break;
1176 case CONFIG_REMOVED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001177 appCfgHandler.processAppConfigRemoved(event);
1178 break;
1179 default:
1180 break;
1181 }
Charles Chan03a73e02016-10-24 14:52:01 -07001182 configureNetwork();
Charles Chanfc5c7802016-05-17 13:13:55 -07001183 } else if (event.configClass().equals(XConnectConfig.class)) {
1184 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
1185 switch (event.type()) {
1186 case CONFIG_ADDED:
1187 xConnectHandler.processXConnectConfigAdded(event);
1188 break;
1189 case CONFIG_UPDATED:
1190 xConnectHandler.processXConnectConfigUpdated(event);
1191 break;
1192 case CONFIG_REMOVED:
1193 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001194 break;
1195 default:
1196 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001197 }
Pier Ventref34966c2016-11-07 16:21:04 -08001198 } else if (event.configClass().equals(PwaasConfig.class)) {
1199 checkState(l2TunnelHandler != null, "L2TunnelHandler is not initialized");
1200 switch (event.type()) {
1201 case CONFIG_ADDED:
1202 l2TunnelHandler.processPwaasConfigAdded(event);
1203 break;
1204 case CONFIG_UPDATED:
1205 l2TunnelHandler.processPwaasConfigUpdated(event);
1206 break;
1207 case CONFIG_REMOVED:
1208 l2TunnelHandler.processPwaasConfigRemoved(event);
1209 break;
1210 default:
1211 break;
1212 }
Charles Chand6832882015-10-05 17:50:33 -07001213 }
1214 }
1215 }
Charles Chan68aa62d2015-11-09 16:37:23 -08001216
1217 private class InternalHostListener implements HostListener {
Charles Chan68aa62d2015-11-09 16:37:23 -08001218 @Override
1219 public void event(HostEvent event) {
1220 // Do not proceed without mastership
1221 DeviceId deviceId = event.subject().location().deviceId();
1222 if (!mastershipService.isLocalMaster(deviceId)) {
1223 return;
1224 }
1225
1226 switch (event.type()) {
1227 case HOST_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001228 hostHandler.processHostAddedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001229 break;
1230 case HOST_MOVED:
Charles Chand2990362016-04-18 13:44:03 -07001231 hostHandler.processHostMovedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001232 break;
1233 case HOST_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001234 hostHandler.processHostRemoveEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001235 break;
1236 case HOST_UPDATED:
Charles Chand2990362016-04-18 13:44:03 -07001237 hostHandler.processHostUpdatedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001238 break;
1239 default:
1240 log.warn("Unsupported host event type: {}", event.type());
1241 break;
1242 }
1243 }
1244 }
1245
Charles Chand55e84d2016-03-30 17:54:24 -07001246 private class InternalMcastListener implements McastListener {
1247 @Override
1248 public void event(McastEvent event) {
1249 switch (event.type()) {
1250 case SOURCE_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001251 mcastHandler.processSourceAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001252 break;
1253 case SINK_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001254 mcastHandler.processSinkAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001255 break;
1256 case SINK_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001257 mcastHandler.processSinkRemoved(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001258 break;
1259 case ROUTE_ADDED:
1260 case ROUTE_REMOVED:
1261 default:
1262 break;
1263 }
1264 }
1265 }
Charles Chan35fd1a72016-06-13 18:54:31 -07001266
1267 private class InternalCordConfigListener implements CordConfigListener {
1268 @Override
1269 public void event(CordConfigEvent event) {
1270 switch (event.type()) {
1271 case ACCESS_AGENT_ADDED:
1272 cordConfigHandler.processAccessAgentAddedEvent(event);
1273 break;
1274 case ACCESS_AGENT_UPDATED:
1275 cordConfigHandler.processAccessAgentUpdatedEvent(event);
1276 break;
1277 case ACCESS_AGENT_REMOVED:
1278 cordConfigHandler.processAccessAgentRemovedEvent(event);
1279 break;
1280 case ACCESS_DEVICE_ADDED:
1281 case ACCESS_DEVICE_UPDATED:
1282 case ACCESS_DEVICE_REMOVED:
1283 default:
1284 break;
1285 }
1286 }
1287 }
Charles Chan03a73e02016-10-24 14:52:01 -07001288
1289 private class InternalRouteEventListener implements RouteListener {
1290 @Override
1291 public void event(RouteEvent event) {
1292 switch (event.type()) {
1293 case ROUTE_ADDED:
1294 routeHandler.processRouteAdded(event);
1295 break;
1296 case ROUTE_UPDATED:
1297 routeHandler.processRouteUpdated(event);
1298 break;
1299 case ROUTE_REMOVED:
1300 routeHandler.processRouteRemoved(event);
1301 break;
1302 default:
1303 break;
1304 }
1305 }
1306 }
sanghob35a6192015-04-01 13:05:26 -07001307}