blob: c5395e8ee40f79f96fe437cdddbb61b586380210 [file] [log] [blame]
Jonathan Hartea750842015-04-23 17:44:49 -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 */
16
17package org.onosproject.cordfabric;
18
19import com.google.common.collect.HashMultimap;
20import com.google.common.collect.Multimap;
Jonathan Hartea750842015-04-23 17:44:49 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
Jonathan Hart0b989982015-05-14 15:40:07 -070027import org.onlab.packet.Ethernet;
28import org.onlab.packet.IPv4;
Jonathan Hart64da69d2015-07-15 15:10:28 -070029import org.onlab.packet.MacAddress;
Jonathan Hartea750842015-04-23 17:44:49 -070030import org.onlab.packet.VlanId;
31import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
33import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.PortNumber;
Jonathan Hart408d24d2015-06-02 10:21:47 -070036import org.onosproject.net.device.DeviceEvent;
37import org.onosproject.net.device.DeviceListener;
38import org.onosproject.net.device.DeviceService;
Jonathan Hartea750842015-04-23 17:44:49 -070039import org.onosproject.net.flow.DefaultTrafficSelector;
40import org.onosproject.net.flow.DefaultTrafficTreatment;
41import org.onosproject.net.flow.TrafficSelector;
42import org.onosproject.net.flow.TrafficTreatment;
43import org.onosproject.net.flowobjective.DefaultForwardingObjective;
44import org.onosproject.net.flowobjective.FlowObjectiveService;
45import org.onosproject.net.flowobjective.ForwardingObjective;
46import org.onosproject.net.flowobjective.Objective;
47import org.onosproject.net.flowobjective.ObjectiveContext;
48import org.onosproject.net.flowobjective.ObjectiveError;
49import org.slf4j.Logger;
50import org.slf4j.LoggerFactory;
51
Jonathan Hart443ebed2015-05-05 14:02:12 -070052import java.util.ArrayList;
Jonathan Hartab8b0c02015-06-10 14:06:51 -070053import java.util.Collection;
Jonathan Hartea750842015-04-23 17:44:49 -070054import java.util.List;
55import java.util.stream.Collectors;
56
57import static com.google.common.base.Preconditions.checkArgument;
58import static com.google.common.base.Preconditions.checkNotNull;
59import static org.slf4j.LoggerFactory.getLogger;
60
61/**
62 * CORD fabric application.
63 */
64@Service
65@Component(immediate = true)
66public class CordFabricManager implements FabricService {
67
68 private final Logger log = getLogger(getClass());
69
70 private ApplicationId appId;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected CoreService coreService;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected FlowObjectiveService flowObjectiveService;
77
Jonathan Hart408d24d2015-06-02 10:21:47 -070078 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected DeviceService deviceService;
Jonathan Hartea750842015-04-23 17:44:49 -070080
Jonathan Hart408d24d2015-06-02 10:21:47 -070081 private InternalDeviceListener deviceListener = new InternalDeviceListener();
82
83 private static final int PRIORITY = 50000;
alshabibe9532ab2015-08-05 10:50:30 -070084 private static final int TESTPRIO = 49999;
Jonathan Hart0b989982015-05-14 15:40:07 -070085
alshabibc494f992015-05-15 09:51:54 -070086 private short radiusPort = 1812;
87
alshabib0603afb2015-06-05 14:10:33 -070088 private short ofPort = 6633;
89
Jonathan Hart0b989982015-05-14 15:40:07 -070090 private DeviceId fabricDeviceId = DeviceId.deviceId("of:5e3e486e73000187");
91
Jonathan Hartea750842015-04-23 17:44:49 -070092 private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create();
93
alshabibe9532ab2015-08-05 10:50:30 -070094 //TODO make this configurable
95 private boolean testMode = true;
96
97
Jonathan Hartea750842015-04-23 17:44:49 -070098 @Activate
99 public void activate() {
100 appId = coreService.registerApplication("org.onosproject.cordfabric");
101
Jonathan Hart408d24d2015-06-02 10:21:47 -0700102 deviceService.addListener(deviceListener);
103
104 if (deviceService.isAvailable(fabricDeviceId)) {
105 setupDefaultFlows();
106 }
Jonathan Hart0b989982015-05-14 15:40:07 -0700107
Jonathan Hartea750842015-04-23 17:44:49 -0700108 log.info("Started");
109 }
110
111 @Deactivate
112 public void deactivate() {
Jonathan Hart408d24d2015-06-02 10:21:47 -0700113 deviceService.removeListener(deviceListener);
114
Jonathan Hartea750842015-04-23 17:44:49 -0700115 log.info("Stopped");
116 }
117
Jonathan Hart0b989982015-05-14 15:40:07 -0700118 private void setupDefaultFlows() {
alshabib0603afb2015-06-05 14:10:33 -0700119 TrafficSelector ofInBandMatchUp = DefaultTrafficSelector.builder()
120 .matchEthType(Ethernet.TYPE_IPV4)
121 .matchIPProtocol(IPv4.PROTOCOL_TCP)
122 .matchTcpDst(ofPort)
123 .matchInPort(PortNumber.portNumber(6))
124 .build();
125
126 TrafficSelector ofInBandMatchDown = DefaultTrafficSelector.builder()
127 .matchEthType(Ethernet.TYPE_IPV4)
128 .matchIPProtocol(IPv4.PROTOCOL_TCP)
129 .matchTcpSrc(ofPort)
alshabib48dd9a12015-06-05 14:45:57 -0700130 .matchInPort(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700131 .build();
132
Jonathan Hart64da69d2015-07-15 15:10:28 -0700133 TrafficSelector oltMgmtUp = DefaultTrafficSelector.builder()
134 .matchEthSrc(MacAddress.valueOf("00:0c:d5:00:01:01"))
135 .matchInPort(PortNumber.portNumber(2))
136 .build();
137
138 TrafficSelector oltMgmtDown = DefaultTrafficSelector.builder()
139 .matchEthDst(MacAddress.valueOf("00:0c:d5:00:01:01"))
140 .matchInPort(PortNumber.portNumber(9))
141 .build();
142
alshabib0603afb2015-06-05 14:10:33 -0700143 TrafficTreatment up = DefaultTrafficTreatment.builder()
alshabib48dd9a12015-06-05 14:45:57 -0700144 .setOutput(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700145 .build();
146
147 TrafficTreatment down = DefaultTrafficTreatment.builder()
148 .setOutput(PortNumber.portNumber(6))
149 .build();
150
151 TrafficSelector toRadius = DefaultTrafficSelector.builder()
alshabibaf734ff2015-07-01 16:35:26 -0700152 .matchInPort(PortNumber.portNumber(2))
Jonathan Hart0b989982015-05-14 15:40:07 -0700153 .matchEthType(Ethernet.TYPE_IPV4)
alshabibc494f992015-05-15 09:51:54 -0700154 .matchIPProtocol(IPv4.PROTOCOL_UDP)
155 .matchUdpDst(radiusPort)
156 .build();
157
alshabibaf734ff2015-07-01 16:35:26 -0700158 TrafficSelector fromRadius = DefaultTrafficSelector.builder()
159 .matchInPort(PortNumber.portNumber(5))
160 .matchEthType(Ethernet.TYPE_IPV4)
161 .matchIPProtocol(IPv4.PROTOCOL_UDP)
162 .matchUdpDst(radiusPort)
Jonathan Hart0b989982015-05-14 15:40:07 -0700163 .build();
164
alshabibaf734ff2015-07-01 16:35:26 -0700165 TrafficTreatment toOlt = DefaultTrafficTreatment.builder()
166 .setOutput(PortNumber.portNumber(2))
167 .build();
168
Jonathan Hart64da69d2015-07-15 15:10:28 -0700169 TrafficTreatment toVolt = DefaultTrafficTreatment.builder()
170 .setOutput(PortNumber.portNumber(9))
171 .build();
alshabibaf734ff2015-07-01 16:35:26 -0700172
173 TrafficTreatment sentToRadius = DefaultTrafficTreatment.builder()
174 .setOutput(PortNumber.portNumber(5))
175 .build();
176
alshabibe9532ab2015-08-05 10:50:30 -0700177 TrafficTreatment testPort = DefaultTrafficTreatment.builder()
178 .setOutput(PortNumber.portNumber(8))
179 .build();
180
181 ForwardingObjective ofTestPath = DefaultForwardingObjective.builder()
182 .fromApp(appId)
183 .makePermanent()
184 .withFlag(ForwardingObjective.Flag.VERSATILE)
185 .withPriority(TESTPRIO)
186 .withSelector(
187 DefaultTrafficSelector.builder()
188 .matchInPort(PortNumber.portNumber(2))
189 .build())
190 .withTreatment(testPort)
191 .add();
192
alshabibaf734ff2015-07-01 16:35:26 -0700193 ForwardingObjective radiusToServer = DefaultForwardingObjective.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700194 .fromApp(appId)
195 .makePermanent()
196 .withFlag(ForwardingObjective.Flag.VERSATILE)
197 .withPriority(PRIORITY)
alshabib0603afb2015-06-05 14:10:33 -0700198 .withSelector(toRadius)
alshabibaf734ff2015-07-01 16:35:26 -0700199 .withTreatment(sentToRadius)
Jonathan Hart0b989982015-05-14 15:40:07 -0700200 .add();
201
alshabibaf734ff2015-07-01 16:35:26 -0700202 ForwardingObjective serverToRadius = DefaultForwardingObjective.builder()
203 .fromApp(appId)
204 .makePermanent()
205 .withFlag(ForwardingObjective.Flag.VERSATILE)
206 .withPriority(PRIORITY)
207 .withSelector(fromRadius)
208 .withTreatment(toOlt)
209 .add();
210
211
212
alshabib0603afb2015-06-05 14:10:33 -0700213 ForwardingObjective upCtrl = DefaultForwardingObjective.builder()
214 .fromApp(appId)
215 .makePermanent()
216 .withFlag(ForwardingObjective.Flag.VERSATILE)
217 .withPriority(PRIORITY)
218 .withSelector(ofInBandMatchUp)
219 .withTreatment(up)
220 .add();
221
222 ForwardingObjective downCtrl = DefaultForwardingObjective.builder()
223 .fromApp(appId)
224 .makePermanent()
225 .withFlag(ForwardingObjective.Flag.VERSATILE)
226 .withPriority(PRIORITY)
227 .withSelector(ofInBandMatchDown)
228 .withTreatment(down)
229 .add();
230
Jonathan Hart64da69d2015-07-15 15:10:28 -0700231 ForwardingObjective upOltMgmt = DefaultForwardingObjective.builder()
232 .fromApp(appId)
233 .makePermanent()
234 .withFlag(ForwardingObjective.Flag.VERSATILE)
235 .withPriority(PRIORITY)
236 .withSelector(oltMgmtUp)
237 .withTreatment(toVolt)
238 .add();
239
240 ForwardingObjective downOltMgmt = DefaultForwardingObjective.builder()
241 .fromApp(appId)
242 .makePermanent()
243 .withFlag(ForwardingObjective.Flag.VERSATILE)
244 .withPriority(PRIORITY)
245 .withSelector(oltMgmtDown)
246 .withTreatment(toOlt)
247 .add();
alshabibc4b5d462015-06-08 23:06:24 -0700248
alshabibe9532ab2015-08-05 10:50:30 -0700249 if (testMode) {
250 flowObjectiveService.forward(fabricDeviceId, ofTestPath);
251 }
alshabibc4b5d462015-06-08 23:06:24 -0700252
alshabib0603afb2015-06-05 14:10:33 -0700253 flowObjectiveService.forward(fabricDeviceId, upCtrl);
254 flowObjectiveService.forward(fabricDeviceId, downCtrl);
alshabibaf734ff2015-07-01 16:35:26 -0700255 flowObjectiveService.forward(fabricDeviceId, radiusToServer);
256 flowObjectiveService.forward(fabricDeviceId, serverToRadius);
Jonathan Hart64da69d2015-07-15 15:10:28 -0700257 flowObjectiveService.forward(fabricDeviceId, upOltMgmt);
258 flowObjectiveService.forward(fabricDeviceId, downOltMgmt);
Jonathan Hart0b989982015-05-14 15:40:07 -0700259 }
260
Jonathan Hartea750842015-04-23 17:44:49 -0700261 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700262 public void addVlan(FabricVlan vlan) {
263 checkNotNull(vlan);
264 checkArgument(vlan.ports().size() > 1);
265 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -0700266
Jonathan Hart443ebed2015-05-05 14:02:12 -0700267 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -0700268
alshabibc4b5d462015-06-08 23:06:24 -0700269 if (vlan.iptv()) {
270 provisionIPTV();
271 }
272
Jonathan Hart443ebed2015-05-05 14:02:12 -0700273 vlan.ports().forEach(cp -> {
274 if (vlans.put(vlan.vlan(), cp)) {
275 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
276 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -0700277 .filter(p -> p != cp)
278 .map(ConnectPoint::port)
279 .collect(Collectors.toList()));
280 }
281 });
282 }
283
alshabibc4b5d462015-06-08 23:06:24 -0700284 //FIXME: pass iptv vlan in here.
285 private void provisionIPTV() {
286 TrafficSelector ipTvUp = DefaultTrafficSelector.builder()
287 .matchVlanId(VlanId.vlanId((short) 7))
288 .matchInPort(PortNumber.portNumber(2))
289 .build();
290
291 TrafficTreatment ipTvActUp = DefaultTrafficTreatment.builder()
292 .setOutput(PortNumber.portNumber(7)).build();
293
294 TrafficSelector ipTvDown = DefaultTrafficSelector.builder()
295 .matchVlanId(VlanId.vlanId((short) 7))
296 .matchInPort(PortNumber.portNumber(7))
297 .build();
298
299 TrafficTreatment ipTvActDown = DefaultTrafficTreatment.builder()
300 .setOutput(PortNumber.portNumber(2)).build();
301
302 ForwardingObjective ipTvUpstream = DefaultForwardingObjective.builder()
303 .fromApp(appId)
304 .makePermanent()
305 .withFlag(ForwardingObjective.Flag.VERSATILE)
306 .withPriority(PRIORITY)
307 .withSelector(ipTvUp)
308 .withTreatment(ipTvActUp)
309 .add();
310
311 ForwardingObjective ipTvDownstream = DefaultForwardingObjective.builder()
312 .fromApp(appId)
313 .makePermanent()
314 .withFlag(ForwardingObjective.Flag.VERSATILE)
315 .withPriority(PRIORITY)
316 .withSelector(ipTvDown)
317 .withTreatment(ipTvActDown)
318 .add();
319
320 flowObjectiveService.forward(fabricDeviceId, ipTvUpstream);
321 flowObjectiveService.forward(fabricDeviceId, ipTvDownstream);
322 }
323
Jonathan Hartea750842015-04-23 17:44:49 -0700324 @Override
325 public void removeVlan(VlanId vlanId) {
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700326 Collection<ConnectPoint> ports = vlans.removeAll(vlanId);
327
328 ports.forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port(),
329 ports.stream()
330 .filter(p -> p != cp)
331 .map(ConnectPoint::port)
332 .collect(Collectors.toList())));
Jonathan Hartea750842015-04-23 17:44:49 -0700333 }
334
335 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700336 public List<FabricVlan> getVlans() {
337 List<FabricVlan> fVlans = new ArrayList<>();
338 vlans.keySet().forEach(vlan -> fVlans.add(
alshabibc4b5d462015-06-08 23:06:24 -0700339 //FIXME: Very aweful but will fo for now
340 new FabricVlan(vlan, vlans.get(vlan),
341 vlan.toShort() == 201 ? true : false)));
Jonathan Hart443ebed2015-05-05 14:02:12 -0700342 return fVlans;
Jonathan Hartea750842015-04-23 17:44:49 -0700343 }
344
345 private static void verifyPorts(List<ConnectPoint> ports) {
346 DeviceId deviceId = ports.get(0).deviceId();
347 for (ConnectPoint connectPoint : ports) {
348 if (!connectPoint.deviceId().equals(deviceId)) {
349 throw new IllegalArgumentException("Ports must all be on the same device");
350 }
351 }
352 }
353
354 private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
355 List<PortNumber> outPorts) {
alshabibc4b5d462015-06-08 23:06:24 -0700356
Jonathan Hartea750842015-04-23 17:44:49 -0700357 TrafficSelector selector = DefaultTrafficSelector.builder()
358 .matchVlanId(vlanId)
359 .matchInPort(inPort)
360 .build();
361
362 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
363
364 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
365
366 ForwardingObjective objective = DefaultForwardingObjective.builder()
367 .fromApp(appId)
368 .makePermanent()
369 .withFlag(ForwardingObjective.Flag.VERSATILE)
370 .withPriority(PRIORITY)
371 .withSelector(selector)
372 .withTreatment(treatmentBuilder.build())
373 .add(new ObjectiveHandler());
374
375 flowObjectiveService.forward(deviceId, objective);
376 }
377
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700378 private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
379 List<PortNumber> outPorts) {
Jonathan Hartea750842015-04-23 17:44:49 -0700380 TrafficSelector selector = DefaultTrafficSelector.builder()
381 .matchVlanId(vlanId)
382 .matchInPort(inPort)
383 .build();
384
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700385 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
386
387 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
388
Jonathan Hartea750842015-04-23 17:44:49 -0700389 ForwardingObjective objective = DefaultForwardingObjective.builder()
390 .fromApp(appId)
391 .makePermanent()
392 .withFlag(ForwardingObjective.Flag.VERSATILE)
393 .withPriority(PRIORITY)
394 .withSelector(selector)
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700395 .withTreatment(treatmentBuilder.build())
Jonathan Hartea750842015-04-23 17:44:49 -0700396 .remove(new ObjectiveHandler());
397
398 flowObjectiveService.forward(deviceId, objective);
399 }
400
401 private static class ObjectiveHandler implements ObjectiveContext {
402 private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class);
403
404 @Override
405 public void onSuccess(Objective objective) {
406 log.info("Flow objective operation successful: {}", objective);
407 }
408
409 @Override
410 public void onError(Objective objective, ObjectiveError error) {
411 log.info("Flow objective operation failed: {}", objective);
412 }
413 }
Jonathan Hart408d24d2015-06-02 10:21:47 -0700414
415 /**
416 * Internal listener for device service events.
417 */
418 private class InternalDeviceListener implements DeviceListener {
419 @Override
420 public void event(DeviceEvent event) {
421 switch (event.type()) {
422 case DEVICE_ADDED:
423 case DEVICE_AVAILABILITY_CHANGED:
424 if (event.subject().id().equals(fabricDeviceId) &&
425 deviceService.isAvailable(event.subject().id())) {
426 setupDefaultFlows();
427 }
428 default:
429 break;
430 }
431 }
432 }
Jonathan Hartea750842015-04-23 17:44:49 -0700433}