blob: 6486d314692b8cb65773caf33afa83fe45313ab4 [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
23import java.util.LinkedList;
24import java.util.List;
25import java.util.ListIterator;
26
27import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.onlab.osgi.DefaultServiceDirectory;
30import org.onlab.osgi.ServiceDirectory;
31import org.onlab.packet.MacAddress;
32import org.onlab.packet.TpPort;
33import org.onlab.packet.VlanId;
34import org.onosproject.core.ApplicationId;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.NshServicePathId;
37import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
38import org.onosproject.net.driver.DriverHandler;
39import org.onosproject.net.driver.DriverService;
40import org.onosproject.net.flow.DefaultTrafficSelector;
41import org.onosproject.net.flow.DefaultTrafficTreatment;
42import org.onosproject.net.flow.TrafficSelector;
43import org.onosproject.net.flow.TrafficTreatment;
44import org.onosproject.net.flow.criteria.Criteria;
45import org.onosproject.net.flow.instructions.ExtensionTreatment;
46import org.onosproject.net.flowobjective.DefaultForwardingObjective;
47import org.onosproject.net.flowobjective.FlowObjectiveService;
48import org.onosproject.net.flowobjective.ForwardingObjective;
49import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
50import org.onosproject.net.flowobjective.Objective;
51import org.onosproject.net.flowobjective.Objective.Operation;
52import org.onosproject.sfc.installer.FlowClassifierInstallerService;
53import org.onosproject.vtnrsc.FlowClassifier;
54import org.onosproject.vtnrsc.FlowClassifierId;
55import org.onosproject.vtnrsc.PortChain;
56import org.onosproject.vtnrsc.PortPair;
57import org.onosproject.vtnrsc.PortPairGroup;
58import org.onosproject.vtnrsc.PortPairGroupId;
59import org.onosproject.vtnrsc.PortPairId;
60import org.onosproject.vtnrsc.VirtualPortId;
61import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
62import org.onosproject.vtnrsc.portpair.PortPairService;
63import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
64import org.onosproject.vtnrsc.service.VtnRscService;
65import org.onosproject.vtnrsc.virtualport.VirtualPortService;
66import org.slf4j.Logger;
67
68/**
69 * Provides flow classifier installer implementation.
70 */
71public 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}