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