blob: caebbd9af9de7d847ae9a979fc3ffd81d765e90d [file] [log] [blame]
Bharat Saraswal0fa12e92015-12-04 02:58:01 +05301/*
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 */
16package org.onosproject.sfc.installer.impl;
17
Jonathan Hart51539b82015-10-29 09:53:04 -070018import org.apache.felix.scr.annotations.Component;
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +053019import org.apache.felix.scr.annotations.Reference;
20import org.apache.felix.scr.annotations.ReferenceCardinality;
21import org.apache.felix.scr.annotations.Service;
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053022import org.onlab.osgi.DefaultServiceDirectory;
23import org.onlab.osgi.ServiceDirectory;
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +053024import org.onlab.packet.Ethernet;
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053025import org.onlab.packet.MacAddress;
26import org.onlab.packet.TpPort;
27import org.onlab.packet.VlanId;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.net.DeviceId;
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +053030import org.onosproject.net.Host;
31import org.onosproject.net.HostId;
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053032import org.onosproject.net.NshServicePathId;
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +053033import org.onosproject.net.PortNumber;
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053034import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
Jonathan Hart51539b82015-10-29 09:53:04 -070035import org.onosproject.net.device.DeviceService;
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053036import org.onosproject.net.driver.DriverHandler;
37import org.onosproject.net.driver.DriverService;
38import 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.flow.criteria.Criteria;
43import org.onosproject.net.flow.instructions.ExtensionTreatment;
44import org.onosproject.net.flowobjective.DefaultForwardingObjective;
45import org.onosproject.net.flowobjective.FlowObjectiveService;
46import org.onosproject.net.flowobjective.ForwardingObjective;
47import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
48import org.onosproject.net.flowobjective.Objective;
49import org.onosproject.net.flowobjective.Objective.Operation;
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +053050import org.onosproject.net.host.HostService;
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053051import org.onosproject.sfc.installer.FlowClassifierInstallerService;
52import org.onosproject.vtnrsc.FlowClassifier;
53import org.onosproject.vtnrsc.FlowClassifierId;
54import org.onosproject.vtnrsc.PortChain;
55import org.onosproject.vtnrsc.PortPair;
56import org.onosproject.vtnrsc.PortPairGroup;
57import org.onosproject.vtnrsc.PortPairGroupId;
58import org.onosproject.vtnrsc.PortPairId;
59import org.onosproject.vtnrsc.VirtualPortId;
60import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
61import org.onosproject.vtnrsc.portpair.PortPairService;
62import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
63import org.onosproject.vtnrsc.service.VtnRscService;
64import org.onosproject.vtnrsc.virtualport.VirtualPortService;
65import org.slf4j.Logger;
66
Jonathan Hart51539b82015-10-29 09:53:04 -070067import java.util.LinkedList;
68import java.util.List;
69import java.util.ListIterator;
70
71import static com.google.common.base.Preconditions.checkNotNull;
72import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI;
73import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI;
74import static org.slf4j.LoggerFactory.getLogger;
75
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053076/**
77 * Provides flow classifier installer implementation.
78 */
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +053079@Component(immediate = true)
80@Service
Bharat Saraswal0fa12e92015-12-04 02:58:01 +053081public class FlowClassifierInstallerImpl implements FlowClassifierInstallerService {
82
83 private final Logger log = getLogger(getClass());
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected VirtualPortService virtualPortService;
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected VtnRscService vtnRscService;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected PortPairService portPairService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected PortPairGroupService portPairGroupService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected FlowClassifierService flowClassifierService;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected DriverService driverService;
102
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected DeviceService deviceService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected HostService hostService;
108
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530109 protected FlowObjectiveService flowObjectiveService;
110 protected ApplicationId appId;
111
112 private static final String DRIVER_NAME = "onosfw";
113 private static final String FLOW_CLASSIFIER_NOT_NULL = "Flow-Classifier cannot be null";
114 private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "Flow-Classifier-Id cannot be null";
115 private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
116 private static final int NULL = 0;
117 private static final int L3FWD_PRIORITY = 0xffff;
118 private static final int NSH_SI_ID = 0xff;
119
120 /**
121 * Default constructor.
122 */
123 public FlowClassifierInstallerImpl() {
124 }
125
126 /**
127 * Explicit constructor.
128 *
129 * @param appId Application ID.
130 */
131 public FlowClassifierInstallerImpl(ApplicationId appId) {
132 this.appId = checkNotNull(appId, "ApplicationId can not be null");
133 ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
134 this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
135 }
136
137 @Override
138 public void installFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
139 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
140 processFlowClassifier(portChain, nshSpiId, Objective.Operation.ADD);
141 }
142
143 @Override
144 public void unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
145 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
146 processFlowClassifier(portChain, nshSpiId, Objective.Operation.REMOVE);
147 }
148
149 public void processFlowClassifier(PortChain portChain, NshServicePathId nshSpiId, Objective.Operation type) {
150
151 // get the portPairGroup
152 List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
153 ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
154 PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
155 PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
156 List<PortPairId> llPortPairIdList = portPairGroup.portPairs();
157
158 // get port pair
159 ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
160 PortPairId portPairId = portPairListIterator.next();
161 PortPair portPair = portPairService.getPortPair(portPairId);
162
163 FlowClassifierInstallerService flowclassifierinstallerService;
164 // get flow classifiers
165 List<FlowClassifierId> llFlowClassifierList = portChain.flowClassifiers();
166 ListIterator<FlowClassifierId> flowClassifierListIterator = llFlowClassifierList.listIterator();
167
168 while (flowClassifierListIterator.hasNext()) {
169 FlowClassifierId flowclassifierId = flowClassifierListIterator.next();
170 FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowclassifierId);
171 prepareFlowClassification(flowClassifier, portPair, nshSpiId, type);
172 }
173 }
174
175 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700176 public void prepareFlowClassification(FlowClassifier flowClassifier, PortPair portPair, NshServicePathId nshSpi,
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530177 Operation type) {
178 DeviceId deviceId = null;
179 // device id if virtual ports are set in flow classifier.
180 DeviceId deviceIdfromFc = null;
181 // device id if port pair is used to fetch device id.
182 DeviceId deviceIdfromPp = null;
183 MacAddress srcMacAddress = null;
184 // Vxlan tunnel port for NSH header(Vxlan + NSH).
185 TpPort nshDstPort = TpPort.tpPort(6633);
186
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530187 if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700188 deviceIdfromFc = vtnRscService.getSfToSffMaping(flowClassifier.srcPort());
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530189 deviceId = deviceIdfromFc;
190 } else {
Jonathan Hart51539b82015-10-29 09:53:04 -0700191 deviceIdfromPp = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530192 srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
193 deviceId = deviceIdfromPp;
194 }
195
196 // Build Traffic selector.
197 TrafficSelector.Builder selector = packTrafficSelector(flowClassifier);
198
199 // Build traffic treatment.
200 TrafficTreatment.Builder treatment = packTrafficTreatment(deviceId, srcMacAddress, nshDstPort, deviceIdfromFc,
Jonathan Hart51539b82015-10-29 09:53:04 -0700201 deviceIdfromPp, nshSpi, flowClassifier);
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530202
203 // Build forwarding objective and send to OVS.
204 sendServiceFunctionForwarder(selector, treatment, deviceId, type);
205 }
206
207 /**
208 * Pack Traffic selector.
209 *
210 * @param flowClassifier flow-classifier
211 * @return traffic selector
212 */
213 public TrafficSelector.Builder packTrafficSelector(FlowClassifier flowClassifier) {
214 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
215
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530216 if ((flowClassifier.srcIpPrefix() != null) && (flowClassifier.srcIpPrefix().prefixLength() != 0)) {
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530217 selector.matchIPSrc(flowClassifier.srcIpPrefix());
218 }
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530219
220 if ((flowClassifier.dstIpPrefix() != null) && (flowClassifier.dstIpPrefix().prefixLength() != 0)) {
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530221 selector.matchIPDst(flowClassifier.dstIpPrefix());
222 }
223
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530224 if ((flowClassifier.protocol() != null) && (!flowClassifier.protocol().isEmpty())) {
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530225 selector.add(Criteria.matchIPProtocol(Short.parseShort(flowClassifier.protocol())));
226 }
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530227
228 if (((flowClassifier.etherType() != null) && (!flowClassifier.etherType().isEmpty()))
229 && (flowClassifier.etherType().equals("IPv4") || flowClassifier.etherType().equals("IPv6"))) {
230 if (flowClassifier.etherType().equals("IPv4")) {
231 selector.matchEthType(Ethernet.TYPE_IPV4);
232 } else {
233 selector.matchEthType(Ethernet.TYPE_IPV6);
234 }
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530235 }
236
237 List<TpPort> srcPortRange = new LinkedList<>();
238 List<TpPort> dstPortRange = new LinkedList<>();
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530239 if ((flowClassifier.minSrcPortRange() != 0) && flowClassifier.maxSrcPortRange() != 0
240 && flowClassifier.minDstPortRange() != 0 && flowClassifier.maxDstPortRange() != 0) {
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530241
242 for (int port = flowClassifier.minSrcPortRange(); port <= flowClassifier.maxSrcPortRange(); port++) {
243 srcPortRange.add(TpPort.tpPort(port));
244 }
245 for (int port = flowClassifier.minDstPortRange(); port <= flowClassifier.maxDstPortRange(); port++) {
246 dstPortRange.add(TpPort.tpPort(port));
247 }
248 }
249
250 for (TpPort inPort : srcPortRange) {
251 selector.matchUdpSrc(inPort);
252 }
253 for (TpPort outPort : dstPortRange) {
254 selector.matchUdpDst(outPort);
255 }
256 return selector;
257 }
258
259 /**
260 * Pack traffic treatment.
261 *
262 * @param deviceId device id
263 * @param srcMacAddress source mac-address
264 * @param nshDstPort vxlan tunnel port for nsh header
265 * @param deviceIdfromFc device id if virtual ports are set in flow classifier.
266 * @param deviceIdfromPp device id if port pair is used to fetch device id.
Jonathan Hart51539b82015-10-29 09:53:04 -0700267 * @param nshSpi nsh spi
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530268 * @param flowClassifier flow-classifier
269 * @return traffic treatment
270 */
271 public TrafficTreatment.Builder packTrafficTreatment(DeviceId deviceId, MacAddress srcMacAddress,
272 TpPort nshDstPort, DeviceId deviceIdfromFc, DeviceId deviceIdfromPp,
Jonathan Hart51539b82015-10-29 09:53:04 -0700273 NshServicePathId nshSpi, FlowClassifier flowClassifier) {
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530274 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530275
276 Host host = hostService.getHost(HostId.hostId(srcMacAddress));
277 PortNumber port = host.location().port();
278 if (deviceIdfromPp != null) {
279 treatmentBuilder.setOutput(port);
280 } else if (deviceIdfromFc != null) {
281 treatmentBuilder.setVlanId((VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(flowClassifier
282 .tenantId()).toString())))));
283 }
284
285 // Set NSH
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530286 DriverHandler handler = driverService.createHandler(deviceId);
287 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
288 ExtensionTreatment nspIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SPI.type());
289 ExtensionTreatment nsiIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SI.type());
290
291 treatmentBuilder.extension(nspIdTreatment, deviceId);
292 treatmentBuilder.extension(nsiIdTreatment, deviceId);
293 treatmentBuilder.setUdpDst(nshDstPort);
294
295 try {
Jonathan Hart51539b82015-10-29 09:53:04 -0700296 nspIdTreatment.setPropertyValue("nshSpi", nshSpi);
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530297 } catch (Exception e) {
298 log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
299 }
300 try {
301 nsiIdTreatment.setPropertyValue("nshSi", NSH_SI_ID);
302 } catch (Exception e) {
303 log.error("Failed to get extension instruction to set Nsh Si Id {}", deviceId);
304 }
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530305 return treatmentBuilder;
306 }
307
308 /**
309 * Send service-function-forwarder to OVS.
310 *
311 * @param selector traffic selector
312 * @param treatment traffic treatment
313 * @param deviceId device id
314 * @param type operation type
315 */
316 public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
317 DeviceId deviceId, Objective.Operation type) {
318 ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
Mahesh Poojary S96cdcd22015-12-10 11:01:30 +0530319 .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE)
320 .withPriority(L3FWD_PRIORITY);
Bharat Saraswal0fa12e92015-12-04 02:58:01 +0530321
322 if (type.equals(Objective.Operation.ADD)) {
323 log.debug("flowClassifierRules-->ADD");
324 flowObjectiveService.forward(deviceId, objective.add());
325 } else {
326 log.debug("flowClassifierRules-->REMOVE");
327 flowObjectiveService.forward(deviceId, objective.remove());
328 }
329 }
330}