blob: ca8501a8da3d0f1f85757695cfe6d47fbc00cb7c [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;
27import org.onlab.packet.VlanId;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.net.ConnectPoint;
31import org.onosproject.net.DeviceId;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.flow.DefaultTrafficSelector;
34import org.onosproject.net.flow.DefaultTrafficTreatment;
35import org.onosproject.net.flow.TrafficSelector;
36import org.onosproject.net.flow.TrafficTreatment;
37import org.onosproject.net.flowobjective.DefaultForwardingObjective;
38import org.onosproject.net.flowobjective.FlowObjectiveService;
39import org.onosproject.net.flowobjective.ForwardingObjective;
40import org.onosproject.net.flowobjective.Objective;
41import org.onosproject.net.flowobjective.ObjectiveContext;
42import org.onosproject.net.flowobjective.ObjectiveError;
43import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
Jonathan Hart443ebed2015-05-05 14:02:12 -070046import java.util.ArrayList;
Jonathan Hartea750842015-04-23 17:44:49 -070047import java.util.List;
48import java.util.stream.Collectors;
49
50import static com.google.common.base.Preconditions.checkArgument;
51import static com.google.common.base.Preconditions.checkNotNull;
52import static org.slf4j.LoggerFactory.getLogger;
53
54/**
55 * CORD fabric application.
56 */
57@Service
58@Component(immediate = true)
59public class CordFabricManager implements FabricService {
60
61 private final Logger log = getLogger(getClass());
62
63 private ApplicationId appId;
64
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected CoreService coreService;
67
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected FlowObjectiveService flowObjectiveService;
70
71 private static final int PRIORITY = 1000;
72
73 private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create();
74
75 @Activate
76 public void activate() {
77 appId = coreService.registerApplication("org.onosproject.cordfabric");
78
79 log.info("Started");
80 }
81
82 @Deactivate
83 public void deactivate() {
84 log.info("Stopped");
85 }
86
87 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -070088 public void addVlan(FabricVlan vlan) {
89 checkNotNull(vlan);
90 checkArgument(vlan.ports().size() > 1);
91 verifyPorts(vlan.ports());
Jonathan Hartea750842015-04-23 17:44:49 -070092
Jonathan Hart443ebed2015-05-05 14:02:12 -070093 removeVlan(vlan.vlan());
Jonathan Hartea750842015-04-23 17:44:49 -070094
Jonathan Hart443ebed2015-05-05 14:02:12 -070095 vlan.ports().forEach(cp -> {
96 if (vlans.put(vlan.vlan(), cp)) {
97 addForwarding(vlan.vlan(), cp.deviceId(), cp.port(),
98 vlan.ports().stream()
Jonathan Hartea750842015-04-23 17:44:49 -070099 .filter(p -> p != cp)
100 .map(ConnectPoint::port)
101 .collect(Collectors.toList()));
102 }
103 });
104 }
105
106 @Override
107 public void removeVlan(VlanId vlanId) {
108 vlans.removeAll(vlanId)
109 .forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port()));
110 }
111
112 @Override
Jonathan Hart443ebed2015-05-05 14:02:12 -0700113 public List<FabricVlan> getVlans() {
114 List<FabricVlan> fVlans = new ArrayList<>();
115 vlans.keySet().forEach(vlan -> fVlans.add(
116 new FabricVlan(vlan, vlans.get(vlan))));
117 return fVlans;
Jonathan Hartea750842015-04-23 17:44:49 -0700118 }
119
120 private static void verifyPorts(List<ConnectPoint> ports) {
121 DeviceId deviceId = ports.get(0).deviceId();
122 for (ConnectPoint connectPoint : ports) {
123 if (!connectPoint.deviceId().equals(deviceId)) {
124 throw new IllegalArgumentException("Ports must all be on the same device");
125 }
126 }
127 }
128
129 private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort,
130 List<PortNumber> outPorts) {
131 TrafficSelector selector = DefaultTrafficSelector.builder()
132 .matchVlanId(vlanId)
133 .matchInPort(inPort)
134 .build();
135
136 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
137
138 outPorts.forEach(p -> treatmentBuilder.setOutput(p));
139
140 ForwardingObjective objective = DefaultForwardingObjective.builder()
141 .fromApp(appId)
142 .makePermanent()
143 .withFlag(ForwardingObjective.Flag.VERSATILE)
144 .withPriority(PRIORITY)
145 .withSelector(selector)
146 .withTreatment(treatmentBuilder.build())
147 .add(new ObjectiveHandler());
148
149 flowObjectiveService.forward(deviceId, objective);
150 }
151
152 private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort) {
153 TrafficSelector selector = DefaultTrafficSelector.builder()
154 .matchVlanId(vlanId)
155 .matchInPort(inPort)
156 .build();
157
158 ForwardingObjective objective = DefaultForwardingObjective.builder()
159 .fromApp(appId)
160 .makePermanent()
161 .withFlag(ForwardingObjective.Flag.VERSATILE)
162 .withPriority(PRIORITY)
163 .withSelector(selector)
164 .withTreatment(DefaultTrafficTreatment.builder().build())
165 .remove(new ObjectiveHandler());
166
167 flowObjectiveService.forward(deviceId, objective);
168 }
169
170 private static class ObjectiveHandler implements ObjectiveContext {
171 private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class);
172
173 @Override
174 public void onSuccess(Objective objective) {
175 log.info("Flow objective operation successful: {}", objective);
176 }
177
178 @Override
179 public void onError(Objective objective, ObjectiveError error) {
180 log.info("Flow objective operation failed: {}", objective);
181 }
182 }
183}