Remove redundant names in paths
[netvirt.git] / bgpmanager / impl / src / main / java / org / opendaylight / netvirt / bgpmanager / BgpUtil.java
1 /*
2  * Copyright (c) 2015 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 package org.opendaylight.netvirt.bgpmanager;
9
10 import com.google.common.base.Optional;
11 import java.net.Inet4Address;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.util.concurrent.BlockingQueue;
15 import java.util.concurrent.LinkedBlockingQueue;
16 import javax.annotation.PostConstruct;
17 import javax.annotation.PreDestroy;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.genius.utils.batching.ActionableResource;
24 import org.opendaylight.genius.utils.batching.ActionableResourceImpl;
25 import org.opendaylight.genius.utils.batching.DefaultBatchHandler;
26 import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
27 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
28 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
29 import org.opendaylight.netvirt.bgpmanager.thrift.gen.encap_type;
30 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
31 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
32 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
33 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
34 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
35 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
36 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
37 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrf;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.EvpnRdToNetworks;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.evpn.rd.to.networks.EvpnRdToNetwork;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.evpn.rd.to.networks.EvpnRdToNetworkKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
56 import org.opendaylight.yangtools.yang.binding.DataObject;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
58 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 @Singleton
63 public class BgpUtil implements AutoCloseable {
64     private static final Logger LOG = LoggerFactory.getLogger(BgpUtil.class);
65     private static final String RESOURCE_TYPE = "BGP-RESOURCES";
66     private static final int DEFAULT_BATCH_SIZE = 1000;
67     private static final int DEFAULT_BATCH_INTERVAL = 500;
68
69     private final DataBroker dataBroker;
70
71     private final BlockingQueue<ActionableResource> bgpResourcesBufferQ = new LinkedBlockingQueue<>();
72
73     @Inject
74     public BgpUtil(DataBroker dataBroker) {
75         this.dataBroker = dataBroker;
76     }
77
78     @PostConstruct
79     public void init() {
80         ResourceBatchingManager resBatchingManager = ResourceBatchingManager.getInstance();
81
82         Integer batchSize = Integer.getInteger("batch.size", DEFAULT_BATCH_SIZE);
83         Integer batchInterval = Integer.getInteger("batch.wait.time", DEFAULT_BATCH_INTERVAL);
84
85         resBatchingManager.registerBatchableResource(RESOURCE_TYPE, bgpResourcesBufferQ,
86                 new DefaultBatchHandler(dataBroker, LogicalDatastoreType.CONFIGURATION, batchSize, batchInterval));
87     }
88
89     @Override
90     @PreDestroy
91     public void close() {
92         ResourceBatchingManager.getInstance().deregisterBatchableResource(RESOURCE_TYPE);
93     }
94
95     /**
96      * get a translation from prefix ipv6 to afi<br>.
97      * "ffff::1/128" sets afi as 2 because is an IPv6 value
98      * @param argPrefix ip address as ipv4 or ipv6
99      * @return afi 1 for AFI_IP 2 for AFI_IPV6
100      */
101     public static int getAFItranslatedfromPrefix(String argPrefix) {
102         int retValue = af_afi.AFI_IP.getValue();//default afiValue is 1 (= ipv4)
103         String prefixOnly;
104         if (argPrefix.indexOf("/") == -1) {
105             prefixOnly = argPrefix;
106         } else {
107             prefixOnly = argPrefix.substring(0, argPrefix.indexOf("/"));
108         }
109         try {
110             InetAddress address = InetAddress.getByName(prefixOnly);
111             if (address instanceof Inet6Address) {
112                 retValue = af_afi.AFI_IPV6.getValue();
113             } else if (address instanceof Inet4Address) {
114                 retValue = af_afi.AFI_IP.getValue();
115             }
116         } catch (java.net.UnknownHostException e) {
117             /*if exception is catched then the prefix is not an IPv6 and IPv4*/
118             LOG.error("Unrecognized ip address ipAddress: {}", argPrefix);
119             retValue = af_afi.AFI_IP.getValue();//default afiValue is 1 (= ipv4)
120         }
121         return retValue;
122     }
123
124     public <T extends DataObject> void update(final LogicalDatastoreType datastoreType,
125             final InstanceIdentifier<T> path, final T data) {
126         ActionableResource actResource = new ActionableResourceImpl(path.toString());
127         actResource.setAction(ActionableResource.UPDATE);
128         actResource.setInstanceIdentifier(path);
129         actResource.setInstance(data);
130         bgpResourcesBufferQ.add(actResource);
131     }
132
133     public <T extends DataObject> void write(final LogicalDatastoreType datastoreType, final InstanceIdentifier<T> path,
134             final T data) {
135         ActionableResource actResource = new ActionableResourceImpl(path.toString());
136         actResource.setAction(ActionableResource.CREATE);
137         actResource.setInstanceIdentifier(path);
138         actResource.setInstance(data);
139         bgpResourcesBufferQ.add(actResource);
140     }
141
142     public <T extends DataObject> void delete(final LogicalDatastoreType datastoreType,
143             final InstanceIdentifier<T> path) {
144         ActionableResource actResource = new ActionableResourceImpl(path.toString());
145         actResource.setAction(ActionableResource.DELETE);
146         actResource.setInstanceIdentifier(path);
147         actResource.setInstance(null);
148         bgpResourcesBufferQ.add(actResource);
149     }
150
151     // Convert ProtocolType to thrift protocol_type
152     public static protocol_type convertToThriftProtocolType(BgpControlPlaneType protocolType) {
153         switch (protocolType) {
154             case PROTOCOLLU:
155                 return protocol_type.PROTOCOL_LU;
156             case PROTOCOLL3VPN:
157                 return protocol_type.PROTOCOL_L3VPN;
158             case PROTOCOLEVPN:
159                 return protocol_type.PROTOCOL_EVPN;
160             default:
161                 return protocol_type.PROTOCOL_ANY;
162         }
163     }
164
165     // Convert EncapType to thrift encap_type
166     public static encap_type convertToThriftEncapType(EncapType encapType) {
167         switch (encapType) {
168             case L2TPV3OVERIP:
169                 return encap_type.L2TPV3_OVER_IP;
170             case GRE:
171                 return encap_type.GRE;
172             case IPINIP:
173                 return encap_type.IP_IN_IP;
174             case VXLAN:
175                 return encap_type.VXLAN;
176             case MPLS:
177             default:
178                 return encap_type.MPLS;
179         }
180     }
181
182     public VpnInstanceOpDataEntry getVpnInstanceOpData(String rd)  {
183         InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
184         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = MDSALUtil.read(dataBroker,
185                 LogicalDatastoreType.OPERATIONAL, id);
186         if (vpnInstanceOpData.isPresent()) {
187             return vpnInstanceOpData.get();
188         }
189         return null;
190     }
191
192     public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
193         return InstanceIdentifier.builder(VpnInstanceOpData.class)
194                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
195     }
196
197     private String getElanNamefromRd(String rd)  {
198         InstanceIdentifier<EvpnRdToNetwork> id = getEvpnRdToNetworkIdentifier(rd);
199         Optional<EvpnRdToNetwork> evpnRdToNetworkOpData = MDSALUtil.read(dataBroker,
200                 LogicalDatastoreType.CONFIGURATION, id);
201         if (evpnRdToNetworkOpData.isPresent()) {
202             return evpnRdToNetworkOpData.get().getNetworkId();
203         }
204         return null;
205     }
206
207     private static InstanceIdentifier<EvpnRdToNetwork> getEvpnRdToNetworkIdentifier(String rd) {
208         return InstanceIdentifier.builder(EvpnRdToNetworks.class)
209                 .child(EvpnRdToNetwork.class, new EvpnRdToNetworkKey(rd)).build();
210     }
211
212     public void addTepToElanInstance(String rd, String tepIp) {
213         if (rd == null || tepIp == null) {
214             LOG.error("addTepToElanInstance : Null parameters returning");
215             return;
216         }
217         String elanName = getElanNamefromRd(rd);
218         if (elanName == null) {
219             LOG.error("Elan null while processing RT2 for RD {}", rd);
220             return;
221         }
222         LOG.debug("Adding tepIp {} to elan {}", tepIp, elanName);
223         InstanceIdentifier<ExternalTeps> externalTepsId = getExternalTepsIdentifier(elanName, tepIp);
224         ExternalTepsBuilder externalTepsBuilder = new ExternalTepsBuilder();
225         ExternalTepsKey externalTepsKey = externalTepsId.firstKeyOf(ExternalTeps.class);
226         externalTepsBuilder.setKey(externalTepsKey);
227         externalTepsBuilder.setTepIp(externalTepsKey.getTepIp());
228         update(LogicalDatastoreType.CONFIGURATION, externalTepsId, externalTepsBuilder.build());
229     }
230
231     public void deleteTepFromElanInstance(String rd, String tepIp) {
232         if (rd == null || tepIp == null) {
233             LOG.error("deleteTepFromElanInstance : Null parameters returning");
234             return;
235         }
236         String elanName = getElanNamefromRd(rd);
237         if (elanName == null) {
238             LOG.error("Elan null while processing RT2 withdraw for RD {}", rd);
239             return;
240         }
241         LOG.debug("Deleting tepIp {} from elan {}", tepIp, elanName);
242         InstanceIdentifier<ExternalTeps> externalTepsId = getExternalTepsIdentifier(elanName, tepIp);
243         delete(LogicalDatastoreType.CONFIGURATION, externalTepsId);
244     }
245
246     private static InstanceIdentifier<ExternalTeps> getExternalTepsIdentifier(String elanInstanceName, String tepIp) {
247         IpAddress tepAdress = tepIp == null ? null : new IpAddress(tepIp.toCharArray());
248         return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class,
249                 new ElanInstanceKey(elanInstanceName)).child(ExternalTeps.class,
250                 new ExternalTepsKey(tepAdress)).build();
251     }
252
253     public String getVpnNameFromRd(String rd) {
254         VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
255         return vpnInstanceOpData != null ? vpnInstanceOpData.getVpnInstanceName() : null;
256     }
257
258     /** get the vrf with the RouterDistinguisher pass in param.
259      * @param rd is the RouteDistinguisher of vrf
260      * @return the vrf of rd or null if no exist
261      */
262     public Vrfs getVrfFromRd(String rd) {
263         Vrfs vrfs = null;
264         KeyedInstanceIdentifier<Vrfs, VrfsKey> id = InstanceIdentifier.create(Bgp.class)
265                 .child(Vrfs.class, new VrfsKey(rd));
266         Optional<Vrfs> vrfsFromDs = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
267         if (vrfsFromDs.isPresent()) {
268             vrfs = vrfsFromDs.get();
269         }
270         return vrfs;
271     }
272
273     /** get layerType used from an AddressFamiliesVrf.
274      * @param adf is the AddressFamiliesVrf from which the layer is asked.
275      * @return the layerType to reach from the argument addressFamilyVrf or null if not found
276      */
277     public static LayerType getLayerType(AddressFamiliesVrf adf) {
278         LayerType layerTypeValue = null;
279         if (adf.getSafi() == af_safi.SAFI_EVPN.getValue()) {
280             layerTypeValue = LayerType.LAYER2;
281         } else if (adf.getSafi() == af_safi.SAFI_MPLS_VPN.getValue()) {
282             layerTypeValue = LayerType.LAYER3;
283         }
284         return layerTypeValue;
285     }
286
287     public void removeVrfEntry(String rd, VrfEntry vrfEntry) {
288         LOG.debug("removeVrfEntry : vrf {} prefix {}", rd, vrfEntry.getDestPrefix());
289         InstanceIdentifier<VrfEntry> vrfEntryId =
290                    InstanceIdentifier.builder(FibEntries.class)
291                    .child(VrfTables.class, new VrfTablesKey(rd))
292                    .child(VrfEntry.class, new VrfEntryKey(vrfEntry.getDestPrefix())).build();
293         delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
294     }
295 }