blob: 7c24144feed81b7059cbc05ce85d3bfea48a5c68 [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
Jonathan Hart0b989982015-05-14 15:40:07 -070085 private DeviceId fabricDeviceId = DeviceId.deviceId("of:5e3e486e73000187");
86
Jonathan Hartea750842015-04-23 17:44:49 -070087 private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create();
88
89 @Activate
90 public void activate() {
91 appId = coreService.registerApplication("org.onosproject.cordfabric");
92
Jonathan Hart408d24d2015-06-02 10:21:47 -070093 deviceService.addListener(deviceListener);
94
95 if (deviceService.isAvailable(fabricDeviceId)) {
96 setupDefaultFlows();
97 }
Jonathan Hart0b989982015-05-14 15:40:07 -070098
Jonathan Hartea750842015-04-23 17:44:49 -070099 log.info("Started");
100 }
101
102 @Deactivate
103 public void deactivate() {
Jonathan Hart408d24d2015-06-02 10:21:47 -0700104 deviceService.removeListener(deviceListener);
105
Jonathan Hartea750842015-04-23 17:44:49 -0700106 log.info("Stopped");
107 }
108
Jonathan Hart0b989982015-05-14 15:40:07 -0700109 private void setupDefaultFlows() {
alshabibc494f992015-05-15 09:51:54 -0700110 TrafficSelector toControllerOF = DefaultTrafficSelector.builder()
Jonathan Hart0b989982015-05-14 15:40:07 -0700111 .matchEthType(Ethernet.TYPE_IPV4)
alshabibc494f992015-05-15 09:51:54 -0700112 .matchIPProtocol(IPv4.PROTOCOL_UDP)
113 .matchUdpDst(radiusPort)
114 .build();
115
Jonathan Hart0b989982015-05-14 15:40:07 -0700116 TrafficTreatment forwardToController = DefaultTrafficTreatment.builder()
alshabib51ca37f2015-05-30 18:31:47 -0700117 .punt()
Jonathan Hart0b989982015-05-14 15:40:07 -0700118 .build();
119
Jonathan Hart0b989982015-05-14 15:40:07 -0700120 ForwardingObjective ofToController = DefaultForwardingObjective.builder()
121 .fromApp(appId)
122 .makePermanent()
123 .withFlag(ForwardingObjective.Flag.VERSATILE)
124 .withPriority(PRIORITY)
alshabibc494f992015-05-15 09:51:54 -0700125 .withSelector(toControllerOF)
Jonathan Hart0b989982015-05-14 15:40:07 -0700126 .withTreatment(forwardToController)
127 .add();
128
Jonathan Hart0b989982015-05-14 15:40:07 -0700129 flowObjectiveService.forward(fabricDeviceId, ofToController);
Jonathan Hart0b989982015-05-14 15:40:07 -0700130 }
131
Jonathan Hartea750842015-04-23 17:44:49 -0700132 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700133 public void addVlan(FabricVlan vlan) {
134 checkNotNull(vlan);
135 checkArgument(vlan.ports().size() > 1);
136 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -0700137
Jonathan Hart443ebed2015-05-05 14:02:12 -0700138 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -0700139
Jonathan Hart443ebed2015-05-05 14:02:12 -0700140 vlan.ports().forEach(cp -> {
141 if (vlans.put(vlan.vlan(), cp)) {
142 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
143 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -0700144 .filter(p -> p != cp)
145 .map(ConnectPoint::port)
146 .collect(Collectors.toList()));
147 }
148 });
149 }
150
151 @Override
152 public void removeVlan(VlanId vlanId) {
153 vlans.removeAll(vlanId)
154 .forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port()));
155 }
156
157 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700158 public List<FabricVlan> getVlans() {
159 List<FabricVlan> fVlans = new ArrayList<>();
160 vlans.keySet().forEach(vlan -> fVlans.add(
161 new FabricVlan(vlan, vlans.get(vlan))));
162 return fVlans;
Jonathan Hartea750842015-04-23 17:44:49 -0700163 }
164
165 private static void verifyPorts(List<ConnectPoint> ports) {
166 DeviceId deviceId = ports.get(0).deviceId();
167 for (ConnectPoint connectPoint : ports) {
168 if (!connectPoint.deviceId().equals(deviceId)) {
169 throw new IllegalArgumentException("Ports must all be on the same device");
170 }
171 }
172 }
173
174 private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
175 List<PortNumber> outPorts) {
176 TrafficSelector selector = DefaultTrafficSelector.builder()
177 .matchVlanId(vlanId)
178 .matchInPort(inPort)
179 .build();
180
181 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
182
183 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
184
185 ForwardingObjective objective = DefaultForwardingObjective.builder()
186 .fromApp(appId)
187 .makePermanent()
188 .withFlag(ForwardingObjective.Flag.VERSATILE)
189 .withPriority(PRIORITY)
190 .withSelector(selector)
191 .withTreatment(treatmentBuilder.build())
192 .add(new ObjectiveHandler());
193
194 flowObjectiveService.forward(deviceId, objective);
195 }
196
197 private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort) {
198 TrafficSelector selector = DefaultTrafficSelector.builder()
199 .matchVlanId(vlanId)
200 .matchInPort(inPort)
201 .build();
202
203 ForwardingObjective objective = DefaultForwardingObjective.builder()
204 .fromApp(appId)
205 .makePermanent()
206 .withFlag(ForwardingObjective.Flag.VERSATILE)
207 .withPriority(PRIORITY)
208 .withSelector(selector)
209 .withTreatment(DefaultTrafficTreatment.builder().build())
210 .remove(new ObjectiveHandler());
211
212 flowObjectiveService.forward(deviceId, objective);
213 }
214
215 private static class ObjectiveHandler implements ObjectiveContext {
216 private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class);
217
218 @Override
219 public void onSuccess(Objective objective) {
220 log.info("Flow objective operation successful: {}", objective);
221 }
222
223 @Override
224 public void onError(Objective objective, ObjectiveError error) {
225 log.info("Flow objective operation failed: {}", objective);
226 }
227 }
Jonathan Hart408d24d2015-06-02 10:21:47 -0700228
229 /**
230 * Internal listener for device service events.
231 */
232 private class InternalDeviceListener implements DeviceListener {
233 @Override
234 public void event(DeviceEvent event) {
235 switch (event.type()) {
236 case DEVICE_ADDED:
237 case DEVICE_AVAILABILITY_CHANGED:
238 if (event.subject().id().equals(fabricDeviceId) &&
239 deviceService.isAvailable(event.subject().id())) {
240 setupDefaultFlows();
241 }
242 default:
243 break;
244 }
245 }
246 }
Jonathan Hartea750842015-04-23 17:44:49 -0700247}