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.yangtools.yang.common.RpcError;
34 import org.opendaylight.yangtools.yang.common.RpcResult;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 public class VpnManagerImpl implements IVpnManager {
40 private static final Logger LOG = LoggerFactory.getLogger(VpnManagerImpl.class);
41 private final DataBroker dataBroker;
42 private final VpnInterfaceManager vpnInterfaceManager;
43 private final VpnInstanceListener vpnInstanceListener;
44 private final IdManagerService idManager;
45 private final IMdsalApiManager mdsalManager;
46 private final VpnFootprintService vpnFootprintService;
47 private final OdlInterfaceRpcService ifaceMgrRpcService;
48 private final IElanService elanService;
50 public VpnManagerImpl(final DataBroker dataBroker,
51 final IdManagerService idManagerService,
52 final VpnInstanceListener vpnInstanceListener,
53 final VpnInterfaceManager vpnInterfaceManager,
54 final IMdsalApiManager mdsalManager,
55 final VpnFootprintService vpnFootprintService,
56 final OdlInterfaceRpcService ifaceMgrRpcService,
57 final IElanService elanService) {
58 this.dataBroker = dataBroker;
59 this.vpnInterfaceManager = vpnInterfaceManager;
60 this.vpnInstanceListener = vpnInstanceListener;
61 this.idManager = idManagerService;
62 this.mdsalManager = mdsalManager;
63 this.vpnFootprintService = vpnFootprintService;
64 this.ifaceMgrRpcService = ifaceMgrRpcService;
65 this.elanService = elanService;
69 LOG.info("{} start", getClass().getSimpleName());
73 private void createIdPool() {
74 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
75 .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
76 .setLow(VpnConstants.VPN_IDPOOL_LOW)
77 .setHigh(VpnConstants.VPN_IDPOOL_HIGH)
80 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
81 if (result != null && result.get().isSuccessful()) {
82 LOG.info("Created IdPool for VPN Service");
84 } catch (InterruptedException | ExecutionException e) {
85 LOG.error("Failed to create idPool for VPN Service", e);
88 // Now an IdPool for InterVpnLink endpoint's pseudo ports
89 CreateIdPoolInput createPseudoLporTagPool =
90 new CreateIdPoolInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME)
91 .setLow(VpnConstants.LOWER_PSEUDO_LPORT_TAG)
92 .setHigh(VpnConstants.UPPER_PSEUDO_LPORT_TAG)
95 Future<RpcResult<Void>> result = idManager.createIdPool(createPseudoLporTagPool);
96 if (result != null && result.get().isSuccessful()) {
97 LOG.debug("Created IdPool for Pseudo Port tags");
99 Collection<RpcError> errors = result.get().getErrors();
100 StringBuilder errMsg = new StringBuilder();
101 for (RpcError err : errors) {
102 errMsg.append(err.getMessage()).append("\n");
104 LOG.error("IdPool creation for PseudoPort tags failed. Reasons: {}", errMsg);
106 } catch (InterruptedException | ExecutionException e) {
107 LOG.error("Failed to create idPool for Pseudo Port tags", e);
112 public void setFibManager(IFibManager fibManager) {
117 public void addExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
118 int label,RouteOrigin origin) {
119 LOG.info("Adding extra route with destination {}, nextHop {}, label{} and origin {}",
120 destination, nextHop, label, origin);
121 vpnInterfaceManager.addExtraRoute(vpnName, destination, nextHop, rd, routerID, label, origin,
122 /*intfName*/ null, null);
126 public void delExtraRoute(String destination, String nextHop, String rd, String routerID) {
127 LOG.info("Deleting extra route with destination {} and nextHop {}", destination, nextHop);
128 vpnInterfaceManager.delExtraRoute(destination, nextHop, rd, routerID, null, null);
132 public boolean isVPNConfigured() {
133 return vpnInstanceListener.isVPNConfigured();
137 public List<BigInteger> getDpnsOnVpn(String vpnInstanceName) {
138 return VpnUtil.getDpnsOnVpn(dataBroker, vpnInstanceName);
142 public void updateVpnFootprint(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
143 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, add);
147 public boolean existsVpn(String vpnName) {
148 return VpnUtil.getVpnInstance(dataBroker, vpnName) != null;
152 public long getArpCacheTimeoutMillis() {
153 return ArpConstants.ARP_CACHE_TIMEOUT_MILLIS;
157 public void setupSubnetMacIntoVpnInstance(String vpnName, String subnetVpnName, String srcMacAddress,
158 BigInteger dpnId, WriteTransaction writeTx, int addOrRemove) {
159 if (vpnName == null) {
160 LOG.warn("Cannot setup subnet MAC {} on DPN {}, null vpnName", srcMacAddress, dpnId);
164 VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, subnetVpnName,
165 srcMacAddress, dpnId, writeTx, addOrRemove);
169 public void setupRouterGwMacFlow(String routerName, String routerGwMac, BigInteger dpnId, Uuid extNetworkId,
170 WriteTransaction writeTx, int addOrRemove) {
171 if (routerGwMac == null) {
172 LOG.warn("Failed to handle router GW flow in GW-MAC table. MAC address is missing for router-id {}",
177 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
178 LOG.error("Failed to handle router GW flow in GW-MAC table. DPN id is missing for router-id", routerName);
182 Uuid vpnId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
184 LOG.warn("Network {} is not associated with VPN", extNetworkId.getValue());
188 LOG.info("{} router GW MAC flow for router-id {} on switch {}",
189 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", routerName, dpnId);
190 boolean submit = false;
191 if (writeTx == null) {
193 writeTx = dataBroker.newWriteOnlyTransaction();
196 setupSubnetMacIntoVpnInstance(vpnId.getValue(), null, routerGwMac, dpnId, writeTx,
204 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
205 BigInteger dpnId, Uuid extNetworkId, WriteTransaction writeTx, int addOrRemove) {
207 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
208 LOG.warn("Failed to install arp responder flows for router {}. DPN id is missing.", id);
212 String extInterfaceName = elanService.getExternalElanInterface(extNetworkId.getValue(), dpnId);
213 if (extInterfaceName == null) {
214 LOG.warn("Failed to install responder flows for {}. No external interface found for DPN id {}", id, dpnId);
218 Interface extInterfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, extInterfaceName);
219 if (extInterfaceState == null) {
220 LOG.debug("No interface state found for interface {}. Delaying responder flows for {}", extInterfaceName,
225 Integer lportTag = extInterfaceState.getIfIndex();
226 if (lportTag == null) {
227 LOG.debug("No Lport tag found for interface {}. Delaying flows for router-id {}", extInterfaceName, id);
231 long vpnId = (addOrRemove == NwConstants.ADD_FLOW) ? getVpnIdFromExtNetworkId(extNetworkId)
232 : VpnConstants.INVALID_ID;
233 setupArpResponderFlowsToExternalNetworkIps(id, fixedIps, macAddress, dpnId, vpnId, extInterfaceName, lportTag,
234 writeTx, addOrRemove);
239 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
240 BigInteger dpnId, long vpnId, String extInterfaceName, int lportTag, WriteTransaction writeTx,
242 if (fixedIps == null || fixedIps.isEmpty()) {
243 LOG.debug("No external IPs defined for {}", id);
247 LOG.info("{} ARP responder flows for {} fixed-ips {} on switch {}",
248 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", id, fixedIps, dpnId);
250 boolean submit = false;
251 if (writeTx == null) {
253 writeTx = dataBroker.newWriteOnlyTransaction();
256 for (String fixedIp : fixedIps) {
257 if (addOrRemove == NwConstants.ADD_FLOW) {
258 installArpResponderFlowsToExternalNetworkIp(macAddress, dpnId, extInterfaceName, lportTag, vpnId,
261 removeArpResponderFlowsToExternalNetworkIp(dpnId, lportTag, fixedIp, writeTx);
270 private void installArpResponderFlowsToExternalNetworkIp(String macAddress, BigInteger dpnId,
271 String extInterfaceName, Integer lportTag, long vpnId, String fixedIp, WriteTransaction writeTx) {
272 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
273 List<Instruction> instructions = ArpResponderUtil.getExtInterfaceInstructions(ifaceMgrRpcService,
274 extInterfaceName, fixedIp, macAddress);
275 ArpResponderUtil.installFlow(mdsalManager, writeTx, dpnId, flowId, flowId,
276 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, ArpResponderUtil.generateCookie(lportTag, fixedIp),
277 ArpResponderUtil.getMatchCriteria(lportTag, vpnId, fixedIp), instructions);
280 private void removeArpResponderFlowsToExternalNetworkIp(BigInteger dpnId, Integer lportTag, String fixedIp,
281 WriteTransaction writeTx) {
282 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
283 ArpResponderUtil.removeFlow(mdsalManager, writeTx, dpnId, flowId);
286 private long getVpnIdFromExtNetworkId(Uuid extNetworkId) {
287 Uuid vpnInstanceId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
288 if (vpnInstanceId == null) {
289 LOG.debug("Network {} is not associated with VPN", extNetworkId.getValue());
290 return VpnConstants.INVALID_ID;
293 return VpnUtil.getVpnId(dataBroker, vpnInstanceId.getValue());