blob: a7a3b1113b37442e9a2a47922282c027ee90d971 [file] [log] [blame]
sangho80f11cb2015-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;
28import org.onosproject.grouphandler.DefaultGroupHandler;
29import org.onosproject.grouphandler.NeighborSet;
30import 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;
55import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
57
58import java.util.Map;
59import java.util.concurrent.ConcurrentHashMap;
60import java.util.concurrent.ConcurrentLinkedQueue;
61import java.util.concurrent.Executors;
62import java.util.concurrent.ScheduledExecutorService;
63import java.util.concurrent.ScheduledFuture;
64import java.util.concurrent.TimeUnit;
65
66@SuppressWarnings("ALL")
67@Component(immediate = true)
68public class SegmentRoutingManager {
69
70 private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
71
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)
91 protected FlowRuleService flowRuleService;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected LinkService linkService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected GroupService groupService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected MastershipService mastershipService;
101
102 protected NetworkConfigHandler networkConfigHandler = new NetworkConfigHandler(this);
103 protected ArpHandler arpHandler = new ArpHandler(this);
104 protected IcmpHandler icmpHandler = new IcmpHandler(this);
105 protected IpHandler ipHandler = new IpHandler(this);
106 protected RoutingRulePopulator routingRulePopulator = new RoutingRulePopulator(this);
107 protected ApplicationId appId;
108
109 private DefaultRoutingHandler defaultRoutingHandler = new DefaultRoutingHandler(this);
110 private DeviceConfiguration deviceConfiguration = new DeviceConfiguration();
111 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
121 private static int numOfEvents = 0;
122 private static int numOfHandlerExecution = 0;
123 private static int numOfHandlerScheduled = 0;
124
125 @Activate
126 protected void activate() {
127 appId = coreService.registerApplication("org.onosproject.segmentrouting");
128 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
129 linkService.addListener(new InternalLinkListener());
130 groupService.addListener(new InternalGroupListener());
131 deviceService.addListener(new InternalDeviceListener());
132
133 for (Device device: deviceService.getDevices()) {
134 if (mastershipService.
135 getLocalRole(device.id()) == MastershipRole.MASTER) {
136 DefaultGroupHandler groupHandler =
137 DefaultGroupHandler.createGroupHandler(device.id(),
138 appId, deviceConfiguration, linkService, groupService);
139 groupHandler.createGroups();
140 groupHandlerMap.put(device.id(), groupHandler);
141 log.debug("Initiating default group handling for {}", device.id());
142
143 defaultRoutingHandler.startPopulationProcess();
144 } else {
145 log.debug("Activate: Local role {} "
146 + "is not MASTER for device {}",
147 mastershipService.
148 getLocalRole(device.id()),
149 device.id());
150 }
151 }
152
153 log.info("Started");
154 }
155
156 @Deactivate
157 protected void deactivate() {
158 packetService.removeProcessor(processor);
159 processor = null;
160 log.info("Stopped");
161 }
162
163 /**
164 * Returns the GrouopKey object for the device and the NighborSet given.
165 *
166 * @param ns NeightborSet object for the GroupKey
167 * @return GroupKey object for the NeighborSet
168 */
169 public GroupKey getGroupKey(NeighborSet ns) {
170
171 for (DefaultGroupHandler groupHandler: groupHandlerMap.values()) {
172 return groupHandler.getGroupKey(ns);
173 }
174
175 return null;
176 }
177
178 private class InternalPacketProcessor implements PacketProcessor {
179
180 @Override
181 public void process(PacketContext context) {
182
183 if (context.isHandled()) {
184 return;
185 }
186
187 InboundPacket pkt = context.inPacket();
188 Ethernet ethernet = pkt.parsed();
189
190 if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
191 arpHandler.processPacketIn(pkt);
192 } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
193 IPv4 ipPacket = (IPv4) ethernet.getPayload();
194 ipHandler.addToPacketBuffer(ipPacket);
195 if (ipPacket.getProtocol() == IPv4.PROTOCOL_ICMP) {
196 icmpHandler.processPacketIn(pkt);
197 } else {
198 ipHandler.processPacketIn(pkt);
199 }
200 }
201 }
202 }
203
204 private class InternalLinkListener implements LinkListener {
205 @Override
206 public void event(LinkEvent event) {
207 if (event.type() == LinkEvent.Type.LINK_ADDED ||
208 event.type() == LinkEvent.Type.LINK_REMOVED) {
209 scheduleEventHandlerIfNotScheduled(event);
210 }
211 }
212 }
213
214 private class InternalDeviceListener implements DeviceListener {
215
216 @Override
217 public void event(DeviceEvent event) {
218 if (mastershipService.
219 getLocalRole(event.subject().id()) != MastershipRole.MASTER) {
220 log.debug("Local role {} is not MASTER for device {}",
221 mastershipService.
222 getLocalRole(event.subject().id()),
223 event.subject().id());
224 return;
225 }
226
227 switch (event.type()) {
228 case DEVICE_ADDED:
229 case PORT_REMOVED:
230 scheduleEventHandlerIfNotScheduled(event);
231 break;
232 default:
233 }
234 }
235 }
236
237 private class InternalGroupListener implements GroupListener {
238
239 @Override
240 public void event(GroupEvent event) {
241 switch (event.type()) {
242 case GROUP_ADDED:
243 scheduleEventHandlerIfNotScheduled(event);
244 break;
245 case GROUP_ADD_REQUESTED:
246 log.info("Group add requested");
247 break;
248 case GROUP_UPDATED:
249 break;
250 default:
251 log.warn("Unhandled group event type: {}", event.type());
252 }
253 }
254 }
255
256 private void scheduleEventHandlerIfNotScheduled(Event event) {
257
258 eventQueue.add(event);
259 numOfEvents++;
260 if (eventHandlerFuture == null ||
261 eventHandlerFuture.isDone()) {
262 eventHandlerFuture = executorService.schedule(eventHandler,
263 100, TimeUnit.MILLISECONDS);
264 numOfHandlerScheduled++;
265 }
266
267 log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
268 numOfHandlerScheduled);
269
270 }
271
272 private class InternalEventHandler implements Runnable {
273
274 public void run() {
275 numOfHandlerExecution++;
276 while (!eventQueue.isEmpty()) {
277 Event event = eventQueue.poll();
278 if (event.type() == LinkEvent.Type.LINK_ADDED) {
279 processLinkAdded((Link) event.subject());
280 } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
281 processLinkRemoved((Link) event.subject());
282 } else if (event.type() == GroupEvent.Type.GROUP_ADDED) {
283 processGroupAdded((Group) event.subject());
284 } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED) {
285 processDeviceAdded((Device) event.subject());
286 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
287 processPortRemoved((Device) event.subject(),
288 ((DeviceEvent) event).port());
289 } else {
290 log.warn("Unhandled event type: {}", event.type());
291 }
292 }
293 log.debug("numOfHandlerExecution {} numOfEventHanlderScheduled {} numOfEvents {}",
294 numOfHandlerExecution, numOfHandlerScheduled, numOfEvents);
295 }
296 }
297
298
299
300 private void processLinkAdded(Link link) {
301 log.debug("A new link {} was added", link.toString());
302
303 if (mastershipService.
304 getLocalRole(link.src().deviceId()) == MastershipRole.MASTER) {
305 DefaultGroupHandler groupHandler =
306 groupHandlerMap.get(link.src().deviceId());
307 if (groupHandler != null) {
308 groupHandler.linkUp(link);
309 }
310 }
311 defaultRoutingHandler.startPopulationProcess();
312 }
313
314 private void processLinkRemoved(Link link) {
315 log.debug("A link {} was removed", link.toString());
316 defaultRoutingHandler.startPopulationProcess();
317 }
318
319
320 private void processGroupAdded(Group group) {
321 log.debug("A new group with ID {} was added", group.id());
322 defaultRoutingHandler.resumePopulationProcess();
323 }
324
325 private void processDeviceAdded(Device device) {
326 log.debug("A new device with ID {} was added", device.id());
327 defaultRoutingHandler.populateTtpRules(device.id());
328 DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler(
329 device.id(), appId, new DeviceConfiguration(), linkService, groupService);
330 dgh.createGroups();
331 groupHandlerMap.put(device.id(), dgh);
332 }
333
334 private void processPortRemoved(Device device, Port port) {
335 log.debug("Port {} was removed", port.toString());
336 DefaultGroupHandler groupHandler =
337 groupHandlerMap.get(device.id());
338 if (groupHandler != null) {
339 groupHandler.portDown(port.number());
340 }
341 }
342}