blob: 9875e4d739d8fc28c23bfe35b82cea47ebca1ffa [file] [log] [blame]
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +05303 *
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
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053018import static com.google.common.base.Preconditions.checkNotNull;
19import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI;
20import static org.slf4j.LoggerFactory.getLogger;
21
22import java.util.List;
23import java.util.ListIterator;
24
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053025import org.onlab.osgi.DefaultServiceDirectory;
26import org.onlab.osgi.ServiceDirectory;
27import org.onlab.packet.MacAddress;
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053028import org.onlab.packet.TpPort;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053029import org.onlab.packet.VlanId;
30import org.onosproject.core.ApplicationId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053031import org.onosproject.net.DeviceId;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053032import org.onosproject.net.Host;
33import org.onosproject.net.HostId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053034import org.onosproject.net.NshServicePathId;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053035import org.onosproject.net.PortNumber;
Jonathan Hart51539b82015-10-29 09:53:04 -070036import org.onosproject.net.behaviour.ExtensionSelectorResolver;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053037import org.onosproject.net.driver.DriverHandler;
38import org.onosproject.net.driver.DriverService;
39import org.onosproject.net.flow.DefaultTrafficSelector;
40import org.onosproject.net.flow.DefaultTrafficTreatment;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053041import org.onosproject.net.flow.TrafficSelector;
42import org.onosproject.net.flow.TrafficTreatment;
Jonathan Hart51539b82015-10-29 09:53:04 -070043import org.onosproject.net.flow.criteria.ExtensionSelector;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053044import org.onosproject.net.flowobjective.DefaultForwardingObjective;
45import org.onosproject.net.flowobjective.FlowObjectiveService;
46import org.onosproject.net.flowobjective.ForwardingObjective;
Jonathan Hart51539b82015-10-29 09:53:04 -070047import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053048import org.onosproject.net.flowobjective.Objective;
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +053049import org.onosproject.net.host.HostService;
Jonathan Hart51539b82015-10-29 09:53:04 -070050import org.onosproject.sfc.forwarder.ServiceFunctionForwarderService;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053051import org.onosproject.vtnrsc.PortChain;
52import org.onosproject.vtnrsc.PortPair;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053053import org.onosproject.vtnrsc.PortPairId;
Jonathan Hart51539b82015-10-29 09:53:04 -070054import org.onosproject.vtnrsc.VirtualPortId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053055import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
56import org.onosproject.vtnrsc.portchain.PortChainService;
Jonathan Hart51539b82015-10-29 09:53:04 -070057import org.onosproject.vtnrsc.portpair.PortPairService;
58import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
59import org.onosproject.vtnrsc.service.VtnRscService;
60import org.onosproject.vtnrsc.virtualport.VirtualPortService;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053061import org.slf4j.Logger;
62
63/**
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053064 * Provides service function forwarder implementation.
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053065 */
66public class ServiceFunctionForwarderImpl implements ServiceFunctionForwarderService {
67
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053068 private final Logger log = getLogger(getClass());
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053069 protected VirtualPortService virtualPortService;
70 protected VtnRscService vtnRscService;
71 protected PortPairService portPairService;
72 protected PortPairGroupService portPairGroupService;
73 protected FlowClassifierService flowClassifierService;
74 protected PortChainService portChainService;
75 protected DriverService driverService;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053076 protected FlowObjectiveService flowObjectiveService;
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053077 protected HostService hostService;
78 protected ApplicationId appId;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053079
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053080 private static final String PATH_NOT_NULL = "Load balanced path cannot be null";
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053081 private static final String APP_ID_NOT_NULL = "Application-Id cannot be null";
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053082
83 /**
84 * Default constructor.
85 */
86 public ServiceFunctionForwarderImpl() {
87 }
88
89 /**
90 * Explicit constructor.
Bharat saraswal1adafb32015-12-11 01:29:44 +053091 *
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053092 * @param appId application id
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +053093 */
94 public ServiceFunctionForwarderImpl(ApplicationId appId) {
95 this.appId = checkNotNull(appId, APP_ID_NOT_NULL);
96 ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
97 this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
Phaneendra Mandab88b3f82016-02-12 21:51:30 +053098 this.driverService = serviceDirectory.get(DriverService.class);
99 this.virtualPortService = serviceDirectory.get(VirtualPortService.class);
100 this.vtnRscService = serviceDirectory.get(VtnRscService.class);
101 this.portPairService = serviceDirectory.get(PortPairService.class);
102 this.portPairGroupService = serviceDirectory.get(PortPairGroupService.class);
103 this.flowClassifierService = serviceDirectory.get(FlowClassifierService.class);
104 this.hostService = serviceDirectory.get(HostService.class);
105 this.portChainService = serviceDirectory.get(PortChainService.class);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530106 }
107
108 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700109 public void installForwardingRule(PortChain portChain, NshServicePathId nshSpi) {
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530110 //TODO this method will be removed
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530111 }
112
113 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700114 public void unInstallForwardingRule(PortChain portChain, NshServicePathId nshSpi) {
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530115 //TODO this method will be removed
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530116 }
117
118 @Override
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530119 public void installLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi) {
120 checkNotNull(path, PATH_NOT_NULL);
121 processForwardingRule(path, nshSpi, Objective.Operation.ADD);
122 }
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530123
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530124 @Override
125 public void unInstallLoadBalancedForwardingRule(List<PortPairId> path, NshServicePathId nshSpi) {
126 checkNotNull(path, PATH_NOT_NULL);
127 processForwardingRule(path, nshSpi, Objective.Operation.REMOVE);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530128 }
129
130 /**
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530131 * Process the required forwarding rules for the given path.
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530132 *
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530133 * @param path list of port pair ids
134 * @param nshSpi service path index
135 * @param type operation type ADD/REMOVE
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530136 */
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530137 private void processForwardingRule(List<PortPairId> path, NshServicePathId nshSpi,
138 Objective.Operation type) {
139
140 // Get the first port pair
141 ListIterator<PortPairId> portPairListIterator = path.listIterator();
142 PortPair currentPortPair = portPairService.getPortPair(portPairListIterator.next());
143
144 // Get destination port pair group
145 if (!portPairListIterator.hasNext()) {
146 log.debug("Path is empty");
147 return;
148 }
149 PortPair nextPortPair = portPairService.getPortPair(portPairListIterator.next());
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530150 DeviceId currentDeviceId = null;
151 DeviceId nextDeviceId = null;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530152
153 // Travel from SF to SF.
154 do {
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530155 currentDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(currentPortPair.egress()));
156 nextDeviceId = vtnRscService.getSfToSffMaping(VirtualPortId.portId(nextPortPair.ingress()));
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530157 // pack traffic selector
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530158 TrafficSelector.Builder selector = packTrafficSelector(currentDeviceId, currentPortPair, nshSpi);
159 // Pack treatment
160 if (currentDeviceId.equals(nextDeviceId)) {
161 TrafficTreatment.Builder treatment = packTrafficTreatment(nextPortPair, true);
162 // Send SFF to SFF
163 sendServiceFunctionForwarder(selector, treatment, currentDeviceId, type);
164 } else {
165 TrafficTreatment.Builder treatment = packTrafficTreatment(nextPortPair, false);
166 // Send SFF to OVS
167 sendServiceFunctionForwarder(selector, treatment, currentDeviceId, type);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530168
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530169 // At the other device get the packet from vlan and send to first port pair
170 TrafficSelector.Builder selectorDst = DefaultTrafficSelector.builder();
171 selectorDst.matchVlanId((VlanId.vlanId(Short.parseShort((vtnRscService
172 .getL3vni(nextPortPair.tenantId()).toString())))));
173 TrafficTreatment.Builder treatmentDst = DefaultTrafficTreatment.builder();
174 MacAddress macAddr = virtualPortService.getPort(VirtualPortId.portId(nextPortPair.ingress()))
175 .macAddress();
176 Host host = hostService.getHost(HostId.hostId(macAddr));
177 PortNumber port = host.location().port();
178 treatmentDst.setOutput(port);
179 // Send OVS to SFF
180 sendServiceFunctionForwarder(selectorDst, treatmentDst, nextDeviceId, type);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530181 }
182
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530183 // Move to next service function
184 currentPortPair = nextPortPair;
185 if (!portPairListIterator.hasNext()) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530186 break;
187 }
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530188 nextPortPair = portPairService.getPortPair(portPairListIterator.next());
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530189 } while (true);
190 }
191
192 /**
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530193 * Pack traffic selector.
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530194 *
195 * @param deviceId device id
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530196 * @param portPair port-pair
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530197 * @param nshSpi nsh service path index
198 * @return traffic selector
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530199 */
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530200 public TrafficSelector.Builder packTrafficSelector(DeviceId deviceId,
201 PortPair portPair, NshServicePathId nshSpi) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530202 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530203
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530204 MacAddress dstMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.egress())).macAddress();
205 Host host = hostService.getHost(HostId.hostId(dstMacAddress));
206 PortNumber port = host.location().port();
207 selector.matchInPort(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530208
209 DriverHandler handler = driverService.createHandler(deviceId);
210 ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
211 ExtensionSelector nspSpiSelector = resolver.getExtensionSelector(NICIRA_MATCH_NSH_SPI.type());
212
213 try {
Jonathan Hart51539b82015-10-29 09:53:04 -0700214 nspSpiSelector.setPropertyValue("nshSpi", nshSpi);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530215 } catch (Exception e) {
216 log.error("Failed to get extension instruction to set Nsh Spi Id {}", deviceId);
217 }
218
219 selector.extension(nspSpiSelector, deviceId);
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530220
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530221 return selector;
222 }
223
224 /**
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530225 * Pack traffic treatment.
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530226 *
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530227 * @param portPair port pair
228 * @param isSameOvs whether the next port pair is in the same ovs
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530229 * @return traffic treatment
230 */
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530231 public TrafficTreatment.Builder packTrafficTreatment(PortPair portPair, boolean isSameOvs) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530232 MacAddress srcMacAddress = null;
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530233
234 // Check the treatment whether destination SF is on same OVS or in
235 // different OVS.
236 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530237 if (isSameOvs) {
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530238 srcMacAddress = virtualPortService.getPort(VirtualPortId.portId(portPair.ingress())).macAddress();
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530239 Host host = hostService.getHost(HostId.hostId(srcMacAddress));
240 PortNumber port = host.location().port();
241 treatment.setOutput(port);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530242 } else {
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530243 // Vxlan tunnel port for NSH header(Vxlan + NSH).
244 TpPort nshDstPort = TpPort.tpPort(6633);
245 // TODO check whether this logic is correct
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530246 VlanId vlanId = VlanId.vlanId(Short.parseShort((vtnRscService.getL3vni(portPair.tenantId()).toString())));
247 treatment.setVlanId(vlanId);
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530248 treatment.setUdpDst(nshDstPort);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530249 }
250
251 return treatment;
252 }
253
254 /**
255 * Send service function forwarder to OVS.
256 *
257 * @param selector traffic selector
258 * @param treatment traffic treatment
259 * @param deviceId device id
260 * @param type operation type
261 */
262 public void sendServiceFunctionForwarder(TrafficSelector.Builder selector, TrafficTreatment.Builder treatment,
Phaneendra Mandab88b3f82016-02-12 21:51:30 +0530263 DeviceId deviceId, Objective.Operation type) {
264 log.info("Sending flow to serfice-function-forwarder. Selector {}, Treatment {}",
265 selector.toString(), treatment.toString());
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530266 ForwardingObjective.Builder objective = DefaultForwardingObjective.builder().withTreatment(treatment.build())
Mahesh Poojary Se5cbab92015-12-10 10:52:04 +0530267 .withSelector(selector.build()).fromApp(appId).makePermanent().withFlag(Flag.VERSATILE);
Mahesh Poojary S7e9a78f2015-12-04 01:55:57 +0530268 if (type.equals(Objective.Operation.ADD)) {
269 log.debug("ADD");
270 flowObjectiveService.forward(deviceId, objective.add());
271 } else {
272 log.debug("REMOVE");
273 flowObjectiveService.forward(deviceId, objective.remove());
274 }
275 }
276}