blob: f3bd96c2fb1431f9da3a5fad5e40c740beb2c37f [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
171 flowObjectiveService.forward(fabricDeviceId, upCtrl);
172 flowObjectiveService.forward(fabricDeviceId, downCtrl);
173 flowObjectiveService.forward(fabricDeviceId, radiusToController);
Jonathan Hart0b989982015-05-14 15:40:07 -0700174 }
175
Jonathan Hartea750842015-04-23 17:44:49 -0700176 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700177 public void addVlan(FabricVlan vlan) {
178 checkNotNull(vlan);
179 checkArgument(vlan.ports().size() > 1);
180 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -0700181
Jonathan Hart443ebed2015-05-05 14:02:12 -0700182 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -0700183
Jonathan Hart443ebed2015-05-05 14:02:12 -0700184 vlan.ports().forEach(cp -> {
185 if (vlans.put(vlan.vlan(), cp)) {
186 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
187 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -0700188 .filter(p -> p != cp)
189 .map(ConnectPoint::port)
190 .collect(Collectors.toList()));
191 }
192 });
193 }
194
195 @Override
196 public void removeVlan(VlanId vlanId) {
197 vlans.removeAll(vlanId)
198 .forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port()));
199 }
200
201 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700202 public List<FabricVlan> getVlans() {
203 List<FabricVlan> fVlans = new ArrayList<>();
204 vlans.keySet().forEach(vlan -> fVlans.add(
205 new FabricVlan(vlan, vlans.get(vlan))));
206 return fVlans;
Jonathan Hartea750842015-04-23 17:44:49 -0700207 }
208
209 private static void verifyPorts(List<ConnectPoint> ports) {
210 DeviceId deviceId = ports.get(0).deviceId();
211 for (ConnectPoint connectPoint : ports) {
212 if (!connectPoint.deviceId().equals(deviceId)) {
213 throw new IllegalArgumentException("Ports must all be on the same device");
214 }
215 }
216 }
217
218 private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
219 List<PortNumber> outPorts) {
220 TrafficSelector selector = DefaultTrafficSelector.builder()
221 .matchVlanId(vlanId)
222 .matchInPort(inPort)
223 .build();
224
225 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
226
227 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
228
229 ForwardingObjective objective = DefaultForwardingObjective.builder()
230 .fromApp(appId)
231 .makePermanent()
232 .withFlag(ForwardingObjective.Flag.VERSATILE)
233 .withPriority(PRIORITY)
234 .withSelector(selector)
235 .withTreatment(treatmentBuilder.build())
236 .add(new ObjectiveHandler());
237
238 flowObjectiveService.forward(deviceId, objective);
239 }
240
241 private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort) {
242 TrafficSelector selector = DefaultTrafficSelector.builder()
243 .matchVlanId(vlanId)
244 .matchInPort(inPort)
245 .build();
246
247 ForwardingObjective objective = DefaultForwardingObjective.builder()
248 .fromApp(appId)
249 .makePermanent()
250 .withFlag(ForwardingObjective.Flag.VERSATILE)
251 .withPriority(PRIORITY)
252 .withSelector(selector)
253 .withTreatment(DefaultTrafficTreatment.builder().build())
254 .remove(new ObjectiveHandler());
255
256 flowObjectiveService.forward(deviceId, objective);
257 }
258
259 private static class ObjectiveHandler implements ObjectiveContext {
260 private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class);
261
262 @Override
263 public void onSuccess(Objective objective) {
264 log.info("Flow objective operation successful: {}", objective);
265 }
266
267 @Override
268 public void onError(Objective objective, ObjectiveError error) {
269 log.info("Flow objective operation failed: {}", objective);
270 }
271 }
Jonathan Hart408d24d2015-06-02 10:21:47 -0700272
273 /**
274 * Internal listener for device service events.
275 */
276 private class InternalDeviceListener implements DeviceListener {
277 @Override
278 public void event(DeviceEvent event) {
279 switch (event.type()) {
280 case DEVICE_ADDED:
281 case DEVICE_AVAILABILITY_CHANGED:
282 if (event.subject().id().equals(fabricDeviceId) &&
283 deviceService.isAvailable(event.subject().id())) {
284 setupDefaultFlows();
285 }
286 default:
287 break;
288 }
289 }
290 }
Jonathan Hartea750842015-04-23 17:44:49 -0700291}