blob: dc3f3584dcd2920f140ad26b1e73eaf2cb283407 [file] [log] [blame]
sangho80f11cb2015-04-01 13:05:26 -07001/*
Brian O'Connor43b53542016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sangho80f11cb2015-04-01 13:05:26 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.segmentrouting;
17
Charles Chan90772a72017-02-08 15:52:08 -080018import com.google.common.collect.HashMultimap;
Charles Chand7844e52016-10-20 17:02:44 -070019import com.google.common.collect.Maps;
Charles Chan90772a72017-02-08 15:52:08 -080020import com.google.common.collect.Multimap;
sangho80f11cb2015-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;
sangho27462c62015-05-14 00:39:53 -070026import org.apache.felix.scr.annotations.Service;
sangho80f11cb2015-04-01 13:05:26 -070027import org.onlab.packet.Ethernet;
Pier Ventreb6b81d52016-12-02 08:16:05 -080028import org.onlab.packet.ICMP6;
Charles Chan77277672015-10-20 16:24:19 -070029import org.onlab.packet.IPv4;
Pier Ventreb6a7f342016-11-26 21:05:22 -080030import org.onlab.packet.IPv6;
Charles Chan77277672015-10-20 16:24:19 -070031import org.onlab.packet.IpPrefix;
Jonathan Hart54541d12016-04-12 15:39:44 -070032import org.onlab.packet.VlanId;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -070033import org.onlab.util.KryoNamespace;
Saurav Dasc3604f12016-03-23 11:22:49 -070034import org.onosproject.cfg.ComponentConfigService;
sangho80f11cb2015-04-01 13:05:26 -070035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
37import org.onosproject.event.Event;
Pier Luigiad0a67f2017-02-03 13:34:21 -080038import org.onosproject.incubator.net.config.basics.ConfigException;
Pier Luigi37a35432017-02-01 13:50:04 -080039import org.onosproject.incubator.net.config.basics.InterfaceConfig;
Charles Chanc91c8782016-03-30 17:54:24 -070040import org.onosproject.incubator.net.config.basics.McastConfig;
Pier Luigiad0a67f2017-02-03 13:34:21 -080041import org.onosproject.incubator.net.intf.Interface;
Charles Chan46fdfaf2016-11-09 20:51:44 -080042import org.onosproject.incubator.net.intf.InterfaceService;
Charles Chandebfea32016-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 Ventreb6b81d52016-12-02 08:16:05 -080046import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
Jonathan Hart54541d12016-04-12 15:39:44 -070047import org.onosproject.mastership.MastershipService;
Pier Ventreb6a7f342016-11-26 21:05:22 -080048import org.onosproject.net.ConnectPoint;
Jonathan Hart54541d12016-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 Chanf4586112015-11-09 16:37:23 -080053import org.onosproject.net.PortNumber;
Charles Chan72f556a2015-10-05 17:50:33 -070054import org.onosproject.net.config.ConfigFactory;
55import org.onosproject.net.config.NetworkConfigEvent;
Charles Chan72f556a2015-10-05 17:50:33 -070056import org.onosproject.net.config.NetworkConfigListener;
Jonathan Hart54541d12016-04-12 15:39:44 -070057import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chan72f556a2015-10-05 17:50:33 -070058import org.onosproject.net.config.basics.SubjectFactories;
Jonathan Hart54541d12016-04-12 15:39:44 -070059import org.onosproject.net.device.DeviceEvent;
60import org.onosproject.net.device.DeviceListener;
61import org.onosproject.net.device.DeviceService;
Charles Chanf4586112015-11-09 16:37:23 -080062import org.onosproject.net.flow.TrafficSelector;
63import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart54541d12016-04-12 15:39:44 -070064import org.onosproject.net.flowobjective.FlowObjectiveService;
Charles Chanf4586112015-11-09 16:37:23 -080065import org.onosproject.net.host.HostEvent;
66import org.onosproject.net.host.HostListener;
Pier Ventreb6a7f342016-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 Chanc91c8782016-03-30 17:54:24 -070071import org.onosproject.net.mcast.McastEvent;
72import org.onosproject.net.mcast.McastListener;
73import org.onosproject.net.mcast.MulticastRouteService;
Pier Ventreb6a7f342016-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 Ventref3cf5b92016-11-09 14:17:26 -080078import org.onosproject.net.topology.PathService;
Charles Chanc91c8782016-03-30 17:54:24 -070079import org.onosproject.net.topology.TopologyService;
Pier Luigi37a35432017-02-01 13:50:04 -080080import org.onosproject.routing.config.RouterConfig;
Charles Chanc91c8782016-03-30 17:54:24 -070081import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
82import org.onosproject.segmentrouting.config.DeviceConfiguration;
Pier Ventre6b19e482016-11-07 16:21:04 -080083import org.onosproject.segmentrouting.config.PwaasConfig;
Pier Ventreb6a7f342016-11-26 21:05:22 -080084import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Pier Ventre6b19e482016-11-07 16:21:04 -080085import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
Charles Chan82f19972016-05-17 13:13:55 -070086import org.onosproject.segmentrouting.config.XConnectConfig;
Charles Chanc91c8782016-03-30 17:54:24 -070087import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
88import org.onosproject.segmentrouting.grouphandler.NeighborSet;
Charles Chan1eaf4802016-04-18 13:44:03 -070089import org.onosproject.segmentrouting.storekey.NeighborSetNextObjectiveStoreKey;
90import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
Charles Chan1eaf4802016-04-18 13:44:03 -070091import org.onosproject.segmentrouting.storekey.SubnetAssignedVidStoreKey;
Charles Chan10b0fb72017-02-02 16:20:42 -080092import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
Charles Chan82f19972016-05-17 13:13:55 -070093import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
Pier Ventre6b19e482016-11-07 16:21:04 -080094import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
Jonathan Hart54541d12016-04-12 15:39:44 -070095import org.onosproject.store.serializers.KryoNamespaces;
Srikanth Vavilapalli7cd16712015-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 Chan41f5ec02016-06-13 18:54:31 -0700100import org.opencord.cordconfig.CordConfigEvent;
101import org.opencord.cordconfig.CordConfigListener;
102import org.opencord.cordconfig.CordConfigService;
sangho80f11cb2015-04-01 13:05:26 -0700103import org.slf4j.Logger;
104import org.slf4j.LoggerFactory;
105
sangho27462c62015-05-14 00:39:53 -0700106import java.util.List;
sangho80f11cb2015-04-01 13:05:26 -0700107import java.util.Map;
Saurav Das7c305372015-10-28 12:39:42 -0700108import java.util.Set;
sangho80f11cb2015-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 Chan90772a72017-02-08 15:52:08 -0800115import java.util.stream.Collectors;
sangho80f11cb2015-04-01 13:05:26 -0700116
Charles Chand6d25332016-02-26 22:19:52 -0800117import static com.google.common.base.Preconditions.checkState;
Pier Ventreadb4ae62016-11-23 09:57:42 -0800118import static org.onlab.packet.Ethernet.TYPE_ARP;
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700119import static org.onlab.util.Tools.groupedThreads;
Charles Chand6d25332016-02-26 22:19:52 -0800120
Charles Chanb7f75ac2016-01-11 18:28:54 -0800121/**
122 * Segment routing manager.
123 */
Jonathan Hart54541d12016-04-12 15:39:44 -0700124@Service
125@Component(immediate = true)
sangho27462c62015-05-14 00:39:53 -0700126public class SegmentRoutingManager implements SegmentRoutingService {
sangho80f11cb2015-04-01 13:05:26 -0700127
Charles Chan46fdfaf2016-11-09 20:51:44 -0800128 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
sangho80f11cb2015-04-01 13:05:26 -0700129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700131 private ComponentConfigService compCfgService;
sangho80f11cb2015-04-01 13:05:26 -0700132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventreb6a7f342016-11-26 21:05:22 -0800134 private NeighbourResolutionService neighbourResolutionService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventref3cf5b92016-11-09 14:17:26 -0800137 public PathService pathService;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700140 CoreService coreService;
sangho80f11cb2015-04-01 13:05:26 -0700141
142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700143 PacketService packetService;
sangho80f11cb2015-04-01 13:05:26 -0700144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700146 HostService hostService;
sangho80f11cb2015-04-01 13:05:26 -0700147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700149 DeviceService deviceService;
sangho80f11cb2015-04-01 13:05:26 -0700150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventref3cf5b92016-11-09 14:17:26 -0800152 public FlowObjectiveService flowObjectiveService;
sangho80f11cb2015-04-01 13:05:26 -0700153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chandebfea32016-10-24 14:52:01 -0700155 LinkService linkService;
sangho27462c62015-05-14 00:39:53 -0700156
Charles Chan82ab1932016-01-30 23:22:37 -0800157 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventref3cf5b92016-11-09 14:17:26 -0800158 public MastershipService mastershipService;
Charles Chandebfea32016-10-24 14:52:01 -0700159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pier Ventref3cf5b92016-11-09 14:17:26 -0800161 public StorageService storageService;
Charles Chandebfea32016-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 Chan82ab1932016-01-30 23:22:37 -0800174
175 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan46fdfaf2016-11-09 20:51:44 -0800176 public NetworkConfigRegistry cfgService;
Charles Chan82ab1932016-01-30 23:22:37 -0800177
Saurav Dasc3604f12016-03-23 11:22:49 -0700178 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Charles Chan46fdfaf2016-11-09 20:51:44 -0800179 public InterfaceService interfaceService;
180
Charles Chandebfea32016-10-24 14:52:01 -0700181 ArpHandler arpHandler = null;
182 IcmpHandler icmpHandler = null;
183 IpHandler ipHandler = null;
184 RoutingRulePopulator routingRulePopulator = null;
Charles Chan46fdfaf2016-11-09 20:51:44 -0800185 public ApplicationId appId;
Pier Ventref3cf5b92016-11-09 14:17:26 -0800186 public DeviceConfiguration deviceConfiguration = null;
sangho80f11cb2015-04-01 13:05:26 -0700187
Charles Chandebfea32016-10-24 14:52:01 -0700188 DefaultRoutingHandler defaultRoutingHandler = null;
sangho27462c62015-05-14 00:39:53 -0700189 private TunnelHandler tunnelHandler = null;
190 private PolicyHandler policyHandler = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700191 private InternalPacketProcessor processor = null;
192 private InternalLinkListener linkListener = null;
193 private InternalDeviceListener deviceListener = null;
Charles Chan82f19972016-05-17 13:13:55 -0700194 private AppConfigHandler appCfgHandler = null;
Charles Chandebfea32016-10-24 14:52:01 -0700195 XConnectHandler xConnectHandler = null;
Charles Chan1eaf4802016-04-18 13:44:03 -0700196 private McastHandler mcastHandler = null;
Charles Chandebfea32016-10-24 14:52:01 -0700197 HostHandler hostHandler = null;
Charles Chan41f5ec02016-06-13 18:54:31 -0700198 private CordConfigHandler cordConfigHandler = null;
Pier Ventreb6a7f342016-11-26 21:05:22 -0800199 private RouteHandler routeHandler = null;
Pier Ventreb6b81d52016-12-02 08:16:05 -0800200 private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
Pier Ventre6b19e482016-11-07 16:21:04 -0800201 private L2TunnelHandler l2TunnelHandler = null;
sangho80f11cb2015-04-01 13:05:26 -0700202 private InternalEventHandler eventHandler = new InternalEventHandler();
Charles Chan82ab1932016-01-30 23:22:37 -0800203 private final InternalHostListener hostListener = new InternalHostListener();
Charles Chanc91c8782016-03-30 17:54:24 -0700204 private final InternalConfigListener cfgListener = new InternalConfigListener(this);
205 private final InternalMcastListener mcastListener = new InternalMcastListener();
Charles Chan41f5ec02016-06-13 18:54:31 -0700206 private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
Charles Chandebfea32016-10-24 14:52:01 -0700207 private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
sangho80f11cb2015-04-01 13:05:26 -0700208
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700209 private ScheduledExecutorService executorService = Executors
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700210 .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
sangho80f11cb2015-04-01 13:05:26 -0700211
Saurav Das2d94d312015-11-24 23:21:05 -0800212 @SuppressWarnings("unused")
sangho80f11cb2015-04-01 13:05:26 -0700213 private static ScheduledFuture<?> eventHandlerFuture = null;
Saurav Das2d94d312015-11-24 23:21:05 -0800214 @SuppressWarnings("rawtypes")
Yuta HIGUCHIebee2f12016-07-21 16:54:33 -0700215 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
Charles Chanf4586112015-11-09 16:37:23 -0800216 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
Charles Chanb7f75ac2016-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 Chanf4586112015-11-09 16:37:23 -0800222 nsNextObjStore = null;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800223 /**
224 * Per device next objective ID store with (device id + subnet) as key.
225 */
Charles Chan10b0fb72017-02-02 16:20:42 -0800226 public EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
227 vlanNextObjStore = null;
Charles Chanb7f75ac2016-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 Das2d94d312015-11-24 23:21:05 -0800232 portNextObjStore = null;
Charles Chan10b0fb72017-02-02 16:20:42 -0800233
Saurav Das2d94d312015-11-24 23:21:05 -0800234 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
235 private EventuallyConsistentMap<String, Policy> policyStore = null;
sangho4a5c42a2015-05-20 22:16:38 -0700236
Charles Chanc91c8782016-03-30 17:54:24 -0700237 private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700238 new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
239 SubjectFactories.DEVICE_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700240 SegmentRoutingDeviceConfig.class, "segmentrouting") {
Charles Chan72f556a2015-10-05 17:50:33 -0700241 @Override
Charles Chan82ab1932016-01-30 23:22:37 -0800242 public SegmentRoutingDeviceConfig createConfig() {
243 return new SegmentRoutingDeviceConfig();
Charles Chan72f556a2015-10-05 17:50:33 -0700244 }
245 };
Pier Ventre6b19e482016-11-07 16:21:04 -0800246
Charles Chanc91c8782016-03-30 17:54:24 -0700247 private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700248 new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
249 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700250 SegmentRoutingAppConfig.class, "segmentrouting") {
Charles Chan82ab1932016-01-30 23:22:37 -0800251 @Override
252 public SegmentRoutingAppConfig createConfig() {
253 return new SegmentRoutingAppConfig();
254 }
255 };
Pier Ventre6b19e482016-11-07 16:21:04 -0800256
Charles Chan82f19972016-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 Ventre6b19e482016-11-07 16:21:04 -0800266
Charles Chanc91c8782016-03-30 17:54:24 -0700267 private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
Charles Chan82f19972016-05-17 13:13:55 -0700268 new ConfigFactory<ApplicationId, McastConfig>(
269 SubjectFactories.APP_SUBJECT_FACTORY,
Charles Chanc91c8782016-03-30 17:54:24 -0700270 McastConfig.class, "multicast") {
271 @Override
272 public McastConfig createConfig() {
273 return new McastConfig();
274 }
275 };
276
Pier Ventre6b19e482016-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 Vavilapalli64d96c12015-05-14 20:22:47 -0700287 private Object threadSchedulerLock = new Object();
288 private static int numOfEventsQueued = 0;
289 private static int numOfEventsExecuted = 0;
sangho80f11cb2015-04-01 13:05:26 -0700290 private static int numOfHandlerExecution = 0;
291 private static int numOfHandlerScheduled = 0;
292
Charles Chan1963f4f2016-02-18 14:22:42 -0800293 /**
294 * Segment Routing App ID.
295 */
Charles Chan46fdfaf2016-11-09 20:51:44 -0800296 public static final String APP_NAME = "org.onosproject.segmentrouting";
Charles Chan10b0fb72017-02-02 16:20:42 -0800297
Charles Chanb7f75ac2016-01-11 18:28:54 -0800298 /**
299 * The default VLAN ID assigned to the interfaces without subnet config.
300 */
Charles Chan10b0fb72017-02-02 16:20:42 -0800301 public static final VlanId INTERNAL_VLAN = VlanId.vlanId((short) 4094);
Saurav Das7c305372015-10-28 12:39:42 -0700302
sangho80f11cb2015-04-01 13:05:26 -0700303 @Activate
304 protected void activate() {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800305 appId = coreService.registerApplication(APP_NAME);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700306
307 log.debug("Creating EC map nsnextobjectivestore");
308 EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
309 nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700310 nsNextObjStore = nsNextObjMapBuilder
311 .withName("nsnextobjectivestore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700312 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700313 .withTimestampProvider((k, v) -> new WallClockTimestamp())
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700314 .build();
315 log.trace("Current size {}", nsNextObjStore.size());
316
Charles Chan10b0fb72017-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 Hart54541d12016-04-12 15:39:44 -0700322 .withSerializer(createSerializer())
Charles Chan77277672015-10-20 16:24:19 -0700323 .withTimestampProvider((k, v) -> new WallClockTimestamp())
324 .build();
325
Saurav Das2d94d312015-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 Hart54541d12016-04-12 15:39:44 -0700331 .withSerializer(createSerializer())
Saurav Das2d94d312015-11-24 23:21:05 -0800332 .withTimestampProvider((k, v) -> new WallClockTimestamp())
333 .build();
334
sangho4a5c42a2015-05-20 22:16:38 -0700335 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
336 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700337 tunnelStore = tunnelMapBuilder
338 .withName("tunnelstore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700339 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700340 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700341 .build();
342
343 EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
344 storageService.eventuallyConsistentMapBuilder();
sangho4a5c42a2015-05-20 22:16:38 -0700345 policyStore = policyMapBuilder
346 .withName("policystore")
Jonathan Hart54541d12016-04-12 15:39:44 -0700347 .withSerializer(createSerializer())
Madan Jampani675ae202015-06-24 19:05:56 -0700348 .withTimestampProvider((k, v) -> new WallClockTimestamp())
sangho4a5c42a2015-05-20 22:16:38 -0700349 .build();
350
Saurav Dasc3604f12016-03-23 11:22:49 -0700351 compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
Pier Luigib9632ba2017-01-12 18:14:58 -0800352 "purgeOnDisconnection", "true");
Saurav Dasc3604f12016-03-23 11:22:49 -0700353 compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
Pier Luigib9632ba2017-01-12 18:14:58 -0800354 "purgeOnDisconnection", "true");
Pier Luigib9632ba2017-01-12 18:14:58 -0800355 compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
356 "requestInterceptsEnabled", "false");
Pier Luigibc976df2017-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 Luigi0ebeb312017-02-02 22:31:34 -0800361 compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
362 "greedyLearningIpv6", "true");
Charles Chancf8ea472017-02-28 15:15:17 -0800363 compCfgService.preSetProperty("org.onosproject.routing.cpr.ControlPlaneRedirectManager",
364 "forceUnprovision", "true");
Saurav Dasc3604f12016-03-23 11:22:49 -0700365
Charles Chan2b078ae2015-10-14 11:24:40 -0700366 processor = new InternalPacketProcessor();
367 linkListener = new InternalLinkListener();
368 deviceListener = new InternalDeviceListener();
Charles Chan82f19972016-05-17 13:13:55 -0700369 appCfgHandler = new AppConfigHandler(this);
370 xConnectHandler = new XConnectHandler(this);
Charles Chan1eaf4802016-04-18 13:44:03 -0700371 mcastHandler = new McastHandler(this);
372 hostHandler = new HostHandler(this);
Charles Chan41f5ec02016-06-13 18:54:31 -0700373 cordConfigHandler = new CordConfigHandler(this);
Charles Chandebfea32016-10-24 14:52:01 -0700374 routeHandler = new RouteHandler(this);
Pier Ventreb6b81d52016-12-02 08:16:05 -0800375 neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
Pier Ventre6b19e482016-11-07 16:21:04 -0800376 l2TunnelHandler = new L2TunnelHandler(this);
Charles Chan2b078ae2015-10-14 11:24:40 -0700377
Charles Chand6d25332016-02-26 22:19:52 -0800378 cfgService.addListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700379 cfgService.registerConfigFactory(deviceConfigFactory);
380 cfgService.registerConfigFactory(appConfigFactory);
Charles Chan82f19972016-05-17 13:13:55 -0700381 cfgService.registerConfigFactory(xConnectConfigFactory);
Charles Chanc91c8782016-03-30 17:54:24 -0700382 cfgService.registerConfigFactory(mcastConfigFactory);
Pier Ventre6b19e482016-11-07 16:21:04 -0800383 cfgService.registerConfigFactory(pwaasConfigFactory);
Charles Chan82ab1932016-01-30 23:22:37 -0800384 hostService.addListener(hostListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700385 packetService.addProcessor(processor, PacketProcessor.director(2));
386 linkService.addListener(linkListener);
387 deviceService.addListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700388 multicastRouteService.addListener(mcastListener);
Charles Chan41f5ec02016-06-13 18:54:31 -0700389 cordConfigService.addListener(cordConfigListener);
Charles Chan2b078ae2015-10-14 11:24:40 -0700390
391 cfgListener.configureNetwork();
392
Charles Chandebfea32016-10-24 14:52:01 -0700393 routeService.addListener(routeListener);
394
sangho80f11cb2015-04-01 13:05:26 -0700395 log.info("Started");
396 }
397
Jonathan Hart54541d12016-04-12 15:39:44 -0700398 private KryoNamespace.Builder createSerializer() {
399 return new KryoNamespace.Builder()
400 .register(KryoNamespaces.API)
401 .register(NeighborSetNextObjectiveStoreKey.class,
Charles Chan10b0fb72017-02-02 16:20:42 -0800402 VlanNextObjectiveStoreKey.class,
Jonathan Hart54541d12016-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 Chan82f19972016-05-17 13:13:55 -0700411 XConnectStoreKey.class
Jonathan Hart54541d12016-04-12 15:39:44 -0700412 );
413 }
414
sangho80f11cb2015-04-01 13:05:26 -0700415 @Deactivate
416 protected void deactivate() {
Charles Chan72f556a2015-10-05 17:50:33 -0700417 cfgService.removeListener(cfgListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700418 cfgService.unregisterConfigFactory(deviceConfigFactory);
419 cfgService.unregisterConfigFactory(appConfigFactory);
Charles Chandebfea32016-10-24 14:52:01 -0700420 cfgService.unregisterConfigFactory(xConnectConfigFactory);
Charles Chanc91c8782016-03-30 17:54:24 -0700421 cfgService.unregisterConfigFactory(mcastConfigFactory);
Pier Ventre6b19e482016-11-07 16:21:04 -0800422 cfgService.unregisterConfigFactory(pwaasConfigFactory);
Charles Chan72f556a2015-10-05 17:50:33 -0700423
sangho80f11cb2015-04-01 13:05:26 -0700424 packetService.removeProcessor(processor);
Charles Chan2b078ae2015-10-14 11:24:40 -0700425 linkService.removeListener(linkListener);
426 deviceService.removeListener(deviceListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700427 multicastRouteService.removeListener(mcastListener);
Charles Chan41f5ec02016-06-13 18:54:31 -0700428 cordConfigService.removeListener(cordConfigListener);
Charles Chandebfea32016-10-24 14:52:01 -0700429 routeService.removeListener(routeListener);
Charles Chanc91c8782016-03-30 17:54:24 -0700430
Charles Chan2e71ef32017-02-23 15:44:08 -0800431 neighbourResolutionService.unregisterNeighbourHandlers(appId);
432
sangho80f11cb2015-04-01 13:05:26 -0700433 processor = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700434 linkListener = null;
Charles Chanc91c8782016-03-30 17:54:24 -0700435 deviceListener = null;
Charles Chan2b078ae2015-10-14 11:24:40 -0700436 groupHandlerMap.clear();
437
Charles Chanc91c8782016-03-30 17:54:24 -0700438 nsNextObjStore.destroy();
Charles Chan10b0fb72017-02-02 16:20:42 -0800439 vlanNextObjStore.destroy();
Charles Chanc91c8782016-03-30 17:54:24 -0700440 portNextObjStore.destroy();
Charles Chanc91c8782016-03-30 17:54:24 -0700441 tunnelStore.destroy();
442 policyStore.destroy();
sangho80f11cb2015-04-01 13:05:26 -0700443 log.info("Stopped");
444 }
445
sangho27462c62015-05-14 00:39:53 -0700446 @Override
447 public List<Tunnel> getTunnels() {
448 return tunnelHandler.getTunnels();
449 }
450
451 @Override
sanghobd812f82015-06-29 14:58:47 -0700452 public TunnelHandler.Result createTunnel(Tunnel tunnel) {
453 return tunnelHandler.createTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700454 }
455
456 @Override
sanghobd812f82015-06-29 14:58:47 -0700457 public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
sangho27462c62015-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");
sanghobd812f82015-06-29 14:58:47 -0700463 return TunnelHandler.Result.TUNNEL_IN_USE;
sangho27462c62015-05-14 00:39:53 -0700464 }
465 }
466 }
sanghobd812f82015-06-29 14:58:47 -0700467 return tunnelHandler.removeTunnel(tunnel);
sangho27462c62015-05-14 00:39:53 -0700468 }
469
470 @Override
sanghobd812f82015-06-29 14:58:47 -0700471 public PolicyHandler.Result removePolicy(Policy policy) {
472 return policyHandler.removePolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700473 }
474
475 @Override
sanghobd812f82015-06-29 14:58:47 -0700476 public PolicyHandler.Result createPolicy(Policy policy) {
477 return policyHandler.createPolicy(policy);
sangho27462c62015-05-14 00:39:53 -0700478 }
479
480 @Override
481 public List<Policy> getPolicies() {
482 return policyHandler.getPolicies();
483 }
484
Saurav Das07c74602016-04-27 18:35:50 -0700485 @Override
486 public void rerouteNetwork() {
487 cfgListener.configureNetwork();
488 for (Device device : deviceService.getDevices()) {
Saurav Dasf9332192017-02-18 14:05:44 -0800489 if (mastershipService.isLocalMaster(device.id())) {
490 defaultRoutingHandler.populatePortAddressingRules(device.id());
491 }
Saurav Das07c74602016-04-27 18:35:50 -0700492 }
493 defaultRoutingHandler.startPopulationProcess();
494 }
495
Charles Chand7844e52016-10-20 17:02:44 -0700496 @Override
Pier Ventreb6a7f342016-11-26 21:05:22 -0800497 public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
498 Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
Charles Chand7844e52016-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
sangho80f1f892015-05-19 11:57:42 -0700505 /**
Pier Ventre7a78de22016-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 /**
sangho80f1f892015-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 */
sangho27462c62015-05-14 00:39:53 -0700522 public Tunnel getTunnel(String tunnelId) {
523 return tunnelHandler.getTunnel(tunnelId);
524 }
525
Charles Chan90772a72017-02-08 15:52:08 -0800526 // TODO Consider moving these to InterfaceService
sangho80f11cb2015-04-01 13:05:26 -0700527 /**
Charles Chan10b0fb72017-02-02 16:20:42 -0800528 * Returns untagged VLAN configured on given connect point.
Charles Chan90772a72017-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.
sangho80f11cb2015-04-01 13:05:26 -0700532 *
Charles Chan10b0fb72017-02-02 16:20:42 -0800533 * @param connectPoint connect point
534 * @return untagged VLAN or null if not configured
sangho80f11cb2015-04-01 13:05:26 -0700535 */
Charles Chan10b0fb72017-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);
sangho80f11cb2015-04-01 13:05:26 -0700541 }
542
sangho27462c62015-05-14 00:39:53 -0700543 /**
Charles Chan90772a72017-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 Das7c305372015-10-28 12:39:42 -0700602 * Returns the next objective ID for the given NeighborSet.
Saurav Das4c35fc42015-11-20 15:27:53 -0800603 * If the nextObjective does not exist, a new one is created and
Saurav Das2d94d312015-11-24 23:21:05 -0800604 * its id is returned.
sangho27462c62015-05-14 00:39:53 -0700605 *
sangho80f1f892015-05-19 11:57:42 -0700606 * @param deviceId Device ID
607 * @param ns NegighborSet
Saurav Das4c35fc42015-11-20 15:27:53 -0800608 * @param meta metadata passed into the creation of a Next Objective
Pier Ventre229fd0b2016-10-31 16:49:19 -0700609 * @param isBos indicates if it is BoS or not
Saurav Das4c35fc42015-11-20 15:27:53 -0800610 * @return next objective ID or -1 if an error was encountered during the
611 * creation of the nextObjective
sangho27462c62015-05-14 00:39:53 -0700612 */
Saurav Das4c35fc42015-11-20 15:27:53 -0800613 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
Pier Ventre229fd0b2016-10-31 16:49:19 -0700614 TrafficSelector meta, boolean isBos) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700615 if (groupHandlerMap.get(deviceId) != null) {
616 log.trace("getNextObjectiveId query in device {}", deviceId);
617 return groupHandlerMap
Pier Ventre229fd0b2016-10-31 16:49:19 -0700618 .get(deviceId).getNextObjectiveId(ns, meta, isBos);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700619 } else {
Saurav Das2d94d312015-11-24 23:21:05 -0800620 log.warn("getNextObjectiveId query - groupHandler for device {} "
621 + "not found", deviceId);
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700622 return -1;
623 }
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700624 }
625
Charles Chan77277672015-10-20 16:24:19 -0700626 /**
Pier Ventre229fd0b2016-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 Das2d94d312015-11-24 23:21:05 -0800644 * Returns the next objective ID for the given subnet prefix. It is expected
Charles Chan10b0fb72017-02-02 16:20:42 -0800645 * Returns the next objective ID for the given vlan id. It is expected
Saurav Das2d94d312015-11-24 23:21:05 -0800646 * that the next-objective has been pre-created from configuration.
Charles Chan77277672015-10-20 16:24:19 -0700647 *
648 * @param deviceId Device ID
Charles Chan10b0fb72017-02-02 16:20:42 -0800649 * @param vlanId VLAN ID
Saurav Das2d94d312015-11-24 23:21:05 -0800650 * @return next objective ID or -1 if it was not found
Charles Chan77277672015-10-20 16:24:19 -0700651 */
Charles Chan10b0fb72017-02-02 16:20:42 -0800652 public int getVlanNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
Charles Chan77277672015-10-20 16:24:19 -0700653 if (groupHandlerMap.get(deviceId) != null) {
Charles Chan10b0fb72017-02-02 16:20:42 -0800654 log.trace("getVlanNextObjectiveId query in device {}", deviceId);
655 return groupHandlerMap.get(deviceId).getVlanNextObjectiveId(vlanId);
Charles Chan77277672015-10-20 16:24:19 -0700656 } else {
Charles Chan10b0fb72017-02-02 16:20:42 -0800657 log.warn("getVlanNextObjectiveId query - groupHandler for "
Saurav Das2d94d312015-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 Das07c74602016-04-27 18:35:50 -0700673 * @return next objective ID or -1 if an error occurred during retrieval or creation
Saurav Das2d94d312015-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 Chanb7f75ac2016-01-11 18:28:54 -0800682 log.warn("getPortNextObjectiveId query - groupHandler for device {}"
683 + " not found", deviceId);
684 return -1;
685 }
686 }
687
sangho80f11cb2015-04-01 13:05:26 -0700688 private class InternalPacketProcessor implements PacketProcessor {
sangho80f11cb2015-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 Luigi37a35432017-02-01 13:50:04 -0800698
699 if (ethernet == null) {
700 return;
701 }
702
Saurav Das2d94d312015-11-24 23:21:05 -0800703 log.trace("Rcvd pktin: {}", ethernet);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800704 if (ethernet.getEtherType() == TYPE_ARP) {
Charles Chanef1cfef2017-02-16 11:45:52 -0800705 log.warn("Receive unexpected ARP packet on {}", context.inPacket().receivedFrom());
Pier Ventreb6a7f342016-11-26 21:05:22 -0800706 log.debug("{}", ethernet);
Pier Ventre6b2c1b32016-12-09 17:26:04 -0800707 return;
sangho80f11cb2015-04-01 13:05:26 -0700708 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
Pier Ventreb6b81d52016-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());
sangho80f11cb2015-04-01 13:05:26 -0700713 } else {
Charles Chand041ad82017-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 Ventre6b2c1b32016-12-09 17:26:04 -0800716 // ipHandler.processPacketIn(ipv4Packet, pkt.receivedFrom());
sangho80f11cb2015-04-01 13:05:26 -0700717 }
Pier Ventreb6a7f342016-11-26 21:05:22 -0800718 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
719 IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
Pier Ventreb6b81d52016-12-02 08:16:05 -0800720 //ipHandler.addToPacketBuffer(ipv6Packet);
Pier Luigi37a35432017-02-01 13:50:04 -0800721 // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
Pier Ventreb6b81d52016-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 Luigi37a35432017-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 Ventreb6b81d52016-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 }
sangho80f11cb2015-04-01 13:05:26 -0700742 }
743 }
744 }
745
746 private class InternalLinkListener implements LinkListener {
747 @Override
748 public void event(LinkEvent event) {
Srikanth Vavilapalli64505482015-04-21 13:04:13 -0700749 if (event.type() == LinkEvent.Type.LINK_ADDED
750 || event.type() == LinkEvent.Type.LINK_REMOVED) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700751 log.debug("Event {} received from Link Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700752 scheduleEventHandlerIfNotScheduled(event);
753 }
754 }
755 }
756
757 private class InternalDeviceListener implements DeviceListener {
sangho80f11cb2015-04-01 13:05:26 -0700758 @Override
759 public void event(DeviceEvent event) {
sangho80f11cb2015-04-01 13:05:26 -0700760 switch (event.type()) {
761 case DEVICE_ADDED:
Saurav Dasf0f592d2016-11-18 15:21:57 -0800762 case PORT_UPDATED:
763 case PORT_ADDED:
sanghofb7c7292015-04-13 15:15:58 -0700764 case DEVICE_UPDATED:
765 case DEVICE_AVAILABILITY_CHANGED:
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700766 log.debug("Event {} received from Device Service", event.type());
sangho80f11cb2015-04-01 13:05:26 -0700767 scheduleEventHandlerIfNotScheduled(event);
768 break;
769 default:
770 }
771 }
772 }
773
Saurav Das2d94d312015-11-24 23:21:05 -0800774 @SuppressWarnings("rawtypes")
sangho80f11cb2015-04-01 13:05:26 -0700775 private void scheduleEventHandlerIfNotScheduled(Event event) {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700776 synchronized (threadSchedulerLock) {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700777 eventQueue.add(event);
Srikanth Vavilapalli64d96c12015-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 Vavilapalli7cd16712015-05-04 09:48:09 -0700782 eventHandlerFuture = executorService
783 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
784 numOfHandlerScheduled++;
785 }
Jonathan Hart54541d12016-04-12 15:39:44 -0700786 log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700787 numOfEventsQueued,
788 numOfHandlerScheduled);
sangho80f11cb2015-04-01 13:05:26 -0700789 }
sangho80f11cb2015-04-01 13:05:26 -0700790 }
791
792 private class InternalEventHandler implements Runnable {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700793 @Override
sangho80f11cb2015-04-01 13:05:26 -0700794 public void run() {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700795 try {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700796 while (true) {
Saurav Das2d94d312015-11-24 23:21:05 -0800797 @SuppressWarnings("rawtypes")
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700798 Event event = null;
799 synchronized (threadSchedulerLock) {
800 if (!eventQueue.isEmpty()) {
801 event = eventQueue.poll();
802 numOfEventsExecuted++;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700803 } else {
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700804 numOfHandlerExecution++;
805 log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
806 numOfHandlerExecution, numOfEventsExecuted);
807 break;
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700808 }
sanghofb7c7292015-04-13 15:15:58 -0700809 }
Srikanth Vavilapalli64d96c12015-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 Ventre6d593892016-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 Vavilapalli64d96c12015-05-14 20:22:47 -0700822 processLinkRemoved((Link) event.subject());
Srikanth Vavilapalli64d96c12015-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 Das62af8802015-12-04 10:52:59 -0800826 DeviceId deviceId = ((Device) event.subject()).id();
827 if (deviceService.isAvailable(deviceId)) {
Saurav Dasc28b3432015-10-30 17:45:38 -0700828 log.info("Processing device event {} for available device {}",
829 event.type(), ((Device) event.subject()).id());
Srikanth Vavilapalli64d96c12015-05-14 20:22:47 -0700830 processDeviceAdded((Device) event.subject());
Saurav Dasc3604f12016-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 Dasf0f592d2016-11-18 15:21:57 -0800836 } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
Saurav Dasd1872b02016-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 Dasf0f592d2016-11-18 15:21:57 -0800841 log.debug("** PORT ADDED {}/{} -> {}",
Saurav Dasd1872b02016-12-02 15:43:47 -0800842 ((DeviceEvent) event).subject().id(),
843 ((DeviceEvent) event).port().number(),
844 event.type());
Saurav Dasf0f592d2016-11-18 15:21:57 -0800845 } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
Saurav Dasd1872b02016-12-02 15:43:47 -0800846 // these calls happen for every subsequent event
847 // ports enabled, disabled, switch goes away, comes back
Saurav Dasf0f592d2016-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 Vavilapalli64d96c12015-05-14 20:22:47 -0700854 } else {
855 log.warn("Unhandled event type: {}", event.type());
856 }
sangho80f11cb2015-04-01 13:05:26 -0700857 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700858 } catch (Exception e) {
859 log.error("SegmentRouting event handler "
860 + "thread thrown an exception: {}", e);
sangho80f11cb2015-04-01 13:05:26 -0700861 }
sangho80f11cb2015-04-01 13:05:26 -0700862 }
863 }
864
sangho80f11cb2015-04-01 13:05:26 -0700865 private void processLinkAdded(Link link) {
Saurav Dasb149be12016-06-07 10:08:06 -0700866 log.info("** LINK ADDED {}", link.toString());
Charles Chan319d1a22015-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 Vavilapalli7cd16712015-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 Das4c35fc42015-11-20 15:27:53 -0800879 groupHandler.linkUp(link, mastershipService.isLocalMaster(
880 link.src().deviceId()));
Srikanth Vavilapalli7cd16712015-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 Das4c35fc42015-11-20 15:27:53 -0800890 groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
sangho80f11cb2015-04-01 13:05:26 -0700891 }
892 }
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700893
Srikanth Vavilapalli64d96c12015-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 Chan72779502016-04-23 17:36:10 -0700898
899 mcastHandler.init();
sangho80f11cb2015-04-01 13:05:26 -0700900 }
901
902 private void processLinkRemoved(Link link) {
Saurav Dasb149be12016-06-07 10:08:06 -0700903 log.info("** LINK REMOVED {}", link.toString());
sangho2165d222015-05-01 09:38:25 -0700904 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
905 if (groupHandler != null) {
Saurav Das62af8802015-12-04 10:52:59 -0800906 groupHandler.portDown(link.src().port(),
907 mastershipService.isLocalMaster(link.src().deviceId()));
sangho2165d222015-05-01 09:38:25 -0700908 }
Srikanth Vavilapalli64d96c12015-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 Chan72779502016-04-23 17:36:10 -0700913
914 mcastHandler.processLinkDown(link);
sangho80f11cb2015-04-01 13:05:26 -0700915 }
916
917 private void processDeviceAdded(Device device) {
Saurav Dasb149be12016-06-07 10:08:06 -0700918 log.info("** DEVICE ADDED with ID {}", device.id());
Charles Chan319d1a22015-11-03 10:42:14 -0800919 if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
Saurav Das8ec0ec42015-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 Chan72779502016-04-23 17:36:10 -0700924 processDeviceAddedInternal(device.id());
925 }
926
927 private void processDeviceAddedInternal(DeviceId deviceId) {
Saurav Dasc28b3432015-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 Chan72779502016-04-23 17:36:10 -0700934 log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
935 if (groupHandlerMap.get(deviceId) == null) {
Charles Chan319d1a22015-11-03 10:42:14 -0800936 DefaultGroupHandler groupHandler;
937 try {
938 groupHandler = DefaultGroupHandler.
Charles Chan72779502016-04-23 17:36:10 -0700939 createGroupHandler(deviceId,
940 appId,
941 deviceConfiguration,
942 linkService,
943 flowObjectiveService,
944 this);
Charles Chan319d1a22015-11-03 10:42:14 -0800945 } catch (DeviceConfigNotFoundException e) {
946 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
947 return;
948 }
Charles Chan72779502016-04-23 17:36:10 -0700949 log.debug("updating groupHandlerMap with new config for device: {}",
950 deviceId);
951 groupHandlerMap.put(deviceId, groupHandler);
Saurav Das8ec0ec42015-11-03 14:39:27 -0800952 }
Saurav Dasb149be12016-06-07 10:08:06 -0700953
Charles Chan72779502016-04-23 17:36:10 -0700954 if (mastershipService.isLocalMaster(deviceId)) {
Saurav Dasf9332192017-02-18 14:05:44 -0800955 defaultRoutingHandler.populatePortAddressingRules(deviceId);
Charles Chandebfea32016-10-24 14:52:01 -0700956 hostHandler.init(deviceId);
Charles Chan82f19972016-05-17 13:13:55 -0700957 xConnectHandler.init(deviceId);
Charles Chan41f5ec02016-06-13 18:54:31 -0700958 cordConfigHandler.init(deviceId);
Charles Chan72779502016-04-23 17:36:10 -0700959 DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
Charles Chan10b0fb72017-02-02 16:20:42 -0800960 groupHandler.createGroupsFromVlanConfig();
Charles Chan72779502016-04-23 17:36:10 -0700961 routingRulePopulator.populateSubnetBroadcastRule(deviceId);
Charles Chan77277672015-10-20 16:24:19 -0700962 }
Charles Chan82ab1932016-01-30 23:22:37 -0800963
Charles Chandebfea32016-10-24 14:52:01 -0700964 appCfgHandler.init(deviceId);
965 routeHandler.init(deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700966 }
967
Saurav Dasc3604f12016-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 Chan10b0fb72017-02-02 16:20:42 -0800974 vlanNextObjStore.entrySet().stream()
Saurav Dasc3604f12016-03-23 11:22:49 -0700975 .filter(entry -> entry.getKey().deviceId().equals(device.id()))
976 .forEach(entry -> {
Charles Chan10b0fb72017-02-02 16:20:42 -0800977 vlanNextObjStore.remove(entry.getKey());
Saurav Dasc3604f12016-03-23 11:22:49 -0700978 });
Saurav Dasc3604f12016-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 Dasc3604f12016-03-23 11:22:49 -0700984 groupHandlerMap.remove(device.id());
Saurav Dasc3604f12016-03-23 11:22:49 -0700985 defaultRoutingHandler.purgeEcmpGraph(device.id());
Charles Chan72779502016-04-23 17:36:10 -0700986 mcastHandler.removeDevice(device.id());
Charles Chan82f19972016-05-17 13:13:55 -0700987 xConnectHandler.removeDevice(device.id());
Saurav Dasc3604f12016-03-23 11:22:49 -0700988 }
989
Saurav Dasf0f592d2016-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 Dasf9332192017-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 Chan43be46b2017-02-26 22:59:35 -08001007 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), true);
Saurav Dasf9332192017-02-18 14:05:44 -08001008 } else {
1009 log.info("Switchport {}/{} disabled..removing filters",
1010 device.id(), port.number());
Charles Chan43be46b2017-02-26 22:59:35 -08001011 routingRulePopulator.processSinglePortFilters(device.id(), port.number(), false);
Saurav Dasf9332192017-02-18 14:05:44 -08001012 }
Saurav Dasf0f592d2016-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 Chan10b0fb72017-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 Dasf0f592d2016-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 Chan10b0fb72017-02-02 16:20:42 -08001026 processEdgePort(device, port, vlanId);
Saurav Dasf0f592d2016-11-18 15:21:57 -08001027 }
1028
Charles Chan10b0fb72017-02-02 16:20:42 -08001029 private void processEdgePort(Device device, Port port, VlanId vlanId) {
Saurav Dasf0f592d2016-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 Chan10b0fb72017-02-02 16:20:42 -08001033 port.number(), vlanId);
Saurav Dasf0f592d2016-11-18 15:21:57 -08001034 } else {
1035 log.info("Device:EdgePort {}:{} is disabled in subnet: {}", device.id(),
Charles Chan10b0fb72017-02-02 16:20:42 -08001036 port.number(), vlanId);
Saurav Dasf0f592d2016-11-18 15:21:57 -08001037 }
1038
Srikanth Vavilapalli64505482015-04-21 13:04:13 -07001039 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sangho80f11cb2015-04-01 13:05:26 -07001040 if (groupHandler != null) {
Charles Chan10b0fb72017-02-02 16:20:42 -08001041 groupHandler.processEdgePort(port.number(), vlanId, portUp);
Saurav Dasf0f592d2016-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());
sangho80f11cb2015-04-01 13:05:26 -07001046 }
1047 }
sangho27462c62015-05-14 00:39:53 -07001048
Pier Ventreb6a7f342016-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 Chan2e71ef32017-02-23 15:44:08 -08001056 neighbourResolutionService.registerNeighbourHandler(
Pier Ventreb6a7f342016-11-26 21:05:22 -08001057 portToRegister,
1058 neighbourHandler,
1059 appId
1060 );
1061 }
1062
Charles Chan72f556a2015-10-05 17:50:33 -07001063 private class InternalConfigListener implements NetworkConfigListener {
Charles Chan46fdfaf2016-11-09 20:51:44 -08001064 SegmentRoutingManager srManager;
Charles Chane7c61022015-10-07 14:21:45 -07001065
Charles Chanb7f75ac2016-01-11 18:28:54 -08001066 /**
1067 * Constructs the internal network config listener.
1068 *
Charles Chan46fdfaf2016-11-09 20:51:44 -08001069 * @param srManager segment routing manager
Charles Chanb7f75ac2016-01-11 18:28:54 -08001070 */
Charles Chan46fdfaf2016-11-09 20:51:44 -08001071 public InternalConfigListener(SegmentRoutingManager srManager) {
1072 this.srManager = srManager;
Charles Chane7c61022015-10-07 14:21:45 -07001073 }
1074
Charles Chanb7f75ac2016-01-11 18:28:54 -08001075 /**
1076 * Reads network config and initializes related data structure accordingly.
1077 */
Charles Chane7c61022015-10-07 14:21:45 -07001078 public void configureNetwork() {
Pier Ventreb6a7f342016-11-26 21:05:22 -08001079
Charles Chan46fdfaf2016-11-09 20:51:44 -08001080 deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chane7c61022015-10-07 14:21:45 -07001081
Charles Chan46fdfaf2016-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 Chane7c61022015-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 Chane7c61022015-10-07 14:21:45 -07001094 for (Device device : deviceService.getDevices()) {
Charles Chan72779502016-04-23 17:36:10 -07001095 processDeviceAddedInternal(device.id());
Charles Chane7c61022015-10-07 14:21:45 -07001096 }
1097
1098 defaultRoutingHandler.startPopulationProcess();
Charles Chan72779502016-04-23 17:36:10 -07001099 mcastHandler.init();
Charles Chane7c61022015-10-07 14:21:45 -07001100 }
1101
Charles Chan72f556a2015-10-05 17:50:33 -07001102 @Override
1103 public void event(NetworkConfigEvent event) {
Charles Chan82ab1932016-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 Chan2b078ae2015-10-14 11:24:40 -07001117 }
Charles Chan82ab1932016-01-30 23:22:37 -08001118 } else if (event.configClass().equals(SegmentRoutingAppConfig.class)) {
Charles Chan82f19972016-05-17 13:13:55 -07001119 checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
Charles Chan82ab1932016-01-30 23:22:37 -08001120 switch (event.type()) {
1121 case CONFIG_ADDED:
Charles Chan82f19972016-05-17 13:13:55 -07001122 appCfgHandler.processAppConfigAdded(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001123 break;
1124 case CONFIG_UPDATED:
Charles Chan82f19972016-05-17 13:13:55 -07001125 appCfgHandler.processAppConfigUpdated(event);
Charles Chan82ab1932016-01-30 23:22:37 -08001126 break;
1127 case CONFIG_REMOVED:
Charles Chan82f19972016-05-17 13:13:55 -07001128 appCfgHandler.processAppConfigRemoved(event);
1129 break;
1130 default:
1131 break;
1132 }
Charles Chandebfea32016-10-24 14:52:01 -07001133 configureNetwork();
Charles Chan82f19972016-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 Chan82ab1932016-01-30 23:22:37 -08001145 break;
1146 default:
1147 break;
Charles Chan2b078ae2015-10-14 11:24:40 -07001148 }
Pier Luigi37a35432017-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 Luigiad0a67f2017-02-03 13:34:21 -08001156 updateUPstreamCP();
Pier Luigi37a35432017-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 Luigiad0a67f2017-02-03 13:34:21 -08001170 updateVRouterCP(event);
Pier Luigi37a35432017-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 Ventre6b19e482016-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 Chan72f556a2015-10-05 17:50:33 -07001193 }
1194 }
1195 }
Charles Chanf4586112015-11-09 16:37:23 -08001196
Pier Luigiad0a67f2017-02-03 13:34:21 -08001197 /////////////////////////////////////////////////////////////////
1198 // XXX Neighbour hacking, temporary workaround will be //
Saurav Dasf9332192017-02-18 14:05:44 -08001199 // removed as soon as possible, when bridging based //
1200 // control plane redirect is implemented. //
Pier Luigiad0a67f2017-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 Chanf4586112015-11-09 16:37:23 -08001241 private class InternalHostListener implements HostListener {
Charles Chanf4586112015-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 Chan1eaf4802016-04-18 13:44:03 -07001252 hostHandler.processHostAddedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001253 break;
1254 case HOST_MOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001255 hostHandler.processHostMovedEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001256 break;
1257 case HOST_REMOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001258 hostHandler.processHostRemoveEvent(event);
Charles Chanf4586112015-11-09 16:37:23 -08001259 break;
1260 case HOST_UPDATED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001261 hostHandler.processHostUpdatedEvent(event);
Charles Chanf4586112015-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 Chanc91c8782016-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 Chan1eaf4802016-04-18 13:44:03 -07001275 mcastHandler.processSourceAdded(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001276 break;
1277 case SINK_ADDED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001278 mcastHandler.processSinkAdded(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001279 break;
1280 case SINK_REMOVED:
Charles Chan1eaf4802016-04-18 13:44:03 -07001281 mcastHandler.processSinkRemoved(event);
Charles Chanc91c8782016-03-30 17:54:24 -07001282 break;
1283 case ROUTE_ADDED:
1284 case ROUTE_REMOVED:
1285 default:
1286 break;
1287 }
1288 }
1289 }
Charles Chan41f5ec02016-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 Chandebfea32016-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 }
sangho80f11cb2015-04-01 13:05:26 -07001331}