blob: dc3f3584dcd2920f140ad26b1e73eaf2cb283407 [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) {
Charles Chan7a068742017-02-16 11:45:52 -0800705 log.warn("Receive unexpected ARP packet on {}", context.inPacket().receivedFrom());
Pier Ventre10bd8d12016-11-26 21:05:22 -0800706 log.debug("{}", 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.
Charles Chan59cc16d2017-02-02 16:20:42 -08001018 VlanId untaggedVlan = getUntaggedVlanId(new ConnectPoint(device.id(), port.number()));
1019 VlanId vlanId = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
1020
1021 if (vlanId.equals(INTERNAL_VLAN)) {
Saurav Das1a129a02016-11-18 15:21:57 -08001022 log.debug("Not handling port updated event for unconfigured port "
1023 + "dev/port: {}/{}", device.id(), port.number());
1024 return;
1025 }
Charles Chan59cc16d2017-02-02 16:20:42 -08001026 processEdgePort(device, port, vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001027 }
1028
Charles Chan59cc16d2017-02-02 16:20:42 -08001029 private void processEdgePort(Device device, Port port, VlanId vlanId) {
Saurav Das1a129a02016-11-18 15:21:57 -08001030 boolean portUp = port.isEnabled();
1031 if (portUp) {
1032 log.info("Device:EdgePort {}:{} is enabled in subnet: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001033 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001034 } else {
1035 log.info("Device:EdgePort {}:{} is disabled in subnet: {}", device.id(),
Charles Chan59cc16d2017-02-02 16:20:42 -08001036 port.number(), vlanId);
Saurav Das1a129a02016-11-18 15:21:57 -08001037 }
1038
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -07001039 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -07001040 if (groupHandler != null) {
Charles Chan59cc16d2017-02-02 16:20:42 -08001041 groupHandler.processEdgePort(port.number(), vlanId, portUp);
Saurav Das1a129a02016-11-18 15:21:57 -08001042 } else {
1043 log.warn("Group handler not found for dev:{}. Not handling edge port"
1044 + " {} event for port:{}", device.id(),
1045 (portUp) ? "UP" : "DOWN", port.number());
sanghob35a6192015-04-01 13:05:26 -07001046 }
1047 }
sangho1e575652015-05-14 00:39:53 -07001048
Pier Ventre10bd8d12016-11-26 21:05:22 -08001049 /**
1050 * Registers the given connect point with the NRS, this is necessary
1051 * to receive the NDP and ARP packets from the NRS.
1052 *
1053 * @param portToRegister connect point to register
1054 */
1055 public void registerConnectPoint(ConnectPoint portToRegister) {
Charles Chan0aa674e2017-02-23 15:44:08 -08001056 neighbourResolutionService.registerNeighbourHandler(
Pier Ventre10bd8d12016-11-26 21:05:22 -08001057 portToRegister,
1058 neighbourHandler,
1059 appId
1060 );
1061 }
1062
Charles Chand6832882015-10-05 17:50:33 -07001063 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan2c15aca2016-11-09 20:51:44 -08001064 SegmentRoutingManager srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001065
Charles Chane849c192016-01-11 18:28:54 -08001066 /**
1067 * Constructs the internal network config listener.
1068 *
Charles Chan2c15aca2016-11-09 20:51:44 -08001069 * @param srManager segment routing manager
Charles Chane849c192016-01-11 18:28:54 -08001070 */
Charles Chan2c15aca2016-11-09 20:51:44 -08001071 public InternalConfigListener(SegmentRoutingManager srManager) {
1072 this.srManager = srManager;
Charles Chan4636be02015-10-07 14:21:45 -07001073 }
1074
Charles Chane849c192016-01-11 18:28:54 -08001075 /**
1076 * Reads network config and initializes related data structure accordingly.
1077 */
Charles Chan4636be02015-10-07 14:21:45 -07001078 public void configureNetwork() {
Pier Ventre10bd8d12016-11-26 21:05:22 -08001079
Charles Chan2c15aca2016-11-09 20:51:44 -08001080 deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan4636be02015-10-07 14:21:45 -07001081
Charles Chan2c15aca2016-11-09 20:51:44 -08001082 arpHandler = new ArpHandler(srManager);
1083 icmpHandler = new IcmpHandler(srManager);
1084 ipHandler = new IpHandler(srManager);
1085 routingRulePopulator = new RoutingRulePopulator(srManager);
1086 defaultRoutingHandler = new DefaultRoutingHandler(srManager);
Charles Chan4636be02015-10-07 14:21:45 -07001087
1088 tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
1089 groupHandlerMap, tunnelStore);
1090 policyHandler = new PolicyHandler(appId, deviceConfiguration,
1091 flowObjectiveService,
1092 tunnelHandler, policyStore);
1093
Charles Chan4636be02015-10-07 14:21:45 -07001094 for (Device device : deviceService.getDevices()) {
Charles Chan2199c302016-04-23 17:36:10 -07001095 processDeviceAddedInternal(device.id());
Charles Chan4636be02015-10-07 14:21:45 -07001096 }
1097
1098 defaultRoutingHandler.startPopulationProcess();
Charles Chan2199c302016-04-23 17:36:10 -07001099 mcastHandler.init();
Charles Chan4636be02015-10-07 14:21:45 -07001100 }
1101
Charles Chand6832882015-10-05 17:50:33 -07001102 @Override
1103 public void event(NetworkConfigEvent event) {
Charles Chan5270ed02016-01-30 23:22:37 -08001104 // TODO move this part to NetworkConfigEventHandler
1105 if (event.configClass().equals(SegmentRoutingDeviceConfig.class)) {
1106 switch (event.type()) {
1107 case CONFIG_ADDED:
1108 log.info("Segment Routing Config added.");
1109 configureNetwork();
1110 break;
1111 case CONFIG_UPDATED:
1112 log.info("Segment Routing Config updated.");
1113 // TODO support dynamic configuration
1114 break;
1115 default:
1116 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001117 }
Charles Chan5270ed02016-01-30 23:22:37 -08001118 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chanfc5c7802016-05-17 13:13:55 -07001119 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan5270ed02016-01-30 23:22:37 -08001120 switch (event.type()) {
1121 case CONFIG_ADDED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001122 appCfgHandler.processAppConfigAdded(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001123 break;
1124 case CONFIG_UPDATED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001125 appCfgHandler.processAppConfigUpdated(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001126 break;
1127 case CONFIG_REMOVED:
Charles Chanfc5c7802016-05-17 13:13:55 -07001128 appCfgHandler.processAppConfigRemoved(event);
1129 break;
1130 default:
1131 break;
1132 }
Charles Chan03a73e02016-10-24 14:52:01 -07001133 configureNetwork();
Charles Chanfc5c7802016-05-17 13:13:55 -07001134 } else if (event.configClass().equals(XConnectConfig.class)) {
1135 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
1136 switch (event.type()) {
1137 case CONFIG_ADDED:
1138 xConnectHandler.processXConnectConfigAdded(event);
1139 break;
1140 case CONFIG_UPDATED:
1141 xConnectHandler.processXConnectConfigUpdated(event);
1142 break;
1143 case CONFIG_REMOVED:
1144 xConnectHandler.processXConnectConfigRemoved(event);
Charles Chan5270ed02016-01-30 23:22:37 -08001145 break;
1146 default:
1147 break;
Charles Chanb8e10c82015-10-14 11:24:40 -07001148 }
Pier Luigi7dad71c2017-02-01 13:50:04 -08001149 // XXX Neighbour hacking. This method is looking for
1150 // the Internet-Router interface. In order to retrieve
1151 // the upstream port.
1152 } else if (event.configClass().equals(InterfaceConfig.class)) {
1153 switch (event.type()) {
1154 case CONFIG_ADDED:
1155 case CONFIG_UPDATED:
Pier Luigi721b6622017-02-03 13:34:21 -08001156 updateUPstreamCP();
Pier Luigi7dad71c2017-02-01 13:50:04 -08001157 case CONFIG_REGISTERED:
1158 case CONFIG_UNREGISTERED:
1159 case CONFIG_REMOVED:
1160 break;
1161 default:
1162 break;
1163 }
1164 // XXX Neighbour hacking. This method is looking for
1165 // the vrouter port.
1166 } else if (event.configClass().equals(RouterConfig.class)) {
1167 switch (event.type()) {
1168 case CONFIG_ADDED:
1169 case CONFIG_UPDATED:
Pier Luigi721b6622017-02-03 13:34:21 -08001170 updateVRouterCP(event);
Pier Luigi7dad71c2017-02-01 13:50:04 -08001171 case CONFIG_REGISTERED:
1172 case CONFIG_UNREGISTERED:
1173 case CONFIG_REMOVED:
1174 break;
1175 default:
1176 break;
1177 }
Pier Ventref34966c2016-11-07 16:21:04 -08001178 } else if (event.configClass().equals(PwaasConfig.class)) {
1179 checkState(l2TunnelHandler != null, "L2TunnelHandler is not initialized");
1180 switch (event.type()) {
1181 case CONFIG_ADDED:
1182 l2TunnelHandler.processPwaasConfigAdded(event);
1183 break;
1184 case CONFIG_UPDATED:
1185 l2TunnelHandler.processPwaasConfigUpdated(event);
1186 break;
1187 case CONFIG_REMOVED:
1188 l2TunnelHandler.processPwaasConfigRemoved(event);
1189 break;
1190 default:
1191 break;
1192 }
Charles Chand6832882015-10-05 17:50:33 -07001193 }
1194 }
1195 }
Charles Chan68aa62d2015-11-09 16:37:23 -08001196
Pier Luigi721b6622017-02-03 13:34:21 -08001197 /////////////////////////////////////////////////////////////////
1198 // XXX Neighbour hacking, temporary workaround will be //
Saurav Das018605f2017-02-18 14:05:44 -08001199 // removed as soon as possible, when bridging based //
1200 // control plane redirect is implemented. //
Pier Luigi721b6622017-02-03 13:34:21 -08001201 /////////////////////////////////////////////////////////////////
1202
1203 // XXX Neighbour hacking. To store upstream connect
1204 // point and vRouter connect point
1205 ConnectPoint upstreamCP = null;
1206 ConnectPoint vRouterCP = null;
1207
1208 // XXX Neighbour hacking. To update the Upstream CP
1209 public void updateUPstreamCP() {
1210 Set<ConnectPoint> portSubjects = cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
1211 upstreamCP = null;
1212 portSubjects.stream().forEach(subject -> {
1213 InterfaceConfig config = cfgService.getConfig(subject, InterfaceConfig.class);
1214 Set<Interface> networkInterfaces;
1215 try {
1216 networkInterfaces = config.getInterfaces();
1217 } catch (ConfigException e) {
1218 log.error("Error loading port configuration");
1219 return;
1220 }
1221 networkInterfaces.forEach(networkInterface -> {
1222 if (networkInterface.name().equals("internet-router")) {
1223 upstreamCP = subject;
1224 }
1225 });
1226 });
1227
1228 }
1229
1230 // XXX Neighbour hacking. To update the Upstream CP
1231 public void updateVRouterCP(NetworkConfigEvent event) {
1232 RouterConfig config = (RouterConfig) event.config().get();
1233 if (config == null) {
1234 log.warn("Router config not available");
1235 vRouterCP = null;
1236 return;
1237 }
1238 vRouterCP = config.getControlPlaneConnectPoint();
1239 }
1240
Charles Chan68aa62d2015-11-09 16:37:23 -08001241 private class InternalHostListener implements HostListener {
Charles Chan68aa62d2015-11-09 16:37:23 -08001242 @Override
1243 public void event(HostEvent event) {
1244 // Do not proceed without mastership
1245 DeviceId deviceId = event.subject().location().deviceId();
1246 if (!mastershipService.isLocalMaster(deviceId)) {
1247 return;
1248 }
1249
1250 switch (event.type()) {
1251 case HOST_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001252 hostHandler.processHostAddedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001253 break;
1254 case HOST_MOVED:
Charles Chand2990362016-04-18 13:44:03 -07001255 hostHandler.processHostMovedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001256 break;
1257 case HOST_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001258 hostHandler.processHostRemoveEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001259 break;
1260 case HOST_UPDATED:
Charles Chand2990362016-04-18 13:44:03 -07001261 hostHandler.processHostUpdatedEvent(event);
Charles Chan68aa62d2015-11-09 16:37:23 -08001262 break;
1263 default:
1264 log.warn("Unsupported host event type: {}", event.type());
1265 break;
1266 }
1267 }
1268 }
1269
Charles Chand55e84d2016-03-30 17:54:24 -07001270 private class InternalMcastListener implements McastListener {
1271 @Override
1272 public void event(McastEvent event) {
1273 switch (event.type()) {
1274 case SOURCE_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001275 mcastHandler.processSourceAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001276 break;
1277 case SINK_ADDED:
Charles Chand2990362016-04-18 13:44:03 -07001278 mcastHandler.processSinkAdded(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001279 break;
1280 case SINK_REMOVED:
Charles Chand2990362016-04-18 13:44:03 -07001281 mcastHandler.processSinkRemoved(event);
Charles Chand55e84d2016-03-30 17:54:24 -07001282 break;
1283 case ROUTE_ADDED:
1284 case ROUTE_REMOVED:
1285 default:
1286 break;
1287 }
1288 }
1289 }
Charles Chan35fd1a72016-06-13 18:54:31 -07001290
1291 private class InternalCordConfigListener implements CordConfigListener {
1292 @Override
1293 public void event(CordConfigEvent event) {
1294 switch (event.type()) {
1295 case ACCESS_AGENT_ADDED:
1296 cordConfigHandler.processAccessAgentAddedEvent(event);
1297 break;
1298 case ACCESS_AGENT_UPDATED:
1299 cordConfigHandler.processAccessAgentUpdatedEvent(event);
1300 break;
1301 case ACCESS_AGENT_REMOVED:
1302 cordConfigHandler.processAccessAgentRemovedEvent(event);
1303 break;
1304 case ACCESS_DEVICE_ADDED:
1305 case ACCESS_DEVICE_UPDATED:
1306 case ACCESS_DEVICE_REMOVED:
1307 default:
1308 break;
1309 }
1310 }
1311 }
Charles Chan03a73e02016-10-24 14:52:01 -07001312
1313 private class InternalRouteEventListener implements RouteListener {
1314 @Override
1315 public void event(RouteEvent event) {
1316 switch (event.type()) {
1317 case ROUTE_ADDED:
1318 routeHandler.processRouteAdded(event);
1319 break;
1320 case ROUTE_UPDATED:
1321 routeHandler.processRouteUpdated(event);
1322 break;
1323 case ROUTE_REMOVED:
1324 routeHandler.processRouteRemoved(event);
1325 break;
1326 default:
1327 break;
1328 }
1329 }
1330 }
sanghob35a6192015-04-01 13:05:26 -07001331}