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;
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.MatchInfoBase;
19 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
20 import org.opendaylight.genius.mdsalutil.NwConstants;
21 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
22 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
23 import org.opendaylight.netvirt.elanmanager.api.IElanService;
24 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
25 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
26 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderUtil;
27 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
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 addExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID,
123 int label,RouteOrigin origin) {
124 LOG.info("Adding extra route with destination {}, nextHop {}, label{} and origin {}",
125 destination, nextHop, label, origin);
126 VpnInstanceOpDataEntry vpnOpEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
127 Boolean isVxlan = VpnUtil.isL3VpnOverVxLan(vpnOpEntry.getL3vni());
128 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isVxlan);
129 vpnInterfaceManager.addExtraRoute(vpnName, destination, nextHop, rd, routerID, label, vpnOpEntry.getL3vni(),
130 origin,/*intfName*/ null, null /*Adjacency*/, encapType, null);
134 public void delExtraRoute(String vpnName, String destination, String nextHop, String rd, String routerID) {
135 LOG.info("Deleting extra route with destination {} and nextHop {}", destination, nextHop);
136 vpnInterfaceManager.delExtraRoute(vpnName, destination, nextHop, rd, routerID, null, null);
140 public boolean isVPNConfigured() {
141 return vpnInstanceListener.isVPNConfigured();
145 public List<BigInteger> getDpnsOnVpn(String vpnInstanceName) {
146 return VpnUtil.getDpnsOnVpn(dataBroker, vpnInstanceName);
150 public boolean existsVpn(String vpnName) {
151 return VpnUtil.getVpnInstance(dataBroker, vpnName) != null;
155 public void setupSubnetMacIntoVpnInstance(String vpnName, String subnetVpnName, String srcMacAddress,
156 BigInteger dpnId, WriteTransaction writeTx, int addOrRemove) {
157 if (vpnName == null) {
158 LOG.warn("Cannot setup subnet MAC {} on DPN {}, null vpnName", srcMacAddress, dpnId);
162 VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, subnetVpnName,
163 srcMacAddress, dpnId, writeTx, addOrRemove);
167 public void setupRouterGwMacFlow(String routerName, String routerGwMac, BigInteger dpnId, Uuid extNetworkId,
168 WriteTransaction writeTx, int addOrRemove) {
169 if (routerGwMac == null) {
170 LOG.warn("Failed to handle router GW flow in GW-MAC table. MAC address is missing for router-id {}",
175 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
176 LOG.error("Failed to handle router GW flow in GW-MAC table. DPN id is missing for router-id", routerName);
180 Uuid vpnId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
182 LOG.warn("Network {} is not associated with VPN", extNetworkId.getValue());
186 LOG.info("{} router GW MAC flow for router-id {} on switch {}",
187 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", routerName, dpnId);
188 boolean submit = false;
189 if (writeTx == null) {
191 writeTx = dataBroker.newWriteOnlyTransaction();
194 setupSubnetMacIntoVpnInstance(vpnId.getValue(), null, routerGwMac, dpnId, writeTx,
202 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
203 BigInteger dpnId, Uuid extNetworkId, WriteTransaction writeTx, int addOrRemove) {
205 if (dpnId == null || BigInteger.ZERO.equals(dpnId)) {
206 LOG.warn("Failed to install arp responder flows for router {}. DPN id is missing.", id);
210 String extInterfaceName = elanService.getExternalElanInterface(extNetworkId.getValue(), dpnId);
211 if (extInterfaceName == null) {
212 LOG.warn("Failed to install responder flows for {}. No external interface found for DPN id {}", id, dpnId);
216 Interface extInterfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, extInterfaceName);
217 if (extInterfaceState == null) {
218 LOG.debug("No interface state found for interface {}. Delaying responder flows for {}", extInterfaceName,
223 Integer lportTag = extInterfaceState.getIfIndex();
224 if (lportTag == null) {
225 LOG.debug("No Lport tag found for interface {}. Delaying flows for router-id {}", extInterfaceName, id);
229 long vpnId = (addOrRemove == NwConstants.ADD_FLOW) ? getVpnIdFromExtNetworkId(extNetworkId)
230 : VpnConstants.INVALID_ID;
231 setupArpResponderFlowsToExternalNetworkIps(id, fixedIps, macAddress, dpnId, vpnId, extInterfaceName, lportTag,
232 writeTx, addOrRemove);
237 public void setupArpResponderFlowsToExternalNetworkIps(String id, Collection<String> fixedIps, String macAddress,
238 BigInteger dpnId, long vpnId, String extInterfaceName, int lportTag, WriteTransaction writeTx,
240 if (fixedIps == null || fixedIps.isEmpty()) {
241 LOG.debug("No external IPs defined for {}", id);
245 LOG.info("{} ARP responder flows for {} fixed-ips {} on switch {}",
246 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", id, fixedIps, dpnId);
248 boolean submit = false;
249 if (writeTx == null) {
251 writeTx = dataBroker.newWriteOnlyTransaction();
254 for (String fixedIp : fixedIps) {
255 if (addOrRemove == NwConstants.ADD_FLOW) {
256 installArpResponderFlowsToExternalNetworkIp(macAddress, dpnId, extInterfaceName, lportTag, vpnId,
259 removeArpResponderFlowsToExternalNetworkIp(dpnId, lportTag, fixedIp, writeTx);
269 public List<MatchInfoBase> getEgressMatchesForVpn(String vpnName) {
270 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
271 if (vpnId == VpnConstants.INVALID_ID) {
272 LOG.warn("No VPN id found for {}", vpnName);
273 return Collections.emptyList();
277 .singletonList(new NxMatchRegister(VpnConstants.VPN_REG_ID, vpnId, MetaDataUtil.getVpnIdMaskForReg()));
280 private void installArpResponderFlowsToExternalNetworkIp(String macAddress, BigInteger dpnId,
281 String extInterfaceName, Integer lportTag, long vpnId, String fixedIp, WriteTransaction writeTx) {
282 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
283 List<Instruction> instructions = ArpResponderUtil.getExtInterfaceInstructions(ifaceMgrRpcService,
284 extInterfaceName, fixedIp, macAddress);
285 ArpResponderUtil.installFlow(mdsalManager, writeTx, dpnId, flowId, flowId,
286 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, ArpResponderUtil.generateCookie(lportTag, fixedIp),
287 ArpResponderUtil.getMatchCriteria(lportTag, vpnId, fixedIp), instructions);
290 private void removeArpResponderFlowsToExternalNetworkIp(BigInteger dpnId, Integer lportTag, String fixedIp,
291 WriteTransaction writeTx) {
292 String flowId = ArpResponderUtil.getFlowID(lportTag, fixedIp);
293 ArpResponderUtil.removeFlow(mdsalManager, writeTx, dpnId, flowId);
296 private long getVpnIdFromExtNetworkId(Uuid extNetworkId) {
297 Uuid vpnInstanceId = VpnUtil.getExternalNetworkVpnId(dataBroker, extNetworkId);
298 if (vpnInstanceId == null) {
299 LOG.debug("Network {} is not associated with VPN", extNetworkId.getValue());
300 return VpnConstants.INVALID_ID;
303 return VpnUtil.getVpnId(dataBroker, vpnInstanceId.getValue());
307 public void onSubnetAddedToVpn(Subnetmap subnetmap, boolean isBgpVpn, Long elanTag) {
308 vpnSubnetRouteHandler.onSubnetAddedToVpn(subnetmap, isBgpVpn, elanTag);
312 public void onSubnetDeletedFromVpn(Subnetmap subnetmap, boolean isBgpVpn) {
313 vpnSubnetRouteHandler.onSubnetDeletedFromVpn(subnetmap, isBgpVpn);
316 public VpnInstance getVpnInstance(DataBroker broker, String vpnInstanceName) {
317 return VpnUtil.getVpnInstance(broker, vpnInstanceName);
320 public String getVpnRd(DataBroker broker, String vpnName) {
321 return VpnUtil.getVpnRd(broker, vpnName);
324 public VpnPortipToPort getNeutronPortFromVpnPortFixedIp(DataBroker broker, String vpnName, String fixedIp) {
325 return VpnUtil.getNeutronPortFromVpnPortFixedIp(broker, vpnName, fixedIp);