2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.bgpmanager;
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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.EvpnRdToNetworks;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.evpn.rd.to.networks.EvpnRdToNetwork;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.evpn.rd.to.networks.EvpnRdToNetworkKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
57 import org.opendaylight.yangtools.yang.binding.DataObject;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
64 public class BgpUtil implements AutoCloseable {
65 private static final Logger LOG = LoggerFactory.getLogger(BgpUtil.class);
66 private static final String RESOURCE_TYPE = "BGP-RESOURCES";
67 private static final int DEFAULT_BATCH_SIZE = 1000;
68 private static final int DEFAULT_BATCH_INTERVAL = 500;
70 private final DataBroker dataBroker;
72 private final BlockingQueue<ActionableResource> bgpResourcesBufferQ = new LinkedBlockingQueue<>();
75 public BgpUtil(DataBroker dataBroker) {
76 this.dataBroker = dataBroker;
81 ResourceBatchingManager resBatchingManager = ResourceBatchingManager.getInstance();
83 Integer batchSize = Integer.getInteger("batch.size", DEFAULT_BATCH_SIZE);
84 Integer batchInterval = Integer.getInteger("batch.wait.time", DEFAULT_BATCH_INTERVAL);
86 resBatchingManager.registerBatchableResource(RESOURCE_TYPE, bgpResourcesBufferQ,
87 new DefaultBatchHandler(dataBroker, LogicalDatastoreType.CONFIGURATION, batchSize, batchInterval));
93 ResourceBatchingManager.getInstance().deregisterBatchableResource(RESOURCE_TYPE);
97 * get a translation from prefix ipv6 to afi<br>.
98 * "ffff::1/128" sets afi as 2 because is an IPv6 value
99 * @param argPrefix ip address as ipv4 or ipv6
100 * @return afi 1 for AFI_IP 2 for AFI_IPV6
102 public static int getAFItranslatedfromPrefix(String argPrefix) {
103 int retValue = af_afi.AFI_IP.getValue();//default afiValue is 1 (= ipv4)
105 if (!argPrefix.contains("/")) {
106 prefixOnly = argPrefix;
108 prefixOnly = argPrefix.substring(0, argPrefix.indexOf("/"));
111 InetAddress address = InetAddress.getByName(prefixOnly);
112 if (address instanceof Inet6Address) {
113 retValue = af_afi.AFI_IPV6.getValue();
114 } else if (address instanceof Inet4Address) {
115 retValue = af_afi.AFI_IP.getValue();
117 } catch (java.net.UnknownHostException e) {
118 /*if exception is catched then the prefix is not an IPv6 and IPv4*/
119 LOG.error("Unrecognized ip address ipAddress: {}", argPrefix);
120 retValue = af_afi.AFI_IP.getValue();//default afiValue is 1 (= ipv4)
125 public <T extends DataObject> void update(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);
133 public <T extends DataObject> void write(final InstanceIdentifier<T> path, final T data) {
134 ActionableResource actResource = new ActionableResourceImpl(path.toString());
135 actResource.setAction(ActionableResource.CREATE);
136 actResource.setInstanceIdentifier(path);
137 actResource.setInstance(data);
138 bgpResourcesBufferQ.add(actResource);
141 public <T extends DataObject> void delete(final InstanceIdentifier<T> path) {
142 ActionableResource actResource = new ActionableResourceImpl(path.toString());
143 actResource.setAction(ActionableResource.DELETE);
144 actResource.setInstanceIdentifier(path);
145 actResource.setInstance(null);
146 bgpResourcesBufferQ.add(actResource);
149 // Convert ProtocolType to thrift protocol_type
150 public static protocol_type convertToThriftProtocolType(BgpControlPlaneType protocolType) {
151 switch (protocolType) {
153 return protocol_type.PROTOCOL_LU;
155 return protocol_type.PROTOCOL_L3VPN;
157 return protocol_type.PROTOCOL_EVPN;
159 return protocol_type.PROTOCOL_ANY;
163 // Convert EncapType to thrift encap_type
164 public static encap_type convertToThriftEncapType(EncapType encapType) {
167 return encap_type.L2TPV3_OVER_IP;
169 return encap_type.GRE;
171 return encap_type.IP_IN_IP;
173 return encap_type.VXLAN;
176 return encap_type.MPLS;
180 public VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
181 InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
182 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = MDSALUtil.read(dataBroker,
183 LogicalDatastoreType.OPERATIONAL, id);
184 if (vpnInstanceOpData.isPresent()) {
185 return vpnInstanceOpData.get();
190 public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
191 return InstanceIdentifier.builder(VpnInstanceOpData.class)
192 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
195 private String getElanNamefromRd(String rd) {
196 InstanceIdentifier<EvpnRdToNetwork> id = getEvpnRdToNetworkIdentifier(rd);
197 Optional<EvpnRdToNetwork> evpnRdToNetworkOpData = MDSALUtil.read(dataBroker,
198 LogicalDatastoreType.CONFIGURATION, id);
199 if (evpnRdToNetworkOpData.isPresent()) {
200 return evpnRdToNetworkOpData.get().getNetworkId();
205 private static InstanceIdentifier<EvpnRdToNetwork> getEvpnRdToNetworkIdentifier(String rd) {
206 return InstanceIdentifier.builder(EvpnRdToNetworks.class)
207 .child(EvpnRdToNetwork.class, new EvpnRdToNetworkKey(rd)).build();
210 public void addTepToElanInstance(String rd, String tepIp) {
211 if (rd == null || tepIp == null) {
212 LOG.error("addTepToElanInstance : Null parameters returning");
215 String elanName = getElanNamefromRd(rd);
216 if (elanName == null) {
217 LOG.error("Elan null while processing RT2 for RD {}", rd);
220 LOG.debug("Adding tepIp {} to elan {}", tepIp, elanName);
221 InstanceIdentifier<ExternalTeps> externalTepsId = getExternalTepsIdentifier(elanName, tepIp);
222 ExternalTepsBuilder externalTepsBuilder = new ExternalTepsBuilder();
223 ExternalTepsKey externalTepsKey = externalTepsId.firstKeyOf(ExternalTeps.class);
224 externalTepsBuilder.withKey(externalTepsKey);
225 externalTepsBuilder.setTepIp(externalTepsKey.getTepIp());
226 update(externalTepsId, externalTepsBuilder.build());
229 public void deleteTepFromElanInstance(String rd, String tepIp) {
230 if (rd == null || tepIp == null) {
231 LOG.error("deleteTepFromElanInstance : Null parameters returning");
234 String elanName = getElanNamefromRd(rd);
235 if (elanName == null) {
236 LOG.error("Elan null while processing RT2 withdraw for RD {}", rd);
239 LOG.debug("Deleting tepIp {} from elan {}", tepIp, elanName);
240 InstanceIdentifier<ExternalTeps> externalTepsId = getExternalTepsIdentifier(elanName, tepIp);
241 delete(externalTepsId);
244 private static InstanceIdentifier<ExternalTeps> getExternalTepsIdentifier(String elanInstanceName, String tepIp) {
245 IpAddress tepAdress = tepIp == null ? null : IpAddressBuilder.getDefaultInstance(tepIp);
246 return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class,
247 new ElanInstanceKey(elanInstanceName)).child(ExternalTeps.class,
248 new ExternalTepsKey(tepAdress)).build();
251 public String getVpnNameFromRd(String rd) {
252 VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
253 return vpnInstanceOpData != null ? vpnInstanceOpData.getVpnInstanceName() : null;
256 /** get the vrf with the RouterDistinguisher pass in param.
257 * @param rd is the RouteDistinguisher of vrf
258 * @return the vrf of rd or null if no exist
260 public Vrfs getVrfFromRd(String rd) {
262 KeyedInstanceIdentifier<Vrfs, VrfsKey> id = InstanceIdentifier.create(Bgp.class)
263 .child(Vrfs.class, new VrfsKey(rd));
264 Optional<Vrfs> vrfsFromDs = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
265 if (vrfsFromDs.isPresent()) {
266 vrfs = vrfsFromDs.get();
271 /** get layerType used from an AddressFamiliesVrf.
272 * @param adf is the AddressFamiliesVrf from which the layer is asked.
273 * @return the layerType to reach from the argument addressFamilyVrf or null if not found
275 public static LayerType getLayerType(AddressFamiliesVrf adf) {
276 LayerType layerTypeValue = null;
277 if (adf.getSafi() == af_safi.SAFI_EVPN.getValue()) {
278 layerTypeValue = LayerType.LAYER2;
279 } else if (adf.getSafi() == af_safi.SAFI_MPLS_VPN.getValue()) {
280 layerTypeValue = LayerType.LAYER3;
282 return layerTypeValue;
285 public void removeVrfEntry(String rd, VrfEntry vrfEntry) {
286 LOG.debug("removeVrfEntry : vrf {} prefix {}", rd, vrfEntry.getDestPrefix());
287 InstanceIdentifier<VrfEntry> vrfEntryId =
288 InstanceIdentifier.builder(FibEntries.class)
289 .child(VrfTables.class, new VrfTablesKey(rd))
290 .child(VrfEntry.class, new VrfEntryKey(vrfEntry.getDestPrefix())).build();