import org.opendaylight.netvirt.cloudservicechain.jobs.RemoveVpnPseudoPortDataJob;
import org.opendaylight.netvirt.cloudservicechain.utils.VpnPseudoPortCache;
import org.opendaylight.netvirt.cloudservicechain.utils.VpnServiceChainUtils;
+import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
private final IMdsalApiManager mdsalManager;
private final DataBroker broker;
- private final FibRpcService fibRpcService;
+ private final IVpnManager vpnManager;
- public VPNServiceChainHandler(final DataBroker db, IMdsalApiManager mdsalManager, FibRpcService fibRpcSrv) {
+
+ public VPNServiceChainHandler(final DataBroker db, final IMdsalApiManager mdsalManager,
+ final IVpnManager vpnManager) {
this.broker = db;
this.mdsalManager = mdsalManager;
- this.fibRpcService = fibRpcSrv;
+ this.vpnManager = vpnManager;
}
public void init() {
tableIdToGoTo, addOrRemove);
}
- /**
- * Get fake VPNPseudoPort interface name.
- *
- * @param dpId Dpn Id
- * @param scfTag Service Function tag
- * @param scsTag Service Chain tag
- * @param lportTag Lport tag
- * @return the fake VpnPseudoPort interface name
- */
- private String buildVpnPseudoPortIfName(Long dpId, long scfTag, int scsTag, int lportTag) {
- return new StringBuilder("VpnPseudo.").append(dpId).append(NwConstants.FLOWID_SEPARATOR)
- .append(lportTag).append(NwConstants.FLOWID_SEPARATOR)
- .append(scfTag).append(NwConstants.FLOWID_SEPARATOR)
- .append(scsTag).toString();
- }
/**
* L3VPN Service chaining: It moves traffic from a ServiceChain to a L3VPN.
// We need to keep a fake VpnInterface in the DPN where the last vSF (before the VpnPseudoPort) is
// located, because in case the last real VpnInterface is removed from that DPN, we still need
// the Fib table programmed there
- String intfName = buildVpnPseudoPortIfName(dpnId, scfTag, servChainTag, vpnPseudoLportTag);
- if (addOrRemove == NwConstants.ADD_FLOW ) {
- // Including this DPN in the VPN footprint even if there is no VpnInterface here.
- // This is needed so that FibManager maintains the FIB table in this DPN
- VpnServiceChainUtils.updateMappingDbs(broker, fibRpcService, vpnInstance.getVpnId(),
- BigInteger.valueOf(dpnId), intfName, vpnName);
- } else {
- VpnServiceChainUtils.removeFromMappingDbs(broker, fibRpcService, vpnInstance.getVpnId(),
- BigInteger.valueOf(dpnId), intfName, vpnName);
- }
+ String intfName = VpnServiceChainUtils.buildVpnPseudoPortIfName(dpnId, scfTag, servChainTag,
+ vpnPseudoLportTag);
+ vpnManager.updateVpnFootprint(BigInteger.valueOf(dpnId), vpnName, intfName,
+ (addOrRemove == NwConstants.ADD_FLOW) );
}
LOG.info("L3VPN: Service Chaining programScfToVpnPipeline [End]");
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.VpnToPseudoPortList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.vpn.to.pseudo.port.list.VpnToPseudoPortData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.vpn.to.pseudo.port.list.VpnToPseudoPortDataKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CleanupDpnForVpnInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CleanupDpnForVpnInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.PopulateFibOnDpnInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.PopulateFibOnDpnInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
}
public static InstanceIdentifier<VrfTables> buildVrfId(String rd) {
- InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder = InstanceIdentifier.builder(FibEntries.class)
- .child(VrfTables.class, new VrfTablesKey(rd));
- InstanceIdentifier<VrfTables> id = idBuilder.build();
- return id;
+ return InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
}
public static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
public static InstanceIdentifier<VpnToPseudoPortData> getVpnToPseudoPortTagIid(String rd) {
VpnToPseudoPortDataKey key = new VpnToPseudoPortDataKey(rd);
- InstanceIdentifier<VpnToPseudoPortData> result = InstanceIdentifier.builder(VpnToPseudoPortList.class)
- .child(VpnToPseudoPortData.class, key)
- .build();
- return result;
+ return InstanceIdentifier.builder(VpnToPseudoPortList.class).child(VpnToPseudoPortData.class, key).build();
}
public static Optional<VpnToPseudoPortData> getVpnPseudoPortData(DataBroker broker, String rd) {
return all.isPresent() ? all.get().getVpnToPseudoPortData() : new ArrayList<>();
}
+ /**
+ * Get fake VPNPseudoPort interface name.
+ *
+ * @param dpId Dpn Id
+ * @param scfTag Service Function tag
+ * @param scsTag Service Chain tag
+ * @param lportTag Lport tag
+ * @return the fake VpnPseudoPort interface name
+ */
+ public static String buildVpnPseudoPortIfName(Long dpId, long scfTag, int scsTag, int lportTag) {
+ return new StringBuilder("VpnPseudo.").append(dpId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(lportTag).append(NwConstants.FLOWID_SEPARATOR)
+ .append(scfTag).append(NwConstants.FLOWID_SEPARATOR)
+ .append(scsTag).toString();
+ }
/**
* Retrieves the VpnId (datapath id) searching by VpnInstanceName.
InstanceIdentifier<VrfTables> vpnVrfTables =
InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
Optional<VrfTables> vrfTable = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTables);
- List<VrfEntry> vpnVrfEntries = vrfTable.isPresent() ? vrfTable.get().getVrfEntry()
- : new ArrayList<>();
- return vpnVrfEntries;
+ return vrfTable.isPresent() ? vrfTable.get().getVrfEntry() : new ArrayList<>();
}
/**
}));
instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { gotoTableId }));
String flowRef = getL3VpnToScfLportDispatcherFlowRef(lportTag);
- FlowEntity flowEntity =
- MDSALUtil.buildFlowEntity(dpId, NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
- CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY, flowRef, 0, 0,
- getCookieSCHop(scfTag), matches, instructions);
- return flowEntity;
+
+ return MDSALUtil.buildFlowEntity(dpId, NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
+ CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY, flowRef, 0, 0,
+ getCookieSCHop(scfTag), matches, instructions);
}
NwConstants.L3VPN_SERVICE_INDEX));
List<Instruction> instructions = buildSetVrfTagAndGotoFibInstructions(vpnTag);
String flowRef = getL3VpnToL3VpnLportDispFlowRef(dstLportTag, vpnTag);
- Flow result = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
- CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
- 0, 0, VpnServiceChainUtils.getCookieL3(vpnTag),
- matches, instructions);
- return result;
- }
-
- /**
- * Updates the VPN footprint by adding a 'fake' interface for the
- * VpnPseudoPort. The objective of this operation is that the FibManager,
- * on one hand, maintains the FIB table even in DPNs where there are no
- * real VpnInterfaces and, on other hand, keeps maintaining the FIB table
- * even after the last real VpnInterface is removed.
- *
- */
- public static void updateMappingDbs(DataBroker broker, FibRpcService fibRpcService, long vpnId,
- BigInteger dpnId, String intfName, String vpnName) {
- if (vpnName != null) {
- synchronized (vpnName.intern()) {
- String routeDistinguisher = getVpnRd(broker, vpnName);
- String rd = routeDistinguisher == null ? vpnName : routeDistinguisher;
- InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
- Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
- VpnInterfaces vpnInterface =
- new VpnInterfacesBuilder().setInterfaceName(intfName).build();
- if (dpnInVpn.isPresent()) {
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL,
- id.child(VpnInterfaces.class, new VpnInterfacesKey(intfName)), vpnInterface);
- } else {
- VpnInstanceOpDataEntry vpnOpData = new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId)
- .setVpnInstanceName(vpnName)
- .build();
- MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,getVpnInstanceOpDataIdentifier(rd),
- vpnOpData);
- VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
- List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
- vpnInterfaces.add(vpnInterface);
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
- vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
- PopulateFibOnDpnInput populateFibInput =
- new PopulateFibOnDpnInputBuilder().setDpid(dpnId).setVpnId(vpnId)
- .setRd(rd == null ? vpnName : rd)
- .build();
- fibRpcService.populateFibOnDpn(populateFibInput);
- }
- }
- } else {
- LOG.debug("vpnName is null");
- }
- }
- /**
- * Updates the VPN footprint by removing a 'fake' interface that represents
- * the VpnPseudoPort.
- *
- */
- public static void removeFromMappingDbs(DataBroker broker, FibRpcService fibRpcService, long vpnId,
- BigInteger dpnId, String intfName, String vpnName) {
- //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
- if (vpnName != null) {
- synchronized (vpnName.intern()) {
- String rd = getVpnRd(broker, vpnName);
- InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
- Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
- if (dpnInVpn.isPresent()) {
- List<VpnInterfaces> vpnInterfaces =
- dpnInVpn.get().getVpnInterfaces();
- VpnInterfaces currVpnInterface =
- new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
- if (vpnInterfaces.remove(currVpnInterface)) {
- if (vpnInterfaces.isEmpty()) {
- List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
- if (ipAddresses == null || ipAddresses.isEmpty()) {
- LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
- CleanupDpnForVpnInput cleanupVpnInDpnInput =
- new CleanupDpnForVpnInputBuilder().setDpid(dpnId).setVpnId(vpnId)
- .setRd(rd == null ? vpnName : rd).build();
- fibRpcService.cleanupDpnForVpn(cleanupVpnInDpnInput);
- } else {
- LOG.debug("vpn interfaces are empty but ip addresses are present for the vpn {} "
- + "in dpn {}", vpnName, dpnId);
- }
- } else {
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
- VpnInterfaces.class,
- new VpnInterfacesKey(intfName)));
- }
- }
- }
- }
- }
+ return MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
+ CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
+ 0, 0, VpnServiceChainUtils.getCookieL3(vpnTag),
+ matches, instructions);
}
-
private static BigInteger getCookieSCHop(long scfInstanceTag) {
return CloudServiceChainConstants.COOKIE_SCF_BASE.add(new BigInteger("0610000", 16))
.add(BigInteger.valueOf(scfInstanceTag));
<reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
odl:type="pingpong" />
<reference id="mdsalManager" interface="org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager" />
-
- <odl:rpc-service id="fibRpcService"
- interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService"/>
+ <reference id="vpnManager" interface="org.opendaylight.netvirt.vpnmanager.api.IVpnManager" />
<bean id="vpnServiceChainHandler" class="org.opendaylight.netvirt.cloudservicechain.VPNServiceChainHandler"
init-method="init" destroy-method="close">
<argument ref="dataBroker" />
<argument ref="mdsalManager" />
- <argument ref="fibRpcService" />
+ <argument ref="vpnManager" />
</bean>
<bean id="elanServiceChainHandler" class="org.opendaylight.netvirt.cloudservicechain.ElanServiceChainHandler">
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
-
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import org.opendaylight.netvirt.cloudservicechain.matchers.FlowEntityMatcher;
import org.opendaylight.netvirt.cloudservicechain.matchers.FlowMatcher;
import org.opendaylight.netvirt.cloudservicechain.utils.VpnServiceChainUtils;
+import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
@Mock ReadOnlyTransaction readTx;
@Mock WriteTransaction writeTx;
@Mock IMdsalApiManager mdsalMgr;
+ @Mock IVpnManager vpnManager;
@BeforeClass
when(broker.newWriteOnlyTransaction()).thenReturn(writeTx);
CheckedFuture chkdFuture = mock(CheckedFuture.class);
when(writeTx.submit()).thenReturn(chkdFuture);
- vpnsch = new VPNServiceChainHandler(broker, mdsalMgr, fibRpcService);
+
+ // SUT
+ vpnsch = new VPNServiceChainHandler(broker, mdsalMgr, vpnManager);
}
@After
VpnServiceChainUtils.buildLPortDispFromScfToL3VpnFlow(VPN_ID, DPN_ID, LPORT_TAG, NwConstants.ADD_FLOW);
assert (new FlowMatcher(expectedLportDispatcherFlowEntity).matches(installedFlowsCaptured.get(0)));
- LOG.info("second call = {}", installedFlowsCaptured.get(1));
-
// Verifying VpnToDpn update
- verify(writeTx, times(1)).put(eq(LogicalDatastoreType.OPERATIONAL),
- argThat(isIIdType(VpnInterfaces.class)),
- anyObject(), eq(Boolean.TRUE));
+ String vpnPseudoPortIfaceName =
+ VpnServiceChainUtils.buildVpnPseudoPortIfName(DPN_ID.longValue(), SCF_TAG, SERV_CHAIN_TAG, LPORT_TAG);
+ verify(vpnManager).updateVpnFootprint(eq(DPN_ID), eq(VPN_NAME), eq(vpnPseudoPortIfaceName), eq(Boolean.TRUE));
}
* @return The list of DPNs
*/
List<BigInteger> getDpnsOnVpn(String vpnInstanceName);
+
+ /**
+ * Updates the footprint that a VPN has on a given DPN by adding/removing
+ * the specified interface
+ *
+ * @param dpId DPN where the VPN interface belongs to
+ * @param vpnName Name of the VPN whose footprint is being modified
+ * @param interfaceName Name of the VPN interface to be added/removed
+ * to/from the specified DPN
+ * @param add true for addition, false for removal
+ */
+ void updateVpnFootprint(BigInteger dpId, String vpnName, String interfaceName, boolean add);
+
void setupSubnetMacIntoVpnInstance(String vpnName, String srcMacAddress,
BigInteger dpnId, WriteTransaction writeTx, int addOrRemove);
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.vpnmanager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VpnFootprintService {
+
+ // TODO: Should this class have its own interface instead of being under IVpnManager's umbrella?
+
+ private static final Logger LOG = LoggerFactory.getLogger(VpnFootprintService.class);
+
+ private final DataBroker dataBroker;
+ private final IFibManager fibManager;
+ private final OdlInterfaceRpcService ifaceMgrRpcService;
+ private final NotificationPublishService notificationPublishService;
+
+ public VpnFootprintService(final DataBroker dataBroker,
+ final IFibManager fibManager,
+ final OdlInterfaceRpcService ifaceRpcService,
+ final NotificationPublishService notificationPublishService) {
+ this.dataBroker = dataBroker;
+ this.fibManager = fibManager;
+ this.ifaceMgrRpcService = ifaceRpcService;
+ this.notificationPublishService = notificationPublishService;
+ }
+
+ public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
+ long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+ if (dpId == null) {
+ dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
+ }
+ if(!dpId.equals(BigInteger.ZERO)) {
+ if(add) {
+ createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
+ } else {
+ removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
+ }
+ }
+ }
+
+ private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+ String routeDistinguisher = VpnUtil.getVpnRdFromVpnInstanceConfig(dataBroker, vpnName);
+ String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
+ Boolean newDpnOnVpn = Boolean.FALSE;
+
+ synchronized (vpnName.intern()) {
+ WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (dpnInVpn.isPresent()) {
+ VpnToDpnList vpnToDpnList = dpnInVpn.get();
+ List<VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
+ if (vpnInterfaces == null) {
+ vpnInterfaces = new ArrayList<>();
+ }
+ vpnInterfaces.add(vpnInterface);
+ VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
+ vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
+
+ writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
+ /* If earlier state was inactive, it is considered new DPN coming back to the
+ * same VPN
+ */
+ if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
+ newDpnOnVpn = Boolean.TRUE;
+ }
+ } else {
+ List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
+ vpnInterfaces.add(vpnInterface);
+ VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
+ vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
+
+ writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
+ newDpnOnVpn = Boolean.TRUE;
+ }
+ CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ /*
+ * Informing the Fib only after writeTxn is submitted successfuly.
+ */
+ if (newDpnOnVpn) {
+ LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
+ fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd,
+ true /* entered */));
+ }
+ }
+
+ private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+ Boolean lastDpnOnVpn = Boolean.FALSE;
+ String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
+ synchronized (vpnName.intern()) {
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
+ if (dpnInVpn.isPresent()) {
+ List<VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+ VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (vpnInterfaces.remove(currVpnInterface)) {
+ if (vpnInterfaces.isEmpty()) {
+ List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
+ if (ipAddresses == null || ipAddresses.isEmpty()) {
+ VpnToDpnListBuilder dpnInVpnBuilder =
+ new VpnToDpnListBuilder(dpnInVpn.get()).setDpnState(VpnToDpnList.DpnState.Inactive)
+ .setVpnInterfaces(null);
+ writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
+ lastDpnOnVpn = Boolean.TRUE;
+ } else {
+ LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}",
+ vpnName, dpnId);
+ }
+ } else {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(VpnInterfaces.class,
+ new VpnInterfacesKey(intfName)));
+ }
+ }
+ }
+ CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ if (lastDpnOnVpn) {
+ LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
+ fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd,
+ false /* exited */));
+ }
+ }
+
+ void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
+ LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
+ AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
+ AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
+ final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
+ Futures.addCallback(eventFuture, new FutureCallback<Object>() {
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
+ }
+
+ @Override
+ public void onSuccess(Object arg) {
+ LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
+ }
+ });
+ }
+
+ void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
+ LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
+ RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
+ RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
+ final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
+ Futures.addCallback(eventFuture, new FutureCallback<Object>() {
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
+ }
+
+ @Override
+ public void onSuccess(Object arg) {
+ LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
+ }
+ });
+ }
+
+
+ /**
+ * JobCallback class is used as a future callback for
+ * main and rollback workers to handle success and failure.
+ */
+ private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
+ BigInteger dpnId;
+ String vpnName;
+ String rd;
+ boolean entered;
+
+ public DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
+ this.entered = entered;
+ this.dpnId = dpnId;
+ this.vpnName = vpnName;
+ this.rd = rd;
+ }
+
+ /**
+ * @param voids
+ * This implies that all the future instances have returned success. -- TODO: Confirm this
+ */
+ @Override
+ public void onSuccess(List<Void> voids) {
+ if (entered) {
+ publishAddNotification(dpnId, vpnName, rd);
+ } else {
+ publishRemoveNotification(dpnId, vpnName, rd);
+ }
+ }
+
+ /**
+ *
+ * @param throwable
+ * This method is used to handle failure callbacks.
+ * If more retry needed, the retrycount is decremented and mainworker is executed again.
+ * After retries completed, rollbackworker is executed.
+ * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
+ */
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.warn("Job: failed with exception: ", throwable);
+ }
+ }
+
+}
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterators;
-import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
import org.opendaylight.genius.mdsalutil.FlowEntity;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager>
implements AutoCloseable {
+
private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
+ private static final int vpnInfUpdateTimerTaskDelay = 1000;
+ private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
+
private final DataBroker dataBroker;
private final IBgpManager bgpManager;
private final IFibManager fibManager;
private final IdManagerService idManager;
private final OdlArputilService arpManager;
private final OdlInterfaceRpcService ifaceMgrRpcService;
- private final NotificationPublishService notificationPublishService;
+ private final VpnFootprintService vpnFootprintService;
+
private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
private ConcurrentHashMap<String, List<Runnable>> vpnInstanceToIdSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
private ConcurrentHashMap<String, List<Runnable>> vpnInstanceOpDataSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
- private ExecutorService executorService = Executors.newSingleThreadExecutor();
- private static final int vpnInfUpdateTimerTaskDelay = 1000;
- private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
+
private BlockingQueue<UpdateData> vpnInterfacesUpdateQueue = new LinkedBlockingQueue<>();
private ScheduledThreadPoolExecutor vpnInfUpdateTaskExecutor = (ScheduledThreadPoolExecutor) Executors
.newScheduledThreadPool(1);
final IMdsalApiManager mdsalManager,
final IFibManager fibManager,
final OdlInterfaceRpcService ifaceMgrRpcService,
- final NotificationPublishService notificationPublishService) {
+ final VpnFootprintService vpnFootprintService) {
super(VpnInterface.class, VpnInterfaceManager.class);
this.dataBroker = dataBroker;
this.bgpManager = bgpManager;
this.mdsalManager = mdsalManager;
this.fibManager = fibManager;
this.ifaceMgrRpcService = ifaceMgrRpcService;
- this.notificationPublishService = notificationPublishService;
+ this.vpnFootprintService = vpnFootprintService;
vpnInfUpdateTaskExecutor.scheduleWithFixedDelay(new VpnInterfaceUpdateTimerTask(),
0, vpnInfUpdateTimerTaskDelay, TIME_UNIT);
}
}
if (!waitForVpnInterfaceOpRemoval) {
// Add the VPNInterface and quit
- updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
+ vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
return;
return;
}
// VPNInterface got removed, proceed with Add
- updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
+ vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
} else {
}
}
- public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
- long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
- if (dpId == null) {
- dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
- }
- if(!dpId.equals(BigInteger.ZERO)) {
- if(add) {
- createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
- } else {
- removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
- }
- }
- }
-
private void bindService(BigInteger dpId, final String vpnInstanceName, final String vpnInterfaceName,
int lPortTag, WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
final int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
return rd;
}
- /**
- * JobCallback class is used as a future callback for
- * main and rollback workers to handle success and failure.
- */
- private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
- BigInteger dpnId;
- String vpnName;
- String rd;
- boolean entered;
-
- public DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
- this.entered = entered;
- this.dpnId = dpnId;
- this.vpnName = vpnName;
- this.rd = rd;
- }
-
- /**
- * @param voids
- * This implies that all the future instances have returned success. -- TODO: Confirm this
- */
- @Override
- public void onSuccess(List<Void> voids) {
- if (entered) {
- publishAddNotification(dpnId, vpnName, rd);
- } else {
- publishRemoveNotification(dpnId, vpnName, rd);
- }
- }
-
- /**
- *
- * @param throwable
- * This method is used to handle failure callbacks.
- * If more retry needed, the retrycount is decremented and mainworker is executed again.
- * After retries completed, rollbackworker is executed.
- * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
- */
- @Override
- public void onFailure(Throwable throwable) {
- LOG.warn("Job: failed with exception: ", throwable);
- }
- }
- private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
- String routeDistinguisher = getRouteDistinguisher(vpnName);
- String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
- Boolean newDpnOnVpn = Boolean.FALSE;
-
- synchronized (vpnName.intern()) {
- WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
- InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
- Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data
- .entry.vpn.to.dpn.list.VpnInterfaces
- vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
- if (dpnInVpn.isPresent()) {
- VpnToDpnList vpnToDpnList = dpnInVpn.get();
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
- .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
- if (vpnInterfaces == null) {
- vpnInterfaces = new ArrayList<>();
- }
- vpnInterfaces.add(vpnInterface);
- VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
- vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
- if (writeTxn != null) {
- writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
- } else {
- VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
- }
- /* If earlier state was inactive, it is considered new DPN coming back to the
- * same VPN
- */
- if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
- newDpnOnVpn = Boolean.TRUE;
- }
- } else {
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
- .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
- vpnInterfaces.add(vpnInterface);
- VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
- vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
-
- if (writeTxn != null) {
- writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
- } else {
- VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
- }
- newDpnOnVpn = Boolean.TRUE;
- }
- CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
- try {
- futures.get();
- } catch (InterruptedException | ExecutionException e) {
- LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
- throw new RuntimeException(e.getMessage());
- }
- }
- /*
- * Informing the Fib only after writeTxn is submitted successfuly.
- */
- if (newDpnOnVpn) {
- LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
- fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, true /* entered */));
- }
- }
-
- private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
- Boolean lastDpnOnVpn = Boolean.FALSE;
- String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
- synchronized (vpnName.intern()) {
- InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
- Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
- WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
- if (dpnInVpn.isPresent()) {
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
- .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
- currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
- if (vpnInterfaces.remove(currVpnInterface)) {
- if (vpnInterfaces.isEmpty()) {
- List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
- if (ipAddresses == null || ipAddresses.isEmpty()) {
- VpnToDpnListBuilder dpnInVpnBuilder =
- new VpnToDpnListBuilder(dpnInVpn.get())
- .setDpnState(VpnToDpnList.DpnState.Inactive)
- .setVpnInterfaces(null);
- if (writeTxn != null) {
- writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
- } else {
- VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build());
- }
- lastDpnOnVpn = Boolean.TRUE;
- } else {
- LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
- }
- } else {
- if (writeTxn != null) {
- writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
- .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
- new VpnInterfacesKey(intfName)));
- } else {
- VpnUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
- .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
- new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
- }
- }
- }
- }
- CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
- try {
- futures.get();
- } catch (InterruptedException | ExecutionException e) {
- LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
- throw new RuntimeException(e.getMessage());
- }
- }
- if (lastDpnOnVpn) {
- LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
- fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
- }
- }
void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
}
}
- void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
- LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
- AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
- AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
- final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
- Futures.addCallback(eventFuture, new FutureCallback<Object>() {
- @Override
- public void onFailure(Throwable error) {
- LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
- }
-
- @Override
- public void onSuccess(Object arg) {
- LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
- }
- });
- }
-
- void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
- LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
- RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
- RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
- final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
- Futures.addCallback(eventFuture, new FutureCallback<Object>() {
- @Override
- public void onFailure(Throwable error) {
- LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
- }
-
- @Override
- public void onSuccess(Object arg) {
- LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
- }
- });
- }
InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
return InstanceIdentifier.builder(NeutronRouterDpns.class)
private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceOpListener.class);
private final DataBroker dataBroker;
private final VpnInterfaceManager vpnInterfaceManager;
+ private final VpnFootprintService vpnFootprintService;
private ExecutorService executorService = Executors.newSingleThreadExecutor();
/*public VpnInterfaceOpListener(final DataBroker dataBroker) {
this.dataBroker = dataBroker;
}*/
- public VpnInterfaceOpListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager) {
+ public VpnInterfaceOpListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager,
+ final VpnFootprintService vpnFootprintService) {
super(VpnInterface.class, VpnInterfaceOpListener.class);
this.dataBroker = dataBroker;
this.vpnInterfaceManager = vpnInterfaceManager;
+ this.vpnFootprintService = vpnFootprintService;
}
public void start() {
VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
VpnUtil.DEFAULT_CALLBACK);
}
- vpnInterfaceManager.updateVpnToDpnMapping(pref.getDpnId(), del.getVpnInstanceName(),
- interfaceName, false /* delete */);
+ vpnFootprintService.updateVpnToDpnMapping(pref.getDpnId(), del.getVpnInstanceName(),
+ interfaceName, false /* delete */);
}
}
} else {
= VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, origId);
if (origVpnInstance.isPresent()) {
- String rd = null;
- rd = origVpnInstance.get().getVrfId();
+ String rd = origVpnInstance.get().getVrfId();
vpnInstOp = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
LOG.trace("VpnInterfaceOpListener updated: interface name {} original rd {} original vpnName {}",
}
}
for (Prefixes prefix : prefixToInterfaceList) {
- vpnInterfaceManager.updateVpnToDpnMapping(prefix.getDpnId(), original.getVpnInstanceName(),
- interfaceName, false /* delete */);
+ vpnFootprintService.updateVpnToDpnMapping(prefix.getDpnId(), original.getVpnInstanceName(),
+ interfaceName, false /* delete */);
}
}
}
private final VpnInstanceListener vpnInstanceListener;
private final IdManagerService idManager;
private final IMdsalApiManager mdsalManager;
+ private final VpnFootprintService vpnFootprintService;
public VpnManagerImpl(final DataBroker dataBroker,
final IdManagerService idManagerService,
final VpnInstanceListener vpnInstanceListener,
final VpnInterfaceManager vpnInterfaceManager,
- final IMdsalApiManager mdsalManager) {
+ final IMdsalApiManager mdsalManager,
+ final VpnFootprintService vpnFootprintService) {
this.dataBroker = dataBroker;
this.vpnInterfaceManager = vpnInterfaceManager;
this.vpnInstanceListener = vpnInstanceListener;
this.idManager = idManagerService;
this.mdsalManager = mdsalManager;
+ this.vpnFootprintService = vpnFootprintService;
}
public void start() {
RouteOrigin origin) {
LOG.info("Adding extra route with destination {}, nextHop {}, label{} and origin {}",
destination, nextHop, label, origin);
- vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label, origin, /*intfName*/ null,
+ vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label, origin, /*intfName*/ null,
null, null);
}
return VpnUtil.getDpnsOnVpn(dataBroker, vpnInstanceName);
}
+ @Override
+ public void updateVpnFootprint(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
+ vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, add);
+ }
+
@Override
public boolean existsVpn(String vpnName) {
return VpnUtil.getVpnInstance(dataBroker, vpnName) != null;
.build();
}
- /**
- * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
- * This method is preferably over mergeDpnInVpnToDpnMap(DataBroker, String, String, BigInteger, List)
- * when there are several DPNs to be merged since it saves some readings from MDSAL.
- *
- * @param broker dataBroker service reference
- * @param vpnOpData Reference to the object that holds the Operational data of the VpnInstance
- * @param dpnId Id of the DPN where the interfaces to be added to Operational data are located
- * @param ifaceNames List of interface names
- */
- public static void mergeDpnInVpnToDpnMap(DataBroker broker, VpnInstanceOpDataEntry vpnOpData, BigInteger dpnId,
- List<String> ifaceNames) {
- Preconditions.checkNotNull(vpnOpData);
- Preconditions.checkNotNull(ifaceNames);
-
- for (String ifaceName : ifaceNames) {
- InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnDpnIfaceIid =
- getVpnToDpnInterfacePath(vpnOpData.getKey().getVrfId(), dpnId, ifaceName);
-
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnDpnIface =
- new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list
- .VpnInterfacesBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(ifaceName))
- .setInterfaceName(ifaceName)
- .build();
-
- syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vpnDpnIfaceIid, vpnDpnIface);
- }
- }
-
- /**
- * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
- *
- * @param broker dataBroker service reference
- * @param vpnName Name of the VPN
- * @param rd Route-Distinguisher
- * @param dpnId Id of the DPN that includes the list of Ifaces to be
- * included in the Map
- * @param ifaceNames List of interfaces to be included in the Map
- */
- public static void mergeDpnInVpnToDpnMap(DataBroker broker, String vpnName, String rd, BigInteger dpnId,
- List<String> ifaceNames) {
- InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
- .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
- .build();
-
- Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
- MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
- if (vpnInstanceOpData.isPresent()) {
- mergeDpnInVpnToDpnMap(broker, vpnInstanceOpData.get(), dpnId, ifaceNames);
- }
- }
-
- /**
- * Removes a specific interface from the VpnToDpn operative map.
- *
- * @param broker dataBroker service reference
- * @param rd Route-distinguisher of the VPN
- * @param dpnId Id of the DPN where the interface is
- * @param ifaceName interface name.
- */
- public static void removeIfaceFromVpnToDpnMap(DataBroker broker, String rd, BigInteger dpnId, String ifaceName) {
- tryDelete(broker, LogicalDatastoreType.OPERATIONAL, getVpnToDpnInterfacePath(rd, dpnId, ifaceName));
- // Note: tryDelete is a best-effort. Sometimes we want to update the VpnToDpnMap ifaces when the
- // DPN has gone down (and the VpnToDpnMap has been removed in a different Thread)
- }
public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
try {
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
import org.opendaylight.netvirt.vpnmanager.VpnConstants;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
import org.opendaylight.netvirt.vpnmanager.VpnUtil;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
private final IBgpManager bgpManager;
private final IFibManager fibManager;
private final NotificationPublishService notificationsService;
+ private final VpnFootprintService vpnFootprintService;
// A couple of listener in order to maintain the InterVpnLink cache
private InterVpnLinkCacheFeeder iVpnLinkCacheFeeder;
public InterVpnLinkListener(final DataBroker dataBroker, final IdManagerService idManager,
final IMdsalApiManager mdsalManager, final IBgpManager bgpManager,
- final IFibManager fibManager, final NotificationPublishService notifService) {
+ final IFibManager fibManager, final NotificationPublishService notifService,
+ final VpnFootprintService vpnFootprintService) {
super(InterVpnLink.class, InterVpnLinkListener.class);
this.dataBroker = dataBroker;
this.idManager = idManager;
this.bgpManager = bgpManager;
this.fibManager = fibManager;
this.notificationsService = notifService;
+ this.vpnFootprintService = vpnFootprintService;
}
public void start() {
return InterVpnLinkListener.this;
}
- private String getInterVpnLinkIfaceName(String vpnUuid, BigInteger dpnId ) {
- return String.format("InterVpnLink.%s.%s", vpnUuid, dpnId.toString());
- }
-
@Override
protected void add(InstanceIdentifier<InterVpnLink> identifier, InterVpnLink add) {
MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid, vpnLinkState);
InterVpnLinkKey key = add.getKey();
- Uuid firstEndpointVpnUuid = add.getFirstEndpoint().getVpnUuid();
- Uuid secondEndpointVpnUuid = add.getSecondEndpoint().getVpnUuid();
+ Uuid vpn1Uuid = add.getFirstEndpoint().getVpnUuid();
+ String vpn1Name = vpn1Uuid.getValue();
+ Uuid vpn2Uuid = add.getSecondEndpoint().getVpnUuid();
+ String vpn2Name = vpn2Uuid.getValue();
// First VPN
- if ( VpnUtil.getVpnInstance(this.dataBroker, firstEndpointVpnUuid.getValue()) == null ) {
+ if ( VpnUtil.getVpnInstance(this.dataBroker, vpn1Name) == null ) {
String errMsg = "InterVpnLink " + add.getName() + " creation error: could not find 1st endpoint Vpn "
- + firstEndpointVpnUuid.getValue();
+ + vpn1Name;
setInError(vpnLinkStateIid, vpnLinkState, errMsg);
return;
}
- if (!checkVpnAvailability(key, firstEndpointVpnUuid)) {
- String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + firstEndpointVpnUuid.getValue()
- + " is already associated to an inter-vpn-link ";
+ if (!checkVpnAvailability(key, vpn1Uuid)) {
+ String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + vpn1Name
+ + " is already associated to an inter-vpn-link ";
setInError(vpnLinkStateIid, vpnLinkState, errMsg);
return;
}
// Second VPN
- if ( VpnUtil.getVpnInstance(this.dataBroker, secondEndpointVpnUuid.getValue()) == null ) {
+ if ( VpnUtil.getVpnInstance(this.dataBroker, vpn2Name) == null ) {
String errMsg = "InterVpnLink " + add.getName() + " creation error: could not find 2nd endpoint Vpn "
- + secondEndpointVpnUuid.getValue();
+ + vpn2Name;
setInError(vpnLinkStateIid, vpnLinkState, errMsg);
return;
}
- if (!checkVpnAvailability(key, secondEndpointVpnUuid)) {
- String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + secondEndpointVpnUuid.getValue()
- + " is already associated with an inter-vpn-link";
+ if (!checkVpnAvailability(key, vpn2Uuid)) {
+ String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + vpn2Name
+ + " is already associated with an inter-vpn-link";
setInError(vpnLinkStateIid, vpnLinkState, errMsg);
return;
}
if (firstDpnList != null && !firstDpnList.isEmpty()) {
List<BigInteger> secondDpnList = firstDpnList;
- Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
- Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
+ Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn1Name);
+ Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn2Name);
FirstEndpointState firstEndPointState =
- new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid).setDpId(firstDpnList)
+ new FirstEndpointStateBuilder().setVpnUuid(vpn1Uuid).setDpId(firstDpnList)
.setLportTag(firstVpnLportTag).build();
SecondEndpointState secondEndPointState =
- new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid).setDpId(secondDpnList)
+ new SecondEndpointStateBuilder().setVpnUuid(vpn2Uuid).setDpId(secondDpnList)
.setLportTag(secondVpnLportTag).build();
InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Active,
// Note that in the DPN of the firstEndpoint we install the lportTag of the secondEndpoint and viceversa
InterVpnLinkUtil.installLPortDispatcherTableFlow(dataBroker, mdsalManager, add, firstDpnList,
- secondEndpointVpnUuid, secondVpnLportTag.intValue());
+ vpn2Uuid, secondVpnLportTag.intValue());
InterVpnLinkUtil.installLPortDispatcherTableFlow(dataBroker, mdsalManager, add, secondDpnList,
- firstEndpointVpnUuid, firstVpnLportTag.intValue());
+ vpn1Uuid, firstVpnLportTag.intValue());
// Update the VPN -> DPNs Map.
// Note: when a set of DPNs is calculated for Vpn1, these DPNs are added to the VpnToDpn map of Vpn2. Why?
// because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
// to Vpn2 targets. If new Vpn2 targets are added later, the Fib will be maintained in these DPNs even if
// Vpn2 is not physically present there.
- InterVpnLinkUtil.updateVpnToDpnMap(dataBroker, firstDpnList, secondEndpointVpnUuid);
- InterVpnLinkUtil.updateVpnToDpnMap(dataBroker, secondDpnList, firstEndpointVpnUuid);
+ InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, vpn2Name, firstDpnList);
+ InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, vpn1Name, secondDpnList);
// Program static routes if needed
handleStaticRoutes(iVpnLink.get());
} else {
// If there is no connection to DPNs, the InterVpnLink is created and the InterVpnLinkState is also created
// with the corresponding LPortTags but no DPN is assigned since there is no DPN operative.
- Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
- Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
+ Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn1Name);
+ Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn2Name);
FirstEndpointState firstEndPointState =
- new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid)
- .setLportTag(firstVpnLportTag).build();
+ new FirstEndpointStateBuilder().setVpnUuid(vpn1Uuid).setLportTag(firstVpnLportTag).build();
SecondEndpointState secondEndPointState =
- new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid)
- .setLportTag(secondVpnLportTag).build();
+ new SecondEndpointStateBuilder().setVpnUuid(vpn2Uuid).setLportTag(secondVpnLportTag).build();
InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Error,
firstEndPointState, secondEndPointState);
}
boolean isVpnFirstEndPoint = true;
if (interVpnLinkState.getFirstEndpointState() != null) {
Long firstEndpointLportTag = interVpnLinkState.getFirstEndpointState().getLportTag();
- removeVpnLinkEndpointFlows(del, rd2, vpn2Uuid,
+ removeVpnLinkEndpointFlows(del, vpn2Uuid,
interVpnLinkState.getSecondEndpointState().getDpId(),
firstEndpointLportTag.intValue(),
del.getFirstEndpoint().getIpAddress().getValue(),
isVpnFirstEndPoint = false;
if (interVpnLinkState.getSecondEndpointState() != null) {
Long secondEndpointLportTag = interVpnLinkState.getSecondEndpointState().getLportTag();
- removeVpnLinkEndpointFlows(del, rd1, vpn1Uuid,
+ removeVpnLinkEndpointFlows(del, vpn1Uuid,
interVpnLinkState.getFirstEndpointState().getDpId(),
secondEndpointLportTag.intValue(),
del.getSecondEndpoint().getIpAddress().getValue(),
VpnUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
}
- private void removeVpnLinkEndpointFlows(InterVpnLink del, String rd, String vpnUuid, List<BigInteger> dpns,
+ private void removeVpnLinkEndpointFlows(InterVpnLink del, String vpnUuid, List<BigInteger> dpns,
int otherEndpointLportTag, String otherEndpointIpAddr, List<VrfEntry> vrfEntries,
final boolean isVpnFirstEndPoint) {
mdsalManager.removeFlow(dpnId, flow);
// Also remove the 'fake' iface from the VpnToDpn map
- VpnUtil.removeIfaceFromVpnToDpnMap(dataBroker, rd, dpnId, getInterVpnLinkIfaceName(vpnUuid, dpnId));
+ InterVpnLinkUtil.removeIVpnLinkIfaceFromVpnFootprint(vpnFootprintService, vpnUuid, dpnId);
} catch ( Exception e ) {
// Whatever happens it should not stop it from trying to remove as much as possible
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
import org.opendaylight.netvirt.vpnmanager.VpnUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
private static final String NBR_OF_DPNS_PROPERTY_NAME = "vpnservice.intervpnlink.number.dpns";
private DataBroker broker;
+ private final IMdsalApiManager mdsalManager;
+ private final VpnFootprintService vpnFootprintService;
+
private BigInteger dpnId;
- final IMdsalApiManager mdsalManager;
- public InterVpnLinkNodeAddTask(final DataBroker broker, final IMdsalApiManager mdsalMgr, final BigInteger dpnId) {
+ public InterVpnLinkNodeAddTask(final DataBroker broker, final IMdsalApiManager mdsalMgr,
+ final VpnFootprintService vpnFootprintService, final BigInteger dpnId) {
this.broker = broker;
- this.dpnId = dpnId;
this.mdsalManager = mdsalMgr;
+ this.vpnFootprintService = vpnFootprintService;
+
+ this.dpnId = dpnId;
}
@Override
// because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
// to Vpn2 targets. If new Vpn2 targets are added later, the Fib will be maintained in these DPNs even if
// Vpn2 is not physically present there.
- InterVpnLinkUtil.updateVpnToDpnMap(broker, firstDpnList, secondEndpointVpnUuid);
- InterVpnLinkUtil.updateVpnToDpnMap(broker, secondDpnList, firstEndpointVpnUuid);
+ InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, secondEndpointVpnUuid.getValue(), firstDpnList);
+ InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, firstEndpointVpnUuid.getValue(), secondDpnList);
}
}
import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
private final DataBroker dataBroker;
private final IMdsalApiManager mdsalManager;
+ private final VpnFootprintService vpnFootprintService;
- public InterVpnLinkNodeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalMgr) {
+ public InterVpnLinkNodeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalMgr,
+ final VpnFootprintService vpnFootprintService) {
super(Node.class, InterVpnLinkNodeListener.class);
this.dataBroker = dataBroker;
- mdsalManager = mdsalMgr;
+ this.mdsalManager = mdsalMgr;
+ this.vpnFootprintService = vpnFootprintService;
}
public void start() {
BigInteger dpId = new BigInteger(node[1]);
DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
coordinator.enqueueJob("IVpnLink" + dpId.toString(),
- new InterVpnLinkNodeAddTask(dataBroker, mdsalManager, dpId));
+ new InterVpnLinkNodeAddTask(dataBroker, mdsalManager, vpnFootprintService, dpId));
}
@Override
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
import org.opendaylight.netvirt.vpnmanager.VpnConstants;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
import org.opendaylight.netvirt.vpnmanager.VpnUtil;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
.build();
}
+ public static String buildInterVpnLinkIfaceName(String vpnName, BigInteger dpnId) {
+ return String.format("InterVpnLink.%s.%s", vpnName, dpnId.toString());
+ }
+
/**
* Updates VpnToDpn map by adding a fake VpnInterface related to an
- * InterVpnLink in the corresponding DPNs
+ * InterVpnLink in the corresponding DPNs. If the fake iface is the
+ * first one on the any of the specified DPNs, the installation of
+ * Fib flows on that DPN will be triggered
*
- * @param broker dataBroker service reference
+ * @param vpnFootprintService VpnFootprintService service reference
+ * @param vpnName Name of the VPN to which the fake interfaces belong
* @param dpnList List of DPNs where the fake InterVpnLink interface must
* be added
- * @param vpnUuid UUID of the VPN to which the fake interfaces belong
*/
- public static void updateVpnToDpnMap(DataBroker broker, List<BigInteger> dpnList, Uuid vpnUuid) {
- String rd = VpnUtil.getVpnRd(broker, vpnUuid.getValue());
- InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
- Optional<VpnInstanceOpDataEntry> vpnInstOpData = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
- if ( vpnInstOpData.isPresent() ) {
- for (BigInteger dpnId : dpnList) {
- String linkIfaceName = String.format("InterVpnLink.%s.%s", vpnUuid.getValue(), dpnId.toString());
- VpnUtil.mergeDpnInVpnToDpnMap(broker, vpnInstOpData.get(), dpnId, Arrays.asList(linkIfaceName));
- }
+ public static void updateVpnFootprint(VpnFootprintService vpnFootprintService, String vpnName,
+ List<BigInteger> dpnList) {
+ LOG.debug("updateVpnFootprint (add): vpn={} dpnList={}", vpnName, dpnList);
+ for ( BigInteger dpnId : dpnList ) {
+ String ifaceName = buildInterVpnLinkIfaceName(vpnName, dpnId);
+ vpnFootprintService.updateVpnToDpnMapping(dpnId, vpnName, ifaceName, true /* addition */);
}
}
+ /**
+ * Updates VpnToDpn map by removing the fake VpnInterface related to an
+ * InterVpnLink in the corresponding DPNs.
+ *
+ * @param vpnFootprintService VpnFootprintService service reference
+ * @param vpnName Name of the VPN to which the fake interfaces belong
+ * @param dpnId DPN where the fake InterVpnLink interface must be removed from
+ */
+ public static void removeIVpnLinkIfaceFromVpnFootprint(VpnFootprintService vpnFootprintService,
+ String vpnName, BigInteger dpnId) {
+ String ifaceName = buildInterVpnLinkIfaceName(vpnName, dpnId);
+ LOG.debug("updateVpnFootprint (remove): vpn={} dpn={} ifaceName={}", vpnName, dpnId, ifaceName);
+ vpnFootprintService.updateVpnToDpnMapping(dpnId, vpnName, ifaceName, false /* removal */);
+ }
+
/**
* Retrieves the InterVpnLink object searching by its name
interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OdlL3vpnListener" />
<odl:notification-listener ref="dpnInVpnChangeListener" />
+ <bean id="vpnFootprintService" class="org.opendaylight.netvirt.vpnmanager.VpnFootprintService">
+ <argument ref="dataBroker" />
+ <argument ref="fibManager" />
+ <argument ref="odlInterfaceRpcService" />
+ <argument ref="notificationPublishService" />
+ </bean>
+
<bean id="vpnInterfaceManager"
class="org.opendaylight.netvirt.vpnmanager.VpnInterfaceManager"
init-method="start" destroy-method="close">
<argument ref="mdsalUtils" />
<argument ref="fibManager" />
<argument ref="odlInterfaceRpcService" />
- <argument ref="notificationPublishService" />
+ <argument ref="vpnFootprintService" />
</bean>
<bean id="tunnelInterfaceStateListener"
init-method="start" destroy-method="close">
<argument ref="dataBroker" />
<argument ref="vpnInterfaceManager" />
+ <argument ref="vpnFootprintService" />
</bean>
<bean id="arpMonitorEventListener"
<argument ref="vpnInstanceListener" />
<argument ref="vpnInterfaceManager" />
<argument ref="mdsalUtils" />
+ <argument ref="vpnFootprintService" />
</bean>
<service ref="vpnManagerImpl"
interface="org.opendaylight.netvirt.vpnmanager.api.IVpnManager" />
<argument ref="vpnInstanceListener" />
</bean>
- <bean id="VpnInterfaceOpListener"
- class="org.opendaylight.netvirt.vpnmanager.VpnInterfaceOpListener"
- init-method="start" destroy-method="close">
- <argument ref="dataBroker" />
- <argument ref="vpnInterfaceManager" />
- </bean>
-
<odl:rpc-implementation ref="vpnRpcServiceImpl" />
<bean id="vpnRpcServiceImpl"
class="org.opendaylight.netvirt.vpnmanager.VpnRpcServiceImpl">
<argument ref="bgpmanager" />
<argument ref="fibManager" />
<argument ref="notificationPublishService" />
+ <argument ref="vpnFootprintService" />
</bean>
<bean id="interVpnLinkNodeListener"
init-method="start" destroy-method="close">
<argument ref="dataBroker" />
<argument ref="mdsalUtils" />
+ <argument ref="vpnFootprintService" />
</bean>
<bean id="tunnelEndPointChangeListener"