2 * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.ImmutableBiMap;
12 import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
13 import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbPortMetadata;
14 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfDataPlaneLocatorName;
15 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
16 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
17 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SftTypeName;
18 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.TenantId;
19 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocator;
20 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocatorBuilder;
21 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocatorKey;
22 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
23 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
24 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
25 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.SlTransportType;
26 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.VxlanGpe;
27 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.IpBuilder;
28 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sf.ovs.rev160107.SfDplOvsAugmentation;
29 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sf.ovs.rev160107.SfDplOvsAugmentationBuilder;
30 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sf.ovs.rev160107.connected.port.OvsPortBuilder;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.port.pair.attributes.ServiceFunctionParameters;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import java.util.ArrayList;
44 import java.util.List;
45 import java.util.concurrent.atomic.AtomicInteger;
48 * Class will convert OpenStack Port Pair API yang models present in
49 * neutron northbound project to OpenDaylight SFC Service Function yang models.
51 public class PortPairTranslator {
52 private static final Logger LOG = LoggerFactory.getLogger(PortPairTranslator.class);
53 private static final String NSH_AWARE_PARAM = "nsh-aware";
54 private static final String SF_TYPE_PARAM = "type";
55 private static final String DPL_SUFFIX_PARAM = "-dpl";
56 private static final String DPL_TRANSPORT_PARAM = "dpl-transport";
57 private static final String DPL_IP_PARAM = "dpl-ip";
58 private static final String DPL_PORT_PARAM = "dpl-port";
59 private static final String SFF_STR = "sff";
61 public static final ImmutableBiMap<String, Class<? extends SlTransportType>> DPL_TRANSPORT_TYPE
62 = new ImmutableBiMap.Builder<String, Class<? extends SlTransportType>>()
63 .put("vxlan-gpe", VxlanGpe.class).build();
64 private static final PortNumber SF_LOCATOR_PORT = new PortNumber(6633);
65 private static final AtomicInteger counter = new AtomicInteger(0);
66 private static final String SFF_NAME_PARAM = "sff-name";
68 public static ServiceFunctionBuilder buildServiceFunction(
70 PortPairGroup portPairGroup,
72 OvsdbPortMetadata ovsdbPortMetadata,
73 ServiceFunctionForwarder sff) {
74 Preconditions.checkNotNull(portPair, "Port pair must not be null");
75 Preconditions.checkNotNull(portPairGroup, "Port pair group must not be null");
76 Preconditions.checkNotNull(neutronPort, "Neutron Port related to port pair must not be null");
77 LOG.info("Port pair received : {}", portPair);
79 ServiceFunctionBuilder serviceFunctionBuilder = new ServiceFunctionBuilder();
80 List<SfDataPlaneLocator> sfDataPlaneLocatorList = new ArrayList<>();
81 SfDataPlaneLocatorBuilder sfDataPlaneLocatorBuilder = new SfDataPlaneLocatorBuilder();
82 IpBuilder sfLocator = new IpBuilder();
84 List<ServiceFunctionParameters> sfParams = portPair.getServiceFunctionParameters();
85 //Set SF name, key and tenant-id
86 serviceFunctionBuilder.setName(new SfName(portPair.getName()));
87 serviceFunctionBuilder.setKey(new ServiceFunctionKey(serviceFunctionBuilder.getName()));
88 serviceFunctionBuilder.setTenantId(new TenantId(portPair.getTenantId().getValue()));
90 //Set SF Type. Setting it to PortPairGroup Type, this will be overridden if user pass
91 //it through service_function_params
92 serviceFunctionBuilder.setType(SftTypeName.getDefaultInstance(portPairGroup.getName()));
94 //Set NSH Aware to true, later it will be overridden if user specified otherwise
95 //in service_function_parameters
96 serviceFunctionBuilder.setNshAware(true);
98 //Set data path locator name and key
99 sfDataPlaneLocatorBuilder.setName(new SfDataPlaneLocatorName(portPair.getName() + DPL_SUFFIX_PARAM));
100 sfDataPlaneLocatorBuilder.setKey(new SfDataPlaneLocatorKey(sfDataPlaneLocatorBuilder.getName()));
102 //Set vxlan-gpe as a default transport type, unless user pass specific transport in
103 //service_function_parameters
104 sfDataPlaneLocatorBuilder.setTransport(VxlanGpe.class);
107 if (neutronPort != null) {
108 List<FixedIps> fixedIps = neutronPort.getFixedIps();
109 List<AllowedAddressPairs> attachedIpAddresses = neutronPort.getAllowedAddressPairs();
111 if (fixedIps != null && !fixedIps.isEmpty()){
112 ipAddress = fixedIps.get(0).getIpAddress();
113 sfLocator.setIp(ipAddress);
115 } else if (attachedIpAddresses != null && !attachedIpAddresses.isEmpty()) {
116 //Pick up the first ip address
117 ipAddress = attachedIpAddresses.get(0).getIpAddress().getIpAddress();
118 sfLocator.setIp(ipAddress);
120 LOG.warn("No ip address attached to Neutron Port {} related to Port Pair {}", neutronPort, portPair);
121 //Ideally we should exit here, because without IP address OpenDaylight SFC won't be able to find the
122 //respective overlay. But if user passes additional parameter through service_function_param
123 //that can be leveraged here. Parameter passed through service_function_param will take precedence.
125 sfLocator.setPort(new PortNumber(SF_LOCATOR_PORT));
128 LOG.warn("Neutron port mapped to Port pair ingress/egress port is not found : {}", portPair);
131 if (ovsdbPortMetadata.getOvsdbPort() != null ) {
132 String ovsdbPortName = OvsdbMdsalHelper.getOvsdbPortName(ovsdbPortMetadata.getOvsdbPort());
133 SfDplOvsAugmentationBuilder sfDplOvsAugmentationBuilder = new SfDplOvsAugmentationBuilder();
134 OvsPortBuilder ovsPortBuilder = new OvsPortBuilder();
135 ovsPortBuilder.setPortId(ovsdbPortName);
136 sfDplOvsAugmentationBuilder.setOvsPort(ovsPortBuilder.build());
137 sfDataPlaneLocatorBuilder.addAugmentation(SfDplOvsAugmentation.class, sfDplOvsAugmentationBuilder.build());
139 LOG.warn("No OVSDB Port found for the port pair {}. Lack of ovs-port information might not configure SF " +
140 "properly", portPair);
143 //But if user pass specific param using service_function_parameters, set/override it accordingly
144 if (sfParams != null) {
145 for(ServiceFunctionParameters sfParam : sfParams) {
146 if (sfParam.getServiceFunctionParameter().equals(NSH_AWARE_PARAM)) {
147 serviceFunctionBuilder.setNshAware(new Boolean(sfParam.getServiceFunctionParameterValue()));
149 //There is by default type set to port pair group name, override it if user pass it specific type
150 if (sfParam.getServiceFunctionParameter().equals(SF_TYPE_PARAM)) {
151 serviceFunctionBuilder.setType(new SftTypeName(sfParam.getServiceFunctionParameterValue()));
153 if (sfParam.getServiceFunctionParameter().equals(DPL_TRANSPORT_PARAM)) {
154 Class transportTypeClass
155 = DPL_TRANSPORT_TYPE.get(sfParam.getServiceFunctionParameterValue());
156 sfDataPlaneLocatorBuilder.setTransport(transportTypeClass);
158 if (sfParam.getServiceFunctionParameter().equals(DPL_IP_PARAM)) {
159 IpAddress ipAddress = new IpAddress(new Ipv4Address(sfParam.getServiceFunctionParameterValue()));
160 sfLocator.setIp(ipAddress);
162 if (sfParam.getServiceFunctionParameter().equals(DPL_PORT_PARAM)) {
163 sfLocator.setPort(new PortNumber(new Integer(sfParam.getServiceFunctionParameterValue())));
165 if (sfParam.getServiceFunctionParameter().equals(SFF_NAME_PARAM)) {
166 sfDataPlaneLocatorBuilder.setServiceFunctionForwarder(
167 new SffName(sfParam.getServiceFunctionParameterValue()));
172 //Set service_function_forwarder
173 if (sfDataPlaneLocatorBuilder.getServiceFunctionForwarder() == null
174 && ovsdbPortMetadata.getOvsdbNode() != null) {
175 SffName sffName = sff.getName();
176 if(sffName != null ) {
177 sfDataPlaneLocatorBuilder.setServiceFunctionForwarder(sffName);
179 sfDataPlaneLocatorBuilder.setServiceFunctionForwarder(new SffName(SFF_STR + counter.incrementAndGet()));
183 sfDataPlaneLocatorBuilder.setLocatorType(sfLocator.build());
185 sfDataPlaneLocatorList.add(sfDataPlaneLocatorBuilder.build());
186 //Set management IP to same as DPL IP.
187 serviceFunctionBuilder.setIpMgmtAddress(sfLocator.getIp());
189 //Set all data plane locator
190 serviceFunctionBuilder.setSfDataPlaneLocator(sfDataPlaneLocatorList);
191 LOG.info("Port Pair translated to Service Function: {}", serviceFunctionBuilder);
192 return serviceFunctionBuilder;
195 public static ServiceFunctionKey getSFKey(PortPair portPair) {
196 return new ServiceFunctionKey(new SfName(portPair.getName()));