blob: 08d6220e519b438b94ae59a2a74456216df4cfb1 [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());
sangho20eff1d2015-04-13 15:15:58 -0700154 defaultRoutingHandler.populateTtpRules(device.id());
sanghob35a6192015-04-01 13:05:26 -0700155 } else {
156 log.debug("Activate: Local role {} "
157 + "is not MASTER for device {}",
158 mastershipService.
159 getLocalRole(device.id()),
160 device.id());
161 }
162 }
163
sangho20eff1d2015-04-13 15:15:58 -0700164 defaultRoutingHandler.startPopulationProcess();
165
sanghob35a6192015-04-01 13:05:26 -0700166 log.info("Started");
167 }
168
169 @Deactivate
170 protected void deactivate() {
171 packetService.removeProcessor(processor);
172 processor = null;
173 log.info("Stopped");
174 }
175
176 /**
177 * Returns the GrouopKey object for the device and the NighborSet given.
178 *
179 * @param ns NeightborSet object for the GroupKey
180 * @return GroupKey object for the NeighborSet
181 */
182 public GroupKey getGroupKey(NeighborSet ns) {
183
184 for (DefaultGroupHandler groupHandler: groupHandlerMap.values()) {
185 return groupHandler.getGroupKey(ns);
186 }
187
188 return null;
189 }
190
191 private class InternalPacketProcessor implements PacketProcessor {
192
193 @Override
194 public void process(PacketContext context) {
195
196 if (context.isHandled()) {
197 return;
198 }
199
200 InboundPacket pkt = context.inPacket();
201 Ethernet ethernet = pkt.parsed();
202
203 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
204 arpHandler.processPacketIn(pkt);
205 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
206 IPv4 ipPacket = (IPv4) ethernet.getPayload();
207 ipHandler.addToPacketBuffer(ipPacket);
208 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
209 icmpHandler.processPacketIn(pkt);
210 } else {
211 ipHandler.processPacketIn(pkt);
212 }
213 }
214 }
215 }
216
217 private class InternalLinkListener implements LinkListener {
218 @Override
219 public void event(LinkEvent event) {
220 if (event.type() == LinkEvent.Type.LINK_ADDED ||
221 event.type() == LinkEvent.Type.LINK_REMOVED) {
222 scheduleEventHandlerIfNotScheduled(event);
223 }
224 }
225 }
226
227 private class InternalDeviceListener implements DeviceListener {
228
229 @Override
230 public void event(DeviceEvent event) {
231 if (mastershipService.
232 getLocalRole(event.subject().id()) != MastershipRole.MASTER) {
233 log.debug("Local role {} is not MASTER for device {}",
234 mastershipService.
235 getLocalRole(event.subject().id()),
236 event.subject().id());
237 return;
238 }
239
240 switch (event.type()) {
241 case DEVICE_ADDED:
242 case PORT_REMOVED:
sangho20eff1d2015-04-13 15:15:58 -0700243 case DEVICE_UPDATED:
244 case DEVICE_AVAILABILITY_CHANGED:
sanghob35a6192015-04-01 13:05:26 -0700245 scheduleEventHandlerIfNotScheduled(event);
246 break;
247 default:
248 }
249 }
250 }
251
252 private class InternalGroupListener implements GroupListener {
253
254 @Override
255 public void event(GroupEvent event) {
256 switch (event.type()) {
257 case GROUP_ADDED:
258 scheduleEventHandlerIfNotScheduled(event);
259 break;
260 case GROUP_ADD_REQUESTED:
261 log.info("Group add requested");
262 break;
263 case GROUP_UPDATED:
264 break;
265 default:
266 log.warn("Unhandled group event type: {}", event.type());
267 }
268 }
269 }
270
271 private void scheduleEventHandlerIfNotScheduled(Event event) {
272
273 eventQueue.add(event);
274 numOfEvents++;
275 if (eventHandlerFuture == null ||
276 eventHandlerFuture.isDone()) {
277 eventHandlerFuture = executorService.schedule(eventHandler,
278 100, TimeUnit.MILLISECONDS);
279 numOfHandlerScheduled++;
280 }
281
282 log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
283 numOfHandlerScheduled);
284
285 }
286
287 private class InternalEventHandler implements Runnable {
288
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700289 @Override
sanghob35a6192015-04-01 13:05:26 -0700290 public void run() {
291 numOfHandlerExecution++;
292 while (!eventQueue.isEmpty()) {
293 Event event = eventQueue.poll();
294 if (event.type() == LinkEvent.Type.LINK_ADDED) {
295 processLinkAdded((Link) event.subject());
296 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
297 processLinkRemoved((Link) event.subject());
298 } else if (event.type() == GroupEvent.Type.GROUP_ADDED) {
299 processGroupAdded((Group) event.subject());
sangho20eff1d2015-04-13 15:15:58 -0700300 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
301 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
302 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
303 if (deviceService.isAvailable(((Device) event.subject()).id())) {
304 processDeviceAdded((Device) event.subject());
305 }
sanghob35a6192015-04-01 13:05:26 -0700306 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
307 processPortRemoved((Device) event.subject(),
308 ((DeviceEvent) event).port());
309 } else {
310 log.warn("Unhandled event type: {}", event.type());
311 }
312 }
313 log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}",
314 numOfHandlerExecution, numOfHandlerScheduled, numOfEvents);
315 }
316 }
317
318
319
320 private void processLinkAdded(Link link) {
321 log.debug("A new link {} was added", link.toString());
322
323 if (mastershipService.
324 getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) {
325 DefaultGroupHandler groupHandler =
326 groupHandlerMap.get(link.src().deviceId());
327 if (groupHandler != null) {
328 groupHandler.linkUp(link);
329 }
330 }
sangho20eff1d2015-04-13 15:15:58 -0700331 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
sanghob35a6192015-04-01 13:05:26 -0700332 }
333
334 private void processLinkRemoved(Link link) {
335 log.debug("A link {} was removed", link.toString());
sangho20eff1d2015-04-13 15:15:58 -0700336 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
sanghob35a6192015-04-01 13:05:26 -0700337 }
338
339
340 private void processGroupAdded(Group group) {
341 log.debug("A new group with ID {} was added", group.id());
342 defaultRoutingHandler.resumePopulationProcess();
343 }
344
345 private void processDeviceAdded(Device device) {
346 log.debug("A new device with ID {} was added", device.id());
347 defaultRoutingHandler.populateTtpRules(device.id());
348 DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler(
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700349 device.id(),
350 appId,
351 deviceConfiguration,
352 linkService,
353 groupService);
sanghob35a6192015-04-01 13:05:26 -0700354 dgh.createGroups();
355 groupHandlerMap.put(device.id(), dgh);
356 }
357
358 private void processPortRemoved(Device device, Port port) {
359 log.debug("Port {} was removed", port.toString());
360 DefaultGroupHandler groupHandler =
361 groupHandlerMap.get(device.id());
362 if (groupHandler != null) {
363 groupHandler.portDown(port.number());
364 }
365 }
366}