EVPN RT2 DMAC flow install
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / netvirt / elan / evpn / utils / EvpnUtils.java
1 /*
2  * Copyright © 2017 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.elan.evpn.utils;
9
10
11 import com.google.common.base.Optional;
12
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;
18
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;
38
39 public class EvpnUtils {
40
41     private static final Logger LOG = LoggerFactory.getLogger(EvpnUtils.class);
42
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;
49
50     private volatile IBgpManager bgpManager;
51     private volatile IVpnManager vpnManager;
52
53     public EvpnUtils(DataBroker broker, IInterfaceManager interfaceManager,
54                      ElanUtils elanUtils, ItmRpcService itmRpcService) {
55         this.broker = broker;
56         this.interfaceManager = interfaceManager;
57         this.elanUtils = elanUtils;
58         this.itmRpcService = itmRpcService;
59     }
60
61     public void init() {
62     }
63
64     public void close() {
65     }
66
67     public void setVpnManager(IVpnManager vpnManager) {
68         this.vpnManager = vpnManager;
69     }
70
71     public void setBgpManager(IBgpManager bgpManager) {
72         this.bgpManager = bgpManager;
73     }
74
75     public boolean isWithdrawEvpnRT2Routes(EvpnAugmentation original, EvpnAugmentation update) {
76         return isNetDetach.test(original.getEvpnName(), update.getEvpnName());
77     }
78
79     public boolean isAdvertiseEvpnRT2Routes(EvpnAugmentation original, EvpnAugmentation update) {
80         return isNetAttach.test(original.getEvpnName(), update.getEvpnName())
81                 || isNetAttach.test(original.getL3vpnName(), update.getL3vpnName());
82     }
83
84     @SuppressWarnings("checkstyle:IllegalCatch")
85     public void advertiseEvpnRT2Routes(EvpnAugmentation evpnAugmentation, String elanName)  {
86         if (evpnAugmentation == null || evpnAugmentation.getEvpnName() == null) {
87             return;
88         }
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);
93             return;
94         }
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());
102         });
103     }
104
105     public String getEndpointIpAddressForDPN(BigInteger dpnId) {
106
107         Future<RpcResult<GetDpnEndpointIpsOutput>> result = itmRpcService.getDpnEndpointIps(
108                 new GetDpnEndpointIpsInputBuilder()
109                         .setSourceDpid(dpnId)
110                         .build());
111         RpcResult<GetDpnEndpointIpsOutput> rpcResult = null;
112         try {
113             rpcResult = result.get();
114         } catch (InterruptedException e) {
115             LOG.error("getnextHopIpFromRpcOutput : InterruptedException for dpnid {}", e, dpnId);
116             return null;
117         } catch (ExecutionException e) {
118             LOG.error("getnextHopIpFromRpcOutput : ExecutionException for dpnid {}", e, dpnId);
119             return null;
120         }
121         if (!rpcResult.isSuccessful()) {
122             LOG.warn("RPC Call to getDpnEndpointIps returned with Errors {}", rpcResult.getErrors());
123             return null;
124         }
125
126         List<IpAddress> nexthopIpList = rpcResult.getResult().getNexthopipList();
127         return nexthopIpList.get(0).getIpv4Address().toString();
128     }
129
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());
135     }
136
137     public String getL3vpnNameFromElan(ElanInstance elanInfo) {
138         EvpnAugmentation evpnAugmentation = elanInfo.getAugmentation(EvpnAugmentation.class);
139         return evpnAugmentation != null ? evpnAugmentation.getL3vpnName() : null;
140     }
141
142     public static String getEvpnNameFromElan(ElanInstance elanInfo) {
143         EvpnAugmentation evpnAugmentation = elanInfo.getAugmentation(EvpnAugmentation.class);
144         return evpnAugmentation != null ? evpnAugmentation.getEvpnName() : null;
145     }
146
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);
151             return null;
152         }
153         return vpnManager.getVpnRd(broker, evpnName);
154     }
155
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);
160     }
161
162     @SuppressWarnings("checkstyle:IllegalCatch")
163     private void advertisePrefix(ElanInstance elanInfo, String rd,
164                                  String macAddress, String prefix, String interfaceName, BigInteger dpnId) {
165         if (rd == null) {
166             LOG.error("advertisePrefix : rd is NULL for elanInfo {}, macAddress {}", elanInfo, macAddress);
167             return;
168         }
169         String nextHop = getEndpointIpAddressForDPN(dpnId);
170         if (nextHop == null) {
171             LOG.error("Failed to get the dpn tep ip for dpn {}", dpnId);
172             return;
173         }
174         int vpnLabel = 0;
175         long l2vni = elanInfo.getSegmentationId();
176         long l3vni = 0;
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;
184         }
185         LOG.info("Advertising routes with rd {},  macAddress {}, prefix {}, nextHop {},"
186                         + " vpnLabel {}, l3vni {}, l2vni {}, gatewayMac {}", rd, macAddress, prefix, nextHop,
187                 vpnLabel, l3vni, l2vni, gatewayMacAddr);
188         try {
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);
193         }
194     }
195
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());
201     }
202
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);
207             return;
208         }
209         ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, elanName);
210         String rd = getEVpnRd(elanInfo);
211         if (rd == null) {
212             return;
213         }
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);
218         }
219     }
220
221     public void withdrawPrefix(ElanInstance elanInfo, String prefix) {
222         String rd = getEVpnRd(elanInfo);
223         if (rd == null) {
224             return;
225         }
226         bgpManager.withdrawPrefix(rd, prefix);
227     }
228
229     public void withdrawPrefix(ElanInstance elanInfo, MacEntry macEntry) {
230         withdrawPrefix(elanInfo, macEntry.getIpPrefix().getIpv4Address().getValue());
231     }
232
233 }