2 * Copyright (c) 2015 - 2016 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.List;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
20 import org.opendaylight.netvirt.elanmanager.api.IElanService;
21 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
22 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
23 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
24 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderUtil;
25 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
34 import org.opendaylight.yangtools.yang.common.RpcError;
35 import org.opendaylight.yangtools.yang.common.RpcResult;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 public class VpnManagerImpl implements IVpnManager {
41 private static final Logger LOG = LoggerFactory.getLogger(VpnManagerImpl.class);
42 private final DataBroker dataBroker;
43 private final VpnInterfaceManager vpnInterfaceManager;
44 private final VpnInstanceListener vpnInstanceListener;
45 private final IdManagerService idManager;
46 private final IMdsalApiManager mdsalManager;
47 private final VpnFootprintService vpnFootprintService;
48 private final OdlInterfaceRpcService ifaceMgrRpcService;
49 private final IElanService elanService;
51 public VpnManagerImpl(final DataBroker dataBroker,
52 final IdManagerService idManagerService,
53 final VpnInstanceListener vpnInstanceListener,
54 final VpnInterfaceManager vpnInterfaceManager,
55 final IMdsalApiManager mdsalManager,
56 final VpnFootprintService vpnFootprintService,
57 final OdlInterfaceRpcService ifaceMgrRpcService,
58 final IElanService elanService) {
59 this.dataBroker = dataBroker;
60 this.vpnInterfaceManager = vpnInterfaceManager;
61 this.vpnInstanceListener = vpnInstanceListener;
62 this.idManager = idManagerService;
63 this.mdsalManager = mdsalManager;
64 this.vpnFootprintService = vpnFootprintService;
65 this.ifaceMgrRpcService = ifaceMgrRpcService;
66 this.elanService = elanService;
70 LOG.info("{} start", getClass().getSimpleName());
74 private void createIdPool() {
75 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
76 .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
77 .setLow(VpnConstants.VPN_IDPOOL_LOW)
78 .setHigh(VpnConstants.VPN_IDPOOL_HIGH)
81 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
82 if (result != null && result.get().isSuccessful()) {
83 LOG.info("Created IdPool for VPN Service");
85 } catch (InterruptedException | ExecutionException e) {
86 LOG.error("Failed to create idPool for VPN Service", e);
89 // Now an IdPool for InterVpnLink endpoint's pseudo ports
90 CreateIdPoolInput createPseudoLporTagPool =
91 new CreateIdPoolInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME)
92 .setLow(VpnConstants.LOWER_PSEUDO_LPORT_TAG)
93 .setHigh(VpnConstants.UPPER_PSEUDO_LPORT_TAG)
96 Future<RpcResult<Void>> result = idManager.createIdPool(createPseudoLporTagPool);
97 if (result != null && result.get().isSuccessful()) {
98 LOG.debug("Created IdPool for Pseudo Port tags");
100 Collection<RpcError> errors = result.get().getErrors();
101 StringBuilder errMsg = new StringBuilder();
102 for (RpcError err : errors) {
103 errMsg.append(err.getMessage()).append("\n");
105 LOG.error("IdPool creation for PseudoPort tags failed. Reasons: {}", errMsg);
107 } catch (InterruptedException | ExecutionException e) {
108 LOG.error("Failed to create idPool for Pseudo Port tags", e);
113 public void setFibManager(IFibManager fibManager) {
118 public void addExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
119 int label,RouteOrigin origin) {
120 LOG.info("Adding extra route with destination {}, nextHop {}, label{} and origin {}",
121 destination, nextHop, label, origin);
122 vpnInterfaceManager.addExtraRoute(vpnName, destination, nextHop, rd, routerID, label, 0 /*l3vni*/, origin,
123 /*intfName*/ null, null /*Adjacency*/, VrfEntry.EncapType.Mplsgre, null);
127 public void delExtraRoute(String destination, String nextHop, String rd, String routerID) {
128 LOG.info("Deleting extra route with destination {} and nextHop {}", destination, nextHop);
129 vpnInterfaceManager.delExtraRoute(destination, nextHop, rd, routerID, null, null);
133 public boolean isVPNConfigured() {
134 return vpnInstanceListener.isVPNConfigured();
138 public List<BigInteger> getDpnsOnVpn(String vpnInstanceName) {
139 return VpnUtil.getDpnsOnVpn(dataBroker, vpnInstanceName);
143 public void updateVpnFootprint(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
144 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, add);
148 public boolean existsVpn(String vpnName) {
149 return VpnUtil.getVpnInstance(dataBroker, vpnName) != null;
153 public long getArpCacheTimeoutMillis() {
154 return ArpConstants.ARP_CACHE_TIMEOUT_MILLIS;
158 public void setupSubnetMacIntoVpnInstance(String vpnName, String subnetVpnName, String srcMacAddress,
159 BigInteger dpnId, WriteTransaction writeTx, int addOrRemove) {
160 if (vpnName == null) {
161 LOG.warn("Cannot setup subnet MAC {} on DPN {}, null vpnName", srcMacAddress, dpnId);
165 VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, subnetVpnName,
166 srcMacAddress, dpnId, writeTx, addOrRemove);
170 public void setupRouterGwMacFlow(String routerName, String routerGwMac, BigInteger dpnId, Uuid extNetworkId,
171 WriteTransaction writeTx, int addOrRemove) {
172 if (routerGwMac == null) {
173 LOG.warn("Failed to handle router GW flow in GW-MAC table. MAC address is missing for router-id {}",
178 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
179 LOG.error("Failed to handle router GW flow in GW-MAC table. DPN id is missing for router-id", routerName);
183 Uuid vpnId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
185 LOG.warn("Network {} is not associated with VPN", extNetworkId.getValue());
189 LOG.info("{} router GW MAC flow for router-id {} on switch {}",
190 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", routerName, dpnId);
191 boolean submit = false;
192 if (writeTx == null) {
194 writeTx = dataBroker.newWriteOnlyTransaction();
197 setupSubnetMacIntoVpnInstance(vpnId.getValue(), null, routerGwMac, dpnId, writeTx,
205 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
206 BigInteger dpnId, Uuid extNetworkId, WriteTransaction writeTx, int addOrRemove) {
208 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
209 LOG.warn("Failed to install arp responder flows for router {}. DPN id is missing.", id);
213 String extInterfaceName = elanService.getExternalElanInterface(extNetworkId.getValue(), dpnId);
214 if (extInterfaceName == null) {
215 LOG.warn("Failed to install responder flows for {}. No external interface found for DPN id {}", id, dpnId);
219 Interface extInterfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, extInterfaceName);
220 if (extInterfaceState == null) {
221 LOG.debug("No interface state found for interface {}. Delaying responder flows for {}", extInterfaceName,
226 Integer lportTag = extInterfaceState.getIfIndex();
227 if (lportTag == null) {
228 LOG.debug("No Lport tag found for interface {}. Delaying flows for router-id {}", extInterfaceName, id);
232 long vpnId = (addOrRemove == NwConstants.ADD_FLOW) ? getVpnIdFromExtNetworkId(extNetworkId)
233 : VpnConstants.INVALID_ID;
234 setupArpResponderFlowsToExternalNetworkIps(id, fixedIps, macAddress, dpnId, vpnId, extInterfaceName, lportTag,
235 writeTx, addOrRemove);
240 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
241 BigInteger dpnId, long vpnId, String extInterfaceName, int lportTag, WriteTransaction writeTx,
243 if (fixedIps == null || fixedIps.isEmpty()) {
244 LOG.debug("No external IPs defined for {}", id);
248 LOG.info("{} ARP responder flows for {} fixed-ips {} on switch {}",
249 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", id, fixedIps, dpnId);
251 boolean submit = false;
252 if (writeTx == null) {
254 writeTx = dataBroker.newWriteOnlyTransaction();
257 for (String fixedIp : fixedIps) {
258 if (addOrRemove == NwConstants.ADD_FLOW) {
259 installArpResponderFlowsToExternalNetworkIp(macAddress, dpnId, extInterfaceName, lportTag, vpnId,
262 removeArpResponderFlowsToExternalNetworkIp(dpnId, lportTag, fixedIp, writeTx);
271 private void installArpResponderFlowsToExternalNetworkIp(String macAddress, BigInteger dpnId,
272 String extInterfaceName, Integer lportTag, long vpnId, String fixedIp, WriteTransaction writeTx) {
273 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
274 List<Instruction> instructions = ArpResponderUtil.getExtInterfaceInstructions(ifaceMgrRpcService,
275 extInterfaceName, fixedIp, macAddress);
276 ArpResponderUtil.installFlow(mdsalManager, writeTx, dpnId, flowId, flowId,
277 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, ArpResponderUtil.generateCookie(lportTag, fixedIp),
278 ArpResponderUtil.getMatchCriteria(lportTag, vpnId, fixedIp), instructions);
281 private void removeArpResponderFlowsToExternalNetworkIp(BigInteger dpnId, Integer lportTag, String fixedIp,
282 WriteTransaction writeTx) {
283 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
284 ArpResponderUtil.removeFlow(mdsalManager, writeTx, dpnId, flowId);
287 private long getVpnIdFromExtNetworkId(Uuid extNetworkId) {
288 Uuid vpnInstanceId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
289 if (vpnInstanceId == null) {
290 LOG.debug("Network {} is not associated with VPN", extNetworkId.getValue());
291 return VpnConstants.INVALID_ID;
294 return VpnUtil.getVpnId(dataBroker, vpnInstanceId.getValue());