blob: b7167c8fdddd1f05975f2165b351e2faa932148f [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.onlab.packet.Ethernet;
24import org.onlab.packet.IPv4;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.event.Event;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070028import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
29import org.onosproject.segmentrouting.grouphandler.NeighborSet;
sanghob35a6192015-04-01 13:05:26 -070030import org.onosproject.mastership.MastershipService;
31import org.onosproject.net.Device;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.Link;
34import org.onosproject.net.MastershipRole;
35import org.onosproject.net.Port;
36import org.onosproject.net.device.DeviceEvent;
37import org.onosproject.net.device.DeviceListener;
38import org.onosproject.net.device.DeviceService;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070039import org.onosproject.net.flowobjective.FlowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -070040import org.onosproject.net.group.Group;
41import org.onosproject.net.group.GroupEvent;
42import org.onosproject.net.group.GroupKey;
sanghob35a6192015-04-01 13:05:26 -070043import org.onosproject.net.host.HostService;
44import org.onosproject.net.intent.IntentService;
45import org.onosproject.net.link.LinkEvent;
46import org.onosproject.net.link.LinkListener;
47import org.onosproject.net.link.LinkService;
48import org.onosproject.net.packet.InboundPacket;
49import org.onosproject.net.packet.PacketContext;
50import org.onosproject.net.packet.PacketProcessor;
51import org.onosproject.net.packet.PacketService;
52import org.onosproject.net.topology.TopologyService;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070053import org.onosproject.segmentrouting.config.NetworkConfigManager;
sanghob35a6192015-04-01 13:05:26 -070054import org.slf4j.Logger;
55import org.slf4j.LoggerFactory;
56
57import java.util.Map;
58import java.util.concurrent.ConcurrentHashMap;
59import java.util.concurrent.ConcurrentLinkedQueue;
60import java.util.concurrent.Executors;
61import java.util.concurrent.ScheduledExecutorService;
62import java.util.concurrent.ScheduledFuture;
63import java.util.concurrent.TimeUnit;
64
65@SuppressWarnings("ALL")
66@Component(immediate = true)
67public class SegmentRoutingManager {
68
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070069 private static Logger log = LoggerFactory
70 .getLogger(SegmentRoutingManager.class);
sanghob35a6192015-04-01 13:05:26 -070071
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected CoreService coreService;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected TopologyService topologyService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected PacketService packetService;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected IntentService intentService;
83
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected HostService hostService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected DeviceService deviceService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070091 protected FlowObjectiveService flowObjectiveService;
sanghob35a6192015-04-01 13:05:26 -070092
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected LinkService linkService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghob35a6192015-04-01 13:05:26 -070097 protected MastershipService mastershipService;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070098 protected ArpHandler arpHandler = null;
99 protected IcmpHandler icmpHandler = null;
100 protected IpHandler ipHandler = null;
101 protected RoutingRulePopulator routingRulePopulator = null;
sanghob35a6192015-04-01 13:05:26 -0700102 protected ApplicationId appId;
sangho666cd6d2015-04-14 16:27:13 -0700103 protected DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700104
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700105 private DefaultRoutingHandler defaultRoutingHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700106 private InternalPacketProcessor processor = new InternalPacketProcessor();
107 private InternalEventHandler eventHandler = new InternalEventHandler();
108
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700109 private ScheduledExecutorService executorService = Executors
110 .newScheduledThreadPool(1);
sanghob35a6192015-04-01 13:05:26 -0700111
112 private static ScheduledFuture<?> eventHandlerFuture = null;
113 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700114 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
sanghob35a6192015-04-01 13:05:26 -0700115
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700116 private NetworkConfigManager networkConfigService = new NetworkConfigManager();;
117
sanghob35a6192015-04-01 13:05:26 -0700118 private static int numOfEvents = 0;
119 private static int numOfHandlerExecution = 0;
120 private static int numOfHandlerScheduled = 0;
121
122 @Activate
123 protected void activate() {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700124 appId = coreService
125 .registerApplication("org.onosproject.segmentrouting");
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700126 networkConfigService.init();
127 deviceConfiguration = new DeviceConfiguration(networkConfigService);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700128 arpHandler = new ArpHandler(this);
129 icmpHandler = new IcmpHandler(this);
130 ipHandler = new IpHandler(this);
131 routingRulePopulator = new RoutingRulePopulator(this);
132 defaultRoutingHandler = new DefaultRoutingHandler(this);
133
sanghob35a6192015-04-01 13:05:26 -0700134 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
135 linkService.addListener(new InternalLinkListener());
sanghob35a6192015-04-01 13:05:26 -0700136 deviceService.addListener(new InternalDeviceListener());
137
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700138 for (Device device : deviceService.getDevices()) {
139 if (mastershipService.getLocalRole(device.id()) == MastershipRole.MASTER) {
140 DefaultGroupHandler groupHandler = DefaultGroupHandler
141 .createGroupHandler(device.id(), appId,
142 deviceConfiguration, linkService,
143 flowObjectiveService);
sanghob35a6192015-04-01 13:05:26 -0700144 groupHandlerMap.put(device.id(), groupHandler);
sangho20eff1d2015-04-13 15:15:58 -0700145 defaultRoutingHandler.populateTtpRules(device.id());
sangho666cd6d2015-04-14 16:27:13 -0700146 log.debug("Initiating default group handling for {}", device.id());
sanghob35a6192015-04-01 13:05:26 -0700147 } else {
148 log.debug("Activate: Local role {} "
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700149 + "is not MASTER for device {}",
150 mastershipService.getLocalRole(device.id()),
151 device.id());
sanghob35a6192015-04-01 13:05:26 -0700152 }
153 }
154
sangho20eff1d2015-04-13 15:15:58 -0700155 defaultRoutingHandler.startPopulationProcess();
sanghob35a6192015-04-01 13:05:26 -0700156 log.info("Started");
157 }
158
159 @Deactivate
160 protected void deactivate() {
161 packetService.removeProcessor(processor);
162 processor = null;
163 log.info("Stopped");
164 }
165
166 /**
167 * Returns the GrouopKey object for the device and the NighborSet given.
168 *
169 * @param ns NeightborSet object for the GroupKey
170 * @return GroupKey object for the NeighborSet
171 */
172 public GroupKey getGroupKey(NeighborSet ns) {
173
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700174 for (DefaultGroupHandler groupHandler : groupHandlerMap.values()) {
sanghob35a6192015-04-01 13:05:26 -0700175 return groupHandler.getGroupKey(ns);
176 }
177
178 return null;
179 }
180
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700181 public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) {
182
183 return (groupHandlerMap.get(deviceId) != null) ? groupHandlerMap
184 .get(deviceId).getNextObjectiveId(ns) : -1;
185 }
186
sanghob35a6192015-04-01 13:05:26 -0700187 private class InternalPacketProcessor implements PacketProcessor {
188
189 @Override
190 public void process(PacketContext context) {
191
192 if (context.isHandled()) {
193 return;
194 }
195
196 InboundPacket pkt = context.inPacket();
197 Ethernet ethernet = pkt.parsed();
198
199 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
200 arpHandler.processPacketIn(pkt);
201 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
202 IPv4 ipPacket = (IPv4) ethernet.getPayload();
203 ipHandler.addToPacketBuffer(ipPacket);
204 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
205 icmpHandler.processPacketIn(pkt);
206 } else {
207 ipHandler.processPacketIn(pkt);
208 }
209 }
210 }
211 }
212
213 private class InternalLinkListener implements LinkListener {
214 @Override
215 public void event(LinkEvent event) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700216 if (event.type() == LinkEvent.Type.LINK_ADDED
217 || event.type() == LinkEvent.Type.LINK_REMOVED) {
sanghob35a6192015-04-01 13:05:26 -0700218 scheduleEventHandlerIfNotScheduled(event);
219 }
220 }
221 }
222
223 private class InternalDeviceListener implements DeviceListener {
224
225 @Override
226 public void event(DeviceEvent event) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700227 if (mastershipService.getLocalRole(event.subject().id()) != MastershipRole.MASTER) {
sanghob35a6192015-04-01 13:05:26 -0700228 log.debug("Local role {} is not MASTER for device {}",
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700229 mastershipService.getLocalRole(event.subject().id()),
230 event.subject().id());
sanghob35a6192015-04-01 13:05:26 -0700231 return;
232 }
233
234 switch (event.type()) {
235 case DEVICE_ADDED:
236 case PORT_REMOVED:
sangho20eff1d2015-04-13 15:15:58 -0700237 case DEVICE_UPDATED:
238 case DEVICE_AVAILABILITY_CHANGED:
sanghob35a6192015-04-01 13:05:26 -0700239 scheduleEventHandlerIfNotScheduled(event);
240 break;
241 default:
242 }
243 }
244 }
245
sanghob35a6192015-04-01 13:05:26 -0700246 private void scheduleEventHandlerIfNotScheduled(Event event) {
247
248 eventQueue.add(event);
249 numOfEvents++;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700250 if (eventHandlerFuture == null || eventHandlerFuture.isDone()) {
251 eventHandlerFuture = executorService
252 .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
sanghob35a6192015-04-01 13:05:26 -0700253 numOfHandlerScheduled++;
254 }
255
256 log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700257 numOfHandlerScheduled);
sanghob35a6192015-04-01 13:05:26 -0700258
259 }
260
261 private class InternalEventHandler implements Runnable {
262
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700263 @Override
sanghob35a6192015-04-01 13:05:26 -0700264 public void run() {
265 numOfHandlerExecution++;
266 while (!eventQueue.isEmpty()) {
267 Event event = eventQueue.poll();
268 if (event.type() == LinkEvent.Type.LINK_ADDED) {
269 processLinkAdded((Link) event.subject());
270 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
271 processLinkRemoved((Link) event.subject());
272 } else if (event.type() == GroupEvent.Type.GROUP_ADDED) {
273 processGroupAdded((Group) event.subject());
sangho20eff1d2015-04-13 15:15:58 -0700274 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
275 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
276 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
277 if (deviceService.isAvailable(((Device) event.subject()).id())) {
278 processDeviceAdded((Device) event.subject());
279 }
sanghob35a6192015-04-01 13:05:26 -0700280 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
281 processPortRemoved((Device) event.subject(),
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700282 ((DeviceEvent) event).port());
sanghob35a6192015-04-01 13:05:26 -0700283 } else {
284 log.warn("Unhandled event type: {}", event.type());
285 }
286 }
287 log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}",
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700288 numOfHandlerExecution, numOfHandlerScheduled, numOfEvents);
sanghob35a6192015-04-01 13:05:26 -0700289 }
290 }
291
sanghob35a6192015-04-01 13:05:26 -0700292 private void processLinkAdded(Link link) {
293 log.debug("A new link {} was added", link.toString());
294
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700295 if (mastershipService.getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) {
296 DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
297 .deviceId());
sanghob35a6192015-04-01 13:05:26 -0700298 if (groupHandler != null) {
299 groupHandler.linkUp(link);
300 }
301 }
sangho20eff1d2015-04-13 15:15:58 -0700302 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
sanghob35a6192015-04-01 13:05:26 -0700303 }
304
305 private void processLinkRemoved(Link link) {
306 log.debug("A link {} was removed", link.toString());
sangho20eff1d2015-04-13 15:15:58 -0700307 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
sanghob35a6192015-04-01 13:05:26 -0700308 }
309
sanghob35a6192015-04-01 13:05:26 -0700310 private void processGroupAdded(Group group) {
311 log.debug("A new group with ID {} was added", group.id());
312 defaultRoutingHandler.resumePopulationProcess();
313 }
314
315 private void processDeviceAdded(Device device) {
316 log.debug("A new device with ID {} was added", device.id());
317 defaultRoutingHandler.populateTtpRules(device.id());
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700318 DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler(device
319 .id(), appId, deviceConfiguration, linkService, flowObjectiveService);
sanghob35a6192015-04-01 13:05:26 -0700320 groupHandlerMap.put(device.id(), dgh);
321 }
322
323 private void processPortRemoved(Device device, Port port) {
324 log.debug("Port {} was removed", port.toString());
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700325 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
sanghob35a6192015-04-01 13:05:26 -0700326 if (groupHandler != null) {
327 groupHandler.portDown(port.number());
328 }
329 }
330}