Mahesh Poojary S
Committed by Gerrit Code Review

[ONOS-3120] Service Function Forwarder Implementation

Change-Id: I483ce290be21ed35a30994d5685005a0dfd3f13d
...@@ -15,29 +15,37 @@ ...@@ -15,29 +15,37 @@
15 */ 15 */
16 package org.onosproject.sfc.forwarder; 16 package org.onosproject.sfc.forwarder;
17 17
18 -import org.onosproject.core.ApplicationId;
19 import org.onosproject.net.flowobjective.Objective; 18 import org.onosproject.net.flowobjective.Objective;
19 +import org.onosproject.net.NshServicePathId;
20 import org.onosproject.vtnrsc.PortChain; 20 import org.onosproject.vtnrsc.PortChain;
21 21
22 /** 22 /**
23 * Abstraction of an entity which provides Service function forwarder. 23 * Abstraction of an entity which provides Service function forwarder.
24 */ 24 */
25 -public interface ServiceFunctionForwarder { 25 +public interface ServiceFunctionForwarderService {
26 26
27 /** 27 /**
28 - * Install Service function chain. 28 + * Install Forwarding rule.
29 * 29 *
30 - * @param portChain Port chain 30 + * @param portChain port-chain
31 + * @param nshSPI nsh spi
31 */ 32 */
32 - void install(PortChain portChain); 33 + void installForwardingRule(PortChain portChain, NshServicePathId nshSPI);
33 34
34 /** 35 /**
35 - * Programs forwarding object for Service Function. 36 + * Uninstall Forwarding rule.
36 * 37 *
37 - * @param portChain port chain 38 + * @param portChain port-chain
38 - * @param appid application id 39 + * @param nshSPI nsh spi
40 + */
41 + void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSPI);
42 +
43 + /**
44 + * Prepare forwarding object for Service Function.
45 + *
46 + * @param portChain port-chain
47 + * @param nshSPI nsh spi
39 * @param type forwarding objective operation type 48 * @param type forwarding objective operation type
40 */ 49 */
41 - void programServiceFunctionForwarder(PortChain portChain, ApplicationId appid, 50 + void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSPI, Objective.Operation type);
42 - Objective.Operation type);
43 } 51 }
......
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.forwarder.impl;
17 +
18 +import static org.slf4j.LoggerFactory.getLogger;
19 +import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI;
20 +import static com.google.common.base.Preconditions.checkNotNull;
21 +
22 +import java.util.List;
23 +import java.util.ListIterator;
24 +
25 +import org.apache.felix.scr.annotations.Reference;
26 +import org.apache.felix.scr.annotations.ReferenceCardinality;
27 +import org.onlab.osgi.DefaultServiceDirectory;
28 +import org.onlab.osgi.ServiceDirectory;
29 +import org.onlab.packet.MacAddress;
30 +import org.onlab.packet.VlanId;
31 +import org.onosproject.core.ApplicationId;
32 +import org.onosproject.net.behaviour.ExtensionSelectorResolver;
33 +import org.onosproject.net.DeviceId;
34 +import org.onosproject.net.NshServicePathId;
35 +import org.onosproject.net.driver.DriverHandler;
36 +import org.onosproject.net.driver.DriverService;
37 +import org.onosproject.net.flow.DefaultTrafficSelector;
38 +import org.onosproject.net.flow.DefaultTrafficTreatment;
39 +import org.onosproject.net.flow.criteria.ExtensionSelector;
40 +import org.onosproject.net.flow.TrafficSelector;
41 +import org.onosproject.net.flow.TrafficTreatment;
42 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
43 +import org.onosproject.net.flowobjective.FlowObjectiveService;
44 +import org.onosproject.net.flowobjective.ForwardingObjective;
45 +import org.onosproject.net.flowobjective.Objective;
46 +import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
47 +import org.onosproject.vtnrsc.VirtualPortId;
48 +import org.onosproject.vtnrsc.service.VtnRscService;
49 +import org.onosproject.vtnrsc.PortChain;
50 +import org.onosproject.vtnrsc.PortPair;
51 +import org.onosproject.vtnrsc.PortPairGroup;
52 +import org.onosproject.vtnrsc.PortPairGroupId;
53 +import org.onosproject.vtnrsc.PortPairId;
54 +import org.onosproject.vtnrsc.virtualport.VirtualPortService;
55 +import org.onosproject.vtnrsc.portpair.PortPairService;
56 +import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
57 +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
58 +import org.onosproject.vtnrsc.portchain.PortChainService;
59 +import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService;
60 +
61 +import org.slf4j.Logger;
62 +
63 +/**
64 + * Provides Service Function Forwarder implementation.
65 + */
66 +public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderService {
67 +
68 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 + protected DriverService driverService;
70 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 + protected VirtualPortService virtualPortService;
72 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 + protected VtnRscService vtnRscService;
74 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 + protected PortPairService portPairService;
76 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 + protected PortPairGroupService portPairGroupService;
78 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 + protected FlowClassifierService flowClassifierService;
80 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 + protected PortChainService portChainService;
82 +
83 + private final Logger log = getLogger(getClass());
84 + protected ApplicationId appId;
85 + protected FlowObjectiveService flowObjectiveService;
86 +
87 + private static final String DRIVER_NAME = "onosfw";
88 + private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
89 + private static final String PORT_CHAIN_ID_NOT_NULL = "Port-Chain-Id cannot be null";
90 + private static final String APP_ID_NOT_NULL = "Application-Id cannot be null";
91 + private static final int NULL = 0;
92 +
93 + /**
94 + * Default constructor.
95 + */
96 + public ServiceFunctionForwarderImpl() {
97 + }
98 +
99 + /**
100 + * Explicit constructor.
101 + */
102 + public ServiceFunctionForwarderImpl(ApplicationId appId) {
103 + this.appId = checkNotNull(appId, APP_ID_NOT_NULL);
104 + ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
105 + this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
106 + }
107 +
108 + @Override
109 + public void installForwardingRule(PortChain portChain, NshServicePathId nshSPI) {
110 + checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
111 + prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.ADD);
112 + }
113 +
114 + @Override
115 + public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSPI) {
116 + checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
117 + prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.REMOVE);
118 + }
119 +
120 + @Override
121 + public void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSPI,
122 + Objective.Operation type) {
123 +
124 + // Go through the port pair group list
125 + List<PortPairGroupId> portPairGrpList = portChain.portPairGroups();
126 + ListIterator<PortPairGroupId> listGrpIterator = portPairGrpList.listIterator();
127 +
128 + // Get source port pair group
129 + if (!listGrpIterator.hasNext()) {
130 + return;
131 + }
132 + PortPairGroupId portPairGrpId = listGrpIterator.next();
133 + PortPairGroup currentPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
134 +
135 + // Get destination port pair group
136 + if (!listGrpIterator.hasNext()) {
137 + return;
138 + }
139 + portPairGrpId = listGrpIterator.next();
140 + PortPairGroup nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
141 +
142 + // push SFF to OVS
143 + pushServiceFunctionForwarder(currentPortPairGroup, nextPortPairGroup, listGrpIterator, nshSPI, type);
144 + }
145 +
146 + /**
147 + * Push service-function-forwarder to OVS.
148 + *
149 + * @param currentPortPairGroup current port-pair-group
150 + * @param nextPortPairGroup next port-pair-group
151 + * @param listGrpIterator pointer to port-pair-group list
152 + */
153 + public void pushServiceFunctionForwarder(PortPairGroup currentPortPairGroup, PortPairGroup nextPortPairGroup,
154 + ListIterator<PortPairGroupId> listGrpIterator, NshServicePathId nshSPI, Objective.Operation type) {
155 + MacAddress srcMacAddress = null;
156 + MacAddress dstMacAddress = null;
157 + DeviceId deviceId = null;
158 + DeviceId currentDeviceId = null;
159 + DeviceId nextDeviceId = null;
160 + PortPairGroupId portPairGrpId = null;
161 +
162 + // Travel from SF to SF.
163 + do {
164 + // Get the required information on port pairs from source port pair
165 + // group
166 + List<PortPairId> portPairList = currentPortPairGroup.portPairs();
167 + ListIterator<PortPairId> portPLIterator = portPairList.listIterator();
168 + if (!portPLIterator.hasNext()) {
169 + break;
170 + }
171 +
172 + PortPairId portPairId = portPLIterator.next();
173 + PortPair portPair = portPairService.getPortPair(portPairId);
174 +
175 + currentDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress()));
176 + if (deviceId == null) {
177 + deviceId = currentDeviceId;
178 + }
179 + srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
180 + dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
181 +
182 + // pack traffic selector
183 + TrafficSelector.Builder selector = packTrafficSelector(deviceId, srcMacAddress, dstMacAddress, nshSPI);
184 +
185 + // Get the required information on port pairs from destination port
186 + // pair group
187 + portPairList = nextPortPairGroup.portPairs();
188 + portPLIterator = portPairList.listIterator();
189 + if (!portPLIterator.hasNext()) {
190 + break;
191 + }
192 +
193 + portPairId = portPLIterator.next();
194 + portPair = portPairService.getPortPair(portPairId);
195 +
196 + nextDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress()));
197 +
198 + // pack traffic treatment
199 + TrafficTreatment.Builder treatment = packTrafficTreatment(currentDeviceId, nextDeviceId, portPair);
200 +
201 + // Send SFF to OVS
202 + sendServiceFunctionForwarder(selector, treatment, deviceId, type);
203 +
204 + // Replace source port pair group with destination port pair group
205 + // for moving to next SFF processing.
206 + currentPortPairGroup = nextPortPairGroup;
207 + if (!listGrpIterator.hasNext()) {
208 + break;
209 + }
210 + portPairGrpId = listGrpIterator.next();
211 + nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
212 + } while (true);
213 + }
214 +
215 + /**
216 + * Pack Traffic selector.
217 + *
218 + * @param deviceId device id
219 + * @param srcMacAddress source mac-address
220 + * @param dstMacAddress destination mac-address
221 + * @param nshSPI nsh spi
222 + * @return traffic treatment
223 + */
224 + public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId, MacAddress srcMacAddress,
225 + MacAddress dstMacAddress, NshServicePathId nshSPI) {
226 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
227 + selector.matchEthSrc(srcMacAddress);
228 + selector.matchEthDst(dstMacAddress);
229 +
230 + DriverHandler handler = driverService.createHandler(deviceId);
231 + ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
232 + ExtensionSelector nspSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
233 +
234 + try {
235 + nspSpiSelector.setPropertyValue("nshSpi", nshSPI);
236 + } catch (Exception e) {
237 + log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
238 + }
239 +
240 + selector.extension(nspSpiSelector, deviceId);
241 + return selector;
242 + }
243 +
244 + /**
245 + * Pack Traffic treatment.
246 + *
247 + * @param currentDeviceId current device id
248 + * @param nextDeviceId next device id
249 + * @param portPair port-pair
250 + * @return traffic treatment
251 + */
252 + public TrafficTreatment.Builder packTrafficTreatment(DeviceId currentDeviceId, DeviceId nextDeviceId,
253 + PortPair portPair) {
254 + MacAddress srcMacAddress = null;
255 + MacAddress dstMacAddress = null;
256 +
257 + // Check the treatment whether destination SF is on same OVS or in
258 + // different OVS.
259 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
260 + if (currentDeviceId.equals(nextDeviceId)) {
261 + srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
262 + dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
263 + treatment.setEthSrc(srcMacAddress);
264 + treatment.setEthDst(dstMacAddress);
265 + } else {
266 + treatment.setVlanId(VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(portPair
267 + .tenantId()).toString()))));
268 + }
269 +
270 + return treatment;
271 + }
272 +
273 + /**
274 + * Send service function forwarder to OVS.
275 + *
276 + * @param selector traffic selector
277 + * @param treatment traffic treatment
278 + * @param deviceId device id
279 + * @param type operation type
280 + */
281 + public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
282 + DeviceId deviceId, Objective.Operation type) {
283 + ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
284 + .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
285 + if (type.equals(Objective.Operation.ADD)) {
286 + log.debug("ADD");
287 + flowObjectiveService.forward(deviceId, objective.add());
288 + } else {
289 + log.debug("REMOVE");
290 + flowObjectiveService.forward(deviceId, objective.remove());
291 + }
292 + }
293 +}
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 +
17 +/**
18 + * SFC Service manager for interacting with SFC.
19 + */
20 +package org.onosproject.sfc.forwarder.impl;