blob: 690a3581d9af1731ea2dc1e30744a63896829fac [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;
Hyunsun Mooncf732fb2015-08-22 21:04:23 -070030import org.onlab.packet.TpPort;
Jonathan Hartea750842015-04-23 17:44:49 -070031import org.onlab.packet.VlanId;
32import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreService;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.PortNumber;
Jonathan Hart408d24d2015-06-02 10:21:47 -070037import org.onosproject.net.device.DeviceEvent;
38import org.onosproject.net.device.DeviceListener;
39import org.onosproject.net.device.DeviceService;
Jonathan Hartea750842015-04-23 17:44:49 -070040import org.onosproject.net.flow.DefaultTrafficSelector;
41import org.onosproject.net.flow.DefaultTrafficTreatment;
42import org.onosproject.net.flow.TrafficSelector;
43import org.onosproject.net.flow.TrafficTreatment;
44import org.onosproject.net.flowobjective.DefaultForwardingObjective;
45import org.onosproject.net.flowobjective.FlowObjectiveService;
46import org.onosproject.net.flowobjective.ForwardingObjective;
47import org.onosproject.net.flowobjective.Objective;
48import org.onosproject.net.flowobjective.ObjectiveContext;
49import org.onosproject.net.flowobjective.ObjectiveError;
50import org.slf4j.Logger;
51import org.slf4j.LoggerFactory;
52
Jonathan Hart443ebed2015-05-05 14:02:12 -070053import java.util.ArrayList;
Jonathan Hartab8b0c02015-06-10 14:06:51 -070054import java.util.Collection;
Jonathan Hartea750842015-04-23 17:44:49 -070055import java.util.List;
56import java.util.stream.Collectors;
57
58import static com.google.common.base.Preconditions.checkArgument;
59import static com.google.common.base.Preconditions.checkNotNull;
60import static org.slf4j.LoggerFactory.getLogger;
61
62/**
63 * CORD fabric application.
64 */
65@Service
66@Component(immediate = true)
67public class CordFabricManager implements FabricService {
68
69 private final Logger log = getLogger(getClass());
70
71 private ApplicationId appId;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected CoreService coreService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected FlowObjectiveService flowObjectiveService;
78
Jonathan Hart408d24d2015-06-02 10:21:47 -070079 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected DeviceService deviceService;
Jonathan Hartea750842015-04-23 17:44:49 -070081
Jonathan Hart408d24d2015-06-02 10:21:47 -070082 private InternalDeviceListener deviceListener = new InternalDeviceListener();
83
84 private static final int PRIORITY = 50000;
alshabibe9532ab2015-08-05 10:50:30 -070085 private static final int TESTPRIO = 49999;
Jonathan Hart0b989982015-05-14 15:40:07 -070086
alshabibc494f992015-05-15 09:51:54 -070087 private short radiusPort = 1812;
88
Charles Chan45624b82015-08-24 00:29:20 +080089 private short ofPort = 6653;
alshabib0603afb2015-06-05 14:10:33 -070090
Jonathan Hart0b989982015-05-14 15:40:07 -070091 private DeviceId fabricDeviceId = DeviceId.deviceId("of:5e3e486e73000187");
92
Jonathan Hartea750842015-04-23 17:44:49 -070093 private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create();
94
alshabibe9532ab2015-08-05 10:50:30 -070095 //TODO make this configurable
96 private boolean testMode = true;
97
98
Jonathan Hartea750842015-04-23 17:44:49 -070099 @Activate
100 public void activate() {
101 appId = coreService.registerApplication("org.onosproject.cordfabric");
102
Jonathan Hart408d24d2015-06-02 10:21:47 -0700103 deviceService.addListener(deviceListener);
104
105 if (deviceService.isAvailable(fabricDeviceId)) {
106 setupDefaultFlows();
107 }
Jonathan Hart0b989982015-05-14 15:40:07 -0700108
Jonathan Hartea750842015-04-23 17:44:49 -0700109 log.info("Started");
110 }
111
112 @Deactivate
113 public void deactivate() {
Jonathan Hart408d24d2015-06-02 10:21:47 -0700114 deviceService.removeListener(deviceListener);
115
Jonathan Hartea750842015-04-23 17:44:49 -0700116 log.info("Stopped");
117 }
118
Jonathan Hart0b989982015-05-14 15:40:07 -0700119 private void setupDefaultFlows() {
alshabib0603afb2015-06-05 14:10:33 -0700120 TrafficSelector ofInBandMatchUp = DefaultTrafficSelector.builder()
121 .matchEthType(Ethernet.TYPE_IPV4)
122 .matchIPProtocol(IPv4.PROTOCOL_TCP)
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700123 .matchTcpDst(TpPort.tpPort(ofPort))
alshabib0603afb2015-06-05 14:10:33 -0700124 .matchInPort(PortNumber.portNumber(6))
125 .build();
126
127 TrafficSelector ofInBandMatchDown = DefaultTrafficSelector.builder()
128 .matchEthType(Ethernet.TYPE_IPV4)
129 .matchIPProtocol(IPv4.PROTOCOL_TCP)
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700130 .matchTcpSrc(TpPort.tpPort(ofPort))
alshabib48dd9a12015-06-05 14:45:57 -0700131 .matchInPort(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700132 .build();
133
Jonathan Hart64da69d2015-07-15 15:10:28 -0700134 TrafficSelector oltMgmtUp = DefaultTrafficSelector.builder()
135 .matchEthSrc(MacAddress.valueOf("00:0c:d5:00:01:01"))
136 .matchInPort(PortNumber.portNumber(2))
137 .build();
138
139 TrafficSelector oltMgmtDown = DefaultTrafficSelector.builder()
140 .matchEthDst(MacAddress.valueOf("00:0c:d5:00:01:01"))
141 .matchInPort(PortNumber.portNumber(9))
142 .build();
143
alshabib0603afb2015-06-05 14:10:33 -0700144 TrafficTreatment up = DefaultTrafficTreatment.builder()
alshabib48dd9a12015-06-05 14:45:57 -0700145 .setOutput(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700146 .build();
147
148 TrafficTreatment down = DefaultTrafficTreatment.builder()
149 .setOutput(PortNumber.portNumber(6))
150 .build();
151
152 TrafficSelector toRadius = DefaultTrafficSelector.builder()
alshabibaf734ff2015-07-01 16:35:26 -0700153 .matchInPort(PortNumber.portNumber(2))
Jonathan Hart0b989982015-05-14 15:40:07 -0700154 .matchEthType(Ethernet.TYPE_IPV4)
alshabibc494f992015-05-15 09:51:54 -0700155 .matchIPProtocol(IPv4.PROTOCOL_UDP)
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700156 .matchUdpDst(TpPort.tpPort(radiusPort))
alshabibc494f992015-05-15 09:51:54 -0700157 .build();
158
alshabibaf734ff2015-07-01 16:35:26 -0700159 TrafficSelector fromRadius = DefaultTrafficSelector.builder()
160 .matchInPort(PortNumber.portNumber(5))
161 .matchEthType(Ethernet.TYPE_IPV4)
162 .matchIPProtocol(IPv4.PROTOCOL_UDP)
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700163 .matchUdpDst(TpPort.tpPort(radiusPort))
Jonathan Hart0b989982015-05-14 15:40:07 -0700164 .build();
165
alshabibaf734ff2015-07-01 16:35:26 -0700166 TrafficTreatment toOlt = DefaultTrafficTreatment.builder()
167 .setOutput(PortNumber.portNumber(2))
168 .build();
169
Jonathan Hart64da69d2015-07-15 15:10:28 -0700170 TrafficTreatment toVolt = DefaultTrafficTreatment.builder()
171 .setOutput(PortNumber.portNumber(9))
172 .build();
alshabibaf734ff2015-07-01 16:35:26 -0700173
174 TrafficTreatment sentToRadius = DefaultTrafficTreatment.builder()
175 .setOutput(PortNumber.portNumber(5))
176 .build();
177
alshabibe9532ab2015-08-05 10:50:30 -0700178 TrafficTreatment testPort = DefaultTrafficTreatment.builder()
179 .setOutput(PortNumber.portNumber(8))
180 .build();
181
182 ForwardingObjective ofTestPath = DefaultForwardingObjective.builder()
183 .fromApp(appId)
184 .makePermanent()
185 .withFlag(ForwardingObjective.Flag.VERSATILE)
186 .withPriority(TESTPRIO)
187 .withSelector(
188 DefaultTrafficSelector.builder()
189 .matchInPort(PortNumber.portNumber(2))
190 .build())
191 .withTreatment(testPort)
192 .add();
193
alshabibaf734ff2015-07-01 16:35:26 -0700194 ForwardingObjective radiusToServer = DefaultForwardingObjective.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700195 .fromApp(appId)
196 .makePermanent()
197 .withFlag(ForwardingObjective.Flag.VERSATILE)
198 .withPriority(PRIORITY)
alshabib0603afb2015-06-05 14:10:33 -0700199 .withSelector(toRadius)
alshabibaf734ff2015-07-01 16:35:26 -0700200 .withTreatment(sentToRadius)
Jonathan Hart0b989982015-05-14 15:40:07 -0700201 .add();
202
alshabibaf734ff2015-07-01 16:35:26 -0700203 ForwardingObjective serverToRadius = DefaultForwardingObjective.builder()
204 .fromApp(appId)
205 .makePermanent()
206 .withFlag(ForwardingObjective.Flag.VERSATILE)
207 .withPriority(PRIORITY)
208 .withSelector(fromRadius)
209 .withTreatment(toOlt)
210 .add();
211
212
213
alshabib0603afb2015-06-05 14:10:33 -0700214 ForwardingObjective upCtrl = DefaultForwardingObjective.builder()
215 .fromApp(appId)
216 .makePermanent()
217 .withFlag(ForwardingObjective.Flag.VERSATILE)
218 .withPriority(PRIORITY)
219 .withSelector(ofInBandMatchUp)
220 .withTreatment(up)
221 .add();
222
223 ForwardingObjective downCtrl = DefaultForwardingObjective.builder()
224 .fromApp(appId)
225 .makePermanent()
226 .withFlag(ForwardingObjective.Flag.VERSATILE)
227 .withPriority(PRIORITY)
228 .withSelector(ofInBandMatchDown)
229 .withTreatment(down)
230 .add();
231
Jonathan Hart64da69d2015-07-15 15:10:28 -0700232 ForwardingObjective upOltMgmt = DefaultForwardingObjective.builder()
233 .fromApp(appId)
234 .makePermanent()
235 .withFlag(ForwardingObjective.Flag.VERSATILE)
236 .withPriority(PRIORITY)
237 .withSelector(oltMgmtUp)
238 .withTreatment(toVolt)
239 .add();
240
241 ForwardingObjective downOltMgmt = DefaultForwardingObjective.builder()
242 .fromApp(appId)
243 .makePermanent()
244 .withFlag(ForwardingObjective.Flag.VERSATILE)
245 .withPriority(PRIORITY)
246 .withSelector(oltMgmtDown)
247 .withTreatment(toOlt)
248 .add();
alshabibc4b5d462015-06-08 23:06:24 -0700249
alshabibe9532ab2015-08-05 10:50:30 -0700250 if (testMode) {
251 flowObjectiveService.forward(fabricDeviceId, ofTestPath);
252 }
alshabibc4b5d462015-06-08 23:06:24 -0700253
alshabib0603afb2015-06-05 14:10:33 -0700254 flowObjectiveService.forward(fabricDeviceId, upCtrl);
255 flowObjectiveService.forward(fabricDeviceId, downCtrl);
alshabibaf734ff2015-07-01 16:35:26 -0700256 flowObjectiveService.forward(fabricDeviceId, radiusToServer);
257 flowObjectiveService.forward(fabricDeviceId, serverToRadius);
Jonathan Hart64da69d2015-07-15 15:10:28 -0700258 flowObjectiveService.forward(fabricDeviceId, upOltMgmt);
259 flowObjectiveService.forward(fabricDeviceId, downOltMgmt);
Jonathan Hart0b989982015-05-14 15:40:07 -0700260 }
261
Jonathan Hartea750842015-04-23 17:44:49 -0700262 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700263 public void addVlan(FabricVlan vlan) {
264 checkNotNull(vlan);
265 checkArgument(vlan.ports().size() > 1);
266 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -0700267
Jonathan Hart443ebed2015-05-05 14:02:12 -0700268 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -0700269
alshabibc4b5d462015-06-08 23:06:24 -0700270 if (vlan.iptv()) {
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800271 provisionIpTv();
alshabibc4b5d462015-06-08 23:06:24 -0700272 }
273
Jonathan Hart443ebed2015-05-05 14:02:12 -0700274 vlan.ports().forEach(cp -> {
275 if (vlans.put(vlan.vlan(), cp)) {
276 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
277 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -0700278 .filter(p -> p != cp)
279 .map(ConnectPoint::port)
280 .collect(Collectors.toList()));
281 }
282 });
283 }
284
alshabibc4b5d462015-06-08 23:06:24 -0700285 //FIXME: pass iptv vlan in here.
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800286 private void provisionIpTv() {
alshabibc4b5d462015-06-08 23:06:24 -0700287 TrafficSelector ipTvUp = DefaultTrafficSelector.builder()
288 .matchVlanId(VlanId.vlanId((short) 7))
289 .matchInPort(PortNumber.portNumber(2))
290 .build();
291
292 TrafficTreatment ipTvActUp = DefaultTrafficTreatment.builder()
293 .setOutput(PortNumber.portNumber(7)).build();
294
295 TrafficSelector ipTvDown = DefaultTrafficSelector.builder()
296 .matchVlanId(VlanId.vlanId((short) 7))
297 .matchInPort(PortNumber.portNumber(7))
298 .build();
299
300 TrafficTreatment ipTvActDown = DefaultTrafficTreatment.builder()
301 .setOutput(PortNumber.portNumber(2)).build();
302
303 ForwardingObjective ipTvUpstream = DefaultForwardingObjective.builder()
304 .fromApp(appId)
305 .makePermanent()
306 .withFlag(ForwardingObjective.Flag.VERSATILE)
307 .withPriority(PRIORITY)
308 .withSelector(ipTvUp)
309 .withTreatment(ipTvActUp)
310 .add();
311
312 ForwardingObjective ipTvDownstream = DefaultForwardingObjective.builder()
313 .fromApp(appId)
314 .makePermanent()
315 .withFlag(ForwardingObjective.Flag.VERSATILE)
316 .withPriority(PRIORITY)
317 .withSelector(ipTvDown)
318 .withTreatment(ipTvActDown)
319 .add();
320
321 flowObjectiveService.forward(fabricDeviceId, ipTvUpstream);
322 flowObjectiveService.forward(fabricDeviceId, ipTvDownstream);
323 }
324
Jonathan Hartea750842015-04-23 17:44:49 -0700325 @Override
326 public void removeVlan(VlanId vlanId) {
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700327 Collection<ConnectPoint> ports = vlans.removeAll(vlanId);
328
329 ports.forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port(),
330 ports.stream()
331 .filter(p -> p != cp)
332 .map(ConnectPoint::port)
333 .collect(Collectors.toList())));
Jonathan Hartea750842015-04-23 17:44:49 -0700334 }
335
336 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700337 public List<FabricVlan> getVlans() {
338 List<FabricVlan> fVlans = new ArrayList<>();
339 vlans.keySet().forEach(vlan -> fVlans.add(
alshabibc4b5d462015-06-08 23:06:24 -0700340 //FIXME: Very aweful but will fo for now
Sho SHIMIZU7a4e9952015-09-02 18:22:59 -0700341 new FabricVlan(vlan, vlans.get(vlan), vlan.toShort() == 201)));
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}