2 * Copyright (c) 2015 - 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.vpnmanager;
10 import java.math.BigInteger;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.Future;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
20 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
21 import org.opendaylight.genius.mdsalutil.NwConstants;
22 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
23 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
24 import org.opendaylight.netvirt.elanmanager.api.IElanService;
25 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
26 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
27 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
28 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderUtil;
29 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
40 import org.opendaylight.yangtools.yang.common.RpcError;
41 import org.opendaylight.yangtools.yang.common.RpcResult;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 public class VpnManagerImpl implements IVpnManager {
47 private static final Logger LOG = LoggerFactory.getLogger(VpnManagerImpl.class);
48 private final DataBroker dataBroker;
49 private final VpnInterfaceManager vpnInterfaceManager;
50 private final VpnInstanceListener vpnInstanceListener;
51 private final IdManagerService idManager;
52 private final IMdsalApiManager mdsalManager;
53 private final VpnFootprintService vpnFootprintService;
54 private final OdlInterfaceRpcService ifaceMgrRpcService;
55 private final IElanService elanService;
56 private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
58 public VpnManagerImpl(final DataBroker dataBroker,
59 final IdManagerService idManagerService,
60 final VpnInstanceListener vpnInstanceListener,
61 final VpnInterfaceManager vpnInterfaceManager,
62 final IMdsalApiManager mdsalManager,
63 final VpnFootprintService vpnFootprintService,
64 final OdlInterfaceRpcService ifaceMgrRpcService,
65 final IElanService elanService,
66 final VpnSubnetRouteHandler vpnSubnetRouteHandler) {
67 this.dataBroker = dataBroker;
68 this.vpnInterfaceManager = vpnInterfaceManager;
69 this.vpnInstanceListener = vpnInstanceListener;
70 this.idManager = idManagerService;
71 this.mdsalManager = mdsalManager;
72 this.vpnFootprintService = vpnFootprintService;
73 this.ifaceMgrRpcService = ifaceMgrRpcService;
74 this.elanService = elanService;
75 this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
79 LOG.info("{} start", getClass().getSimpleName());
83 private void createIdPool() {
84 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
85 .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
86 .setLow(VpnConstants.VPN_IDPOOL_LOW)
87 .setHigh(VpnConstants.VPN_IDPOOL_HIGH)
90 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
91 if (result != null && result.get().isSuccessful()) {
92 LOG.info("Created IdPool for VPN Service");
94 } catch (InterruptedException | ExecutionException e) {
95 LOG.error("Failed to create idPool for VPN Service", e);
98 // Now an IdPool for InterVpnLink endpoint's pseudo ports
99 CreateIdPoolInput createPseudoLporTagPool =
100 new CreateIdPoolInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME)
101 .setLow(VpnConstants.LOWER_PSEUDO_LPORT_TAG)
102 .setHigh(VpnConstants.UPPER_PSEUDO_LPORT_TAG)
105 Future<RpcResult<Void>> result = idManager.createIdPool(createPseudoLporTagPool);
106 if (result != null && result.get().isSuccessful()) {
107 LOG.debug("Created IdPool for Pseudo Port tags");
109 Collection<RpcError> errors = result.get().getErrors();
110 StringBuilder errMsg = new StringBuilder();
111 for (RpcError err : errors) {
112 errMsg.append(err.getMessage()).append("\n");
114 LOG.error("IdPool creation for PseudoPort tags failed. Reasons: {}", errMsg);
116 } catch (InterruptedException | ExecutionException e) {
117 LOG.error("Failed to create idPool for Pseudo Port tags", e);
122 public void setFibManager(IFibManager fibManager) {
127 public void addExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
128 int label,RouteOrigin origin) {
129 LOG.info("Adding extra route with destination {}, nextHop {}, label{} and origin {}",
130 destination, nextHop, label, origin);
131 VpnInstanceOpDataEntry vpnOpEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
132 Boolean isVxlan = VpnUtil.isL3VpnOverVxLan(vpnOpEntry.getL3vni());
133 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isVxlan);
134 vpnInterfaceManager.addExtraRoute(vpnName, destination, nextHop, rd, routerID, label, vpnOpEntry.getL3vni(),
135 origin,/*intfName*/ null, null /*Adjacency*/, encapType, null);
139 public void delExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID) {
140 LOG.info("Deleting extra route with destination {} and nextHop {}", destination, nextHop);
141 vpnInterfaceManager.delExtraRoute(vpnName, destination, nextHop, rd, routerID, null, null);
145 public boolean isVPNConfigured() {
146 return vpnInstanceListener.isVPNConfigured();
150 public List<BigInteger> getDpnsOnVpn(String vpnInstanceName) {
151 return VpnUtil.getDpnsOnVpn(dataBroker, vpnInstanceName);
155 public boolean existsVpn(String vpnName) {
156 return VpnUtil.getVpnInstance(dataBroker, vpnName) != null;
160 public long getArpCacheTimeoutMillis() {
161 return ArpConstants.ARP_CACHE_TIMEOUT_MILLIS;
165 public void setupSubnetMacIntoVpnInstance(String vpnName, String subnetVpnName, String srcMacAddress,
166 BigInteger dpnId, WriteTransaction writeTx, int addOrRemove) {
167 if (vpnName == null) {
168 LOG.warn("Cannot setup subnet MAC {} on DPN {}, null vpnName", srcMacAddress, dpnId);
172 VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, subnetVpnName,
173 srcMacAddress, dpnId, writeTx, addOrRemove);
177 public void setupRouterGwMacFlow(String routerName, String routerGwMac, BigInteger dpnId, Uuid extNetworkId,
178 WriteTransaction writeTx, int addOrRemove) {
179 if (routerGwMac == null) {
180 LOG.warn("Failed to handle router GW flow in GW-MAC table. MAC address is missing for router-id {}",
185 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
186 LOG.error("Failed to handle router GW flow in GW-MAC table. DPN id is missing for router-id", routerName);
190 Uuid vpnId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
192 LOG.warn("Network {} is not associated with VPN", extNetworkId.getValue());
196 LOG.info("{} router GW MAC flow for router-id {} on switch {}",
197 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", routerName, dpnId);
198 boolean submit = false;
199 if (writeTx == null) {
201 writeTx = dataBroker.newWriteOnlyTransaction();
204 setupSubnetMacIntoVpnInstance(vpnId.getValue(), null, routerGwMac, dpnId, writeTx,
212 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
213 BigInteger dpnId, Uuid extNetworkId, WriteTransaction writeTx, int addOrRemove) {
215 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
216 LOG.warn("Failed to install arp responder flows for router {}. DPN id is missing.", id);
220 String extInterfaceName = elanService.getExternalElanInterface(extNetworkId.getValue(), dpnId);
221 if (extInterfaceName == null) {
222 LOG.warn("Failed to install responder flows for {}. No external interface found for DPN id {}", id, dpnId);
226 Interface extInterfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, extInterfaceName);
227 if (extInterfaceState == null) {
228 LOG.debug("No interface state found for interface {}. Delaying responder flows for {}", extInterfaceName,
233 Integer lportTag = extInterfaceState.getIfIndex();
234 if (lportTag == null) {
235 LOG.debug("No Lport tag found for interface {}. Delaying flows for router-id {}", extInterfaceName, id);
239 long vpnId = (addOrRemove == NwConstants.ADD_FLOW) ? getVpnIdFromExtNetworkId(extNetworkId)
240 : VpnConstants.INVALID_ID;
241 setupArpResponderFlowsToExternalNetworkIps(id, fixedIps, macAddress, dpnId, vpnId, extInterfaceName, lportTag,
242 writeTx, addOrRemove);
247 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
248 BigInteger dpnId, long vpnId, String extInterfaceName, int lportTag, WriteTransaction writeTx,
250 if (fixedIps == null || fixedIps.isEmpty()) {
251 LOG.debug("No external IPs defined for {}", id);
255 LOG.info("{} ARP responder flows for {} fixed-ips {} on switch {}",
256 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", id, fixedIps, dpnId);
258 boolean submit = false;
259 if (writeTx == null) {
261 writeTx = dataBroker.newWriteOnlyTransaction();
264 for (String fixedIp : fixedIps) {
265 if (addOrRemove == NwConstants.ADD_FLOW) {
266 installArpResponderFlowsToExternalNetworkIp(macAddress, dpnId, extInterfaceName, lportTag, vpnId,
269 removeArpResponderFlowsToExternalNetworkIp(dpnId, lportTag, fixedIp, writeTx);
279 public List<MatchInfoBase> getEgressMatchesForVpn(String vpnName) {
280 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
281 if (vpnId == VpnConstants.INVALID_ID) {
282 LOG.warn("No VPN id found for {}", vpnName);
283 return Collections.emptyList();
287 .singletonList(new NxMatchRegister(VpnConstants.VPN_REG_ID, vpnId, MetaDataUtil.getVpnIdMaskForReg()));
290 private void installArpResponderFlowsToExternalNetworkIp(String macAddress, BigInteger dpnId,
291 String extInterfaceName, Integer lportTag, long vpnId, String fixedIp, WriteTransaction writeTx) {
292 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
293 List<Instruction> instructions = ArpResponderUtil.getExtInterfaceInstructions(ifaceMgrRpcService,
294 extInterfaceName, fixedIp, macAddress);
295 ArpResponderUtil.installFlow(mdsalManager, writeTx, dpnId, flowId, flowId,
296 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, ArpResponderUtil.generateCookie(lportTag, fixedIp),
297 ArpResponderUtil.getMatchCriteria(lportTag, vpnId, fixedIp), instructions);
300 private void removeArpResponderFlowsToExternalNetworkIp(BigInteger dpnId, Integer lportTag, String fixedIp,
301 WriteTransaction writeTx) {
302 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
303 ArpResponderUtil.removeFlow(mdsalManager, writeTx, dpnId, flowId);
306 private long getVpnIdFromExtNetworkId(Uuid extNetworkId) {
307 Uuid vpnInstanceId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
308 if (vpnInstanceId == null) {
309 LOG.debug("Network {} is not associated with VPN", extNetworkId.getValue());
310 return VpnConstants.INVALID_ID;
313 return VpnUtil.getVpnId(dataBroker, vpnInstanceId.getValue());
317 public void onSubnetAddedToVpn(Subnetmap subnetmap, boolean isBgpVpn, Long elanTag) {
318 vpnSubnetRouteHandler.onSubnetAddedToVpn(subnetmap, isBgpVpn, elanTag);
322 public void onSubnetDeletedFromVpn(Subnetmap subnetmap, boolean isBgpVpn) {
323 vpnSubnetRouteHandler.onSubnetDeletedFromVpn(subnetmap, isBgpVpn);