Bharat Saraswal
Committed by Gerrit Code Review

[ONOS-3119] FlowClassifier installer impl.

Change-Id: I48b2378ad185528f5775f547bc965ebbbd009116
1 -/*
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 -package org.onosproject.sfc.installer;
17 -
18 -import org.onosproject.core.ApplicationId;
19 -import org.onosproject.net.flowobjective.Objective;
20 -import org.onosproject.vtnrsc.FlowClassifier;
21 -import org.onosproject.vtnrsc.PortPair;
22 -
23 -/**
24 - * Abstraction of an entity which installs flow classification rules in ovs.
25 - */
26 -public interface FlowClassifierInstaller {
27 -
28 - /**
29 - * Install flow classifier rules.
30 - *
31 - * @param flowClassifier Flow Classifier
32 - * @param portPair Port pair
33 - */
34 - void install(FlowClassifier flowClassifier, PortPair portPair);
35 -
36 - /**
37 - * Programs forwarding object for flow classifier.
38 - *
39 - * @param flowClassifier flow classifier
40 - * @param portPair port pair
41 - * @param appid application id
42 - * @param type forwarding objective operation type
43 - */
44 - void programFlowClassification(FlowClassifier flowClassifier, PortPair portPair, ApplicationId appid,
45 - Objective.Operation type);
46 -}
1 +package org.onosproject.sfc.installer;
2 +
3 +import org.onosproject.net.NshServicePathId;
4 +import org.onosproject.net.flowobjective.Objective.Operation;
5 +import org.onosproject.vtnrsc.FlowClassifier;
6 +import org.onosproject.vtnrsc.PortChain;
7 +import org.onosproject.vtnrsc.PortPair;
8 +
9 +/**
10 + * Abstraction of an entity which installs flow classification rules in ovs.
11 + */
12 +public interface FlowClassifierInstallerService {
13 +
14 + /**
15 + * Install Flow-Classifier.
16 + *
17 + * @param portChain port-chain
18 + * @param nshSpiId nsh spi-id
19 + */
20 + void installFlowClassifier(PortChain portChain, NshServicePathId nshSpiId);
21 +
22 + /**
23 + * Uninstall Flow-Classifier.
24 + *
25 + * @param portChain port-chain
26 + * @param nshSpiId nsh spi-id
27 + */
28 + void unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId);
29 +
30 + /**
31 + * Prepare forwarding object for flow classifier.
32 + *
33 + * @param flowClassifier flow classifier
34 + * @param portPair port pair
35 + * @param nshSpiId nsh spi id
36 + * @param type forwarding objective operation type
37 + */
38 + void prepareFlowClassification(FlowClassifier flowClassifier, PortPair portPair, NshServicePathId nshSpiId,
39 + Operation type);
40 +}
1 -/*
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 -package org.onosproject.sfc.installer.impl;
17 -
18 -import org.onosproject.core.ApplicationId;
19 -import org.onosproject.net.flowobjective.Objective.Operation;
20 -import org.onosproject.sfc.installer.FlowClassifierInstaller;
21 -import org.onosproject.vtnrsc.FlowClassifier;
22 -import org.onosproject.vtnrsc.PortPair;
23 -
24 -/**
25 - * Provides flow classifier installer.
26 - */
27 -public class DefaultFlowClassifierInstaller implements FlowClassifierInstaller {
28 -
29 - /**
30 - * Default constructor.
31 - */
32 - public DefaultFlowClassifierInstaller() {
33 - }
34 -
35 - @Override
36 - public void install(FlowClassifier flowClassifier, PortPair portPair) {
37 - // TODO: Process flow-classifier for installation.
38 - }
39 -
40 - @Override
41 - public void programFlowClassification(FlowClassifier flowClassifier, PortPair portPair, ApplicationId appid,
42 - Operation type) {
43 - // TODO: program forwarding objective for flow-classifier installation.
44 - }
45 -}
1 +/*
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 +package org.onosproject.sfc.installer.impl;
17 +
18 +import static com.google.common.base.Preconditions.checkNotNull;
19 +import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI;
20 +import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI;
21 +import static org.slf4j.LoggerFactory.getLogger;
22 +
23 +import java.util.LinkedList;
24 +import java.util.List;
25 +import java.util.ListIterator;
26 +
27 +import org.apache.felix.scr.annotations.Reference;
28 +import org.apache.felix.scr.annotations.ReferenceCardinality;
29 +import org.onlab.osgi.DefaultServiceDirectory;
30 +import org.onlab.osgi.ServiceDirectory;
31 +import org.onlab.packet.MacAddress;
32 +import org.onlab.packet.TpPort;
33 +import org.onlab.packet.VlanId;
34 +import org.onosproject.core.ApplicationId;
35 +import org.onosproject.net.DeviceId;
36 +import org.onosproject.net.NshServicePathId;
37 +import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
38 +import org.onosproject.net.driver.DriverHandler;
39 +import org.onosproject.net.driver.DriverService;
40 +import org.onosproject.net.flow.DefaultTrafficSelector;
41 +import org.onosproject.net.flow.DefaultTrafficTreatment;
42 +import org.onosproject.net.flow.TrafficSelector;
43 +import org.onosproject.net.flow.TrafficTreatment;
44 +import org.onosproject.net.flow.criteria.Criteria;
45 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
46 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
47 +import org.onosproject.net.flowobjective.FlowObjectiveService;
48 +import org.onosproject.net.flowobjective.ForwardingObjective;
49 +import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
50 +import org.onosproject.net.flowobjective.Objective;
51 +import org.onosproject.net.flowobjective.Objective.Operation;
52 +import org.onosproject.sfc.installer.FlowClassifierInstallerService;
53 +import org.onosproject.vtnrsc.FlowClassifier;
54 +import org.onosproject.vtnrsc.FlowClassifierId;
55 +import org.onosproject.vtnrsc.PortChain;
56 +import org.onosproject.vtnrsc.PortPair;
57 +import org.onosproject.vtnrsc.PortPairGroup;
58 +import org.onosproject.vtnrsc.PortPairGroupId;
59 +import org.onosproject.vtnrsc.PortPairId;
60 +import org.onosproject.vtnrsc.VirtualPortId;
61 +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
62 +import org.onosproject.vtnrsc.portpair.PortPairService;
63 +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
64 +import org.onosproject.vtnrsc.service.VtnRscService;
65 +import org.onosproject.vtnrsc.virtualport.VirtualPortService;
66 +import org.slf4j.Logger;
67 +
68 +/**
69 + * Provides flow classifier installer implementation.
70 + */
71 +public class FlowClassifierInstallerImpl implements FlowClassifierInstallerService {
72 +
73 + private final Logger log = getLogger(getClass());
74 +
75 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 + protected VirtualPortService virtualPortService;
77 +
78 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 + protected VtnRscService vtnRscService;
80 +
81 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 + protected PortPairService portPairService;
83 +
84 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 + protected PortPairGroupService portPairGroupService;
86 +
87 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 + protected FlowClassifierService flowClassifierService;
89 +
90 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 + protected DriverService driverService;
92 +
93 + protected FlowObjectiveService flowObjectiveService;
94 + protected ApplicationId appId;
95 +
96 + private static final String DRIVER_NAME = "onosfw";
97 + private static final String FLOW_CLASSIFIER_NOT_NULL = "Flow-Classifier cannot be null";
98 + private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "Flow-Classifier-Id cannot be null";
99 + private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
100 + private static final int NULL = 0;
101 + private static final int L3FWD_PRIORITY = 0xffff;
102 + private static final int NSH_SI_ID = 0xff;
103 +
104 + /**
105 + * Default constructor.
106 + */
107 + public FlowClassifierInstallerImpl() {
108 + }
109 +
110 + /**
111 + * Explicit constructor.
112 + *
113 + * @param appId Application ID.
114 + */
115 + public FlowClassifierInstallerImpl(ApplicationId appId) {
116 + this.appId = checkNotNull(appId, "ApplicationId can not be null");
117 + ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
118 + this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
119 + }
120 +
121 + @Override
122 + public void installFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
123 + checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
124 + processFlowClassifier(portChain, nshSpiId, Objective.Operation.ADD);
125 + }
126 +
127 + @Override
128 + public void unInstallFlowClassifier(PortChain portChain, NshServicePathId nshSpiId) {
129 + checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
130 + processFlowClassifier(portChain, nshSpiId, Objective.Operation.REMOVE);
131 + }
132 +
133 + public void processFlowClassifier(PortChain portChain, NshServicePathId nshSpiId, Objective.Operation type) {
134 +
135 + // get the portPairGroup
136 + List<PortPairGroupId> llPortPairGroupIdList = portChain.portPairGroups();
137 + ListIterator<PortPairGroupId> portPairGroupIdListIterator = llPortPairGroupIdList.listIterator();
138 + PortPairGroupId portPairGroupId = portPairGroupIdListIterator.next();
139 + PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
140 + List<PortPairId> llPortPairIdList = portPairGroup.portPairs();
141 +
142 + // get port pair
143 + ListIterator<PortPairId> portPairListIterator = llPortPairIdList.listIterator();
144 + PortPairId portPairId = portPairListIterator.next();
145 + PortPair portPair = portPairService.getPortPair(portPairId);
146 +
147 + FlowClassifierInstallerService flowclassifierinstallerService;
148 + // get flow classifiers
149 + List<FlowClassifierId> llFlowClassifierList = portChain.flowClassifiers();
150 + ListIterator<FlowClassifierId> flowClassifierListIterator = llFlowClassifierList.listIterator();
151 +
152 + while (flowClassifierListIterator.hasNext()) {
153 + FlowClassifierId flowclassifierId = flowClassifierListIterator.next();
154 + FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowclassifierId);
155 + prepareFlowClassification(flowClassifier, portPair, nshSpiId, type);
156 + }
157 + }
158 +
159 + @Override
160 + public void prepareFlowClassification(FlowClassifier flowClassifier, PortPair portPair, NshServicePathId nshSPI,
161 + Operation type) {
162 + DeviceId deviceId = null;
163 + // device id if virtual ports are set in flow classifier.
164 + DeviceId deviceIdfromFc = null;
165 + // device id if port pair is used to fetch device id.
166 + DeviceId deviceIdfromPp = null;
167 + MacAddress srcMacAddress = null;
168 + // Vxlan tunnel port for NSH header(Vxlan + NSH).
169 + TpPort nshDstPort = TpPort.tpPort(6633);
170 +
171 + if (flowClassifier.srcPort() != null) {
172 + deviceIdfromFc = vtnRscService.getSFToSFFMaping(flowClassifier.srcPort());
173 + deviceId = deviceIdfromFc;
174 + } else {
175 + deviceIdfromPp = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress()));
176 + srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
177 + deviceId = deviceIdfromPp;
178 + }
179 +
180 + // Build Traffic selector.
181 + TrafficSelector.Builder selector = packTrafficSelector(flowClassifier);
182 +
183 + // Build traffic treatment.
184 + TrafficTreatment.Builder treatment = packTrafficTreatment(deviceId, srcMacAddress, nshDstPort, deviceIdfromFc,
185 + deviceIdfromPp, nshSPI, flowClassifier);
186 +
187 + // Build forwarding objective and send to OVS.
188 + sendServiceFunctionForwarder(selector, treatment, deviceId, type);
189 + }
190 +
191 + /**
192 + * Pack Traffic selector.
193 + *
194 + * @param flowClassifier flow-classifier
195 + * @return traffic selector
196 + */
197 + public TrafficSelector.Builder packTrafficSelector(FlowClassifier flowClassifier) {
198 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
199 +
200 + if (flowClassifier.srcIpPrefix() != null) {
201 + selector.matchIPSrc(flowClassifier.srcIpPrefix());
202 + }
203 + if (flowClassifier.dstIpPrefix() != null) {
204 + selector.matchIPDst(flowClassifier.dstIpPrefix());
205 + }
206 +
207 + if (flowClassifier.protocol() != null) {
208 + selector.add(Criteria.matchIPProtocol(Short.parseShort(flowClassifier.protocol())));
209 + }
210 + if ((flowClassifier.etherType() != null)
211 + && (flowClassifier.etherType() == "IPv4" || flowClassifier.etherType() == "IPv6")) {
212 + selector.matchEthType(Short.parseShort((flowClassifier.etherType())));
213 + }
214 +
215 + List<TpPort> srcPortRange = new LinkedList<>();
216 + List<TpPort> dstPortRange = new LinkedList<>();
217 + if ((flowClassifier.minSrcPortRange() != NULL) && flowClassifier.maxSrcPortRange() != NULL
218 + && flowClassifier.minDstPortRange() != NULL && flowClassifier.maxDstPortRange() != NULL) {
219 +
220 + for (int port = flowClassifier.minSrcPortRange(); port <= flowClassifier.maxSrcPortRange(); port++) {
221 + srcPortRange.add(TpPort.tpPort(port));
222 + }
223 + for (int port = flowClassifier.minDstPortRange(); port <= flowClassifier.maxDstPortRange(); port++) {
224 + dstPortRange.add(TpPort.tpPort(port));
225 + }
226 + }
227 +
228 + for (TpPort inPort : srcPortRange) {
229 + selector.matchUdpSrc(inPort);
230 + }
231 + for (TpPort outPort : dstPortRange) {
232 + selector.matchUdpDst(outPort);
233 + }
234 + return selector;
235 + }
236 +
237 + /**
238 + * Pack traffic treatment.
239 + *
240 + * @param deviceId device id
241 + * @param srcMacAddress source mac-address
242 + * @param nshDstPort vxlan tunnel port for nsh header
243 + * @param deviceIdfromFc device id if virtual ports are set in flow classifier.
244 + * @param deviceIdfromPp device id if port pair is used to fetch device id.
245 + * @param nshSPI nsh spi
246 + * @param flowClassifier flow-classifier
247 + * @return traffic treatment
248 + */
249 + public TrafficTreatment.Builder packTrafficTreatment(DeviceId deviceId, MacAddress srcMacAddress,
250 + TpPort nshDstPort, DeviceId deviceIdfromFc, DeviceId deviceIdfromPp,
251 + NshServicePathId nshSPI, FlowClassifier flowClassifier) {
252 + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
253 + DriverHandler handler = driverService.createHandler(deviceId);
254 + ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
255 + ExtensionTreatment nspIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SPI.type());
256 + ExtensionTreatment nsiIdTreatment = resolver.getExtensionInstruction(NICIRA_SET_NSH_SI.type());
257 +
258 + treatmentBuilder.extension(nspIdTreatment, deviceId);
259 + treatmentBuilder.extension(nsiIdTreatment, deviceId);
260 + treatmentBuilder.setUdpDst(nshDstPort);
261 +
262 + try {
263 + nspIdTreatment.setPropertyValue("nshSpi", nshSPI);
264 + } catch (Exception e) {
265 + log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
266 + }
267 + try {
268 + nsiIdTreatment.setPropertyValue("nshSi", NSH_SI_ID);
269 + } catch (Exception e) {
270 + log.error("Failed to get extension instruction to set Nsh Si Id {}", deviceId);
271 + }
272 +
273 + if (deviceIdfromPp != null) {
274 + treatmentBuilder.setEthSrc(srcMacAddress);
275 + } else if (deviceIdfromFc != null) {
276 + treatmentBuilder.setVlanId((VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(flowClassifier
277 + .tenantId()).toString())))));
278 + }
279 + return treatmentBuilder;
280 + }
281 +
282 + /**
283 + * Send service-function-forwarder to OVS.
284 + *
285 + * @param selector traffic selector
286 + * @param treatment traffic treatment
287 + * @param deviceId device id
288 + * @param type operation type
289 + */
290 + public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
291 + DeviceId deviceId, Objective.Operation type) {
292 + ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
293 + .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC).withPriority(
294 + L3FWD_PRIORITY);
295 +
296 + if (type.equals(Objective.Operation.ADD)) {
297 + log.debug("flowClassifierRules-->ADD");
298 + flowObjectiveService.forward(deviceId, objective.add());
299 + } else {
300 + log.debug("flowClassifierRules-->REMOVE");
301 + flowObjectiveService.forward(deviceId, objective.remove());
302 + }
303 + }
304 +}