blob: ab31aeea35c2252afe17a57e51eab2a1f0977465 [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 Hartea750842015-04-23 17:44:49 -070052import java.util.List;
53import java.util.stream.Collectors;
54
55import static com.google.common.base.Preconditions.checkArgument;
56import static com.google.common.base.Preconditions.checkNotNull;
57import static org.slf4j.LoggerFactory.getLogger;
58
59/**
60 * CORD fabric application.
61 */
62@Service
63@Component(immediate = true)
64public class CordFabricManager implements FabricService {
65
66 private final Logger log = getLogger(getClass());
67
68 private ApplicationId appId;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected CoreService coreService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected FlowObjectiveService flowObjectiveService;
75
Jonathan Hart408d24d2015-06-02 10:21:47 -070076 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected DeviceService deviceService;
Jonathan Hartea750842015-04-23 17:44:49 -070078
Jonathan Hart408d24d2015-06-02 10:21:47 -070079 private InternalDeviceListener deviceListener = new InternalDeviceListener();
80
81 private static final int PRIORITY = 50000;
Jonathan Hart0b989982015-05-14 15:40:07 -070082
alshabibc494f992015-05-15 09:51:54 -070083 private short radiusPort = 1812;
84
alshabib0603afb2015-06-05 14:10:33 -070085 private short ofPort = 6633;
86
Jonathan Hart0b989982015-05-14 15:40:07 -070087 private DeviceId fabricDeviceId = DeviceId.deviceId("of:5e3e486e73000187");
88
Jonathan Hartea750842015-04-23 17:44:49 -070089 private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create();
90
91 @Activate
92 public void activate() {
93 appId = coreService.registerApplication("org.onosproject.cordfabric");
94
Jonathan Hart408d24d2015-06-02 10:21:47 -070095 deviceService.addListener(deviceListener);
96
97 if (deviceService.isAvailable(fabricDeviceId)) {
98 setupDefaultFlows();
99 }
Jonathan Hart0b989982015-05-14 15:40:07 -0700100
Jonathan Hartea750842015-04-23 17:44:49 -0700101 log.info("Started");
102 }
103
104 @Deactivate
105 public void deactivate() {
Jonathan Hart408d24d2015-06-02 10:21:47 -0700106 deviceService.removeListener(deviceListener);
107
Jonathan Hartea750842015-04-23 17:44:49 -0700108 log.info("Stopped");
109 }
110
Jonathan Hart0b989982015-05-14 15:40:07 -0700111 private void setupDefaultFlows() {
alshabib0603afb2015-06-05 14:10:33 -0700112 TrafficSelector ofInBandMatchUp = DefaultTrafficSelector.builder()
113 .matchEthType(Ethernet.TYPE_IPV4)
114 .matchIPProtocol(IPv4.PROTOCOL_TCP)
115 .matchTcpDst(ofPort)
116 .matchInPort(PortNumber.portNumber(6))
117 .build();
118
119 TrafficSelector ofInBandMatchDown = DefaultTrafficSelector.builder()
120 .matchEthType(Ethernet.TYPE_IPV4)
121 .matchIPProtocol(IPv4.PROTOCOL_TCP)
122 .matchTcpSrc(ofPort)
alshabib48dd9a12015-06-05 14:45:57 -0700123 .matchInPort(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700124 .build();
125
126 TrafficTreatment up = DefaultTrafficTreatment.builder()
alshabib48dd9a12015-06-05 14:45:57 -0700127 .setOutput(PortNumber.portNumber(1))
alshabib0603afb2015-06-05 14:10:33 -0700128 .build();
129
130 TrafficTreatment down = DefaultTrafficTreatment.builder()
131 .setOutput(PortNumber.portNumber(6))
132 .build();
133
134 TrafficSelector toRadius = DefaultTrafficSelector.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700135 .matchEthType(Ethernet.TYPE_IPV4)
alshabibc494f992015-05-15 09:51:54 -0700136 .matchIPProtocol(IPv4.PROTOCOL_UDP)
137 .matchUdpDst(radiusPort)
138 .build();
139
alshabib0603afb2015-06-05 14:10:33 -0700140 TrafficTreatment puntToController = DefaultTrafficTreatment.builder()
alshabib51ca37f2015-05-30 18:31:47 -0700141 .punt()
Jonathan Hart0b989982015-05-14 15:40:07 -0700142 .build();
143
alshabib0603afb2015-06-05 14:10:33 -0700144 ForwardingObjective radiusToController = DefaultForwardingObjective.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700145 .fromApp(appId)
146 .makePermanent()
147 .withFlag(ForwardingObjective.Flag.VERSATILE)
148 .withPriority(PRIORITY)
alshabib0603afb2015-06-05 14:10:33 -0700149 .withSelector(toRadius)
150 .withTreatment(puntToController)
Jonathan Hart0b989982015-05-14 15:40:07 -0700151 .add();
152
alshabib0603afb2015-06-05 14:10:33 -0700153 ForwardingObjective upCtrl = DefaultForwardingObjective.builder()
154 .fromApp(appId)
155 .makePermanent()
156 .withFlag(ForwardingObjective.Flag.VERSATILE)
157 .withPriority(PRIORITY)
158 .withSelector(ofInBandMatchUp)
159 .withTreatment(up)
160 .add();
161
162 ForwardingObjective downCtrl = DefaultForwardingObjective.builder()
163 .fromApp(appId)
164 .makePermanent()
165 .withFlag(ForwardingObjective.Flag.VERSATILE)
166 .withPriority(PRIORITY)
167 .withSelector(ofInBandMatchDown)
168 .withTreatment(down)
169 .add();
170
alshabibc4b5d462015-06-08 23:06:24 -0700171
172
alshabib0603afb2015-06-05 14:10:33 -0700173 flowObjectiveService.forward(fabricDeviceId, upCtrl);
174 flowObjectiveService.forward(fabricDeviceId, downCtrl);
175 flowObjectiveService.forward(fabricDeviceId, radiusToController);
Jonathan Hart0b989982015-05-14 15:40:07 -0700176 }
177
Jonathan Hartea750842015-04-23 17:44:49 -0700178 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700179 public void addVlan(FabricVlan vlan) {
180 checkNotNull(vlan);
181 checkArgument(vlan.ports().size() > 1);
182 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -0700183
Jonathan Hart443ebed2015-05-05 14:02:12 -0700184 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -0700185
alshabibc4b5d462015-06-08 23:06:24 -0700186 if (vlan.iptv()) {
187 provisionIPTV();
188 }
189
Jonathan Hart443ebed2015-05-05 14:02:12 -0700190 vlan.ports().forEach(cp -> {
191 if (vlans.put(vlan.vlan(), cp)) {
192 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
193 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -0700194 .filter(p -> p != cp)
195 .map(ConnectPoint::port)
196 .collect(Collectors.toList()));
197 }
198 });
199 }
200
alshabibc4b5d462015-06-08 23:06:24 -0700201 //FIXME: pass iptv vlan in here.
202 private void provisionIPTV() {
203 TrafficSelector ipTvUp = DefaultTrafficSelector.builder()
204 .matchVlanId(VlanId.vlanId((short) 7))
205 .matchInPort(PortNumber.portNumber(2))
206 .build();
207
208 TrafficTreatment ipTvActUp = DefaultTrafficTreatment.builder()
209 .setOutput(PortNumber.portNumber(7)).build();
210
211 TrafficSelector ipTvDown = DefaultTrafficSelector.builder()
212 .matchVlanId(VlanId.vlanId((short) 7))
213 .matchInPort(PortNumber.portNumber(7))
214 .build();
215
216 TrafficTreatment ipTvActDown = DefaultTrafficTreatment.builder()
217 .setOutput(PortNumber.portNumber(2)).build();
218
219 ForwardingObjective ipTvUpstream = DefaultForwardingObjective.builder()
220 .fromApp(appId)
221 .makePermanent()
222 .withFlag(ForwardingObjective.Flag.VERSATILE)
223 .withPriority(PRIORITY)
224 .withSelector(ipTvUp)
225 .withTreatment(ipTvActUp)
226 .add();
227
228 ForwardingObjective ipTvDownstream = DefaultForwardingObjective.builder()
229 .fromApp(appId)
230 .makePermanent()
231 .withFlag(ForwardingObjective.Flag.VERSATILE)
232 .withPriority(PRIORITY)
233 .withSelector(ipTvDown)
234 .withTreatment(ipTvActDown)
235 .add();
236
237 flowObjectiveService.forward(fabricDeviceId, ipTvUpstream);
238 flowObjectiveService.forward(fabricDeviceId, ipTvDownstream);
239 }
240
Jonathan Hartea750842015-04-23 17:44:49 -0700241 @Override
242 public void removeVlan(VlanId vlanId) {
243 vlans.removeAll(vlanId)
244 .forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port()));
245 }
246
247 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700248 public List<FabricVlan> getVlans() {
249 List<FabricVlan> fVlans = new ArrayList<>();
250 vlans.keySet().forEach(vlan -> fVlans.add(
alshabibc4b5d462015-06-08 23:06:24 -0700251 //FIXME: Very aweful but will fo for now
252 new FabricVlan(vlan, vlans.get(vlan),
253 vlan.toShort() == 201 ? true : false)));
Jonathan Hart443ebed2015-05-05 14:02:12 -0700254 return fVlans;
Jonathan Hartea750842015-04-23 17:44:49 -0700255 }
256
257 private static void verifyPorts(List<ConnectPoint> ports) {
258 DeviceId deviceId = ports.get(0).deviceId();
259 for (ConnectPoint connectPoint : ports) {
260 if (!connectPoint.deviceId().equals(deviceId)) {
261 throw new IllegalArgumentException("Ports must all be on the same device");
262 }
263 }
264 }
265
266 private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
267 List<PortNumber> outPorts) {
alshabibc4b5d462015-06-08 23:06:24 -0700268
Jonathan Hartea750842015-04-23 17:44:49 -0700269 TrafficSelector selector = DefaultTrafficSelector.builder()
270 .matchVlanId(vlanId)
271 .matchInPort(inPort)
272 .build();
273
274 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
275
276 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
277
278 ForwardingObjective objective = DefaultForwardingObjective.builder()
279 .fromApp(appId)
280 .makePermanent()
281 .withFlag(ForwardingObjective.Flag.VERSATILE)
282 .withPriority(PRIORITY)
283 .withSelector(selector)
284 .withTreatment(treatmentBuilder.build())
285 .add(new ObjectiveHandler());
286
287 flowObjectiveService.forward(deviceId, objective);
288 }
289
290 private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort) {
291 TrafficSelector selector = DefaultTrafficSelector.builder()
292 .matchVlanId(vlanId)
293 .matchInPort(inPort)
294 .build();
295
296 ForwardingObjective objective = DefaultForwardingObjective.builder()
297 .fromApp(appId)
298 .makePermanent()
299 .withFlag(ForwardingObjective.Flag.VERSATILE)
300 .withPriority(PRIORITY)
301 .withSelector(selector)
302 .withTreatment(DefaultTrafficTreatment.builder().build())
303 .remove(new ObjectiveHandler());
304
305 flowObjectiveService.forward(deviceId, objective);
306 }
307
308 private static class ObjectiveHandler implements ObjectiveContext {
309 private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class);
310
311 @Override
312 public void onSuccess(Objective objective) {
313 log.info("Flow objective operation successful: {}", objective);
314 }
315
316 @Override
317 public void onError(Objective objective, ObjectiveError error) {
318 log.info("Flow objective operation failed: {}", objective);
319 }
320 }
Jonathan Hart408d24d2015-06-02 10:21:47 -0700321
322 /**
323 * Internal listener for device service events.
324 */
325 private class InternalDeviceListener implements DeviceListener {
326 @Override
327 public void event(DeviceEvent event) {
328 switch (event.type()) {
329 case DEVICE_ADDED:
330 case DEVICE_AVAILABILITY_CHANGED:
331 if (event.subject().id().equals(fabricDeviceId) &&
332 deviceService.isAvailable(event.subject().id())) {
333 setupDefaultFlows();
334 }
335 default:
336 break;
337 }
338 }
339 }
Jonathan Hartea750842015-04-23 17:44:49 -0700340}