blob: 82c7bcb33abae4fd2b0aa8662dd316f98c70a98f [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
18import static org.slf4j.LoggerFactory.getLogger;
19import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI;
20import static com.google.common.base.Preconditions.checkNotNull;
21
22import java.util.List;
23import java.util.ListIterator;
24
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053025import org.apache.felix.scr.annotations.Component;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053026import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053028import org.apache.felix.scr.annotations.Service;
29
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053030import org.onlab.osgi.DefaultServiceDirectory;
31import org.onlab.osgi.ServiceDirectory;
32import org.onlab.packet.MacAddress;
33import org.onlab.packet.VlanId;
34import org.onosproject.core.ApplicationId;
35import org.onosproject.net.behaviour.ExtensionSelectorResolver;
36import org.onosproject.net.DeviceId;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053037import org.onosproject.net.Host;
38import org.onosproject.net.HostId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053039import org.onosproject.net.NshServicePathId;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053040import org.onosproject.net.PortNumber;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053041import org.onosproject.net.driver.DriverHandler;
42import org.onosproject.net.driver.DriverService;
43import org.onosproject.net.flow.DefaultTrafficSelector;
44import org.onosproject.net.flow.DefaultTrafficTreatment;
45import org.onosproject.net.flow.criteria.ExtensionSelector;
46import org.onosproject.net.flow.TrafficSelector;
47import org.onosproject.net.flow.TrafficTreatment;
48import org.onosproject.net.flowobjective.DefaultForwardingObjective;
49import org.onosproject.net.flowobjective.FlowObjectiveService;
50import org.onosproject.net.flowobjective.ForwardingObjective;
51import org.onosproject.net.flowobjective.Objective;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053052import org.onosproject.net.host.HostService;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053053import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
54import org.onosproject.vtnrsc.VirtualPortId;
55import org.onosproject.vtnrsc.service.VtnRscService;
56import org.onosproject.vtnrsc.PortChain;
57import org.onosproject.vtnrsc.PortPair;
58import org.onosproject.vtnrsc.PortPairGroup;
59import org.onosproject.vtnrsc.PortPairGroupId;
60import org.onosproject.vtnrsc.PortPairId;
61import org.onosproject.vtnrsc.virtualport.VirtualPortService;
62import org.onosproject.vtnrsc.portpair.PortPairService;
63import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
64import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
65import org.onosproject.vtnrsc.portchain.PortChainService;
66import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService;
67
68import org.slf4j.Logger;
69
70/**
71 * Provides Service Function Forwarder implementation.
72 */
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053073@Component(immediate = true)
74@Service
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053075public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderService {
76
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053078 protected HostService hostService;
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053080 protected DriverService driverService;
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected VirtualPortService virtualPortService;
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected VtnRscService vtnRscService;
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected PortPairService portPairService;
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected PortPairGroupService portPairGroupService;
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected FlowClassifierService flowClassifierService;
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected PortChainService portChainService;
93
94 private final Logger log = getLogger(getClass());
95 protected ApplicationId appId;
96 protected FlowObjectiveService flowObjectiveService;
97
98 private static final String DRIVER_NAME = "onosfw";
99 private static final String PORT_CHAIN_NOT_NULL = "Port-Chain cannot be null";
100 private static final String PORT_CHAIN_ID_NOT_NULL = "Port-Chain-Id cannot be null";
101 private static final String APP_ID_NOT_NULL = "Application-Id cannot be null";
102 private static final int NULL = 0;
103
104 /**
105 * Default constructor.
106 */
107 public ServiceFunctionForwarderImpl() {
108 }
109
110 /**
111 * Explicit constructor.
Bharat saraswal1adafb32015-12-11 01:29:44 +0530112 *
113 * @param appId Application id
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530114 */
115 public ServiceFunctionForwarderImpl(ApplicationId appId) {
116 this.appId = checkNotNull(appId, APP_ID_NOT_NULL);
117 ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
118 this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
119 }
120
121 @Override
122 public void installForwardingRule(PortChain portChain, NshServicePathId nshSPI) {
123 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
124 prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.ADD);
125 }
126
127 @Override
128 public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSPI) {
129 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
130 prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.REMOVE);
131 }
132
133 @Override
134 public void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSPI,
135 Objective.Operation type) {
136
137 // Go through the port pair group list
138 List<PortPairGroupId> portPairGrpList = portChain.portPairGroups();
139 ListIterator<PortPairGroupId> listGrpIterator = portPairGrpList.listIterator();
140
141 // Get source port pair group
142 if (!listGrpIterator.hasNext()) {
143 return;
144 }
145 PortPairGroupId portPairGrpId = listGrpIterator.next();
146 PortPairGroup currentPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
147
148 // Get destination port pair group
149 if (!listGrpIterator.hasNext()) {
150 return;
151 }
152 portPairGrpId = listGrpIterator.next();
153 PortPairGroup nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
154
155 // push SFF to OVS
156 pushServiceFunctionForwarder(currentPortPairGroup, nextPortPairGroup, listGrpIterator, nshSPI, type);
157 }
158
159 /**
160 * Push service-function-forwarder to OVS.
161 *
162 * @param currentPortPairGroup current port-pair-group
163 * @param nextPortPairGroup next port-pair-group
164 * @param listGrpIterator pointer to port-pair-group list
Bharat saraswal1adafb32015-12-11 01:29:44 +0530165 * @param nshSPI nsh service path id
166 * @param type objective type
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530167 */
168 public void pushServiceFunctionForwarder(PortPairGroup currentPortPairGroup, PortPairGroup nextPortPairGroup,
169 ListIterator<PortPairGroupId> listGrpIterator, NshServicePathId nshSPI, Objective.Operation type) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530170 DeviceId deviceId = null;
171 DeviceId currentDeviceId = null;
172 DeviceId nextDeviceId = null;
173 PortPairGroupId portPairGrpId = null;
174
175 // Travel from SF to SF.
176 do {
177 // Get the required information on port pairs from source port pair
178 // group
179 List<PortPairId> portPairList = currentPortPairGroup.portPairs();
180 ListIterator<PortPairId> portPLIterator = portPairList.listIterator();
181 if (!portPLIterator.hasNext()) {
182 break;
183 }
184
185 PortPairId portPairId = portPLIterator.next();
186 PortPair portPair = portPairService.getPortPair(portPairId);
187
188 currentDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress()));
189 if (deviceId == null) {
190 deviceId = currentDeviceId;
191 }
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530192
193 // pack traffic selector
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530194 TrafficSelector.Builder selector = packTrafficSelector(deviceId, portPair, nshSPI);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530195
196 // Get the required information on port pairs from destination port
197 // pair group
198 portPairList = nextPortPairGroup.portPairs();
199 portPLIterator = portPairList.listIterator();
200 if (!portPLIterator.hasNext()) {
201 break;
202 }
203
204 portPairId = portPLIterator.next();
205 portPair = portPairService.getPortPair(portPairId);
206
207 nextDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress()));
208
209 // pack traffic treatment
210 TrafficTreatment.Builder treatment = packTrafficTreatment(currentDeviceId, nextDeviceId, portPair);
211
212 // Send SFF to OVS
213 sendServiceFunctionForwarder(selector, treatment, deviceId, type);
214
215 // Replace source port pair group with destination port pair group
216 // for moving to next SFF processing.
217 currentPortPairGroup = nextPortPairGroup;
218 if (!listGrpIterator.hasNext()) {
219 break;
220 }
221 portPairGrpId = listGrpIterator.next();
222 nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
223 } while (true);
224 }
225
226 /**
227 * Pack Traffic selector.
228 *
229 * @param deviceId device id
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530230 * @param portPair port-pair
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530231 * @param nshSPI nsh spi
232 * @return traffic treatment
233 */
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530234 public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId, PortPair portPair, NshServicePathId nshSPI) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530235 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530236 MacAddress dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
237 Host host = hostService.getHost(HostId.hostId(dstMacAddress));
238 PortNumber port = host.location().port();
239 selector.matchInPort(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530240
241 DriverHandler handler = driverService.createHandler(deviceId);
242 ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
243 ExtensionSelector nspSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
244
245 try {
246 nspSpiSelector.setPropertyValue("nshSpi", nshSPI);
247 } catch (Exception e) {
248 log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
249 }
250
251 selector.extension(nspSpiSelector, deviceId);
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530252
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530253 return selector;
254 }
255
256 /**
257 * Pack Traffic treatment.
258 *
259 * @param currentDeviceId current device id
260 * @param nextDeviceId next device id
261 * @param portPair port-pair
262 * @return traffic treatment
263 */
264 public TrafficTreatment.Builder packTrafficTreatment(DeviceId currentDeviceId, DeviceId nextDeviceId,
265 PortPair portPair) {
266 MacAddress srcMacAddress = null;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530267
268 // Check the treatment whether destination SF is on same OVS or in
269 // different OVS.
270 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
271 if (currentDeviceId.equals(nextDeviceId)) {
272 srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530273
274 Host host = hostService.getHost(HostId.hostId(srcMacAddress));
275 PortNumber port = host.location().port();
276 treatment.setOutput(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530277 } else {
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530278 VlanId vlanId = VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(portPair.tenantId()).toString())));
279 treatment.setVlanId(vlanId);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530280 }
281
282 return treatment;
283 }
284
285 /**
286 * Send service function forwarder to OVS.
287 *
288 * @param selector traffic selector
289 * @param treatment traffic treatment
290 * @param deviceId device id
291 * @param type operation type
292 */
293 public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
294 DeviceId deviceId, Objective.Operation type) {
295 ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530296 .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530297 if (type.equals(Objective.Operation.ADD)) {
298 log.debug("ADD");
299 flowObjectiveService.forward(deviceId, objective.add());
300 } else {
301 log.debug("REMOVE");
302 flowObjectiveService.forward(deviceId, objective.remove());
303 }
304 }
305}