Merge "Fixed the use of index NwConstants"
[netvirt.git] / openstack / sfc-translator / impl / src / main / java / org / opendaylight / netvirt / openstack / sfc / translator / portchain / PortPairTranslator.java
1 /*
2  * Copyright (c) 2016 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
9
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;
42
43 import java.util.ArrayList;
44 import java.util.List;
45 import java.util.concurrent.atomic.AtomicInteger;
46
47 /**
48  * Class will convert OpenStack Port Pair API yang models present in
49  * neutron northbound project to OpenDaylight SFC Service Function yang models.
50  */
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";
60
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";
67
68     public static ServiceFunctionBuilder buildServiceFunction(
69             PortPair portPair,
70             PortPairGroup portPairGroup,
71             Port neutronPort,
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);
78
79         ServiceFunctionBuilder serviceFunctionBuilder = new ServiceFunctionBuilder();
80         List<SfDataPlaneLocator> sfDataPlaneLocatorList = new ArrayList<>();
81         SfDataPlaneLocatorBuilder sfDataPlaneLocatorBuilder = new SfDataPlaneLocatorBuilder();
82         IpBuilder sfLocator = new IpBuilder();
83
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()));
89
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()));
93
94         //Set NSH Aware to true, later it will be overridden if user specified otherwise
95         //in service_function_parameters
96         serviceFunctionBuilder.setNshAware(true);
97
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()));
101
102         //Set vxlan-gpe as a default transport type, unless user pass specific transport in
103         //service_function_parameters
104         sfDataPlaneLocatorBuilder.setTransport(VxlanGpe.class);
105
106         //Set locator type
107         if (neutronPort != null) {
108             List<FixedIps> fixedIps = neutronPort.getFixedIps();
109             List<AllowedAddressPairs> attachedIpAddresses = neutronPort.getAllowedAddressPairs();
110             IpAddress ipAddress;
111             if (fixedIps != null && !fixedIps.isEmpty()){
112                 ipAddress = fixedIps.get(0).getIpAddress();
113                 sfLocator.setIp(ipAddress);
114
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);
119             } else {
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.
124             }
125             sfLocator.setPort(new PortNumber(SF_LOCATOR_PORT));
126
127         } else {
128             LOG.warn("Neutron port mapped to Port pair ingress/egress port is not found : {}", portPair);
129         }
130
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());
138         } else {
139             LOG.warn("No OVSDB Port found for the port pair {}. Lack of ovs-port information might not configure SF " +
140                     "properly", portPair);
141         }
142
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()));
148                 }
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()));
152                 }
153                 if (sfParam.getServiceFunctionParameter().equals(DPL_TRANSPORT_PARAM)) {
154                     Class transportTypeClass
155                             = DPL_TRANSPORT_TYPE.get(sfParam.getServiceFunctionParameterValue());
156                     sfDataPlaneLocatorBuilder.setTransport(transportTypeClass);
157                 }
158                 if (sfParam.getServiceFunctionParameter().equals(DPL_IP_PARAM)) {
159                     IpAddress ipAddress = new IpAddress(new Ipv4Address(sfParam.getServiceFunctionParameterValue()));
160                     sfLocator.setIp(ipAddress);
161                 }
162                 if (sfParam.getServiceFunctionParameter().equals(DPL_PORT_PARAM)) {
163                     sfLocator.setPort(new PortNumber(new Integer(sfParam.getServiceFunctionParameterValue())));
164                 }
165                 if (sfParam.getServiceFunctionParameter().equals(SFF_NAME_PARAM)) {
166                     sfDataPlaneLocatorBuilder.setServiceFunctionForwarder(
167                             new SffName(sfParam.getServiceFunctionParameterValue()));
168                 }
169             }
170         }
171
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);
178             } else {
179                 sfDataPlaneLocatorBuilder.setServiceFunctionForwarder(new SffName(SFF_STR + counter.incrementAndGet()));
180             }
181         }
182
183         sfDataPlaneLocatorBuilder.setLocatorType(sfLocator.build());
184
185         sfDataPlaneLocatorList.add(sfDataPlaneLocatorBuilder.build());
186         //Set management IP to same as DPL IP.
187         serviceFunctionBuilder.setIpMgmtAddress(sfLocator.getIp());
188
189         //Set all data plane locator
190         serviceFunctionBuilder.setSfDataPlaneLocator(sfDataPlaneLocatorList);
191         LOG.info("Port Pair translated to Service Function: {}", serviceFunctionBuilder);
192         return serviceFunctionBuilder;
193     }
194
195     public static ServiceFunctionKey getSFKey(PortPair portPair) {
196         return new ServiceFunctionKey(new SfName(portPair.getName()));
197     }
198 }