2 * Copyright © 2017 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.elan.evpn.utils;
11 import com.google.common.base.Optional;
13 import java.math.BigInteger;
14 import java.util.List;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.Future;
17 import java.util.function.BiPredicate;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
21 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
22 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
23 import org.opendaylight.netvirt.elan.utils.ElanUtils;
24 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.EvpnAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
35 import org.opendaylight.yangtools.yang.common.RpcResult;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 public class EvpnUtils {
41 private static final Logger LOG = LoggerFactory.getLogger(EvpnUtils.class);
43 private final BiPredicate<String, String> isNetAttach = (var1, var2) -> ((var1 == null) && (var2 != null));
44 private final BiPredicate<String, String> isNetDetach = (var1, var2) -> ((var1 != null) && (var2 == null));
45 private final DataBroker broker;
46 private final IInterfaceManager interfaceManager;
47 private final ElanUtils elanUtils;
48 private final ItmRpcService itmRpcService;
50 private volatile IBgpManager bgpManager;
51 private volatile IVpnManager vpnManager;
53 public EvpnUtils(DataBroker broker, IInterfaceManager interfaceManager,
54 ElanUtils elanUtils, ItmRpcService itmRpcService) {
56 this.interfaceManager = interfaceManager;
57 this.elanUtils = elanUtils;
58 this.itmRpcService = itmRpcService;
67 public void setVpnManager(IVpnManager vpnManager) {
68 this.vpnManager = vpnManager;
71 public void setBgpManager(IBgpManager bgpManager) {
72 this.bgpManager = bgpManager;
75 public boolean isWithdrawEvpnRT2Routes(EvpnAugmentation original, EvpnAugmentation update) {
76 return isNetDetach.test(original.getEvpnName(), update.getEvpnName());
79 public boolean isAdvertiseEvpnRT2Routes(EvpnAugmentation original, EvpnAugmentation update) {
80 return isNetAttach.test(original.getEvpnName(), update.getEvpnName())
81 || isNetAttach.test(original.getL3vpnName(), update.getL3vpnName());
84 @SuppressWarnings("checkstyle:IllegalCatch")
85 public void advertiseEvpnRT2Routes(EvpnAugmentation evpnAugmentation, String elanName) {
86 if (evpnAugmentation == null || evpnAugmentation.getEvpnName() == null) {
89 String evpnName = evpnAugmentation.getEvpnName();
90 List<MacEntry> macEntries = elanUtils.getElanMacEntries(elanName);
91 if (macEntries == null || macEntries.isEmpty()) {
92 LOG.trace("advertiseEvpnRT2Routes no elan mac entries found for {}", elanName);
95 String rd = vpnManager.getVpnRd(broker, evpnName);
96 ElanInstance elanInfo = elanUtils.getElanInstanceByName(broker, elanName);
97 macEntries.forEach((macEntry) -> {
98 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(macEntry.getInterface());
99 advertisePrefix(elanInfo, rd, macEntry.getMacAddress().getValue(),
100 macEntry.getIpPrefix().getIpv4Address().getValue(),
101 interfaceInfo.getInterfaceName(), interfaceInfo.getDpId());
105 public String getEndpointIpAddressForDPN(BigInteger dpnId) {
107 Future<RpcResult<GetDpnEndpointIpsOutput>> result = itmRpcService.getDpnEndpointIps(
108 new GetDpnEndpointIpsInputBuilder()
109 .setSourceDpid(dpnId)
111 RpcResult<GetDpnEndpointIpsOutput> rpcResult = null;
113 rpcResult = result.get();
114 } catch (InterruptedException e) {
115 LOG.error("getnextHopIpFromRpcOutput : InterruptedException for dpnid {}", e, dpnId);
117 } catch (ExecutionException e) {
118 LOG.error("getnextHopIpFromRpcOutput : ExecutionException for dpnid {}", e, dpnId);
121 if (!rpcResult.isSuccessful()) {
122 LOG.warn("RPC Call to getDpnEndpointIps returned with Errors {}", rpcResult.getErrors());
126 List<IpAddress> nexthopIpList = rpcResult.getResult().getNexthopipList();
127 return nexthopIpList.get(0).getIpv4Address().toString();
130 public Optional<String> getGatewayMacAddressForInterface(String vpnName, String ifName, String ipAddress) {
131 VpnPortipToPort gwPort = vpnManager.getNeutronPortFromVpnPortFixedIp(broker, vpnName, ipAddress);
132 return Optional.of((gwPort != null && gwPort.isSubnetIp())
133 ? gwPort.getMacAddress()
134 : interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName).getMacAddress());
137 public String getL3vpnNameFromElan(ElanInstance elanInfo) {
138 EvpnAugmentation evpnAugmentation = elanInfo.getAugmentation(EvpnAugmentation.class);
139 return evpnAugmentation != null ? evpnAugmentation.getL3vpnName() : null;
142 public static String getEvpnNameFromElan(ElanInstance elanInfo) {
143 EvpnAugmentation evpnAugmentation = elanInfo.getAugmentation(EvpnAugmentation.class);
144 return evpnAugmentation != null ? evpnAugmentation.getEvpnName() : null;
147 public String getEVpnRd(ElanInstance elanInfo) {
148 String evpnName = getEvpnNameFromElan(elanInfo);
149 if (evpnName == null) {
150 LOG.error("getEVpnRd : evpnName is NULL for elanInfo {}", elanInfo);
153 return vpnManager.getVpnRd(broker, evpnName);
156 public void advertisePrefix(ElanInstance elanInfo, String macAddress, String prefix,
157 String interfaceName, BigInteger dpnId) {
158 String rd = getEVpnRd(elanInfo);
159 advertisePrefix(elanInfo, rd, macAddress, prefix, interfaceName, dpnId);
162 @SuppressWarnings("checkstyle:IllegalCatch")
163 private void advertisePrefix(ElanInstance elanInfo, String rd,
164 String macAddress, String prefix, String interfaceName, BigInteger dpnId) {
166 LOG.error("advertisePrefix : rd is NULL for elanInfo {}, macAddress {}", elanInfo, macAddress);
169 String nextHop = getEndpointIpAddressForDPN(dpnId);
170 if (nextHop == null) {
171 LOG.error("Failed to get the dpn tep ip for dpn {}", dpnId);
175 long l2vni = elanInfo.getSegmentationId();
177 String gatewayMacAddr = null;
178 String l3VpName = getL3vpnNameFromElan(elanInfo);
179 if (l3VpName != null) {
180 VpnInstance l3VpnInstance = vpnManager.getVpnInstance(broker, l3VpName);
181 l3vni = l3VpnInstance.getL3vni();
182 Optional<String> gatewayMac = getGatewayMacAddressForInterface(l3VpName, interfaceName, prefix);
183 gatewayMacAddr = gatewayMac.isPresent() ? gatewayMac.get() : null;
185 LOG.info("Advertising routes with rd {}, macAddress {}, prefix {}, nextHop {},"
186 + " vpnLabel {}, l3vni {}, l2vni {}, gatewayMac {}", rd, macAddress, prefix, nextHop,
187 vpnLabel, l3vni, l2vni, gatewayMacAddr);
189 bgpManager.advertisePrefix(rd, macAddress, prefix, nextHop,
190 VrfEntryBase.EncapType.Vxlan, vpnLabel, l3vni, l2vni, gatewayMacAddr);
191 } catch (Exception e) {
192 LOG.error("Failed to advertisePrefix", e);
196 public void advertisePrefix(ElanInstance elanInfo, MacEntry macEntry) {
197 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(macEntry.getInterface());
198 advertisePrefix(elanInfo, macEntry.getMacAddress().getValue(),
199 macEntry.getIpPrefix().getIpv4Address().getValue(),
200 interfaceInfo.getInterfaceName(), interfaceInfo.getDpId());
203 public void withdrawEvpnRT2Routes(EvpnAugmentation evpnAugmentation, String elanName) {
204 List<MacEntry> macEntries = elanUtils.getElanMacEntries(elanName);
205 if (macEntries == null || macEntries.isEmpty()) {
206 LOG.trace("withdrawEvpnRT2Routes : macEntries is empty for elan {} ", elanName);
209 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, elanName);
210 String rd = getEVpnRd(elanInfo);
214 for (MacEntry macEntry : macEntries) {
215 String prefix = macEntry.getIpPrefix().getIpv4Address().getValue();
216 LOG.info("Withdrawing routes with rd {}, prefix {}", rd, prefix);
217 bgpManager.withdrawPrefix(rd, prefix);
221 public void withdrawPrefix(ElanInstance elanInfo, String prefix) {
222 String rd = getEVpnRd(elanInfo);
226 bgpManager.withdrawPrefix(rd, prefix);
229 public void withdrawPrefix(ElanInstance elanInfo, MacEntry macEntry) {
230 withdrawPrefix(elanInfo, macEntry.getIpPrefix().getIpv4Address().getValue());