blob: 3bdde77a77d16b0f5ef0e1f11f9656f34a87a39c [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;
Pier Luigi721b6622017-02-03 13:34:21 -080038import org.onosproject.incubator.net.config.basics.ConfigException;
Pier Luigi7dad71c2017-02-01 13:50:04 -080039import org.onosproject.incubator.net.config.basics.InterfaceConfig;
Charles Chand55e84d2016-03-30 17:54:24 -070040import org.onosproject.incubator.net.config.basics.McastConfig;
Pier Luigi721b6622017-02-03 13:34:21 -080041import org.onosproject.incubator.net.intf.Interface;
Charles Chan2c15aca2016-11-09 20:51:44 -080042import org.onosproject.incubator.net.intf.InterfaceService;
Charles Chan03a73e02016-10-24 14:52:01 -070043import org.onosproject.incubator.net.routing.RouteEvent;
44import org.onosproject.incubator.net.routing.RouteListener;
45import org.onosproject.incubator.net.routing.RouteService;
Pier Ventre735b8c82016-12-02 08:16:05 -080046import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070047import org.onosproject.mastership.MastershipService;
Pier Ventre10bd8d12016-11-26 21:05:22 -080048import org.onosproject.net.ConnectPoint;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070049import org.onosproject.net.Device;
50import org.onosproject.net.DeviceId;
51import org.onosproject.net.Link;
52import org.onosproject.net.Port;
Charles Chan68aa62d2015-11-09 16:37:23 -080053import org.onosproject.net.PortNumber;
Charles Chand6832882015-10-05 17:50:33 -070054import org.onosproject.net.config.ConfigFactory;
55import org.onosproject.net.config.NetworkConfigEvent;
Charles Chand6832882015-10-05 17:50:33 -070056import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070057import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chand6832882015-10-05 17:50:33 -070058import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070059import org.onosproject.net.device.DeviceEvent;
60import org.onosproject.net.device.DeviceListener;
61import org.onosproject.net.device.DeviceService;
Charles Chan68aa62d2015-11-09 16:37:23 -080062import org.onosproject.net.flow.TrafficSelector;
63import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070064import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chan68aa62d2015-11-09 16:37:23 -080065import org.onosproject.net.host.HostEvent;
66import org.onosproject.net.host.HostListener;
Pier Ventre10bd8d12016-11-26 21:05:22 -080067import org.onosproject.net.host.HostService;
68import org.onosproject.net.link.LinkEvent;
69import org.onosproject.net.link.LinkListener;
70import org.onosproject.net.link.LinkService;
Charles Chand55e84d2016-03-30 17:54:24 -070071import org.onosproject.net.mcast.McastEvent;
72import org.onosproject.net.mcast.McastListener;
73import org.onosproject.net.mcast.MulticastRouteService;
Pier Ventre10bd8d12016-11-26 21:05:22 -080074import org.onosproject.net.packet.InboundPacket;
75import org.onosproject.net.packet.PacketContext;
76import org.onosproject.net.packet.PacketProcessor;
77import org.onosproject.net.packet.PacketService;
Pier Ventre42287df2016-11-09 14:17:26 -080078import org.onosproject.net.topology.PathService;
Charles Chand55e84d2016-03-30 17:54:24 -070079import org.onosproject.net.topology.TopologyService;
Pier Luigi7dad71c2017-02-01 13:50:04 -080080import org.onosproject.routing.config.RouterConfig;
Charles Chand55e84d2016-03-30 17:54:24 -070081import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
82import org.onosproject.segmentrouting.config.DeviceConfiguration;
Pier Ventref34966c2016-11-07 16:21:04 -080083import org.onosproject.segmentrouting.config.PwaasConfig;
Pier Ventre10bd8d12016-11-26 21:05:22 -080084import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Pier Ventref34966c2016-11-07 16:21:04 -080085import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Charles Chanfc5c7802016-05-17 13:13:55 -070086import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chand55e84d2016-03-30 17:54:24 -070087import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
88import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Charles Chand2990362016-04-18 13:44:03 -070089import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
90import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
Charles Chand2990362016-04-18 13:44:03 -070091import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
Charles Chan59cc16d2017-02-02 16:20:42 -080092import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
Charles Chanfc5c7802016-05-17 13:13:55 -070093import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Pier Ventref34966c2016-11-07 16:21:04 -080094import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
Jonathan Hartc19f7c12016-04-12 15:39:44 -070095import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070096import org.onosproject.store.service.EventuallyConsistentMap;
97import org.onosproject.store.service.EventuallyConsistentMapBuilder;
98import org.onosproject.store.service.StorageService;
99import org.onosproject.store.service.WallClockTimestamp;
Charles Chan35fd1a72016-06-13 18:54:31 -0700100import org.opencord.cordconfig.CordConfigEvent;
101import org.opencord.cordconfig.CordConfigListener;
102import org.opencord.cordconfig.CordConfigService;
sanghob35a6192015-04-01 13:05:26 -0700103import org.slf4j.Logger;
104import org.slf4j.LoggerFactory;
105
sangho1e575652015-05-14 00:39:53 -0700106import java.util.List;
sanghob35a6192015-04-01 13:05:26 -0700107import java.util.Map;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700108import java.util.Set;
sanghob35a6192015-04-01 13:05:26 -0700109import java.util.concurrent.ConcurrentHashMap;
110import java.util.concurrent.ConcurrentLinkedQueue;
111import java.util.concurrent.Executors;
112import java.util.concurrent.ScheduledExecutorService;
113import java.util.concurrent.ScheduledFuture;
114import java.util.concurrent.TimeUnit;
Charles Chan7ffd81f2017-02-08 15:52:08 -0800115import java.util.stream.Collectors;
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)
170 CordConfigService cordConfigService;
171
172 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
173 RouteService routeService;
Charles Chan5270ed02016-01-30 23:22:37 -0800174
175 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan2c15aca2016-11-09 20:51:44 -0800176 public NetworkConfigRegistry cfgService;
Charles Chan5270ed02016-01-30 23:22:37 -0800177
Saurav Das80980c72016-03-23 11:22:49 -0700178 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan2c15aca2016-11-09 20:51:44 -0800179 public InterfaceService interfaceService;
180
Charles Chan03a73e02016-10-24 14:52:01 -0700181 ArpHandler arpHandler = null;
182 IcmpHandler icmpHandler = null;
183 IpHandler ipHandler = null;
184 RoutingRulePopulator routingRulePopulator = null;
Charles Chan2c15aca2016-11-09 20:51:44 -0800185 public ApplicationId appId;
Pier Ventre42287df2016-11-09 14:17:26 -0800186 public DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700187
Charles Chan03a73e02016-10-24 14:52:01 -0700188 DefaultRoutingHandler defaultRoutingHandler = null;
sangho1e575652015-05-14 00:39:53 -0700189 private TunnelHandler tunnelHandler = null;
190 private PolicyHandler policyHandler = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700191 private InternalPacketProcessor processor = null;
192 private InternalLinkListener linkListener = null;
193 private InternalDeviceListener deviceListener = null;
Charles Chanfc5c7802016-05-17 13:13:55 -0700194 private AppConfigHandler appCfgHandler = null;
Charles Chan03a73e02016-10-24 14:52:01 -0700195 XConnectHandler xConnectHandler = null;
Charles Chand2990362016-04-18 13:44:03 -0700196 private McastHandler mcastHandler = null;
Charles Chan03a73e02016-10-24 14:52:01 -0700197 HostHandler hostHandler = null;
Charles Chan35fd1a72016-06-13 18:54:31 -0700198 private CordConfigHandler cordConfigHandler = null;
Pier Ventre10bd8d12016-11-26 21:05:22 -0800199 private RouteHandler routeHandler = null;
Pier Ventre735b8c82016-12-02 08:16:05 -0800200 private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
Pier Ventref34966c2016-11-07 16:21:04 -0800201 private L2TunnelHandler l2TunnelHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700202 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan5270ed02016-01-30 23:22:37 -0800203 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chand55e84d2016-03-30 17:54:24 -0700204 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
205 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan35fd1a72016-06-13 18:54:31 -0700206 private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
Charles Chan03a73e02016-10-24 14:52:01 -0700207 private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
sanghob35a6192015-04-01 13:05:26 -0700208
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700209 private ScheduledExecutorService executorService = Executors
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700210 .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
sanghob35a6192015-04-01 13:05:26 -0700211
Saurav Das4ce45962015-11-24 23:21:05 -0800212 @SuppressWarnings("unused")
sanghob35a6192015-04-01 13:05:26 -0700213 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das4ce45962015-11-24 23:21:05 -0800214 @SuppressWarnings("rawtypes")
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700215 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
Charles Chan68aa62d2015-11-09 16:37:23 -0800216 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chane849c192016-01-11 18:28:54 -0800217 new ConcurrentHashMap<>();
218 /**
219 * Per device next objective ID store with (device id + neighbor set) as key.
220 */
221 public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
Charles Chan68aa62d2015-11-09 16:37:23 -0800222 nsNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800223 /**
224 * Per device next objective ID store with (device id + subnet) as key.
225 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800226 public EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
227 vlanNextObjStore = null;
Charles Chane849c192016-01-11 18:28:54 -0800228 /**
229 * Per device next objective ID store with (device id + port) as key.
230 */
231 public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
Saurav Das4ce45962015-11-24 23:21:05 -0800232 portNextObjStore = null;
Charles Chan59cc16d2017-02-02 16:20:42 -0800233
Saurav Das4ce45962015-11-24 23:21:05 -0800234 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
235 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho0b2b6d12015-05-20 22:16:38 -0700236
Charles Chand55e84d2016-03-30 17:54:24 -0700237 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700238 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
239 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700240 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chand6832882015-10-05 17:50:33 -0700241 @Override
Charles Chan5270ed02016-01-30 23:22:37 -0800242 public SegmentRoutingDeviceConfig createConfig() {
243 return new SegmentRoutingDeviceConfig();
Charles Chand6832882015-10-05 17:50:33 -0700244 }
245 };
Pier Ventref34966c2016-11-07 16:21:04 -0800246
Charles Chand55e84d2016-03-30 17:54:24 -0700247 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700248 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
249 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700250 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan5270ed02016-01-30 23:22:37 -0800251 @Override
252 public SegmentRoutingAppConfig createConfig() {
253 return new SegmentRoutingAppConfig();
254 }
255 };
Pier Ventref34966c2016-11-07 16:21:04 -0800256
Charles Chanfc5c7802016-05-17 13:13:55 -0700257 private final ConfigFactory<ApplicationId, XConnectConfig> xConnectConfigFactory =
258 new ConfigFactory<ApplicationId, XConnectConfig>(
259 SubjectFactories.APP_SUBJECT_FACTORY,
260 XConnectConfig.class, "xconnect") {
261 @Override
262 public XConnectConfig createConfig() {
263 return new XConnectConfig();
264 }
265 };
Pier Ventref34966c2016-11-07 16:21:04 -0800266
Charles Chand55e84d2016-03-30 17:54:24 -0700267 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chanfc5c7802016-05-17 13:13:55 -0700268 new ConfigFactory<ApplicationId, McastConfig>(
269 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chand55e84d2016-03-30 17:54:24 -0700270 McastConfig.class, "multicast") {
271 @Override
272 public McastConfig createConfig() {
273 return new McastConfig();
274 }
275 };
276
Pier Ventref34966c2016-11-07 16:21:04 -0800277 private final ConfigFactory<ApplicationId, PwaasConfig> pwaasConfigFactory =
278 new ConfigFactory<ApplicationId, PwaasConfig>(
279 SubjectFactories.APP_SUBJECT_FACTORY,
280 PwaasConfig.class, "pwaas") {
281 @Override
282 public PwaasConfig createConfig() {
283 return new PwaasConfig();
284 }
285 };
286
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700287 private Object threadSchedulerLock = new Object();
288 private static int numOfEventsQueued = 0;
289 private static int numOfEventsExecuted = 0;
sanghob35a6192015-04-01 13:05:26 -0700290 private static int numOfHandlerExecution = 0;
291 private static int numOfHandlerScheduled = 0;
292
Charles Chan116188d2016-02-18 14:22:42 -0800293 /**
294 * Segment Routing App ID.
295 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800296 public static final String APP_NAME = "org.onosproject.segmentrouting";
Charles Chan59cc16d2017-02-02 16:20:42 -0800297
Charles Chane849c192016-01-11 18:28:54 -0800298 /**
299 * The default VLAN ID assigned to the interfaces without subnet config.
300 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800301 public static final VlanId INTERNAL_VLAN = VlanId.vlanId((short) 4094);
Saurav Das0e99e2b2015-10-28 12:39:42 -0700302
sanghob35a6192015-04-01 13:05:26 -0700303 @Activate
304 protected void activate() {
Charles Chan2c15aca2016-11-09 20:51:44 -0800305 appId = coreService.registerApplication(APP_NAME);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700306
307 log.debug("Creating EC map nsnextobjectivestore");
308 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
309 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700310 nsNextObjStore = nsNextObjMapBuilder
311 .withName("nsnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700312 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700313 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700314 .build();
315 log.trace("Current size {}", nsNextObjStore.size());
316
Charles Chan59cc16d2017-02-02 16:20:42 -0800317 log.debug("Creating EC map vlannextobjectivestore");
318 EventuallyConsistentMapBuilder<VlanNextObjectiveStoreKey, Integer>
319 vlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
320 vlanNextObjStore = vlanNextObjMapBuilder
321 .withName("vlannextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700322 .withSerializer(createSerializer())
Charles Chanc42e84e2015-10-20 16:24:19 -0700323 .withTimestampProvider((k, v) -> new WallClockTimestamp())
324 .build();
325
Saurav Das4ce45962015-11-24 23:21:05 -0800326 log.debug("Creating EC map subnetnextobjectivestore");
327 EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
328 portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
329 portNextObjStore = portNextObjMapBuilder
330 .withName("portnextobjectivestore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700331 .withSerializer(createSerializer())
Saurav Das4ce45962015-11-24 23:21:05 -0800332 .withTimestampProvider((k, v) -> new WallClockTimestamp())
333 .build();
334
sangho0b2b6d12015-05-20 22:16:38 -0700335 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
336 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700337 tunnelStore = tunnelMapBuilder
338 .withName("tunnelstore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700339 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700340 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700341 .build();
342
343 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
344 storageService.eventuallyConsistentMapBuilder();
sangho0b2b6d12015-05-20 22:16:38 -0700345 policyStore = policyMapBuilder
346 .withName("policystore")
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700347 .withSerializer(createSerializer())
Madan Jampanibcf1a482015-06-24 19:05:56 -0700348 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho0b2b6d12015-05-20 22:16:38 -0700349 .build();
350
Saurav Das80980c72016-03-23 11:22:49 -0700351 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800352 "purgeOnDisconnection", "true");
Saurav Das80980c72016-03-23 11:22:49 -0700353 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800354 "purgeOnDisconnection", "true");
Pier Luigi9e5c5ca2017-01-12 18:14:58 -0800355 compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
356 "requestInterceptsEnabled", "false");
Pier Luigi7e415132017-01-12 22:46:39 -0800357 compCfgService.preSetProperty("org.onosproject.incubator.net.neighbour.impl.NeighbourResolutionManager",
358 "requestInterceptsEnabled", "false");
359 compCfgService.preSetProperty("org.onosproject.dhcprelay.DhcpRelay",
360 "arpEnabled", "false");
Pier Luigi9b1d6262017-02-02 22:31:34 -0800361 compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
362 "greedyLearningIpv6", "true");
Charles Chanc6d227e2017-02-28 15:15:17 -0800363 compCfgService.preSetProperty("org.onosproject.routing.cpr.ControlPlaneRedirectManager",
364 "forceUnprovision", "true");
Saurav Das80980c72016-03-23 11:22:49 -0700365
Charles Chanb8e10c82015-10-14 11:24:40 -0700366 processor = new InternalPacketProcessor();
367 linkListener = new InternalLinkListener();
368 deviceListener = new InternalDeviceListener();
Charles Chanfc5c7802016-05-17 13:13:55 -0700369 appCfgHandler = new AppConfigHandler(this);
370 xConnectHandler = new XConnectHandler(this);
Charles Chand2990362016-04-18 13:44:03 -0700371 mcastHandler = new McastHandler(this);
372 hostHandler = new HostHandler(this);
Charles Chan35fd1a72016-06-13 18:54:31 -0700373 cordConfigHandler = new CordConfigHandler(this);
Charles Chan03a73e02016-10-24 14:52:01 -0700374 routeHandler = new RouteHandler(this);
Pier Ventre735b8c82016-12-02 08:16:05 -0800375 neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
Pier Ventref34966c2016-11-07 16:21:04 -0800376 l2TunnelHandler = new L2TunnelHandler(this);
Charles Chanb8e10c82015-10-14 11:24:40 -0700377
Charles Chan3e783d02016-02-26 22:19:52 -0800378 cfgService.addListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700379 cfgService.registerConfigFactory(deviceConfigFactory);
380 cfgService.registerConfigFactory(appConfigFactory);
Charles Chanfc5c7802016-05-17 13:13:55 -0700381 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700382 cfgService.registerConfigFactory(mcastConfigFactory);
Pier Ventref34966c2016-11-07 16:21:04 -0800383 cfgService.registerConfigFactory(pwaasConfigFactory);
Charles Chan5270ed02016-01-30 23:22:37 -0800384 hostService.addListener(hostListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700385 packetService.addProcessor(processor, PacketProcessor.director(2));
386 linkService.addListener(linkListener);
387 deviceService.addListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700388 multicastRouteService.addListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700389 cordConfigService.addListener(cordConfigListener);
Charles Chanb8e10c82015-10-14 11:24:40 -0700390
391 cfgListener.configureNetwork();
392
Charles Chan03a73e02016-10-24 14:52:01 -0700393 routeService.addListener(routeListener);
394
sanghob35a6192015-04-01 13:05:26 -0700395 log.info("Started");
396 }
397
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700398 private KryoNamespace.Builder createSerializer() {
399 return new KryoNamespace.Builder()
400 .register(KryoNamespaces.API)
401 .register(NeighborSetNextObjectiveStoreKey.class,
Charles Chan59cc16d2017-02-02 16:20:42 -0800402 VlanNextObjectiveStoreKey.class,
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700403 SubnetAssignedVidStoreKey.class,
404 NeighborSet.class,
405 Tunnel.class,
406 DefaultTunnel.class,
407 Policy.class,
408 TunnelPolicy.class,
409 Policy.Type.class,
410 PortNextObjectiveStoreKey.class,
Charles Chanfc5c7802016-05-17 13:13:55 -0700411 XConnectStoreKey.class
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700412 );
413 }
414
sanghob35a6192015-04-01 13:05:26 -0700415 @Deactivate
416 protected void deactivate() {
Charles Chand6832882015-10-05 17:50:33 -0700417 cfgService.removeListener(cfgListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700418 cfgService.unregisterConfigFactory(deviceConfigFactory);
419 cfgService.unregisterConfigFactory(appConfigFactory);
Charles Chan03a73e02016-10-24 14:52:01 -0700420 cfgService.unregisterConfigFactory(xConnectConfigFactory);
Charles Chand55e84d2016-03-30 17:54:24 -0700421 cfgService.unregisterConfigFactory(mcastConfigFactory);
Pier Ventref34966c2016-11-07 16:21:04 -0800422 cfgService.unregisterConfigFactory(pwaasConfigFactory);
Charles Chand6832882015-10-05 17:50:33 -0700423
sanghob35a6192015-04-01 13:05:26 -0700424 packetService.removeProcessor(processor);
Charles Chanb8e10c82015-10-14 11:24:40 -0700425 linkService.removeListener(linkListener);
426 deviceService.removeListener(deviceListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700427 multicastRouteService.removeListener(mcastListener);
Charles Chan35fd1a72016-06-13 18:54:31 -0700428 cordConfigService.removeListener(cordConfigListener);
Charles Chan03a73e02016-10-24 14:52:01 -0700429 routeService.removeListener(routeListener);
Charles Chand55e84d2016-03-30 17:54:24 -0700430
Charles Chan0aa674e2017-02-23 15:44:08 -0800431 neighbourResolutionService.unregisterNeighbourHandlers(appId);
432
sanghob35a6192015-04-01 13:05:26 -0700433 processor = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700434 linkListener = null;
Charles Chand55e84d2016-03-30 17:54:24 -0700435 deviceListener = null;
Charles Chanb8e10c82015-10-14 11:24:40 -0700436 groupHandlerMap.clear();
437
Charles Chand55e84d2016-03-30 17:54:24 -0700438 nsNextObjStore.destroy();
Charles Chan59cc16d2017-02-02 16:20:42 -0800439 vlanNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700440 portNextObjStore.destroy();
Charles Chand55e84d2016-03-30 17:54:24 -0700441 tunnelStore.destroy();
442 policyStore.destroy();
sanghob35a6192015-04-01 13:05:26 -0700443 log.info("Stopped");
444 }
445
sangho1e575652015-05-14 00:39:53 -0700446 @Override
447 public List<Tunnel> getTunnels() {
448 return tunnelHandler.getTunnels();
449 }
450
451 @Override
sangho71abe1b2015-06-29 14:58:47 -0700452 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
453 return tunnelHandler.createTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700454 }
455
456 @Override
sangho71abe1b2015-06-29 14:58:47 -0700457 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho1e575652015-05-14 00:39:53 -0700458 for (Policy policy: policyHandler.getPolicies()) {
459 if (policy.type() == Policy.Type.TUNNEL_FLOW) {
460 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
461 if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
462 log.warn("Cannot remove the tunnel used by a policy");
sangho71abe1b2015-06-29 14:58:47 -0700463 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho1e575652015-05-14 00:39:53 -0700464 }
465 }
466 }
sangho71abe1b2015-06-29 14:58:47 -0700467 return tunnelHandler.removeTunnel(tunnel);
sangho1e575652015-05-14 00:39:53 -0700468 }
469
470 @Override
sangho71abe1b2015-06-29 14:58:47 -0700471 public PolicyHandler.Result removePolicy(Policy policy) {
472 return policyHandler.removePolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700473 }
474
475 @Override
sangho71abe1b2015-06-29 14:58:47 -0700476 public PolicyHandler.Result createPolicy(Policy policy) {
477 return policyHandler.createPolicy(policy);
sangho1e575652015-05-14 00:39:53 -0700478 }
479
480 @Override
481 public List<Policy> getPolicies() {
482 return policyHandler.getPolicies();
483 }
484
Saurav Das59232cf2016-04-27 18:35:50 -0700485 @Override
486 public void rerouteNetwork() {
487 cfgListener.configureNetwork();
488 for (Device device : deviceService.getDevices()) {
Saurav Das018605f2017-02-18 14:05:44 -0800489 if (mastershipService.isLocalMaster(device.id())) {
490 defaultRoutingHandler.populatePortAddressingRules(device.id());
491 }
Saurav Das59232cf2016-04-27 18:35:50 -0700492 }
493 defaultRoutingHandler.startPopulationProcess();
494 }
495
Charles Chanc81c45b2016-10-20 17:02:44 -0700496 @Override
Pier Ventre10bd8d12016-11-26 21:05:22 -0800497 public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
498 Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
Charles Chanc81c45b2016-10-20 17:02:44 -0700499 deviceService.getAvailableDevices().forEach(device -> {
500 deviceSubnetMap.put(device.id(), deviceConfiguration.getSubnets(device.id()));
501 });
502 return deviceSubnetMap;
503 }
504
sanghof9d0bf12015-05-19 11:57:42 -0700505 /**
Pier Ventre98161782016-10-31 15:00:01 -0700506 * Returns the MPLS-ECMP configuration.
507 *
508 * @return MPLS-ECMP value
509 */
510 public boolean getMplsEcmp() {
511 SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
512 .getConfig(this.appId, SegmentRoutingAppConfig.class);
513 return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
514 }
515
516 /**
sanghof9d0bf12015-05-19 11:57:42 -0700517 * Returns the tunnel object with the tunnel ID.
518 *
519 * @param tunnelId Tunnel ID
520 * @return Tunnel reference
521 */
sangho1e575652015-05-14 00:39:53 -0700522 public Tunnel getTunnel(String tunnelId) {
523 return tunnelHandler.getTunnel(tunnelId);
524 }
525
Charles Chan7ffd81f2017-02-08 15:52:08 -0800526 // TODO Consider moving these to InterfaceService
sanghob35a6192015-04-01 13:05:26 -0700527 /**
Charles Chan59cc16d2017-02-02 16:20:42 -0800528 * Returns untagged VLAN configured on given connect point.
Charles Chan7ffd81f2017-02-08 15:52:08 -0800529 * <p>
530 * Only returns the first match if there are multiple untagged VLAN configured
531 * on the connect point.
sanghob35a6192015-04-01 13:05:26 -0700532 *
Charles Chan59cc16d2017-02-02 16:20:42 -0800533 * @param connectPoint connect point
534 * @return untagged VLAN or null if not configured
sanghob35a6192015-04-01 13:05:26 -0700535 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800536 public VlanId getUntaggedVlanId(ConnectPoint connectPoint) {
537 return interfaceService.getInterfacesByPort(connectPoint).stream()
538 .filter(intf -> !intf.vlanUntagged().equals(VlanId.NONE))
539 .map(Interface::vlanUntagged)
540 .findFirst().orElse(null);
sanghob35a6192015-04-01 13:05:26 -0700541 }
542
sangho1e575652015-05-14 00:39:53 -0700543 /**
Charles Chan7ffd81f2017-02-08 15:52:08 -0800544 * Returns tagged VLAN configured on given connect point.
545 * <p>
546 * Returns all matches if there are multiple tagged VLAN configured
547 * on the connect point.
548 *
549 * @param connectPoint connect point
550 * @return tagged VLAN or empty set if not configured
551 */
552 public Set<VlanId> getTaggedVlanId(ConnectPoint connectPoint) {
553 Set<Interface> interfaces = interfaceService.getInterfacesByPort(connectPoint);
554 return interfaces.stream()
555 .map(Interface::vlanTagged)
556 .flatMap(vlanIds -> vlanIds.stream())
557 .collect(Collectors.toSet());
558 }
559
560 /**
561 * Returns native VLAN configured on given connect point.
562 * <p>
563 * Only returns the first match if there are multiple native VLAN configured
564 * on the connect point.
565 *
566 * @param connectPoint connect point
567 * @return native VLAN or null if not configured
568 */
569 public VlanId getNativeVlanId(ConnectPoint connectPoint) {
570 Set<Interface> interfaces = interfaceService.getInterfacesByPort(connectPoint);
571 return interfaces.stream()
572 .filter(intf -> !intf.vlanNative().equals(VlanId.NONE))
573 .map(Interface::vlanNative)
574 .findFirst()
575 .orElse(null);
576 }
577
578 /**
579 * Returns vlan port map of given device.
580 *
581 * @param deviceId device id
582 * @return vlan-port multimap
583 */
584 public Multimap<VlanId, PortNumber> getVlanPortMap(DeviceId deviceId) {
585 HashMultimap<VlanId, PortNumber> vlanPortMap = HashMultimap.create();
586
587 interfaceService.getInterfaces().stream()
588 .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
589 .forEach(intf -> {
590 vlanPortMap.put(intf.vlanUntagged(), intf.connectPoint().port());
591 intf.vlanTagged().forEach(vlanTagged -> {
592 vlanPortMap.put(vlanTagged, intf.connectPoint().port());
593 });
594 vlanPortMap.put(intf.vlanNative(), intf.connectPoint().port());
595 });
596 vlanPortMap.removeAll(VlanId.NONE);
597
598 return vlanPortMap;
599 }
600
601 /**
Saurav Das0e99e2b2015-10-28 12:39:42 -0700602 * Returns the next objective ID for the given NeighborSet.
Saurav Das8a0732e2015-11-20 15:27:53 -0800603 * If the nextObjective does not exist, a new one is created and
Saurav Das4ce45962015-11-24 23:21:05 -0800604 * its id is returned.
sangho1e575652015-05-14 00:39:53 -0700605 *
sanghof9d0bf12015-05-19 11:57:42 -0700606 * @param deviceId Device ID
607 * @param ns NegighborSet
Saurav Das8a0732e2015-11-20 15:27:53 -0800608 * @param meta metadata passed into the creation of a Next Objective
Pier Ventre917127a2016-10-31 16:49:19 -0700609 * @param isBos indicates if it is BoS or not
Saurav Das8a0732e2015-11-20 15:27:53 -0800610 * @return next objective ID or -1 if an error was encountered during the
611 * creation of the nextObjective
sangho1e575652015-05-14 00:39:53 -0700612 */
Saurav Das8a0732e2015-11-20 15:27:53 -0800613 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
Pier Ventre917127a2016-10-31 16:49:19 -0700614 TrafficSelector meta, boolean isBos) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700615 if (groupHandlerMap.get(deviceId) != null) {
616 log.trace("getNextObjectiveId query in device {}", deviceId);
617 return groupHandlerMap
Pier Ventre917127a2016-10-31 16:49:19 -0700618 .get(deviceId).getNextObjectiveId(ns, meta, isBos);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700619 } else {
Saurav Das4ce45962015-11-24 23:21:05 -0800620 log.warn("getNextObjectiveId query - groupHandler for device {} "
621 + "not found", deviceId);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700622 return -1;
623 }
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700624 }
625
Charles Chanc42e84e2015-10-20 16:24:19 -0700626 /**
Pier Ventre917127a2016-10-31 16:49:19 -0700627 * Returns the next objective ID for the given NeighborSet.
628 * If the nextObjective does not exist, a new one is created and
629 * its id is returned.
630 *
631 * @param deviceId Device ID
632 * @param ns NegighborSet
633 * @param meta metadata passed into the creation of a Next Objective
634 * @return next objective ID or -1 if an error was encountered during the
635 * creation of the nextObjective
636 */
637 public int getNextObjectiveId(DeviceId deviceId,
638 NeighborSet ns,
639 TrafficSelector meta) {
640 return this.getNextObjectiveId(deviceId, ns, meta, true);
641 }
642
643 /**
Saurav Das4ce45962015-11-24 23:21:05 -0800644 * Returns the next objective ID for the given subnet prefix. It is expected
Charles Chan59cc16d2017-02-02 16:20:42 -0800645 * Returns the next objective ID for the given vlan id. It is expected
Saurav Das4ce45962015-11-24 23:21:05 -0800646 * that the next-objective has been pre-created from configuration.
Charles Chanc42e84e2015-10-20 16:24:19 -0700647 *
648 * @param deviceId Device ID
Charles Chan59cc16d2017-02-02 16:20:42 -0800649 * @param vlanId VLAN ID
Saurav Das4ce45962015-11-24 23:21:05 -0800650 * @return next objective ID or -1 if it was not found
Charles Chanc42e84e2015-10-20 16:24:19 -0700651 */
Charles Chan59cc16d2017-02-02 16:20:42 -0800652 public int getVlanNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
Charles Chanc42e84e2015-10-20 16:24:19 -0700653 if (groupHandlerMap.get(deviceId) != null) {
Charles Chan59cc16d2017-02-02 16:20:42 -0800654 log.trace("getVlanNextObjectiveId query in device {}", deviceId);
655 return groupHandlerMap.get(deviceId).getVlanNextObjectiveId(vlanId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700656 } else {
Charles Chan59cc16d2017-02-02 16:20:42 -0800657 log.warn("getVlanNextObjectiveId query - groupHandler for "
Saurav Das4ce45962015-11-24 23:21:05 -0800658 + "device {} not found", deviceId);
659 return -1;
660 }
661 }
662
663 /**
664 * Returns the next objective ID for the given portNumber, given the treatment.
665 * There could be multiple different treatments to the same outport, which
666 * would result in different objectives. If the next object
667 * does not exist, a new one is created and its id is returned.
668 *
669 * @param deviceId Device ID
670 * @param portNum port number on device for which NextObjective is queried
671 * @param treatment the actions to apply on the packets (should include outport)
672 * @param meta metadata passed into the creation of a Next Objective if necessary
Saurav Das59232cf2016-04-27 18:35:50 -0700673 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das4ce45962015-11-24 23:21:05 -0800674 */
675 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
676 TrafficTreatment treatment,
677 TrafficSelector meta) {
678 DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
679 if (ghdlr != null) {
680 return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
681 } else {
Charles Chane849c192016-01-11 18:28:54 -0800682 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
683 + " not found", deviceId);
684 return -1;
685 }
686 }
687
sanghob35a6192015-04-01 13:05:26 -0700688 private class InternalPacketProcessor implements PacketProcessor {
sanghob35a6192015-04-01 13:05:26 -0700689 @Override
690 public void process(PacketContext context) {
691
692 if (context.isHandled()) {
693 return;
694 }
695
696 InboundPacket pkt = context.inPacket();
697 Ethernet ethernet = pkt.parsed();
Pier Luigi7dad71c2017-02-01 13:50:04 -0800698
699 if (ethernet == null) {
700 return;
701 }
702
Saurav Das4ce45962015-11-24 23:21:05 -0800703 log.trace("Rcvd pktin: {}", ethernet);
Pier Ventree0ae7a32016-11-23 09:57:42 -0800704 if (ethernet.getEtherType() == TYPE_ARP) {
Saurav Das76ae6812017-03-15 15:15:14 -0700705 log.warn("Received unexpected ARP packet on {}", context.inPacket().receivedFrom());
706 log.trace("{}", ethernet);
Pier Ventre968da122016-12-09 17:26:04 -0800707 return;
sanghob35a6192015-04-01 13:05:26 -0700708 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
Pier Ventre735b8c82016-12-02 08:16:05 -0800709 IPv4 ipv4Packet = (IPv4) ethernet.getPayload();
710 //ipHandler.addToPacketBuffer(ipv4Packet);
711 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) {
712 icmpHandler.processIcmp(ethernet, pkt.receivedFrom());
sanghob35a6192015-04-01 13:05:26 -0700713 } else {
Charles Chan50035632017-01-13 17:20:44 -0800714 // NOTE: We don't support IP learning at this moment so this
715 // is not necessary. Also it causes duplication of DHCP packets.
Pier Ventre968da122016-12-09 17:26:04 -0800716 // ipHandler.processPacketIn(ipv4Packet, pkt.receivedFrom());
sanghob35a6192015-04-01 13:05:26 -0700717 }
Pier Ventre10bd8d12016-11-26 21:05:22 -0800718 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
719 IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
Pier Ventre735b8c82016-12-02 08:16:05 -0800720 //ipHandler.addToPacketBuffer(ipv6Packet);
Pier Luigi7dad71c2017-02-01 13:50:04 -0800721 // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
Pier Ventre735b8c82016-12-02 08:16:05 -0800722 if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
723 ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
724 if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST ||
725 icmp6Packet.getIcmpType() == ICMP6.ECHO_REPLY) {
726 icmpHandler.processIcmpv6(ethernet, pkt.receivedFrom());
727 } else {
Pier Luigi7dad71c2017-02-01 13:50:04 -0800728 // XXX Neigbour hacking, to handle the ICMPv6 packet
729 // not under our control
730 if (icmpHandler.handleUPstreamPackets(context)) {
731 log.debug("Rcvd pktin from UpStream: {}", ipv6Packet);
732 } else {
733 log.debug("Received ICMPv6 0x{} - not handled",
734 Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
735 }
Pier Ventre735b8c82016-12-02 08:16:05 -0800736 }
737 } else {
738 // NOTE: We don't support IP learning at this moment so this
739 // is not necessary. Also it causes duplication of DHCPv6 packets.
740 // ipHandler.processPacketIn(ipv6Packet, pkt.receivedFrom());
741 }
sanghob35a6192015-04-01 13:05:26 -0700742 }
743 }
744 }
745
746 private class InternalLinkListener implements LinkListener {
747 @Override
748 public void event(LinkEvent event) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700749 if (event.type() == LinkEvent.Type.LINK_ADDED
750 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700751 log.debug("Event {} received from Link Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700752 scheduleEventHandlerIfNotScheduled(event);
753 }
754 }
755 }
756
757 private class InternalDeviceListener implements DeviceListener {
sanghob35a6192015-04-01 13:05:26 -0700758 @Override
759 public void event(DeviceEvent event) {
sanghob35a6192015-04-01 13:05:26 -0700760 switch (event.type()) {
761 case DEVICE_ADDED:
Saurav Das1a129a02016-11-18 15:21:57 -0800762 case PORT_UPDATED:
763 case PORT_ADDED:
sangho20eff1d2015-04-13 15:15:58 -0700764 case DEVICE_UPDATED:
765 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700766 log.debug("Event {} received from Device Service", event.type());
sanghob35a6192015-04-01 13:05:26 -0700767 scheduleEventHandlerIfNotScheduled(event);
768 break;
769 default:
770 }
771 }
772 }
773
Saurav Das4ce45962015-11-24 23:21:05 -0800774 @SuppressWarnings("rawtypes")
sanghob35a6192015-04-01 13:05:26 -0700775 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700776 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700777 eventQueue.add(event);
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700778 numOfEventsQueued++;
779
780 if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
781 //No pending scheduled event handling threads. So start a new one.
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700782 eventHandlerFuture = executorService
783 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
784 numOfHandlerScheduled++;
785 }
Jonathan Hartc19f7c12016-04-12 15:39:44 -0700786 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700787 numOfEventsQueued,
788 numOfHandlerScheduled);
sanghob35a6192015-04-01 13:05:26 -0700789 }
sanghob35a6192015-04-01 13:05:26 -0700790 }
791
792 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700793 @Override
sanghob35a6192015-04-01 13:05:26 -0700794 public void run() {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700795 try {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700796 while (true) {
Saurav Das4ce45962015-11-24 23:21:05 -0800797 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700798 Event event = null;
799 synchronized (threadSchedulerLock) {
800 if (!eventQueue.isEmpty()) {
801 event = eventQueue.poll();
802 numOfEventsExecuted++;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700803 } else {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700804 numOfHandlerExecution++;
805 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
806 numOfHandlerExecution, numOfEventsExecuted);
807 break;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700808 }
sangho20eff1d2015-04-13 15:15:58 -0700809 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700810 if (event.type() == LinkEvent.Type.LINK_ADDED) {
811 processLinkAdded((Link) event.subject());
812 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
Pier Ventre2c515312016-09-13 21:33:40 -0700813 Link linkRemoved = (Link) event.subject();
814 if (linkRemoved.src().elementId() instanceof DeviceId &&
815 !deviceService.isAvailable(linkRemoved.src().deviceId())) {
816 continue;
817 }
818 if (linkRemoved.dst().elementId() instanceof DeviceId &&
819 !deviceService.isAvailable(linkRemoved.dst().deviceId())) {
820 continue;
821 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700822 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700823 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
824 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
825 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800826 DeviceId deviceId = ((Device) event.subject()).id();
827 if (deviceService.isAvailable(deviceId)) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700828 log.info("Processing device event {} for available device {}",
829 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700830 processDeviceAdded((Device) event.subject());
Saurav Das80980c72016-03-23 11:22:49 -0700831 } else {
832 log.info("Processing device event {} for unavailable device {}",
833 event.type(), ((Device) event.subject()).id());
834 processDeviceRemoved((Device) event.subject());
835 }
Saurav Das1a129a02016-11-18 15:21:57 -0800836 } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
Saurav Dasd2fded02016-12-02 15:43:47 -0800837 // typically these calls come when device is added first time
838 // so port filtering rules are handled at the device_added event.
839 // port added calls represent all ports on the device,
840 // enabled or not.
Saurav Das1a129a02016-11-18 15:21:57 -0800841 log.debug("** PORT ADDED {}/{} -> {}",
Saurav Dasd2fded02016-12-02 15:43:47 -0800842 ((DeviceEvent) event).subject().id(),
843 ((DeviceEvent) event).port().number(),
844 event.type());
Saurav Das1a129a02016-11-18 15:21:57 -0800845 } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
Saurav Dasd2fded02016-12-02 15:43:47 -0800846 // these calls happen for every subsequent event
847 // ports enabled, disabled, switch goes away, comes back
Saurav Das1a129a02016-11-18 15:21:57 -0800848 log.info("** PORT UPDATED {}/{} -> {}",
849 event.subject(),
850 ((DeviceEvent) event).port(),
851 event.type());
852 processPortUpdated(((Device) event.subject()),
853 ((DeviceEvent) event).port());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700854 } else {
855 log.warn("Unhandled event type: {}", event.type());
856 }
sanghob35a6192015-04-01 13:05:26 -0700857 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700858 } catch (Exception e) {
859 log.error("SegmentRouting event handler "
860 + "thread thrown an exception: {}", e);
sanghob35a6192015-04-01 13:05:26 -0700861 }
sanghob35a6192015-04-01 13:05:26 -0700862 }
863 }
864
sanghob35a6192015-04-01 13:05:26 -0700865 private void processLinkAdded(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700866 log.info("** LINK ADDED {}", link.toString());
Charles Chan0b4e6182015-11-03 10:42:14 -0800867 if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
868 log.warn("Source device of this link is not configured.");
869 return;
870 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700871 //Irrespective whether the local is a MASTER or not for this device,
872 //create group handler instance and push default TTP flow rules.
873 //Because in a multi-instance setup, instances can initiate
874 //groups for any devices. Also the default TTP rules are needed
875 //to be pushed before inserting any IP table entries for any device
876 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
877 .deviceId());
878 if (groupHandler != null) {
Saurav Das8a0732e2015-11-20 15:27:53 -0800879 groupHandler.linkUp(link, mastershipService.isLocalMaster(
880 link.src().deviceId()));
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700881 } else {
882 Device device = deviceService.getDevice(link.src().deviceId());
883 if (device != null) {
884 log.warn("processLinkAdded: Link Added "
885 + "Notification without Device Added "
886 + "event, still handling it");
887 processDeviceAdded(device);
888 groupHandler = groupHandlerMap.get(link.src()
889 .deviceId());
Saurav Das8a0732e2015-11-20 15:27:53 -0800890 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sanghob35a6192015-04-01 13:05:26 -0700891 }
892 }
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700893
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700894 log.trace("Starting optimized route population process");
895 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
896 //log.trace("processLinkAdded: re-starting route population process");
897 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700898
899 mcastHandler.init();
sanghob35a6192015-04-01 13:05:26 -0700900 }
901
902 private void processLinkRemoved(Link link) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700903 log.info("** LINK REMOVED {}", link.toString());
sangho834e4b02015-05-01 09:38:25 -0700904 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
905 if (groupHandler != null) {
Saurav Das423fe2b2015-12-04 10:52:59 -0800906 groupHandler.portDown(link.src().port(),
907 mastershipService.isLocalMaster(link.src().deviceId()));
sangho834e4b02015-05-01 09:38:25 -0700908 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700909 log.trace("Starting optimized route population process");
910 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
911 //log.trace("processLinkRemoved: re-starting route population process");
912 //defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -0700913
914 mcastHandler.processLinkDown(link);
sanghob35a6192015-04-01 13:05:26 -0700915 }
916
917 private void processDeviceAdded(Device device) {
Saurav Dasb5c236e2016-06-07 10:08:06 -0700918 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan0b4e6182015-11-03 10:42:14 -0800919 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das2857f382015-11-03 14:39:27 -0800920 log.warn("Device configuration uploading. Device {} will be "
921 + "processed after config completes.", device.id());
922 return;
923 }
Charles Chan2199c302016-04-23 17:36:10 -0700924 processDeviceAddedInternal(device.id());
925 }
926
927 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Das837e0bb2015-10-30 17:45:38 -0700928 // Irrespective of whether the local is a MASTER or not for this device,
929 // we need to create a SR-group-handler instance. This is because in a
930 // multi-instance setup, any instance can initiate forwarding/next-objectives
931 // for any switch (even if this instance is a SLAVE or not even connected
932 // to the switch). To handle this, a default-group-handler instance is necessary
933 // per switch.
Charles Chan2199c302016-04-23 17:36:10 -0700934 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
935 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan0b4e6182015-11-03 10:42:14 -0800936 DefaultGroupHandler groupHandler;
937 try {
938 groupHandler = DefaultGroupHandler.
Charles Chan2199c302016-04-23 17:36:10 -0700939 createGroupHandler(deviceId,
940 appId,
941 deviceConfiguration,
942 linkService,
943 flowObjectiveService,
944 this);
Charles Chan0b4e6182015-11-03 10:42:14 -0800945 } catch (DeviceConfigNotFoundException e) {
946 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
947 return;
948 }
Charles Chan2199c302016-04-23 17:36:10 -0700949 log.debug("updating groupHandlerMap with new config for device: {}",
950 deviceId);
951 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das2857f382015-11-03 14:39:27 -0800952 }
Saurav Dasb5c236e2016-06-07 10:08:06 -0700953
Charles Chan2199c302016-04-23 17:36:10 -0700954 if (mastershipService.isLocalMaster(deviceId)) {
Saurav Das018605f2017-02-18 14:05:44 -0800955 defaultRoutingHandler.populatePortAddressingRules(deviceId);
Charles Chan03a73e02016-10-24 14:52:01 -0700956 hostHandler.init(deviceId);
Charles Chanfc5c7802016-05-17 13:13:55 -0700957 xConnectHandler.init(deviceId);
Charles Chan35fd1a72016-06-13 18:54:31 -0700958 cordConfigHandler.init(deviceId);
Charles Chan2199c302016-04-23 17:36:10 -0700959 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chan59cc16d2017-02-02 16:20:42 -0800960 groupHandler.createGroupsFromVlanConfig();
Charles Chan2199c302016-04-23 17:36:10 -0700961 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chanc42e84e2015-10-20 16:24:19 -0700962 }
Charles Chan5270ed02016-01-30 23:22:37 -0800963
Charles Chan03a73e02016-10-24 14:52:01 -0700964 appCfgHandler.init(deviceId);
965 routeHandler.init(deviceId);
sanghob35a6192015-04-01 13:05:26 -0700966 }
967
Saurav Das80980c72016-03-23 11:22:49 -0700968 private void processDeviceRemoved(Device device) {
969 nsNextObjStore.entrySet().stream()
970 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
971 .forEach(entry -> {
972 nsNextObjStore.remove(entry.getKey());
973 });
Charles Chan59cc16d2017-02-02 16:20:42 -0800974 vlanNextObjStore.entrySet().stream()
Saurav Das80980c72016-03-23 11:22:49 -0700975 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
976 .forEach(entry -> {
Charles Chan59cc16d2017-02-02 16:20:42 -0800977 vlanNextObjStore.remove(entry.getKey());
Saurav Das80980c72016-03-23 11:22:49 -0700978 });
Saurav Das80980c72016-03-23 11:22:49 -0700979 portNextObjStore.entrySet().stream()
980 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
981 .forEach(entry -> {
982 portNextObjStore.remove(entry.getKey());
983 });
Saurav Das80980c72016-03-23 11:22:49 -0700984 groupHandlerMap.remove(device.id());
Saurav Das80980c72016-03-23 11:22:49 -0700985 defaultRoutingHandler.purgeEcmpGraph(device.id());
Charles Chan2199c302016-04-23 17:36:10 -0700986 mcastHandler.removeDevice(device.id());
Charles Chanfc5c7802016-05-17 13:13:55 -0700987 xConnectHandler.removeDevice(device.id());
Saurav Das80980c72016-03-23 11:22:49 -0700988 }
989
Saurav Das1a129a02016-11-18 15:21:57 -0800990 private void processPortUpdated(Device device, Port port) {
991 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
992 log.warn("Device configuration uploading. Not handling port event for"
993 + "dev: {} port: {}", device.id(), port.number());
994 return;
995 }
Saurav Das018605f2017-02-18 14:05:44 -0800996
997 if (!mastershipService.isLocalMaster(device.id())) {
998 log.debug("Not master for dev:{} .. not handling port updated event"
999 + "for port {}", device.id(), port.number());
1000 return;
1001 }
1002
1003 // first we handle filtering rules associated with the port
1004 if (port.isEnabled()) {
1005 log.info("Switchport {}/{} enabled..programming filters",
1006 device.id(), port.number());
Charles Chan7e4f8192017-02-26 22:59:35 -08001007 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), true);
Saurav Das018605f2017-02-18 14:05:44 -08001008 } else {
1009 log.info("Switchport {}/{} disabled..removing filters",
1010 device.id(), port.number());
Charles Chan7e4f8192017-02-26 22:59:35 -08001011 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), false);
Saurav Das018605f2017-02-18 14:05:44 -08001012 }
Saurav Das1a129a02016-11-18 15:21:57 -08001013
1014 // portUpdated calls are for ports that have gone down or up. For switch
1015 // to switch ports, link-events should take care of any re-routing or
1016 // group editing necessary for port up/down. Here we only process edge ports
1017 // that are already configured.
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001018 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
1019 VlanId untaggedVlan = getUntaggedVlanId(cp);
1020 VlanId nativeVlan = getNativeVlanId(cp);
1021 Set<VlanId> taggedVlans = getTaggedVlanId(cp);
Charles Chan59cc16d2017-02-02 16:20:42 -08001022
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001023 if (untaggedVlan == null && nativeVlan == null && taggedVlans.isEmpty()) {
Saurav Das1a129a02016-11-18 15:21:57 -08001024 log.debug("Not handling port updated event for unconfigured port "
1025 + "dev/port: {}/{}", device.id(), port.number());
1026 return;
1027 }
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001028 if (untaggedVlan != null) {
1029 processEdgePort(device, port, untaggedVlan, true);
1030 }
1031 if (nativeVlan != null) {
1032 processEdgePort(device, port, nativeVlan, true);
1033 }
1034 if (!taggedVlans.isEmpty()) {
1035 taggedVlans.forEach(tag -> processEdgePort(device, port, tag, false));
1036 }
Saurav Das1a129a02016-11-18 15:21:57 -08001037 }
1038
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001039 private void processEdgePort(Device device, Port port, VlanId vlanId,
1040 boolean popVlan) {
Saurav Das1a129a02016-11-18 15:21:57 -08001041 boolean portUp = port.isEnabled();
1042 if (portUp) {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001043 log.info("Device:EdgePort {}:{} is enabled in vlan: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001044 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001045 } else {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001046 log.info("Device:EdgePort {}:{} is disabled in vlan: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001047 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001048 }
1049
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -07001050 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -07001051 if (groupHandler != null) {
Saurav Dasb0ae6ee2017-03-04 16:08:47 -08001052 groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
Saurav Das1a129a02016-11-18 15:21:57 -08001053 } else {
1054 log.warn("Group handler not found for dev:{}. Not handling edge port"
1055 + " {} event for port:{}", device.id(),
1056 (portUp) ? "UP" : "DOWN", port.number());
sanghob35a6192015-04-01 13:05:26 -07001057 }
1058 }
sangho1e575652015-05-14 00:39:53 -07001059
Pier Ventre10bd8d12016-11-26 21:05:22 -08001060 /**
1061 * Registers the given connect point with the NRS, this is necessary
1062 * to receive the NDP and ARP packets from the NRS.
1063 *
1064 * @param portToRegister connect point to register
1065 */
1066 public void registerConnectPoint(ConnectPoint portToRegister) {
Charles Chan0aa674e2017-02-23 15:44:08 -08001067 neighbourResolutionService.registerNeighbourHandler(
Pier Ventre10bd8d12016-11-26 21:05:22 -08001068 portToRegister,
1069 neighbourHandler,
1070 appId
1071 );
1072 }
1073
Charles Chand6832882015-10-05 17:50:33 -07001074 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan2c15aca2016-11-09 20:51:44 -08001075 SegmentRoutingManager srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001076
Charles Chane849c192016-01-11 18:28:54 -08001077 /**
1078 * Constructs the internal network config listener.
1079 *
Charles Chan2c15aca2016-11-09 20:51:44 -08001080 * @param srManager segment routing manager
Charles Chane849c192016-01-11 18:28:54 -08001081 */
Charles Chan2c15aca2016-11-09 20:51:44 -08001082 public InternalConfigListener(SegmentRoutingManager srManager) {
1083 this.srManager = srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001084 }
1085
Charles Chane849c192016-01-11 18:28:54 -08001086 /**
1087 * Reads network config and initializes related data structure accordingly.
1088 */
Charles Chan4636be02015-10-07 14:21:45 -07001089 public void configureNetwork() {
Pier Ventre10bd8d12016-11-26 21:05:22 -08001090
Charles Chan2c15aca2016-11-09 20:51:44 -08001091 deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan4636be02015-10-07 14:21:45 -07001092
Charles Chan2c15aca2016-11-09 20:51:44 -08001093 arpHandler = new ArpHandler(srManager);
1094 icmpHandler = new IcmpHandler(srManager);
1095 ipHandler = new IpHandler(srManager);
1096 routingRulePopulator = new RoutingRulePopulator(srManager);
1097 defaultRoutingHandler = new DefaultRoutingHandler(srManager);
Charles Chan4636be02015-10-07 14:21:45 -07001098
1099 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
1100 groupHandlerMap, tunnelStore);
1101 policyHandler = new PolicyHandler(appId, deviceConfiguration,
1102 flowObjectiveService,
1103 tunnelHandler, policyStore);
1104
Charles Chan4636be02015-10-07 14:21:45 -07001105 for (Device device : deviceService.getDevices()) {
Charles Chan2199c302016-04-23 17:36:10 -07001106 processDeviceAddedInternal(device.id());
Charles Chan4636be02015-10-07 14:21:45 -07001107 }
1108
1109 defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -07001110 mcastHandler.init();
Charles Chan4636be02015-10-07 14:21:45 -07001111 }
1112
Charles Chand6832882015-10-05 17:50:33 -07001113 @Override
1114 public void event(NetworkConfigEvent event) {
Charles Chan5270ed02016-01-30 23:22:37 -08001115 // TODO move this part to NetworkConfigEventHandler
1116 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
1117 switch (event.type()) {
1118 case CONFIG_ADDED:
1119 log.info("Segment Routing Config added.");
1120 configureNetwork();
1121 break;
1122 case CONFIG_UPDATED:
1123 log.info("Segment Routing Config updated.");
1124 // TODO support dynamic configuration
1125 break;
1126 default:
1127 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001128 }
Charles Chan5270ed02016-01-30 23:22:37 -08001129 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chanfc5c7802016-05-17 13:13:55 -07001130 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan5270ed02016-01-30 23:22:37 -08001131 switch (event.type()) {
1132 case CONFIG_ADDED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001133 appCfgHandler.processAppConfigAdded(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001134 break;
1135 case CONFIG_UPDATED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001136 appCfgHandler.processAppConfigUpdated(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001137 break;
1138 case CONFIG_REMOVED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001139 appCfgHandler.processAppConfigRemoved(event);
1140 break;
1141 default:
1142 break;
1143 }
Charles Chan03a73e02016-10-24 14:52:01 -07001144 configureNetwork();
Charles Chanfc5c7802016-05-17 13:13:55 -07001145 } else if (event.configClass().equals(XConnectConfig.class)) {
1146 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
1147 switch (event.type()) {
1148 case CONFIG_ADDED:
1149 xConnectHandler.processXConnectConfigAdded(event);
1150 break;
1151 case CONFIG_UPDATED:
1152 xConnectHandler.processXConnectConfigUpdated(event);
1153 break;
1154 case CONFIG_REMOVED:
1155 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001156 break;
1157 default:
1158 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001159 }
Pier Luigi7dad71c2017-02-01 13:50:04 -08001160 // XXX Neighbour hacking. This method is looking for
1161 // the Internet-Router interface. In order to retrieve
1162 // the upstream port.
1163 } else if (event.configClass().equals(InterfaceConfig.class)) {
1164 switch (event.type()) {
1165 case CONFIG_ADDED:
1166 case CONFIG_UPDATED:
Pier Luigi721b6622017-02-03 13:34:21 -08001167 updateUPstreamCP();
Pier Luigi7dad71c2017-02-01 13:50:04 -08001168 case CONFIG_REGISTERED:
1169 case CONFIG_UNREGISTERED:
1170 case CONFIG_REMOVED:
1171 break;
1172 default:
1173 break;
1174 }
1175 // XXX Neighbour hacking. This method is looking for
1176 // the vrouter port.
1177 } else if (event.configClass().equals(RouterConfig.class)) {
1178 switch (event.type()) {
1179 case CONFIG_ADDED:
1180 case CONFIG_UPDATED:
Pier Luigi721b6622017-02-03 13:34:21 -08001181 updateVRouterCP(event);
Pier Luigi7dad71c2017-02-01 13:50:04 -08001182 case CONFIG_REGISTERED:
1183 case CONFIG_UNREGISTERED:
1184 case CONFIG_REMOVED:
1185 break;
1186 default:
1187 break;
1188 }
Pier Ventref34966c2016-11-07 16:21:04 -08001189 } else if (event.configClass().equals(PwaasConfig.class)) {
1190 checkState(l2TunnelHandler != null, "L2TunnelHandler is not initialized");
1191 switch (event.type()) {
1192 case CONFIG_ADDED:
1193 l2TunnelHandler.processPwaasConfigAdded(event);
1194 break;
1195 case CONFIG_UPDATED:
1196 l2TunnelHandler.processPwaasConfigUpdated(event);
1197 break;
1198 case CONFIG_REMOVED:
1199 l2TunnelHandler.processPwaasConfigRemoved(event);
1200 break;
1201 default:
1202 break;
1203 }
Charles Chand6832882015-10-05 17:50:33 -07001204 }
1205 }
1206 }
Charles Chan68aa62d2015-11-09 16:37:23 -08001207
Pier Luigi721b6622017-02-03 13:34:21 -08001208 /////////////////////////////////////////////////////////////////
1209 // XXX Neighbour hacking, temporary workaround will be //
Saurav Das018605f2017-02-18 14:05:44 -08001210 // removed as soon as possible, when bridging based //
1211 // control plane redirect is implemented. //
Pier Luigi721b6622017-02-03 13:34:21 -08001212 /////////////////////////////////////////////////////////////////
1213
1214 // XXX Neighbour hacking. To store upstream connect
1215 // point and vRouter connect point
1216 ConnectPoint upstreamCP = null;
1217 ConnectPoint vRouterCP = null;
1218
1219 // XXX Neighbour hacking. To update the Upstream CP
1220 public void updateUPstreamCP() {
1221 Set<ConnectPoint> portSubjects = cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
1222 upstreamCP = null;
1223 portSubjects.stream().forEach(subject -> {
1224 InterfaceConfig config = cfgService.getConfig(subject, InterfaceConfig.class);
1225 Set<Interface> networkInterfaces;
1226 try {
1227 networkInterfaces = config.getInterfaces();
1228 } catch (ConfigException e) {
1229 log.error("Error loading port configuration");
1230 return;
1231 }
1232 networkInterfaces.forEach(networkInterface -> {
1233 if (networkInterface.name().equals("internet-router")) {
1234 upstreamCP = subject;
1235 }
1236 });
1237 });
1238
1239 }
1240
1241 // XXX Neighbour hacking. To update the Upstream CP
1242 public void updateVRouterCP(NetworkConfigEvent event) {
1243 RouterConfig config = (RouterConfig) event.config().get();
1244 if (config == null) {
1245 log.warn("Router config not available");
1246 vRouterCP = null;
1247 return;
1248 }
1249 vRouterCP = config.getControlPlaneConnectPoint();
1250 }
1251
Charles Chan68aa62d2015-11-09 16:37:23 -08001252 private class InternalHostListener implements HostListener {
Charles Chan68aa62d2015-11-09 16:37:23 -08001253 @Override
1254 public void event(HostEvent event) {
1255 // Do not proceed without mastership
1256 DeviceId deviceId = event.subject().location().deviceId();
1257 if (!mastershipService.isLocalMaster(deviceId)) {
1258 return;
1259 }
1260
1261 switch (event.type()) {
1262 case HOST_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001263 hostHandler.processHostAddedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001264 break;
1265 case HOST_MOVED:
Charles Chand2990362016-04-18 13:44:03 -07001266 hostHandler.processHostMovedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001267 break;
1268 case HOST_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001269 hostHandler.processHostRemoveEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001270 break;
1271 case HOST_UPDATED:
Charles Chand2990362016-04-18 13:44:03 -07001272 hostHandler.processHostUpdatedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001273 break;
1274 default:
1275 log.warn("Unsupported host event type: {}", event.type());
1276 break;
1277 }
1278 }
1279 }
1280
Charles Chand55e84d2016-03-30 17:54:24 -07001281 private class InternalMcastListener implements McastListener {
1282 @Override
1283 public void event(McastEvent event) {
1284 switch (event.type()) {
1285 case SOURCE_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001286 mcastHandler.processSourceAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001287 break;
1288 case SINK_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001289 mcastHandler.processSinkAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001290 break;
1291 case SINK_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001292 mcastHandler.processSinkRemoved(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001293 break;
1294 case ROUTE_ADDED:
1295 case ROUTE_REMOVED:
1296 default:
1297 break;
1298 }
1299 }
1300 }
Charles Chan35fd1a72016-06-13 18:54:31 -07001301
1302 private class InternalCordConfigListener implements CordConfigListener {
1303 @Override
1304 public void event(CordConfigEvent event) {
1305 switch (event.type()) {
1306 case ACCESS_AGENT_ADDED:
1307 cordConfigHandler.processAccessAgentAddedEvent(event);
1308 break;
1309 case ACCESS_AGENT_UPDATED:
1310 cordConfigHandler.processAccessAgentUpdatedEvent(event);
1311 break;
1312 case ACCESS_AGENT_REMOVED:
1313 cordConfigHandler.processAccessAgentRemovedEvent(event);
1314 break;
1315 case ACCESS_DEVICE_ADDED:
1316 case ACCESS_DEVICE_UPDATED:
1317 case ACCESS_DEVICE_REMOVED:
1318 default:
1319 break;
1320 }
1321 }
1322 }
Charles Chan03a73e02016-10-24 14:52:01 -07001323
1324 private class InternalRouteEventListener implements RouteListener {
1325 @Override
1326 public void event(RouteEvent event) {
1327 switch (event.type()) {
1328 case ROUTE_ADDED:
1329 routeHandler.processRouteAdded(event);
1330 break;
1331 case ROUTE_UPDATED:
1332 routeHandler.processRouteUpdated(event);
1333 break;
1334 case ROUTE_REMOVED:
1335 routeHandler.processRouteRemoved(event);
1336 break;
1337 default:
1338 break;
1339 }
1340 }
1341 }
sanghob35a6192015-04-01 13:05:26 -07001342}