blob: 4549bd0978aebc61ce1eea98374b4871fc7166d1 [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 Hartea750842015-04-23 17:44:49 -070029import org.onlab.packet.VlanId;
30import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
32import org.onosproject.net.ConnectPoint;
33import org.onosproject.net.DeviceId;
34import org.onosproject.net.PortNumber;
Jonathan Hart408d24d2015-06-02 10:21:47 -070035import org.onosproject.net.device.DeviceEvent;
36import org.onosproject.net.device.DeviceListener;
37import org.onosproject.net.device.DeviceService;
Jonathan Hartea750842015-04-23 17:44:49 -070038import org.onosproject.net.flow.DefaultTrafficSelector;
39import org.onosproject.net.flow.DefaultTrafficTreatment;
40import org.onosproject.net.flow.TrafficSelector;
41import org.onosproject.net.flow.TrafficTreatment;
42import org.onosproject.net.flowobjective.DefaultForwardingObjective;
43import org.onosproject.net.flowobjective.FlowObjectiveService;
44import org.onosproject.net.flowobjective.ForwardingObjective;
45import org.onosproject.net.flowobjective.Objective;
46import org.onosproject.net.flowobjective.ObjectiveContext;
47import org.onosproject.net.flowobjective.ObjectiveError;
48import org.slf4j.Logger;
49import org.slf4j.LoggerFactory;
50
Jonathan Hart443ebed2015-05-05 14:02:12 -070051import java.util.ArrayList;
Jonathan Hartab8b0c02015-06-10 14:06:51 -070052import java.util.Collection;
Jonathan Hartea750842015-04-23 17:44:49 -070053import java.util.List;
54import java.util.stream.Collectors;
55
56import static com.google.common.base.Preconditions.checkArgument;
57import static com.google.common.base.Preconditions.checkNotNull;
58import static org.slf4j.LoggerFactory.getLogger;
59
60/**
61 * CORD fabric application.
62 */
63@Service
64@Component(immediate = true)
65public class CordFabricManager implements FabricService {
66
67 private final Logger log = getLogger(getClass());
68
69 private ApplicationId appId;
70
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected CoreService coreService;
73
74 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected FlowObjectiveService flowObjectiveService;
76
Jonathan Hart408d24d2015-06-02 10:21:47 -070077 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 protected DeviceService deviceService;
Jonathan Hartea750842015-04-23 17:44:49 -070079
Jonathan Hart408d24d2015-06-02 10:21:47 -070080 private InternalDeviceListener deviceListener = new InternalDeviceListener();
81
82 private static final int PRIORITY = 50000;
Jonathan Hart0b989982015-05-14 15:40:07 -070083
alshabibc494f992015-05-15 09:51:54 -070084 private short radiusPort = 1812;
85
alshabib0603afb2015-06-05 14:10:33 -070086 private short ofPort = 6633;
87
Jonathan Hart0b989982015-05-14 15:40:07 -070088 private DeviceId fabricDeviceId = DeviceId.deviceId("of:5e3e486e73000187");
89
Jonathan Hartea750842015-04-23 17:44:49 -070090 private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create();
91
92 @Activate
93 public void activate() {
94 appId = coreService.registerApplication("org.onosproject.cordfabric");
95
Jonathan Hart408d24d2015-06-02 10:21:47 -070096 deviceService.addListener(deviceListener);
97
98 if (deviceService.isAvailable(fabricDeviceId)) {
99 setupDefaultFlows();
100 }
Jonathan Hart0b989982015-05-14 15:40:07 -0700101
Jonathan Hartea750842015-04-23 17:44:49 -0700102 log.info("Started");
103 }
104
105 @Deactivate
106 public void deactivate() {
Jonathan Hart408d24d2015-06-02 10:21:47 -0700107 deviceService.removeListener(deviceListener);
108
Jonathan Hartea750842015-04-23 17:44:49 -0700109 log.info("Stopped");
110 }
111
Jonathan Hart0b989982015-05-14 15:40:07 -0700112 private void setupDefaultFlows() {
alshabib0603afb2015-06-05 14:10:33 -0700113 TrafficSelector ofInBandMatchUp = DefaultTrafficSelector.builder()
114 .matchEthType(Ethernet.TYPE_IPV4)
115 .matchIPProtocol(IPv4.PROTOCOL_TCP)
116 .matchTcpDst(ofPort)
117 .matchInPort(PortNumber.portNumber(6))
118 .build();
119
120 TrafficSelector ofInBandMatchDown = DefaultTrafficSelector.builder()
121 .matchEthType(Ethernet.TYPE_IPV4)
122 .matchIPProtocol(IPv4.PROTOCOL_TCP)
123 .matchTcpSrc(ofPort)
alshabib48dd9a12015-06-05 14:45:57 -0700124 .matchInPort(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700125 .build();
126
127 TrafficTreatment up = DefaultTrafficTreatment.builder()
alshabib48dd9a12015-06-05 14:45:57 -0700128 .setOutput(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700129 .build();
130
131 TrafficTreatment down = DefaultTrafficTreatment.builder()
132 .setOutput(PortNumber.portNumber(6))
133 .build();
134
135 TrafficSelector toRadius = DefaultTrafficSelector.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700136 .matchEthType(Ethernet.TYPE_IPV4)
alshabibc494f992015-05-15 09:51:54 -0700137 .matchIPProtocol(IPv4.PROTOCOL_UDP)
138 .matchUdpDst(radiusPort)
139 .build();
140
alshabib0603afb2015-06-05 14:10:33 -0700141 TrafficTreatment puntToController = DefaultTrafficTreatment.builder()
alshabib51ca37f2015-05-30 18:31:47 -0700142 .punt()
Jonathan Hart0b989982015-05-14 15:40:07 -0700143 .build();
144
alshabib0603afb2015-06-05 14:10:33 -0700145 ForwardingObjective radiusToController = DefaultForwardingObjective.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700146 .fromApp(appId)
147 .makePermanent()
148 .withFlag(ForwardingObjective.Flag.VERSATILE)
149 .withPriority(PRIORITY)
alshabib0603afb2015-06-05 14:10:33 -0700150 .withSelector(toRadius)
151 .withTreatment(puntToController)
Jonathan Hart0b989982015-05-14 15:40:07 -0700152 .add();
153
alshabib0603afb2015-06-05 14:10:33 -0700154 ForwardingObjective upCtrl = DefaultForwardingObjective.builder()
155 .fromApp(appId)
156 .makePermanent()
157 .withFlag(ForwardingObjective.Flag.VERSATILE)
158 .withPriority(PRIORITY)
159 .withSelector(ofInBandMatchUp)
160 .withTreatment(up)
161 .add();
162
163 ForwardingObjective downCtrl = DefaultForwardingObjective.builder()
164 .fromApp(appId)
165 .makePermanent()
166 .withFlag(ForwardingObjective.Flag.VERSATILE)
167 .withPriority(PRIORITY)
168 .withSelector(ofInBandMatchDown)
169 .withTreatment(down)
170 .add();
171
alshabibc4b5d462015-06-08 23:06:24 -0700172
173
alshabib0603afb2015-06-05 14:10:33 -0700174 flowObjectiveService.forward(fabricDeviceId, upCtrl);
175 flowObjectiveService.forward(fabricDeviceId, downCtrl);
176 flowObjectiveService.forward(fabricDeviceId, radiusToController);
Jonathan Hart0b989982015-05-14 15:40:07 -0700177 }
178
Jonathan Hartea750842015-04-23 17:44:49 -0700179 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700180 public void addVlan(FabricVlan vlan) {
181 checkNotNull(vlan);
182 checkArgument(vlan.ports().size() > 1);
183 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -0700184
Jonathan Hart443ebed2015-05-05 14:02:12 -0700185 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -0700186
alshabibc4b5d462015-06-08 23:06:24 -0700187 if (vlan.iptv()) {
188 provisionIPTV();
189 }
190
Jonathan Hart443ebed2015-05-05 14:02:12 -0700191 vlan.ports().forEach(cp -> {
192 if (vlans.put(vlan.vlan(), cp)) {
193 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
194 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -0700195 .filter(p -> p != cp)
196 .map(ConnectPoint::port)
197 .collect(Collectors.toList()));
198 }
199 });
200 }
201
alshabibc4b5d462015-06-08 23:06:24 -0700202 //FIXME: pass iptv vlan in here.
203 private void provisionIPTV() {
204 TrafficSelector ipTvUp = DefaultTrafficSelector.builder()
205 .matchVlanId(VlanId.vlanId((short) 7))
206 .matchInPort(PortNumber.portNumber(2))
207 .build();
208
209 TrafficTreatment ipTvActUp = DefaultTrafficTreatment.builder()
210 .setOutput(PortNumber.portNumber(7)).build();
211
212 TrafficSelector ipTvDown = DefaultTrafficSelector.builder()
213 .matchVlanId(VlanId.vlanId((short) 7))
214 .matchInPort(PortNumber.portNumber(7))
215 .build();
216
217 TrafficTreatment ipTvActDown = DefaultTrafficTreatment.builder()
218 .setOutput(PortNumber.portNumber(2)).build();
219
220 ForwardingObjective ipTvUpstream = DefaultForwardingObjective.builder()
221 .fromApp(appId)
222 .makePermanent()
223 .withFlag(ForwardingObjective.Flag.VERSATILE)
224 .withPriority(PRIORITY)
225 .withSelector(ipTvUp)
226 .withTreatment(ipTvActUp)
227 .add();
228
229 ForwardingObjective ipTvDownstream = DefaultForwardingObjective.builder()
230 .fromApp(appId)
231 .makePermanent()
232 .withFlag(ForwardingObjective.Flag.VERSATILE)
233 .withPriority(PRIORITY)
234 .withSelector(ipTvDown)
235 .withTreatment(ipTvActDown)
236 .add();
237
238 flowObjectiveService.forward(fabricDeviceId, ipTvUpstream);
239 flowObjectiveService.forward(fabricDeviceId, ipTvDownstream);
240 }
241
Jonathan Hartea750842015-04-23 17:44:49 -0700242 @Override
243 public void removeVlan(VlanId vlanId) {
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700244 Collection<ConnectPoint> ports = vlans.removeAll(vlanId);
245
246 ports.forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port(),
247 ports.stream()
248 .filter(p -> p != cp)
249 .map(ConnectPoint::port)
250 .collect(Collectors.toList())));
Jonathan Hartea750842015-04-23 17:44:49 -0700251 }
252
253 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700254 public List<FabricVlan> getVlans() {
255 List<FabricVlan> fVlans = new ArrayList<>();
256 vlans.keySet().forEach(vlan -> fVlans.add(
alshabibc4b5d462015-06-08 23:06:24 -0700257 //FIXME: Very aweful but will fo for now
258 new FabricVlan(vlan, vlans.get(vlan),
259 vlan.toShort() == 201 ? true : false)));
Jonathan Hart443ebed2015-05-05 14:02:12 -0700260 return fVlans;
Jonathan Hartea750842015-04-23 17:44:49 -0700261 }
262
263 private static void verifyPorts(List<ConnectPoint> ports) {
264 DeviceId deviceId = ports.get(0).deviceId();
265 for (ConnectPoint connectPoint : ports) {
266 if (!connectPoint.deviceId().equals(deviceId)) {
267 throw new IllegalArgumentException("Ports must all be on the same device");
268 }
269 }
270 }
271
272 private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
273 List<PortNumber> outPorts) {
alshabibc4b5d462015-06-08 23:06:24 -0700274
Jonathan Hartea750842015-04-23 17:44:49 -0700275 TrafficSelector selector = DefaultTrafficSelector.builder()
276 .matchVlanId(vlanId)
277 .matchInPort(inPort)
278 .build();
279
280 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
281
282 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
283
284 ForwardingObjective objective = DefaultForwardingObjective.builder()
285 .fromApp(appId)
286 .makePermanent()
287 .withFlag(ForwardingObjective.Flag.VERSATILE)
288 .withPriority(PRIORITY)
289 .withSelector(selector)
290 .withTreatment(treatmentBuilder.build())
291 .add(new ObjectiveHandler());
292
293 flowObjectiveService.forward(deviceId, objective);
294 }
295
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700296 private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
297 List<PortNumber> outPorts) {
Jonathan Hartea750842015-04-23 17:44:49 -0700298 TrafficSelector selector = DefaultTrafficSelector.builder()
299 .matchVlanId(vlanId)
300 .matchInPort(inPort)
301 .build();
302
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700303 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
304
305 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
306
Jonathan Hartea750842015-04-23 17:44:49 -0700307 ForwardingObjective objective = DefaultForwardingObjective.builder()
308 .fromApp(appId)
309 .makePermanent()
310 .withFlag(ForwardingObjective.Flag.VERSATILE)
311 .withPriority(PRIORITY)
312 .withSelector(selector)
Jonathan Hartab8b0c02015-06-10 14:06:51 -0700313 .withTreatment(treatmentBuilder.build())
Jonathan Hartea750842015-04-23 17:44:49 -0700314 .remove(new ObjectiveHandler());
315
316 flowObjectiveService.forward(deviceId, objective);
317 }
318
319 private static class ObjectiveHandler implements ObjectiveContext {
320 private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class);
321
322 @Override
323 public void onSuccess(Objective objective) {
324 log.info("Flow objective operation successful: {}", objective);
325 }
326
327 @Override
328 public void onError(Objective objective, ObjectiveError error) {
329 log.info("Flow objective operation failed: {}", objective);
330 }
331 }
Jonathan Hart408d24d2015-06-02 10:21:47 -0700332
333 /**
334 * Internal listener for device service events.
335 */
336 private class InternalDeviceListener implements DeviceListener {
337 @Override
338 public void event(DeviceEvent event) {
339 switch (event.type()) {
340 case DEVICE_ADDED:
341 case DEVICE_AVAILABILITY_CHANGED:
342 if (event.subject().id().equals(fabricDeviceId) &&
343 deviceService.isAvailable(event.subject().id())) {
344 setupDefaultFlows();
345 }
346 default:
347 break;
348 }
349 }
350 }
Jonathan Hartea750842015-04-23 17:44:49 -0700351}