blob: 956fc1ec6ee693b58c365ac0672a05bdb46abb33 [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 ArpHandler arpHandler = null;
103 protected IcmpHandler icmpHandler = null;
104 protected IpHandler ipHandler = null;
105 protected RoutingRulePopulator routingRulePopulator = null;
sanghob35a6192015-04-01 13:05:26 -0700106 protected ApplicationId appId;
sangho666cd6d2015-04-14 16:27:13 -0700107 protected DeviceConfiguration deviceConfiguration = null;
sanghob35a6192015-04-01 13:05:26 -0700108
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700109 private DefaultRoutingHandler defaultRoutingHandler = null;
sanghob35a6192015-04-01 13:05:26 -0700110 private InternalPacketProcessor processor = new InternalPacketProcessor();
111 private InternalEventHandler eventHandler = new InternalEventHandler();
112
113 private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
114
115 private static ScheduledFuture<?> eventHandlerFuture = null;
116 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
117 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap
118 = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
119
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700120 private NetworkConfigManager networkConfigService = new NetworkConfigManager();;
121
sanghob35a6192015-04-01 13:05:26 -0700122 private static int numOfEvents = 0;
123 private static int numOfHandlerExecution = 0;
124 private static int numOfHandlerScheduled = 0;
125
126 @Activate
127 protected void activate() {
128 appId = coreService.registerApplication("org.onosproject.segmentrouting");
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700129 networkConfigService.init();
130 deviceConfiguration = new DeviceConfiguration(networkConfigService);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700131 arpHandler = new ArpHandler(this);
132 icmpHandler = new IcmpHandler(this);
133 ipHandler = new IpHandler(this);
134 routingRulePopulator = new RoutingRulePopulator(this);
135 defaultRoutingHandler = new DefaultRoutingHandler(this);
136
sanghob35a6192015-04-01 13:05:26 -0700137 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
138 linkService.addListener(new InternalLinkListener());
139 groupService.addListener(new InternalGroupListener());
140 deviceService.addListener(new InternalDeviceListener());
141
142 for (Device device: deviceService.getDevices()) {
143 if (mastershipService.
144 getLocalRole(device.id()) == MastershipRole.MASTER) {
145 DefaultGroupHandler groupHandler =
146 DefaultGroupHandler.createGroupHandler(device.id(),
147 appId, deviceConfiguration, linkService, groupService);
148 groupHandler.createGroups();
149 groupHandlerMap.put(device.id(), groupHandler);
sangho20eff1d2015-04-13 15:15:58 -0700150 defaultRoutingHandler.populateTtpRules(device.id());
sangho666cd6d2015-04-14 16:27:13 -0700151 log.debug("Initiating default group handling for {}", device.id());
sanghob35a6192015-04-01 13:05:26 -0700152 } else {
153 log.debug("Activate: Local role {} "
154 + "is not MASTER for device {}",
155 mastershipService.
156 getLocalRole(device.id()),
157 device.id());
158 }
159 }
160
sangho20eff1d2015-04-13 15:15:58 -0700161 defaultRoutingHandler.startPopulationProcess();
sanghob35a6192015-04-01 13:05:26 -0700162 log.info("Started");
163 }
164
165 @Deactivate
166 protected void deactivate() {
167 packetService.removeProcessor(processor);
168 processor = null;
169 log.info("Stopped");
170 }
171
172 /**
173 * Returns the GrouopKey object for the device and the NighborSet given.
174 *
175 * @param ns NeightborSet object for the GroupKey
176 * @return GroupKey object for the NeighborSet
177 */
178 public GroupKey getGroupKey(NeighborSet ns) {
179
180 for (DefaultGroupHandler groupHandler: groupHandlerMap.values()) {
181 return groupHandler.getGroupKey(ns);
182 }
183
184 return null;
185 }
186
187 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) {
216 if (event.type() == LinkEvent.Type.LINK_ADDED ||
217 event.type() == LinkEvent.Type.LINK_REMOVED) {
218 scheduleEventHandlerIfNotScheduled(event);
219 }
220 }
221 }
222
223 private class InternalDeviceListener implements DeviceListener {
224
225 @Override
226 public void event(DeviceEvent event) {
227 if (mastershipService.
228 getLocalRole(event.subject().id()) != MastershipRole.MASTER) {
229 log.debug("Local role {} is not MASTER for device {}",
230 mastershipService.
231 getLocalRole(event.subject().id()),
232 event.subject().id());
233 return;
234 }
235
236 switch (event.type()) {
237 case DEVICE_ADDED:
238 case PORT_REMOVED:
sangho20eff1d2015-04-13 15:15:58 -0700239 case DEVICE_UPDATED:
240 case DEVICE_AVAILABILITY_CHANGED:
sanghob35a6192015-04-01 13:05:26 -0700241 scheduleEventHandlerIfNotScheduled(event);
242 break;
243 default:
244 }
245 }
246 }
247
248 private class InternalGroupListener implements GroupListener {
249
250 @Override
251 public void event(GroupEvent event) {
252 switch (event.type()) {
253 case GROUP_ADDED:
254 scheduleEventHandlerIfNotScheduled(event);
255 break;
256 case GROUP_ADD_REQUESTED:
257 log.info("Group add requested");
258 break;
259 case GROUP_UPDATED:
260 break;
261 default:
262 log.warn("Unhandled group event type: {}", event.type());
263 }
264 }
265 }
266
267 private void scheduleEventHandlerIfNotScheduled(Event event) {
268
269 eventQueue.add(event);
270 numOfEvents++;
271 if (eventHandlerFuture == null ||
272 eventHandlerFuture.isDone()) {
273 eventHandlerFuture = executorService.schedule(eventHandler,
274 100, TimeUnit.MILLISECONDS);
275 numOfHandlerScheduled++;
276 }
277
278 log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
279 numOfHandlerScheduled);
280
281 }
282
283 private class InternalEventHandler implements Runnable {
284
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700285 @Override
sanghob35a6192015-04-01 13:05:26 -0700286 public void run() {
287 numOfHandlerExecution++;
288 while (!eventQueue.isEmpty()) {
289 Event event = eventQueue.poll();
290 if (event.type() == LinkEvent.Type.LINK_ADDED) {
291 processLinkAdded((Link) event.subject());
292 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
293 processLinkRemoved((Link) event.subject());
294 } else if (event.type() == GroupEvent.Type.GROUP_ADDED) {
295 processGroupAdded((Group) event.subject());
sangho20eff1d2015-04-13 15:15:58 -0700296 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
297 event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
298 event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
299 if (deviceService.isAvailable(((Device) event.subject()).id())) {
300 processDeviceAdded((Device) event.subject());
301 }
sanghob35a6192015-04-01 13:05:26 -0700302 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
303 processPortRemoved((Device) event.subject(),
304 ((DeviceEvent) event).port());
305 } else {
306 log.warn("Unhandled event type: {}", event.type());
307 }
308 }
309 log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}",
310 numOfHandlerExecution, numOfHandlerScheduled, numOfEvents);
311 }
312 }
313
314
315
316 private void processLinkAdded(Link link) {
317 log.debug("A new link {} was added", link.toString());
318
319 if (mastershipService.
320 getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) {
321 DefaultGroupHandler groupHandler =
322 groupHandlerMap.get(link.src().deviceId());
323 if (groupHandler != null) {
324 groupHandler.linkUp(link);
325 }
326 }
sangho20eff1d2015-04-13 15:15:58 -0700327 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null);
sanghob35a6192015-04-01 13:05:26 -0700328 }
329
330 private void processLinkRemoved(Link link) {
331 log.debug("A link {} was removed", link.toString());
sangho20eff1d2015-04-13 15:15:58 -0700332 defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link);
sanghob35a6192015-04-01 13:05:26 -0700333 }
334
335
336 private void processGroupAdded(Group group) {
337 log.debug("A new group with ID {} was added", group.id());
338 defaultRoutingHandler.resumePopulationProcess();
339 }
340
341 private void processDeviceAdded(Device device) {
342 log.debug("A new device with ID {} was added", device.id());
343 defaultRoutingHandler.populateTtpRules(device.id());
344 DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler(
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700345 device.id(),
346 appId,
347 deviceConfiguration,
348 linkService,
349 groupService);
sanghob35a6192015-04-01 13:05:26 -0700350 dgh.createGroups();
351 groupHandlerMap.put(device.id(), dgh);
352 }
353
354 private void processPortRemoved(Device device, Port port) {
355 log.debug("Port {} was removed", port.toString());
356 DefaultGroupHandler groupHandler =
357 groupHandlerMap.get(device.id());
358 if (groupHandler != null) {
359 groupHandler.portDown(port.number());
360 }
361 }
362}