blob: 28f7709a287e8801fe427b45200d085f879197ba [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.
112 */
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
120 public void installForwardingRule(PortChain portChain, NshServicePathId nshSPI) {
121 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
122 prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.ADD);
123 }
124
125 @Override
126 public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSPI) {
127 checkNotNull(portChain, PORT_CHAIN_NOT_NULL);
128 prepareServiceFunctionForwarder(portChain, nshSPI, Objective.Operation.REMOVE);
129 }
130
131 @Override
132 public void prepareServiceFunctionForwarder(PortChain portChain, NshServicePathId nshSPI,
133 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
154 pushServiceFunctionForwarder(currentPortPairGroup, nextPortPairGroup, listGrpIterator, nshSPI, type);
155 }
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
163 */
164 public void pushServiceFunctionForwarder(PortPairGroup currentPortPairGroup, PortPairGroup nextPortPairGroup,
165 ListIterator<PortPairGroupId> listGrpIterator, NshServicePathId nshSPI, Objective.Operation type) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530166 DeviceId deviceId = null;
167 DeviceId currentDeviceId = null;
168 DeviceId nextDeviceId = null;
169 PortPairGroupId portPairGrpId = null;
170
171 // Travel from SF to SF.
172 do {
173 // Get the required information on port pairs from source port pair
174 // group
175 List<PortPairId> portPairList = currentPortPairGroup.portPairs();
176 ListIterator<PortPairId> portPLIterator = portPairList.listIterator();
177 if (!portPLIterator.hasNext()) {
178 break;
179 }
180
181 PortPairId portPairId = portPLIterator.next();
182 PortPair portPair = portPairService.getPortPair(portPairId);
183
184 currentDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress()));
185 if (deviceId == null) {
186 deviceId = currentDeviceId;
187 }
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530188
189 // pack traffic selector
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530190 TrafficSelector.Builder selector = packTrafficSelector(deviceId, portPair, nshSPI);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530191
192 // Get the required information on port pairs from destination port
193 // pair group
194 portPairList = nextPortPairGroup.portPairs();
195 portPLIterator = portPairList.listIterator();
196 if (!portPLIterator.hasNext()) {
197 break;
198 }
199
200 portPairId = portPLIterator.next();
201 portPair = portPairService.getPortPair(portPairId);
202
203 nextDeviceId = vtnRscService.getSFToSFFMaping(VirtualPortId.portId(portPair.ingress()));
204
205 // pack traffic treatment
206 TrafficTreatment.Builder treatment = packTrafficTreatment(currentDeviceId, nextDeviceId, portPair);
207
208 // Send SFF to OVS
209 sendServiceFunctionForwarder(selector, treatment, deviceId, type);
210
211 // Replace source port pair group with destination port pair group
212 // for moving to next SFF processing.
213 currentPortPairGroup = nextPortPairGroup;
214 if (!listGrpIterator.hasNext()) {
215 break;
216 }
217 portPairGrpId = listGrpIterator.next();
218 nextPortPairGroup = portPairGroupService.getPortPairGroup(portPairGrpId);
219 } while (true);
220 }
221
222 /**
223 * Pack Traffic selector.
224 *
225 * @param deviceId device id
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530226 * @param portPair port-pair
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530227 * @param nshSPI nsh spi
228 * @return traffic treatment
229 */
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530230 public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId, PortPair portPair, NshServicePathId nshSPI) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530231 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530232 MacAddress dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
233 Host host = hostService.getHost(HostId.hostId(dstMacAddress));
234 PortNumber port = host.location().port();
235 selector.matchInPort(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530236
237 DriverHandler handler = driverService.createHandler(deviceId);
238 ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
239 ExtensionSelector nspSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
240
241 try {
242 nspSpiSelector.setPropertyValue("nshSpi", nshSPI);
243 } catch (Exception e) {
244 log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
245 }
246
247 selector.extension(nspSpiSelector, deviceId);
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530248
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530249 return selector;
250 }
251
252 /**
253 * Pack Traffic treatment.
254 *
255 * @param currentDeviceId current device id
256 * @param nextDeviceId next device id
257 * @param portPair port-pair
258 * @return traffic treatment
259 */
260 public TrafficTreatment.Builder packTrafficTreatment(DeviceId currentDeviceId, DeviceId nextDeviceId,
261 PortPair portPair) {
262 MacAddress srcMacAddress = null;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530263
264 // Check the treatment whether destination SF is on same OVS or in
265 // different OVS.
266 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
267 if (currentDeviceId.equals(nextDeviceId)) {
268 srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530269
270 Host host = hostService.getHost(HostId.hostId(srcMacAddress));
271 PortNumber port = host.location().port();
272 treatment.setOutput(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530273 } else {
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530274 VlanId vlanId = VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(portPair.tenantId()).toString())));
275 treatment.setVlanId(vlanId);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530276 }
277
278 return treatment;
279 }
280
281 /**
282 * Send service function forwarder to OVS.
283 *
284 * @param selector traffic selector
285 * @param treatment traffic treatment
286 * @param deviceId device id
287 * @param type operation type
288 */
289 public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
290 DeviceId deviceId, Objective.Operation type) {
291 ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530292 .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530293 if (type.equals(Objective.Operation.ADD)) {
294 log.debug("ADD");
295 flowObjectiveService.forward(deviceId, objective.add());
296 } else {
297 log.debug("REMOVE");
298 flowObjectiveService.forward(deviceId, objective.remove());
299 }
300 }
301}