L3 handling for COE services.
[netvirt.git] / coe / impl / src / main / java / org / opendaylight / netvirt / coe / utils / CoeUtils.java
1 /*
2  * Copyright (c) 2017 - 2018 Ericsson India Global Services Pvt Ltd. 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
9 package org.opendaylight.netvirt.coe.utils;
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.ImmutableBiMap;
13
14 import java.nio.charset.StandardCharsets;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.UUID;
21 import java.util.concurrent.ExecutionException;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.apache.aries.blueprint.annotation.service.Reference;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.infra.Datastore;
29 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
30 import org.opendaylight.genius.infra.TypedWriteTransaction;
31 import org.opendaylight.genius.mdsalutil.NwConstants;
32 import org.opendaylight.genius.networkutils.RDUtils;
33 import org.opendaylight.genius.networkutils.VniUtils;
34 import org.opendaylight.netvirt.coe.api.SouthboundInterfaceInfo;
35 import org.opendaylight.netvirt.coe.api.SouthboundInterfaceInfoBuilder;
36 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
42 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
43 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
44 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
46 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
48 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
49 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
50 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
51 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
52 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
53 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNamesBuilder;
54 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNamesKey;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.NetworkAttributes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.coe.Pods;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.service.rev170611.service.information.Services;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.PodidentifierInfo;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.podidentifier.info.PodIdentifier;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.podidentifier.info.PodIdentifierBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.meta.rev180118.podidentifier.info.PodIdentifierKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.service.meta.rev190123.ServiceGatewayInfo;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.service.meta.rev190123.service.gateway.info.ServiceGateway;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.service.meta.rev190123.service.gateway.info.ServiceGatewayBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.coe.service.meta.rev190123.service.gateway.info.ServiceGatewayKey;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeBase;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeFlat;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeGre;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVlan;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVxlan;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntriesBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntriesKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
105 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
106 import org.slf4j.Logger;
107 import org.slf4j.LoggerFactory;
108
109 @Singleton
110 public final class CoeUtils {
111     private static final Logger LOG = LoggerFactory.getLogger(CoeUtils.class);
112
113     private static final String SEPARATOR = ":";
114     public static final ImmutableBiMap<NetworkAttributes.NetworkType, Class<? extends SegmentTypeBase>>
115             NETWORK_MAP =
116             new ImmutableBiMap.Builder<NetworkAttributes.NetworkType, Class<? extends SegmentTypeBase>>()
117                     .put(NetworkAttributes.NetworkType.FLAT, SegmentTypeFlat.class)
118                     .put(NetworkAttributes.NetworkType.GRE, SegmentTypeGre.class)
119                     .put(NetworkAttributes.NetworkType.VLAN, SegmentTypeVlan.class)
120                     .put(NetworkAttributes.NetworkType.VXLAN, SegmentTypeVxlan.class)
121                     .build();
122
123     private final VniUtils vniUtils;
124     private final RDUtils rdUtils;
125
126     @Inject
127     public CoeUtils(@Reference VniUtils vniUtils, @Reference RDUtils rdUtils) {
128         this.vniUtils = vniUtils;
129         this.rdUtils = rdUtils;
130     }
131
132     public static InstanceIdentifier<Interface> buildVlanInterfaceIdentifier(String interfaceName) {
133         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
134                 .interfaces.Interface> id = InstanceIdentifier.builder(Interfaces.class).child(
135                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
136                         .Interface.class, new InterfaceKey(interfaceName)).build();
137         return id;
138     }
139
140     public static String buildInterfaceName(String networkNS, String podName) {
141         return new StringBuilder().append(networkNS).append(SEPARATOR).append(podName).toString();
142     }
143
144     public static Class<? extends SegmentTypeBase> getSegmentTypeFromNetwork(
145             org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod.rev170611.pod_attributes.Interface
146                     elanInterface) {
147         return CoeUtils.NETWORK_MAP.get(elanInterface.getNetworkType());
148     }
149
150     public static String buildElanInstanceName(String nodeIp, String networkNS) {
151         return new StringBuilder().append(nodeIp).append(SEPARATOR).append(networkNS).toString();
152     }
153
154     public static InstanceIdentifier<PodIdentifier> getPodMetaInstanceId(String externalInterfaceId) {
155         return InstanceIdentifier.builder(PodidentifierInfo.class)
156                 .child(PodIdentifier.class, new PodIdentifierKey(externalInterfaceId)).build();
157     }
158
159     public static InstanceIdentifier<BoundServices> buildKubeProxyServicesIId(String interfaceName) {
160         return InstanceIdentifier.builder(ServiceBindings.class)
161                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, ServiceModeIngress.class))
162                 .child(BoundServices.class, new BoundServicesKey(NwConstants.COE_KUBE_PROXY_SERVICE_INDEX)).build();
163     }
164
165     static InstanceIdentifier<VpnInstance> buildVpnInstance(String vpnName) {
166         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
167                 .child(VpnInstance.class, new VpnInstanceKey(vpnName))
168                 .build();
169         return id;
170     }
171
172     static InstanceIdentifier<VpnInterface> buildVpnInterfaceIdentifier(String ifName) {
173         InstanceIdentifier<VpnInterface> id = InstanceIdentifier.builder(VpnInterfaces.class).child(VpnInterface
174                 .class, new VpnInterfaceKey(ifName)).build();
175         return id;
176     }
177
178     static InstanceIdentifier<ElanInstance> createElanInstanceIdentifier(String elanInstanceName) {
179         InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class,
180                 new ElanInstanceKey(elanInstanceName)).build();
181         return id;
182     }
183
184     static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
185             .Interface buildInterface(String interfaceName) {
186         IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
187         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
188         IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
189         ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
190
191         interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
192                 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
193
194         return interfaceBuilder.build();
195     }
196
197     ElanInstance buildElanInstance(String elanInstanceName, Class<? extends SegmentTypeBase> segmentType,
198                                    Boolean isExternal) throws ExecutionException, InterruptedException {
199         ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName);
200         if (segmentType != null) {
201             elanInstanceBuilder.setSegmentType(segmentType);
202             elanInstanceBuilder.setSegmentationId(vniUtils.getVNI(elanInstanceName).longValue());
203         }
204
205         elanInstanceBuilder.setExternal(isExternal);
206         elanInstanceBuilder.withKey(new ElanInstanceKey(elanInstanceName));
207         return elanInstanceBuilder.build();
208     }
209
210     public void createElanInterface(String elanInterfaceName, String elanInstanceName,
211                                            TypedReadWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
212         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
213                 .class, new ElanInterfaceKey(elanInterfaceName)).build();
214         ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
215                 .setName(elanInterfaceName).withKey(new ElanInterfaceKey(elanInterfaceName)).build();
216         wrtConfigTxn.put(id, elanInterface);
217         LOG.debug("Creating new ELAN Interface {}", elanInterface);
218     }
219
220     public void updateElanInterfaceWithStaticMac(String macAddress, IpAddress ipAddress,
221                                                  String elanInterfaceName, String elanInstanceName,
222                                                  TypedReadWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
223         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
224                 .class, new ElanInterfaceKey(elanInterfaceName)).build();
225         PhysAddress physAddress = PhysAddress.getDefaultInstance(macAddress);
226         List<StaticMacEntries> staticMacEntriesList = new ArrayList<>();
227         StaticMacEntries staticMacEntries = new StaticMacEntriesBuilder().withKey(new StaticMacEntriesKey(
228                 physAddress)).setMacAddress(physAddress).setIpPrefix(ipAddress).build();
229         staticMacEntriesList.add(staticMacEntries);
230         ElanInterface elanInterface = new ElanInterfaceBuilder().setName(elanInterfaceName)
231                 .setElanInstanceName(elanInstanceName).withKey(
232                         new ElanInterfaceKey(elanInterfaceName)).setStaticMacEntries(staticMacEntriesList).build();
233         wrtConfigTxn.merge(id, elanInterface);
234         LOG.debug("Updating ELAN Interface with static mac {}", elanInterface);
235     }
236
237     public void createPodNameToPodUuidMap(String podName, InstanceIdentifier<Pods> pod,
238                                                  TypedWriteTransaction<Datastore.Operational> writeTransaction) {
239         InstanceIdentifier<PodIdentifier> id = InstanceIdentifier.builder(PodidentifierInfo.class)
240                 .child(PodIdentifier.class, new PodIdentifierKey(podName)).build();
241         PodIdentifier podIdentifier = new PodIdentifierBuilder().withKey(new PodIdentifierKey(podName))
242                 .setPodName(podName).setPodUuid(pod).build();
243         writeTransaction.put(id, podIdentifier);
244         LOG.debug("Creating podnametouuid map {} to {}", podName, pod);
245     }
246
247     public void deletePodNameToPodUuidMap(String podName,
248                                                  TypedWriteTransaction<Datastore.Operational> writeTransaction) {
249         InstanceIdentifier<PodIdentifier> id = InstanceIdentifier.builder(PodidentifierInfo.class)
250                 .child(PodIdentifier.class, new PodIdentifierKey(podName)).build();
251         writeTransaction.delete(id);
252         LOG.debug("Deleting podnametouuid map for {}", podName);
253     }
254
255     public InstanceIdentifier<Pods> getPodUUIDforPodName(String podName, DataBroker dataBroker)
256             throws ExecutionException, InterruptedException {
257         ReadTransaction readTransaction = dataBroker.newReadOnlyTransaction();
258         InstanceIdentifier<PodIdentifier> id = InstanceIdentifier.builder(PodidentifierInfo.class)
259                 .child(PodIdentifier.class, new PodIdentifierKey(podName)).build();
260         InstanceIdentifier<?> instanceIdentifier = readTransaction.read(LogicalDatastoreType.OPERATIONAL, id)
261                 .get().toJavaUtil().map(PodIdentifier::getPodUuid).orElse(null);
262         if (instanceIdentifier != null) {
263             return (InstanceIdentifier<Pods>) instanceIdentifier;
264         }
265         return null;
266     }
267
268     public void deleteElanInterface(String elanInterfaceName,
269                                            TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
270         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
271                 .class, new ElanInterfaceKey(elanInterfaceName)).build();
272         wrtConfigTxn.delete(id);
273         LOG.debug("Deleting ELAN Interface {}", elanInterfaceName);
274     }
275
276     public String createOfPortInterface(String interfaceName,
277                                                TypedReadWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
278         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface inf =
279                 buildInterface(interfaceName);
280         String infName = inf.getName();
281         LOG.info("Creating OFPort Interface {}", infName);
282         InstanceIdentifier interfaceIdentifier = CoeUtils.buildVlanInterfaceIdentifier(infName);
283         wrtConfigTxn.put(interfaceIdentifier, inf);
284         return infName;
285     }
286
287     public void deleteOfPortInterface(String infName,
288                                              TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
289         LOG.debug("Deleting OFPort Interface {}", infName);
290         InstanceIdentifier interfaceIdentifier = CoeUtils.buildVlanInterfaceIdentifier(infName);
291         wrtConfigTxn.delete(interfaceIdentifier);
292     }
293
294     public ElanInstance
295         createElanInstanceForTheFirstPodInTheNetwork(String clusterId, String nodeIp,
296                                                  org.opendaylight.yang.gen.v1.urn.opendaylight.coe.northbound.pod
297                                                          .rev170611.pod_attributes.Interface podInterface,
298                                                  TypedReadWriteTransaction<Datastore.Configuration> wrtConfigTxn)
299             throws ExecutionException, InterruptedException {
300         String elanInstanceName = buildElanInstanceName(nodeIp, clusterId);
301         InstanceIdentifier<ElanInstance> id = createElanInstanceIdentifier(elanInstanceName);
302         ElanInstance existingElanInstance = wrtConfigTxn.read(id).get().orNull();
303         if (existingElanInstance != null) {
304             return existingElanInstance;
305         }
306         Class<? extends SegmentTypeBase> segmentType = getSegmentTypeFromNetwork(podInterface);
307         //FIXME String physicalNetworkName = ??
308         // TODO external network support not added currently
309         Boolean isExternal = false;
310         ElanInstance elanInstance = buildElanInstance(elanInstanceName, segmentType, isExternal);
311         wrtConfigTxn.put(id, elanInstance);
312         LOG.info("ELAN instance created for the first pod in the network {}", podInterface.getUid());
313         return elanInstance;
314     }
315
316     public SouthboundInterfaceInfo getSouthboundInterfaceDetails(OvsdbTerminationPointAugmentation ovsdbTp) {
317         SouthboundInterfaceInfoBuilder southboundInterfaceInfoBuilder = new SouthboundInterfaceInfoBuilder();
318         if (ovsdbTp != null) {
319             List<InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
320             if (ifaceExtIds != null) {
321                 Iterator var2 = ifaceExtIds.iterator();
322                 while (var2.hasNext()) {
323                     InterfaceExternalIds entry = (InterfaceExternalIds)var2.next();
324                     if (entry.getExternalIdKey().equals("iface-id")) {
325                         southboundInterfaceInfoBuilder.setInterfaceName(entry.getExternalIdValue());
326                         continue;
327                     }
328                     if (entry.getExternalIdKey().equals("attached-mac")) {
329                         southboundInterfaceInfoBuilder.setMacAddress(entry.getExternalIdValue());
330                         continue;
331                     }
332                     if (entry.getExternalIdKey().equals("ip-address")) {
333                         southboundInterfaceInfoBuilder.setNodeIp(entry.getExternalIdValue());
334                         continue;
335                     }
336                     if (entry.getExternalIdKey().equals("is-service-gateway")) {
337                         southboundInterfaceInfoBuilder.setIsServiceGateway(true);
338                         continue;
339                     }
340                 }
341             }
342         }
343
344         return southboundInterfaceInfoBuilder.build();
345     }
346
347     public void createVpnInstance(String vpnName, List<String> rd, List<String> irt, List<String> ert,
348                                          VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion,
349                                          TypedReadWriteTransaction<Datastore.Configuration> tx)
350             throws ExecutionException, InterruptedException {
351         List<VpnTarget> vpnTargetList = new ArrayList<>();
352         LOG.debug("Creating/Updating a new vpn-instance node:{}", vpnName);
353
354         VpnInstanceBuilder builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName))
355                 .setVpnInstanceName(vpnName)
356                 .setType(type).setL3vni(l3vni);
357         if (rd == null) {
358             String autoRd = rdUtils.getRD(vpnName);
359             rd = Arrays.asList(autoRd);
360             LOG.debug("Autogenerated RD {} for vpn {}", autoRd, vpnName);
361         }
362         if (irt != null && !irt.isEmpty()) {
363             if (ert != null && !ert.isEmpty()) {
364                 List<String> commonRT = new ArrayList<>(irt);
365                 commonRT.retainAll(ert);
366
367                 for (String common : commonRT) {
368                     irt.remove(common);
369                     ert.remove(common);
370                     VpnTarget vpnTarget =
371                             new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
372                                     .setVrfRTType(VpnTarget.VrfRTType.Both).build();
373                     vpnTargetList.add(vpnTarget);
374                 }
375             }
376             for (String importRT : irt) {
377                 VpnTarget vpnTarget =
378                         new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
379                                 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
380                 vpnTargetList.add(vpnTarget);
381             }
382         }
383
384         if (ert != null && !ert.isEmpty()) {
385             for (String exportRT : ert) {
386                 VpnTarget vpnTarget =
387                         new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
388                                 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
389                 vpnTargetList.add(vpnTarget);
390             }
391         }
392
393         VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
394
395         Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
396         Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
397
398         if (rd != null && !rd.isEmpty()) {
399             ipv4vpnBuilder.setRouteDistinguisher(rd);
400             ipv6vpnBuilder.setRouteDistinguisher(rd);
401         }
402
403         if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
404             builder.setIpv4Family(ipv4vpnBuilder.build());
405         }
406         if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
407             builder.setIpv6Family(ipv6vpnBuilder.build());
408         }
409         if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
410             builder.setIpv4Family(ipv4vpnBuilder.build());
411         }
412         VpnInstance newVpn = builder.build();
413         LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
414         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
415                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
416         tx.put(vpnIdentifier, newVpn);
417     }
418
419     public void deleteVpnInstance(String vpnName,
420                                   TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
421         LOG.trace("deleteVpnInstance  {}", vpnName);
422         InstanceIdentifier<VpnInstance> vpnIfIdentifier = buildVpnInstance(vpnName);
423         wrtConfigTxn.delete(vpnIfIdentifier);
424     }
425
426
427     public void createVpnInterface(String vpnName, Pods pod, String interfaceName, String macAddress,
428                                           boolean isRouterInterface,
429                                           TypedReadWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
430         LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", interfaceName, isRouterInterface);
431         List<VpnInstanceNames> listVpn = new ArrayList<>();
432         listVpn.add(new VpnInstanceNamesBuilder().withKey(new VpnInstanceNamesKey(vpnName))
433                 .setVpnName(vpnName).setAssociatedSubnetType(VpnInstanceNames.AssociatedSubnetType
434                         .V4Subnet).build());
435         VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(interfaceName))
436                 .setName(interfaceName)
437                 .setVpnInstanceNames(listVpn)
438                 .setRouterInterface(isRouterInterface);
439         Adjacencies adjs = createPortIpAdjacencies(pod, interfaceName, macAddress);
440         if (adjs != null) {
441             vpnb.addAugmentation(Adjacencies.class, adjs);
442         }
443         VpnInterface vpnIf = vpnb.build();
444         LOG.info("Creating vpn interface {}", vpnIf);
445         InstanceIdentifier<VpnInterface> vpnIfIdentifier = buildVpnInterfaceIdentifier(interfaceName);
446         wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
447
448     }
449
450     public void deleteVpnInterface(String interfaceName,
451                                           TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
452         LOG.trace("deleteVpnInterface for Pod {}", interfaceName);
453         InstanceIdentifier<VpnInterface> vpnIfIdentifier = buildVpnInterfaceIdentifier(interfaceName);
454         wrtConfigTxn.delete(vpnIfIdentifier);
455     }
456
457     Adjacencies createPortIpAdjacencies(Pods pod, String interfaceName, String macAddress) {
458         List<Adjacency> adjList = new ArrayList<>();
459         LOG.trace("create config adjacencies for Port: {}", interfaceName);
460         IpAddress ip = pod.getInterface().get(0).getIpAddress();
461         String ipValue = ip.getIpv4Address() != null ? ip.getIpv4Address().getValue() : ip.getIpv6Address().getValue();
462         String ipPrefix = ip.getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
463         String hostIp = pod.getHostIpAddress().stringValue();
464         UUID subnetId = UUID.nameUUIDFromBytes(hostIp.getBytes(StandardCharsets.UTF_8));
465         String gatewayIP = ipValue.replaceFirst("\\d+$", "1");
466         Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
467                 .setMacAddress(macAddress).setAdjacencyType(Adjacency.AdjacencyType.PrimaryAdjacency)
468                 .setSubnetId(new Uuid(subnetId.toString())).setSubnetGatewayIp(gatewayIP).build();
469         if (!adjList.contains(vmAdj)) {
470             adjList.add(vmAdj);
471         }
472         return new AdjacenciesBuilder().setAdjacency(adjList).build();
473     }
474
475     public void unbindKubeProxyService(String interfaceName, TypedWriteTransaction<Datastore.Configuration> tx) {
476         tx.delete(buildKubeProxyServicesIId(interfaceName));
477     }
478
479     public void updateServiceGatewayList(TypedWriteTransaction<Datastore.Configuration> tx, String serviceGatewayPod,
480                                          String serviceGatewayIp,  String serviceGatewayMac) {
481         InstanceIdentifier<ServiceGateway> serviceGatewayInstanceIdentifier =
482                 InstanceIdentifier.builder(ServiceGatewayInfo.class).child(
483                         ServiceGateway.class, new ServiceGatewayKey(serviceGatewayPod)).build();
484         ServiceGateway serviceGateway = new ServiceGatewayBuilder().setGatewayPodName(serviceGatewayPod)
485                 .setGatewayPodIpAddress(serviceGatewayIp).setGatewayPodMacAddress(serviceGatewayMac).build();
486         tx.put(serviceGatewayInstanceIdentifier, serviceGateway);
487     }
488
489     private InstanceIdentifier<ServiceGatewayInfo> buildServiceGatewayInstanceIndentifier() {
490         return InstanceIdentifier.builder(ServiceGatewayInfo.class).build();
491     }
492
493     public void updateVpnInterfaceWithExtraRouteAdjacency(TypedReadWriteTransaction<Datastore.Configuration> tx,
494                                                           Services services) throws ExecutionException,
495             InterruptedException {
496         if (services.getClusterIpAddress() == null) {
497             LOG.error("Incorrect input received for extra route. {}", services.getName());
498         } else {
499             LOG.info("update vpn-interface with extra route adjacencies for {}", services.getName());
500             Optional<ServiceGatewayInfo> serviceGatewayList = tx.read(buildServiceGatewayInstanceIndentifier()).get();
501             if (serviceGatewayList.isPresent() && serviceGatewayList.get() != null) {
502                 for (ServiceGateway serviceGateway : serviceGatewayList.get().nonnullServiceGateway()) {
503                     String nextHop = serviceGateway.getGatewayPodIpAddress();
504                     IpAddress destination = services.getClusterIpAddress();
505                     String destinationIpValue = destination.getIpv4Address() != null
506                             ? destination.getIpv4Address().getValue() :
507                             destination.getIpv6Address().getValue();
508                     String destinationIpPrefix = destination.getIpv4Address() != null ? destinationIpValue + "/32"
509                             : destinationIpValue + "/128";
510                     String infName = serviceGateway.getGatewayPodName();
511                     if (infName != null) {
512                         LOG.info("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
513                                 destination, services.getClusterId(), nextHop, infName);
514                         InstanceIdentifier<Adjacency> path = InstanceIdentifier.builder(VpnInterfaces.class)
515                                 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build()
516                                 .augmentation(Adjacencies.class).child(Adjacency.class,
517                                         new AdjacencyKey(destinationIpPrefix));
518                         Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destinationIpPrefix)
519                                 .setNextHopIpList(Collections.singletonList(nextHop))
520                                 .setAdjacencyType(Adjacency.AdjacencyType.ExtraRoute).build();
521                         tx.put(path, erAdj);
522
523                     } else {
524                         LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
525                                 + "with nexthop {}", destination, services.getClusterId(), nextHop);
526                     }
527                 }
528             }
529         }
530     }
531 }