blob: b5e11816ced7f67d3fb494c507d12c3f0814d3f3 [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;
39import org.onosproject.net.flow.FlowRuleService;
40import org.onosproject.net.group.Group;
41import org.onosproject.net.group.GroupEvent;
42import org.onosproject.net.group.GroupKey;
43import org.onosproject.net.group.GroupListener;
44import org.onosproject.net.group.GroupService;
45import org.onosproject.net.host.HostService;
46import org.onosproject.net.intent.IntentService;
47import org.onosproject.net.link.LinkEvent;
48import org.onosproject.net.link.LinkListener;
49import org.onosproject.net.link.LinkService;
50import org.onosproject.net.packet.InboundPacket;
51import org.onosproject.net.packet.PacketContext;
52import org.onosproject.net.packet.PacketProcessor;
53import org.onosproject.net.packet.PacketService;
54import org.onosproject.net.topology.TopologyService;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070055import org.onosproject.segmentrouting.config.NetworkConfigManager;
sanghob35a6192015-04-01 13:05:26 -070056import org.slf4j.Logger;
57import org.slf4j.LoggerFactory;
58
59import java.util.Map;
60import java.util.concurrent.ConcurrentHashMap;
61import java.util.concurrent.ConcurrentLinkedQueue;
62import java.util.concurrent.Executors;
63import java.util.concurrent.ScheduledExecutorService;
64import java.util.concurrent.ScheduledFuture;
65import java.util.concurrent.TimeUnit;
66
67@SuppressWarnings("ALL")
68@Component(immediate = true)
69public class SegmentRoutingManager {
70
71 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected CoreService coreService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected TopologyService topologyService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected PacketService packetService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected IntentService intentService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected HostService hostService;
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected DeviceService deviceService;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected FlowRuleService flowRuleService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected LinkService linkService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected GroupService groupService;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected MastershipService mastershipService;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700102 protected NetworkConfigHandler networkConfigHandler = null;
103 protected ArpHandler arpHandler = null;
104 protected IcmpHandler icmpHandler = null;
105 protected IpHandler ipHandler = null;
106 protected RoutingRulePopulator routingRulePopulator = null;
sanghob35a6192015-04-01 13:05:26 -0700107 protected ApplicationId appId;
108
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700109 private DefaultRoutingHandler defaultRoutingHandler = null;
110 private DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700111 private InternalPacketProcessor processor = new InternalPacketProcessor();
112 private InternalEventHandler eventHandler = new InternalEventHandler();
113
114 private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
115
116 private static ScheduledFuture<?> eventHandlerFuture = null;
117 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
118 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap
119 = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
120
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700121 private NetworkConfigManager networkConfigService = new NetworkConfigManager();;
122
sanghob35a6192015-04-01 13:05:26 -0700123 private static int numOfEvents = 0;
124 private static int numOfHandlerExecution = 0;
125 private static int numOfHandlerScheduled = 0;
126
127 @Activate
128 protected void activate() {
129 appId = coreService.registerApplication("org.onosproject.segmentrouting");
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700130 networkConfigService.init();
131 deviceConfiguration = new DeviceConfiguration(networkConfigService);
132 networkConfigHandler = new NetworkConfigHandler(this,
133 deviceConfiguration);
134 arpHandler = new ArpHandler(this);
135 icmpHandler = new IcmpHandler(this);
136 ipHandler = new IpHandler(this);
137 routingRulePopulator = new RoutingRulePopulator(this);
138 defaultRoutingHandler = new DefaultRoutingHandler(this);
139
sanghob35a6192015-04-01 13:05:26 -0700140 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
141 linkService.addListener(new InternalLinkListener());
142 groupService.addListener(new InternalGroupListener());
143 deviceService.addListener(new InternalDeviceListener());
144
145 for (Device device: deviceService.getDevices()) {
146 if (mastershipService.
147 getLocalRole(device.id()) == MastershipRole.MASTER) {
148 DefaultGroupHandler groupHandler =
149 DefaultGroupHandler.createGroupHandler(device.id(),
150 appId, deviceConfiguration, linkService, groupService);
151 groupHandler.createGroups();
152 groupHandlerMap.put(device.id(), groupHandler);
153 log.debug("Initiating default group handling for {}", device.id());
154
155 defaultRoutingHandler.startPopulationProcess();
156 } else {
157 log.debug("Activate: Local role {} "
158 + "is not MASTER for device {}",
159 mastershipService.
160 getLocalRole(device.id()),
161 device.id());
162 }
163 }
164
165 log.info("Started");
166 }
167
168 @Deactivate
169 protected void deactivate() {
170 packetService.removeProcessor(processor);
171 processor = null;
172 log.info("Stopped");
173 }
174
175 /**
176 * Returns the GrouopKey object for the device and the NighborSet given.
177 *
178 * @param ns NeightborSet object for the GroupKey
179 * @return GroupKey object for the NeighborSet
180 */
181 public GroupKey getGroupKey(NeighborSet ns) {
182
183 for (DefaultGroupHandler groupHandler: groupHandlerMap.values()) {
184 return groupHandler.getGroupKey(ns);
185 }
186
187 return null;
188 }
189
190 private class InternalPacketProcessor implements PacketProcessor {
191
192 @Override
193 public void process(PacketContext context) {
194
195 if (context.isHandled()) {
196 return;
197 }
198
199 InboundPacket pkt = context.inPacket();
200 Ethernet ethernet = pkt.parsed();
201
202 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
203 arpHandler.processPacketIn(pkt);
204 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
205 IPv4 ipPacket = (IPv4) ethernet.getPayload();
206 ipHandler.addToPacketBuffer(ipPacket);
207 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
208 icmpHandler.processPacketIn(pkt);
209 } else {
210 ipHandler.processPacketIn(pkt);
211 }
212 }
213 }
214 }
215
216 private class InternalLinkListener implements LinkListener {
217 @Override
218 public void event(LinkEvent event) {
219 if (event.type() == LinkEvent.Type.LINK_ADDED ||
220 event.type() == LinkEvent.Type.LINK_REMOVED) {
221 scheduleEventHandlerIfNotScheduled(event);
222 }
223 }
224 }
225
226 private class InternalDeviceListener implements DeviceListener {
227
228 @Override
229 public void event(DeviceEvent event) {
230 if (mastershipService.
231 getLocalRole(event.subject().id()) != MastershipRole.MASTER) {
232 log.debug("Local role {} is not MASTER for device {}",
233 mastershipService.
234 getLocalRole(event.subject().id()),
235 event.subject().id());
236 return;
237 }
238
239 switch (event.type()) {
240 case DEVICE_ADDED:
241 case PORT_REMOVED:
242 scheduleEventHandlerIfNotScheduled(event);
243 break;
244 default:
245 }
246 }
247 }
248
249 private class InternalGroupListener implements GroupListener {
250
251 @Override
252 public void event(GroupEvent event) {
253 switch (event.type()) {
254 case GROUP_ADDED:
255 scheduleEventHandlerIfNotScheduled(event);
256 break;
257 case GROUP_ADD_REQUESTED:
258 log.info("Group add requested");
259 break;
260 case GROUP_UPDATED:
261 break;
262 default:
263 log.warn("Unhandled group event type: {}", event.type());
264 }
265 }
266 }
267
268 private void scheduleEventHandlerIfNotScheduled(Event event) {
269
270 eventQueue.add(event);
271 numOfEvents++;
272 if (eventHandlerFuture == null ||
273 eventHandlerFuture.isDone()) {
274 eventHandlerFuture = executorService.schedule(eventHandler,
275 100, TimeUnit.MILLISECONDS);
276 numOfHandlerScheduled++;
277 }
278
279 log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
280 numOfHandlerScheduled);
281
282 }
283
284 private class InternalEventHandler implements Runnable {
285
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700286 @Override
sanghob35a6192015-04-01 13:05:26 -0700287 public void run() {
288 numOfHandlerExecution++;
289 while (!eventQueue.isEmpty()) {
290 Event event = eventQueue.poll();
291 if (event.type() == LinkEvent.Type.LINK_ADDED) {
292 processLinkAdded((Link) event.subject());
293 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
294 processLinkRemoved((Link) event.subject());
295 } else if (event.type() == GroupEvent.Type.GROUP_ADDED) {
296 processGroupAdded((Group) event.subject());
297 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED) {
298 processDeviceAdded((Device) event.subject());
299 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
300 processPortRemoved((Device) event.subject(),
301 ((DeviceEvent) event).port());
302 } else {
303 log.warn("Unhandled event type: {}", event.type());
304 }
305 }
306 log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}",
307 numOfHandlerExecution, numOfHandlerScheduled, numOfEvents);
308 }
309 }
310
311
312
313 private void processLinkAdded(Link link) {
314 log.debug("A new link {} was added", link.toString());
315
316 if (mastershipService.
317 getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) {
318 DefaultGroupHandler groupHandler =
319 groupHandlerMap.get(link.src().deviceId());
320 if (groupHandler != null) {
321 groupHandler.linkUp(link);
322 }
323 }
324 defaultRoutingHandler.startPopulationProcess();
325 }
326
327 private void processLinkRemoved(Link link) {
328 log.debug("A link {} was removed", link.toString());
329 defaultRoutingHandler.startPopulationProcess();
330 }
331
332
333 private void processGroupAdded(Group group) {
334 log.debug("A new group with ID {} was added", group.id());
335 defaultRoutingHandler.resumePopulationProcess();
336 }
337
338 private void processDeviceAdded(Device device) {
339 log.debug("A new device with ID {} was added", device.id());
340 defaultRoutingHandler.populateTtpRules(device.id());
341 DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler(
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700342 device.id(),
343 appId,
344 deviceConfiguration,
345 linkService,
346 groupService);
sanghob35a6192015-04-01 13:05:26 -0700347 dgh.createGroups();
348 groupHandlerMap.put(device.id(), dgh);
349 }
350
351 private void processPortRemoved(Device device, Port port) {
352 log.debug("Port {} was removed", port.toString());
353 DefaultGroupHandler groupHandler =
354 groupHandlerMap.get(device.id());
355 if (groupHandler != null) {
356 groupHandler.portDown(port.number());
357 }
358 }
359}