blob: c8af1c1a58f523650f77c4355debeceadb9b5f0c [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;
Jonathan Hart0b989982015-05-14 15:40:07 -070084
alshabibc494f992015-05-15 09:51:54 -070085 private short radiusPort = 1812;
86
alshabib0603afb2015-06-05 14:10:33 -070087 private short ofPort = 6633;
88
Jonathan Hart0b989982015-05-14 15:40:07 -070089 private DeviceId fabricDeviceId = DeviceId.deviceId("of:5e3e486e73000187");
90
Jonathan Hartea750842015-04-23 17:44:49 -070091 private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create();
92
93 @Activate
94 public void activate() {
95 appId = coreService.registerApplication("org.onosproject.cordfabric");
96
Jonathan Hart408d24d2015-06-02 10:21:47 -070097 deviceService.addListener(deviceListener);
98
99 if (deviceService.isAvailable(fabricDeviceId)) {
100 setupDefaultFlows();
101 }
Jonathan Hart0b989982015-05-14 15:40:07 -0700102
Jonathan Hartea750842015-04-23 17:44:49 -0700103 log.info("Started");
104 }
105
106 @Deactivate
107 public void deactivate() {
Jonathan Hart408d24d2015-06-02 10:21:47 -0700108 deviceService.removeListener(deviceListener);
109
Jonathan Hartea750842015-04-23 17:44:49 -0700110 log.info("Stopped");
111 }
112
Jonathan Hart0b989982015-05-14 15:40:07 -0700113 private void setupDefaultFlows() {
alshabib0603afb2015-06-05 14:10:33 -0700114 TrafficSelector ofInBandMatchUp = DefaultTrafficSelector.builder()
115 .matchEthType(Ethernet.TYPE_IPV4)
116 .matchIPProtocol(IPv4.PROTOCOL_TCP)
117 .matchTcpDst(ofPort)
118 .matchInPort(PortNumber.portNumber(6))
119 .build();
120
121 TrafficSelector ofInBandMatchDown = DefaultTrafficSelector.builder()
122 .matchEthType(Ethernet.TYPE_IPV4)
123 .matchIPProtocol(IPv4.PROTOCOL_TCP)
124 .matchTcpSrc(ofPort)
alshabib48dd9a12015-06-05 14:45:57 -0700125 .matchInPort(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700126 .build();
127
Jonathan Hart64da69d2015-07-15 15:10:28 -0700128 TrafficSelector oltMgmtUp = DefaultTrafficSelector.builder()
129 .matchEthSrc(MacAddress.valueOf("00:0c:d5:00:01:01"))
130 .matchInPort(PortNumber.portNumber(2))
131 .build();
132
133 TrafficSelector oltMgmtDown = DefaultTrafficSelector.builder()
134 .matchEthDst(MacAddress.valueOf("00:0c:d5:00:01:01"))
135 .matchInPort(PortNumber.portNumber(9))
136 .build();
137
alshabib0603afb2015-06-05 14:10:33 -0700138 TrafficTreatment up = DefaultTrafficTreatment.builder()
alshabib48dd9a12015-06-05 14:45:57 -0700139 .setOutput(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700140 .build();
141
142 TrafficTreatment down = DefaultTrafficTreatment.builder()
143 .setOutput(PortNumber.portNumber(6))
144 .build();
145
146 TrafficSelector toRadius = DefaultTrafficSelector.builder()
alshabibaf734ff2015-07-01 16:35:26 -0700147 .matchInPort(PortNumber.portNumber(2))
Jonathan Hart0b989982015-05-14 15:40:07 -0700148 .matchEthType(Ethernet.TYPE_IPV4)
alshabibc494f992015-05-15 09:51:54 -0700149 .matchIPProtocol(IPv4.PROTOCOL_UDP)
150 .matchUdpDst(radiusPort)
151 .build();
152
alshabibaf734ff2015-07-01 16:35:26 -0700153 TrafficSelector fromRadius = DefaultTrafficSelector.builder()
154 .matchInPort(PortNumber.portNumber(5))
155 .matchEthType(Ethernet.TYPE_IPV4)
156 .matchIPProtocol(IPv4.PROTOCOL_UDP)
157 .matchUdpDst(radiusPort)
Jonathan Hart0b989982015-05-14 15:40:07 -0700158 .build();
159
alshabibaf734ff2015-07-01 16:35:26 -0700160 TrafficTreatment toOlt = DefaultTrafficTreatment.builder()
161 .setOutput(PortNumber.portNumber(2))
162 .build();
163
Jonathan Hart64da69d2015-07-15 15:10:28 -0700164 TrafficTreatment toVolt = DefaultTrafficTreatment.builder()
165 .setOutput(PortNumber.portNumber(9))
166 .build();
alshabibaf734ff2015-07-01 16:35:26 -0700167
168 TrafficTreatment sentToRadius = DefaultTrafficTreatment.builder()
169 .setOutput(PortNumber.portNumber(5))
170 .build();
171
172 ForwardingObjective radiusToServer = DefaultForwardingObjective.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700173 .fromApp(appId)
174 .makePermanent()
175 .withFlag(ForwardingObjective.Flag.VERSATILE)
176 .withPriority(PRIORITY)
alshabib0603afb2015-06-05 14:10:33 -0700177 .withSelector(toRadius)
alshabibaf734ff2015-07-01 16:35:26 -0700178 .withTreatment(sentToRadius)
Jonathan Hart0b989982015-05-14 15:40:07 -0700179 .add();
180
alshabibaf734ff2015-07-01 16:35:26 -0700181 ForwardingObjective serverToRadius = DefaultForwardingObjective.builder()
182 .fromApp(appId)
183 .makePermanent()
184 .withFlag(ForwardingObjective.Flag.VERSATILE)
185 .withPriority(PRIORITY)
186 .withSelector(fromRadius)
187 .withTreatment(toOlt)
188 .add();
189
190
191
alshabib0603afb2015-06-05 14:10:33 -0700192 ForwardingObjective upCtrl = DefaultForwardingObjective.builder()
193 .fromApp(appId)
194 .makePermanent()
195 .withFlag(ForwardingObjective.Flag.VERSATILE)
196 .withPriority(PRIORITY)
197 .withSelector(ofInBandMatchUp)
198 .withTreatment(up)
199 .add();
200
201 ForwardingObjective downCtrl = DefaultForwardingObjective.builder()
202 .fromApp(appId)
203 .makePermanent()
204 .withFlag(ForwardingObjective.Flag.VERSATILE)
205 .withPriority(PRIORITY)
206 .withSelector(ofInBandMatchDown)
207 .withTreatment(down)
208 .add();
209
Jonathan Hart64da69d2015-07-15 15:10:28 -0700210 ForwardingObjective upOltMgmt = DefaultForwardingObjective.builder()
211 .fromApp(appId)
212 .makePermanent()
213 .withFlag(ForwardingObjective.Flag.VERSATILE)
214 .withPriority(PRIORITY)
215 .withSelector(oltMgmtUp)
216 .withTreatment(toVolt)
217 .add();
218
219 ForwardingObjective downOltMgmt = DefaultForwardingObjective.builder()
220 .fromApp(appId)
221 .makePermanent()
222 .withFlag(ForwardingObjective.Flag.VERSATILE)
223 .withPriority(PRIORITY)
224 .withSelector(oltMgmtDown)
225 .withTreatment(toOlt)
226 .add();
alshabibc4b5d462015-06-08 23:06:24 -0700227
228
alshabib0603afb2015-06-05 14:10:33 -0700229 flowObjectiveService.forward(fabricDeviceId, upCtrl);
230 flowObjectiveService.forward(fabricDeviceId, downCtrl);
alshabibaf734ff2015-07-01 16:35:26 -0700231 flowObjectiveService.forward(fabricDeviceId, radiusToServer);
232 flowObjectiveService.forward(fabricDeviceId, serverToRadius);
Jonathan Hart64da69d2015-07-15 15:10:28 -0700233 flowObjectiveService.forward(fabricDeviceId, upOltMgmt);
234 flowObjectiveService.forward(fabricDeviceId, downOltMgmt);
Jonathan Hart0b989982015-05-14 15:40:07 -0700235 }
236
Jonathan Hartea750842015-04-23 17:44:49 -0700237 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700238 public void addVlan(FabricVlan vlan) {
239 checkNotNull(vlan);
240 checkArgument(vlan.ports().size() > 1);
241 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -0700242
Jonathan Hart443ebed2015-05-05 14:02:12 -0700243 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -0700244
alshabibc4b5d462015-06-08 23:06:24 -0700245 if (vlan.iptv()) {
246 provisionIPTV();
247 }
248
Jonathan Hart443ebed2015-05-05 14:02:12 -0700249 vlan.ports().forEach(cp -> {
250 if (vlans.put(vlan.vlan(), cp)) {
251 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
252 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -0700253 .filter(p -> p != cp)
254 .map(ConnectPoint::port)
255 .collect(Collectors.toList()));
256 }
257 });
258 }
259
alshabibc4b5d462015-06-08 23:06:24 -0700260 //FIXME: pass iptv vlan in here.
261 private void provisionIPTV() {
262 TrafficSelector ipTvUp = DefaultTrafficSelector.builder()
263 .matchVlanId(VlanId.vlanId((short) 7))
264 .matchInPort(PortNumber.portNumber(2))
265 .build();
266
267 TrafficTreatment ipTvActUp = DefaultTrafficTreatment.builder()
268 .setOutput(PortNumber.portNumber(7)).build();
269
270 TrafficSelector ipTvDown = DefaultTrafficSelector.builder()
271 .matchVlanId(VlanId.vlanId((short) 7))
272 .matchInPort(PortNumber.portNumber(7))
273 .build();
274
275 TrafficTreatment ipTvActDown = DefaultTrafficTreatment.builder()
276 .setOutput(PortNumber.portNumber(2)).build();
277
278 ForwardingObjective ipTvUpstream = DefaultForwardingObjective.builder()
279 .fromApp(appId)
280 .makePermanent()
281 .withFlag(ForwardingObjective.Flag.VERSATILE)
282 .withPriority(PRIORITY)
283 .withSelector(ipTvUp)
284 .withTreatment(ipTvActUp)
285 .add();
286
287 ForwardingObjective ipTvDownstream = DefaultForwardingObjective.builder()
288 .fromApp(appId)
289 .makePermanent()
290 .withFlag(ForwardingObjective.Flag.VERSATILE)
291 .withPriority(PRIORITY)
292 .withSelector(ipTvDown)
293 .withTreatment(ipTvActDown)
294 .add();
295
296 flowObjectiveService.forward(fabricDeviceId, ipTvUpstream);
297 flowObjectiveService.forward(fabricDeviceId, ipTvDownstream);
298 }
299
Jonathan Hartea750842015-04-23 17:44:49 -0700300 @Override
301 public void removeVlan(VlanId vlanId) {
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700302 Collection<ConnectPoint> ports = vlans.removeAll(vlanId);
303
304 ports.forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port(),
305 ports.stream()
306 .filter(p -> p != cp)
307 .map(ConnectPoint::port)
308 .collect(Collectors.toList())));
Jonathan Hartea750842015-04-23 17:44:49 -0700309 }
310
311 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700312 public List<FabricVlan> getVlans() {
313 List<FabricVlan> fVlans = new ArrayList<>();
314 vlans.keySet().forEach(vlan -> fVlans.add(
alshabibc4b5d462015-06-08 23:06:24 -0700315 //FIXME: Very aweful but will fo for now
316 new FabricVlan(vlan, vlans.get(vlan),
317 vlan.toShort() == 201 ? true : false)));
Jonathan Hart443ebed2015-05-05 14:02:12 -0700318 return fVlans;
Jonathan Hartea750842015-04-23 17:44:49 -0700319 }
320
321 private static void verifyPorts(List<ConnectPoint> ports) {
322 DeviceId deviceId = ports.get(0).deviceId();
323 for (ConnectPoint connectPoint : ports) {
324 if (!connectPoint.deviceId().equals(deviceId)) {
325 throw new IllegalArgumentException("Ports must all be on the same device");
326 }
327 }
328 }
329
330 private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
331 List<PortNumber> outPorts) {
alshabibc4b5d462015-06-08 23:06:24 -0700332
Jonathan Hartea750842015-04-23 17:44:49 -0700333 TrafficSelector selector = DefaultTrafficSelector.builder()
334 .matchVlanId(vlanId)
335 .matchInPort(inPort)
336 .build();
337
338 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
339
340 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
341
342 ForwardingObjective objective = DefaultForwardingObjective.builder()
343 .fromApp(appId)
344 .makePermanent()
345 .withFlag(ForwardingObjective.Flag.VERSATILE)
346 .withPriority(PRIORITY)
347 .withSelector(selector)
348 .withTreatment(treatmentBuilder.build())
349 .add(new ObjectiveHandler());
350
351 flowObjectiveService.forward(deviceId, objective);
352 }
353
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700354 private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
355 List<PortNumber> outPorts) {
Jonathan Hartea750842015-04-23 17:44:49 -0700356 TrafficSelector selector = DefaultTrafficSelector.builder()
357 .matchVlanId(vlanId)
358 .matchInPort(inPort)
359 .build();
360
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700361 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
362
363 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
364
Jonathan Hartea750842015-04-23 17:44:49 -0700365 ForwardingObjective objective = DefaultForwardingObjective.builder()
366 .fromApp(appId)
367 .makePermanent()
368 .withFlag(ForwardingObjective.Flag.VERSATILE)
369 .withPriority(PRIORITY)
370 .withSelector(selector)
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700371 .withTreatment(treatmentBuilder.build())
Jonathan Hartea750842015-04-23 17:44:49 -0700372 .remove(new ObjectiveHandler());
373
374 flowObjectiveService.forward(deviceId, objective);
375 }
376
377 private static class ObjectiveHandler implements ObjectiveContext {
378 private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class);
379
380 @Override
381 public void onSuccess(Objective objective) {
382 log.info("Flow objective operation successful: {}", objective);
383 }
384
385 @Override
386 public void onError(Objective objective, ObjectiveError error) {
387 log.info("Flow objective operation failed: {}", objective);
388 }
389 }
Jonathan Hart408d24d2015-06-02 10:21:47 -0700390
391 /**
392 * Internal listener for device service events.
393 */
394 private class InternalDeviceListener implements DeviceListener {
395 @Override
396 public void event(DeviceEvent event) {
397 switch (event.type()) {
398 case DEVICE_ADDED:
399 case DEVICE_AVAILABILITY_CHANGED:
400 if (event.subject().id().equals(fabricDeviceId) &&
401 deviceService.isAvailable(event.subject().id())) {
402 setupDefaultFlows();
403 }
404 default:
405 break;
406 }
407 }
408 }
Jonathan Hartea750842015-04-23 17:44:49 -0700409}