blob: 4eab2bf9dc81d50b9d7adf272f8828d8b0976d27 [file] [log] [blame]
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +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.forwarder.impl;
17
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053018import org.apache.felix.scr.annotations.Component;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053019import org.apache.felix.scr.annotations.Reference;
20import org.apache.felix.scr.annotations.ReferenceCardinality;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053021import org.apache.felix.scr.annotations.Service;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053022import org.onlab.osgi.DefaultServiceDirectory;
23import org.onlab.osgi.ServiceDirectory;
24import org.onlab.packet.MacAddress;
25import org.onlab.packet.VlanId;
26import org.onosproject.core.ApplicationId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053027import org.onosproject.net.DeviceId;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053028import org.onosproject.net.Host;
29import org.onosproject.net.HostId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053030import org.onosproject.net.NshServicePathId;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053031import org.onosproject.net.PortNumber;
Jonathan Hart51539b82015-10-29 09:53:04 -070032import org.onosproject.net.behaviour.ExtensionSelectorResolver;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053033import org.onosproject.net.driver.DriverHandler;
34import org.onosproject.net.driver.DriverService;
35import org.onosproject.net.flow.DefaultTrafficSelector;
36import org.onosproject.net.flow.DefaultTrafficTreatment;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053037import org.onosproject.net.flow.TrafficSelector;
38import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart51539b82015-10-29 09:53:04 -070039import org.onosproject.net.flow.criteria.ExtensionSelector;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053040import org.onosproject.net.flowobjective.DefaultForwardingObjective;
41import org.onosproject.net.flowobjective.FlowObjectiveService;
42import org.onosproject.net.flowobjective.ForwardingObjective;
Jonathan Hart51539b82015-10-29 09:53:04 -070043import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053044import org.onosproject.net.flowobjective.Objective;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053045import org.onosproject.net.host.HostService;
Jonathan Hart51539b82015-10-29 09:53:04 -070046import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053047import org.onosproject.vtnrsc.PortChain;
48import org.onosproject.vtnrsc.PortPair;
49import org.onosproject.vtnrsc.PortPairGroup;
50import org.onosproject.vtnrsc.PortPairGroupId;
51import org.onosproject.vtnrsc.PortPairId;
Jonathan Hart51539b82015-10-29 09:53:04 -070052import org.onosproject.vtnrsc.VirtualPortId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053053import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
54import org.onosproject.vtnrsc.portchain.PortChainService;
Jonathan Hart51539b82015-10-29 09:53:04 -070055import org.onosproject.vtnrsc.portpair.PortPairService;
56import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
57import org.onosproject.vtnrsc.service.VtnRscService;
58import org.onosproject.vtnrsc.virtualport.VirtualPortService;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053059import org.slf4j.Logger;
60
Jonathan Hart51539b82015-10-29 09:53:04 -070061import java.util.List;
62import java.util.ListIterator;
63
64import static com.google.common.base.Preconditions.checkNotNull;
65import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI;
66import static org.slf4j.LoggerFactory.getLogger;
67
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053068/**
69 * Provides Service Function Forwarder implementation.
70 */
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053071@Component(immediate = true)
72@Service
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053073public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderService {
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053076 protected HostService hostService;
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053078 protected DriverService driverService;
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected VirtualPortService virtualPortService;
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected VtnRscService vtnRscService;
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected PortPairService portPairService;
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected PortPairGroupService portPairGroupService;
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected FlowClassifierService flowClassifierService;
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected PortChainService portChainService;
91
92 private final Logger log = getLogger(getClass());
93 protected ApplicationId appId;
94 protected FlowObjectiveService flowObjectiveService;
95
96 private static final String DRIVER_NAME = "onosfw";
97 private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
98 private static final String PORT_CHAIN_ID_NOT_NULL = "Port-Chain-Id cannot be null";
99 private static final String APP_ID_NOT_NULL = "Application-Id cannot be null";
100 private static final int NULL = 0;
101
102 /**
103 * Default constructor.
104 */
105 public ServiceFunctionForwarderImpl() {
106 }
107
108 /**
109 * Explicit constructor.
Bharat saraswal1adafb32015-12-11 01:29:44 +0530110 *
111 * @param appId Application id
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530112 */
113 public ServiceFunctionForwarderImpl(ApplicationId appId) {
114 this.appId = checkNotNull(appId, APP_ID_NOT_NULL);
115 ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
116 this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
117 }
118
119 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700120 public void installForwardingRule(PortChain portChain, NshServicePathId nshSpi) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530121 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
Jonathan Hart51539b82015-10-29 09:53:04 -0700122 prepareServiceFunctionForwarder(portChain, nshSpi, Objective.Operation.ADD);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530123 }
124
125 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700126 public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSpi) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530127 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
Jonathan Hart51539b82015-10-29 09:53:04 -0700128 prepareServiceFunctionForwarder(portChain, nshSpi, Objective.Operation.REMOVE);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530129 }
130
131 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700132 public void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSpi,
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530133 Objective.Operation type) {
134
135 // Go through the port pair group list
136 List<PortPairGroupId> portPairGrpList = portChain.portPairGroups();
137 ListIterator<PortPairGroupId> listGrpIterator = portPairGrpList.listIterator();
138
139 // Get source port pair group
140 if (!listGrpIterator.hasNext()) {
141 return;
142 }
143 PortPairGroupId portPairGrpId = listGrpIterator.next();
144 PortPairGroup currentPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
145
146 // Get destination port pair group
147 if (!listGrpIterator.hasNext()) {
148 return;
149 }
150 portPairGrpId = listGrpIterator.next();
151 PortPairGroup nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
152
153 // push SFF to OVS
Jonathan Hart51539b82015-10-29 09:53:04 -0700154 pushServiceFunctionForwarder(currentPortPairGroup, nextPortPairGroup, listGrpIterator, nshSpi, type);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530155 }
156
157 /**
158 * Push service-function-forwarder to OVS.
159 *
160 * @param currentPortPairGroup current port-pair-group
161 * @param nextPortPairGroup next port-pair-group
162 * @param listGrpIterator pointer to port-pair-group list
Jonathan Hart51539b82015-10-29 09:53:04 -0700163 * @param nshSpi nsh service path id
Bharat saraswal1adafb32015-12-11 01:29:44 +0530164 * @param type objective type
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530165 */
166 public void pushServiceFunctionForwarder(PortPairGroup currentPortPairGroup, PortPairGroup nextPortPairGroup,
Jonathan Hart51539b82015-10-29 09:53:04 -0700167 ListIterator<PortPairGroupId> listGrpIterator, NshServicePathId nshSpi, Objective.Operation type) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530168 DeviceId deviceId = null;
169 DeviceId currentDeviceId = null;
170 DeviceId nextDeviceId = null;
171 PortPairGroupId portPairGrpId = null;
172
173 // Travel from SF to SF.
174 do {
175 // Get the required information on port pairs from source port pair
176 // group
177 List<PortPairId> portPairList = currentPortPairGroup.portPairs();
178 ListIterator<PortPairId> portPLIterator = portPairList.listIterator();
179 if (!portPLIterator.hasNext()) {
180 break;
181 }
182
183 PortPairId portPairId = portPLIterator.next();
184 PortPair portPair = portPairService.getPortPair(portPairId);
185
Jonathan Hart51539b82015-10-29 09:53:04 -0700186 currentDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530187 if (deviceId == null) {
188 deviceId = currentDeviceId;
189 }
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530190
191 // pack traffic selector
Jonathan Hart51539b82015-10-29 09:53:04 -0700192 TrafficSelector.Builder selector = packTrafficSelector(deviceId, portPair, nshSpi);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530193
194 // Get the required information on port pairs from destination port
195 // pair group
196 portPairList = nextPortPairGroup.portPairs();
197 portPLIterator = portPairList.listIterator();
198 if (!portPLIterator.hasNext()) {
199 break;
200 }
201
202 portPairId = portPLIterator.next();
203 portPair = portPairService.getPortPair(portPairId);
204
Jonathan Hart51539b82015-10-29 09:53:04 -0700205 nextDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(portPair.ingress()));
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530206
207 // pack traffic treatment
208 TrafficTreatment.Builder treatment = packTrafficTreatment(currentDeviceId, nextDeviceId, portPair);
209
210 // Send SFF to OVS
211 sendServiceFunctionForwarder(selector, treatment, deviceId, type);
212
213 // Replace source port pair group with destination port pair group
214 // for moving to next SFF processing.
215 currentPortPairGroup = nextPortPairGroup;
216 if (!listGrpIterator.hasNext()) {
217 break;
218 }
219 portPairGrpId = listGrpIterator.next();
220 nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
221 } while (true);
222 }
223
224 /**
225 * Pack Traffic selector.
226 *
227 * @param deviceId device id
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530228 * @param portPair port-pair
Jonathan Hart51539b82015-10-29 09:53:04 -0700229 * @param nshSpi nsh spi
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530230 * @return traffic treatment
231 */
Jonathan Hart51539b82015-10-29 09:53:04 -0700232 public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId, PortPair portPair, NshServicePathId nshSpi) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530233 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530234 MacAddress dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
235 Host host = hostService.getHost(HostId.hostId(dstMacAddress));
236 PortNumber port = host.location().port();
237 selector.matchInPort(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530238
239 DriverHandler handler = driverService.createHandler(deviceId);
240 ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
241 ExtensionSelector nspSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
242
243 try {
Jonathan Hart51539b82015-10-29 09:53:04 -0700244 nspSpiSelector.setPropertyValue("nshSpi", nshSpi);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530245 } catch (Exception e) {
246 log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
247 }
248
249 selector.extension(nspSpiSelector, deviceId);
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530250
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530251 return selector;
252 }
253
254 /**
255 * Pack Traffic treatment.
256 *
257 * @param currentDeviceId current device id
258 * @param nextDeviceId next device id
259 * @param portPair port-pair
260 * @return traffic treatment
261 */
262 public TrafficTreatment.Builder packTrafficTreatment(DeviceId currentDeviceId, DeviceId nextDeviceId,
263 PortPair portPair) {
264 MacAddress srcMacAddress = null;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530265
266 // Check the treatment whether destination SF is on same OVS or in
267 // different OVS.
268 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
269 if (currentDeviceId.equals(nextDeviceId)) {
270 srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530271
272 Host host = hostService.getHost(HostId.hostId(srcMacAddress));
273 PortNumber port = host.location().port();
274 treatment.setOutput(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530275 } else {
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530276 VlanId vlanId = VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(portPair.tenantId()).toString())));
277 treatment.setVlanId(vlanId);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530278 }
279
280 return treatment;
281 }
282
283 /**
284 * Send service function forwarder to OVS.
285 *
286 * @param selector traffic selector
287 * @param treatment traffic treatment
288 * @param deviceId device id
289 * @param type operation type
290 */
291 public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
292 DeviceId deviceId, Objective.Operation type) {
293 ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530294 .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530295 if (type.equals(Objective.Operation.ADD)) {
296 log.debug("ADD");
297 flowObjectiveService.forward(deviceId, objective.add());
298 } else {
299 log.debug("REMOVE");
300 flowObjectiveService.forward(deviceId, objective.remove());
301 }
302 }
303}