import ietf-inet-types {
prefix inet;
+ revision-date "2010-09-24";
}
revision "2015-06-29" {
<ietf.interfaces.version>2014.05.08.9-SNAPSHOT</ietf.interfaces.version>
<iana.if.type.version>2014.05.08.9-SNAPSHOT</iana.if.type.version>
<yang.ext.version>2013.09.07.9-SNAPSHOT</yang.ext.version>
- <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+ <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
<mdsal.version>2.1.0-SNAPSHOT</mdsal.version>
<controller.mdsal.version>1.4.0-SNAPSHOT</controller.mdsal.version>
<vpns.mdsalutil.version>0.3.0-SNAPSHOT</vpns.mdsalutil.version>
<properties>
<!-- ODL -->
<vpnservices.version>0.3.0-SNAPSHOT</vpnservices.version>
- <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+ <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
+ <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
<controller.mdsal.version>1.4.0-SNAPSHOT</controller.mdsal.version>
<vpns.mdsalutil.version>0.3.0-SNAPSHOT</vpns.mdsalutil.version>
<model.bgp.version>2013.07.15.9-SNAPSHOT</model.bgp.version>
<dependency>
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>mdsal-model-artifacts</artifactId>
- <version>0.9.0-SNAPSHOT</version>
+ <version>${mdsal.model.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<maven>3.1.1</maven>
</prerequisites>
<properties>
- <karaf.localFeature>odl-vpnservice-core</karaf.localFeature>
+ <!-- <karaf.localFeature>odl-vpnservice-core</karaf.localFeature> -->
</properties>
<dependencyManagement>
<dependencies>
<mdsal.version>1.4.0-SNAPSHOT</mdsal.version>
<openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
<restconf.version>1.4.0-SNAPSHOT</restconf.version>
- <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+ <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
<mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
<vpnservices.version>0.3.0-SNAPSHOT</vpnservices.version>
<ovsdb.version>1.3.0-SNAPSHOT</ovsdb.version>
<liblldp.version>0.11.0-SNAPSHOT</liblldp.version>
<neutron.version>0.7.0-SNAPSHOT</neutron.version>
+ <nic.version>1.2.0-SNAPSHOT</nic.version>
<arputil.version>${vpnservices.version}</arputil.version>
<mdsalutil.version>${vpnservices.version}</mdsalutil.version>
<vpnmanager.version>${vpnservices.version}</vpnmanager.version>
<type>xml</type>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>features-nic</artifactId>
+ <classifier>features</classifier>
+ <version>${nic.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.ovsdb</groupId>
<artifactId>features-ovsdb</artifactId>
<artifactId>commons-net</artifactId>
<version>${commons.net.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
</dependencies>
</project>
<repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
<repository>mvn:org.opendaylight.ovsdb/features-ovsdb/${ovsdb.version}/xml/features</repository>
<repository>mvn:org.opendaylight.neutron/features-neutron/${neutron.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.nic/features-nic/{{VERSION}}/xml/features</repository>
<feature name='odl-vpnservice-api' version='${project.version}' description='OpenDaylight :: vpnservice :: api '>
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
<bundle>mvn:org.opendaylight.neutron/dummyprovider/${neutron.version}</bundle>
<feature version="${project.version}">odl-vpnservice-impl-rest</feature>
</feature>
+ <feature name='odl-vpnservice-intent' version='${project.version}' description='OpenDaylight :: vpnservice :: intent'>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version='${nic.version}'>odl-nic-core-service-mdsal</feature>
+ <feature version='${nic.version}'>odl-nic-core</feature>
+ <feature version='${nic.version}'>odl-nic-listeners</feature>
+ <bundle>mvn:org.opendaylight.vpnservice/vpnintent-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/vpnintent-impl/{{VERSION}}</bundle>
+ <configfile finalname="vpnintent-impl-default-config.xml">mvn:org.opendaylight.vpnservice/vpnintent-impl/{{VERSION}}/xml/config</configfile>
+ </feature>
</features>
}
container fibEntries {
- config false;
+ config true;
list vrfTables{
key "routeDistinguisher";
leaf routeDistinguisher {type string;}
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnToExtraroute;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetTunnelTypeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
- private static final FutureCallback<Void> DEFAULT_CALLBACK =
- new FutureCallback<Void>() {
- public void onSuccess(Void result) {
- LOG.debug("Success in Datastore write operation");
- }
-
- public void onFailure(Throwable error) {
- LOG.error("Error in Datastore write operation", error);
- };
- };
-
public FibManager(final DataBroker db) {
super(VrfEntry.class);
broker = db;
private void registerListener(final DataBroker db) {
try {
- listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
getWildCardPath(), FibManager.this, DataChangeScope.SUBTREE);
} catch (final Exception e) {
LOG.error("FibManager DataChange listener registration fail!", e);
}
}
- private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
- InstanceIdentifier<T> path) {
-
- ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
-
- Optional<T> result = Optional.absent();
- try {
- result = tx.read(datastoreType, path).get();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- return result;
- }
private InstanceIdentifier<VrfEntry> getWildCardPath() {
return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class).child(VrfEntry.class);
}
- private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
- InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
- WriteTransaction tx = broker.newWriteOnlyTransaction();
- tx.put(datastoreType, path, data, true);
- Futures.addCallback(tx.submit(), callback);
- }
@Override
protected void add(final InstanceIdentifier<VrfEntry> identifier,
public BigInteger createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
BigInteger localDpnId = BigInteger.ZERO;
Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
- boolean staticRoute = false;
+ String localNextHopIP = vrfEntry.getDestPrefix();
- //If the vrf entry is a static/extra route, the nexthop of the entry would be a adjacency in the vpn
if(localNextHopInfo == null) {
- localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getNextHopAddress() + "/32");
- staticRoute = true;
+ //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if (extra_route != null) {
+ localNextHopInfo = getPrefixToInterface(vpnId, extra_route.getNexthopIp() + "/32");
+ localNextHopIP = extra_route.getNexthopIp() + "/32";
+ }
}
if(localNextHopInfo != null) {
localDpnId = localNextHopInfo.getDpnId();
- long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(),
- (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix());
+ long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(), localNextHopIP);
List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
BigInteger localDpnId = BigInteger.ZERO;
VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
- boolean staticRoute = false;
+ String localNextHopIP = vrfEntry.getDestPrefix();
- //If the vrf entry is a static/extra route, the nexthop of the entry would be a adjacency in the vpn
if(localNextHopInfo == null) {
- localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getNextHopAddress() + "/32");
- staticRoute = true;
+ //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if (extra_route != null) {
+ localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp());
+ localNextHopIP = extra_route.getNexthopIp() + "/32";
+ }
}
+
if(localNextHopInfo != null) {
localDpnId = localNextHopInfo.getDpnId();
- if (getPrefixToInterface(vpnId, (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()) == null) {
+ //if (getPrefixToInterface(vpnId, (staticRoute == true) ? extra_route.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()) == null)
+ {
makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, null /* invalid */,
NwConstants.DEL_FLOW);
makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), 0 /* invalid */,
vrfEntry.getNextHopAddress(), NwConstants.DEL_FLOW);
removeTunnelTableEntry(localDpnId, vrfEntry.getLabel());
- deleteLocalAdjacency(localDpnId, vpnId, (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix());
+ deleteLocalAdjacency(localDpnId, vpnId, localNextHopIP);
}
}
return localDpnId;
private Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
Optional<Prefixes> localNextHopInfoData =
- read(LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
+ FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
}
-
+
+ private InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
+ return InstanceIdentifier.builder(VpnToExtraroute.class)
+ .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
+ new ExtrarouteKey(ipPrefix)).build();
+ }
+
+ private Extraroute getVpnToExtraroute(String rd, String ipPrefix) {
+ Optional<Extraroute> extraRouteInfo =
+ FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getVpnToExtrarouteIdentifier(rd, ipPrefix));
+ return extraRouteInfo.isPresent() ? extraRouteInfo.get() : null;
+
+ }
private Class<? extends TunnelTypeBase> getTunnelType(String ifName) {
try {
String rd = vrfTableKey.getRouteDistinguisher();
LOG.debug("adding route " + vrfEntry.getDestPrefix() + " " + rd);
/********************************************/
- String tunnelInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+ String tunnelInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
if(tunnelInterface == null) {
LOG.error("Could not get interface for nexthop: {} in vpn {}",
vrfEntry.getNextHopAddress(), rd);
"Successfully added fib entry for " + vrfEntry.getDestPrefix() + " vpnId " + vpnId);
}
+ private void delIntfFromDpnToVpnList(long vpnId, BigInteger dpnId, String intfName, String rd) {
+ InstanceIdentifier<VpnToDpnList> id = FibUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnInVpn.isPresent()) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.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.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+ currVpnInterface = new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (vpnInterfaces.remove(currVpnInterface)) {
+ if (vpnInterfaces.isEmpty()) {
+ //FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ cleanUpDpnForVpn(dpnId, vpnId, rd);
+ } else {
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(intfName)));
+ }
+ }
+ }
+ }
+
+ private void cleanUpOpDataForFib(Long vpnId, String rd, final VrfEntry vrfEntry) {
+ /* Get interface info from prefix to interface mapping;
+ Use the interface info to get the corresponding vpn interface op DS entry,
+ remove the adjacency corresponding to this fib entry.
+ If adjacency removed is the last adjacency, clean up the following:
+ - vpn interface from dpntovpn list, dpn if last vpn interface on dpn
+ - prefix to interface entry
+ - vpn interface op DS
+ */
+ Prefixes prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
+ boolean extra_route = false;
+ if (prefixInfo == null) {
+ prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getNextHopAddress() + "/32");
+ extra_route = true;
+ }
+ if (prefixInfo == null)
+ return; //Don't have any info for this prefix (shouldn't happen); need to return
+ String ifName = prefixInfo.getVpnInterfaceName();
+ Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjListPath(ifName));
+ int numAdj = 0;
+ if (optAdjacencies.isPresent()) {
+ numAdj = optAdjacencies.get().getAdjacency().size();
+ }
+ //remove adjacency corr to prefix
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
+
+ if((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
+ //clean up the vpn interface from DpnToVpn list
+ delIntfFromDpnToVpnList(vpnId, prefixInfo.getDpnId(), ifName, rd);
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ FibUtil.getPrefixToInterfaceIdentifier(
+ vpnId,
+ (extra_route) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()));
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ FibUtil.getVpnInterfaceIdentifier(ifName));
+ }
+ }
+
private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier,
final VrfEntry vrfEntry) {
final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry);
}
}
-
}
+ //The flow/group entry has been deleted from config DS; need to clean up associated operational
+ //DS entries in VPN Op DS, VpnInstanceOpData and PrefixToInterface to complete deletion
+ cleanUpOpDataForFib(vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(), vrfEntry);
}
public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
final VrfEntry vrfEntry) {
LOG.debug("deleting route "+ vrfEntry.getDestPrefix() + " "+vpnId);
String rd = vrfTableKey.getRouteDistinguisher();
- String egressInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+ String egressInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
if(egressInterface == null) {
LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
vrfEntry.getNextHopAddress(), rd);
* for or for notification that operational DS write for flows is done. We do not turn on the stats writing for flows,
* so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
* wait indefinitely. */
- // FIXME: sync calls.
- //mdsalManager.syncInstallFlow(flowEntity, 1);
- mdsalManager.installFlow(flowEntity);
+ mdsalManager.syncInstallFlow(flowEntity, 1);
} else {
- // FIXME: sync calls.
- // mdsalManager.syncRemoveFlow(flowEntity, 1);
- mdsalManager.removeFlow(flowEntity);
+ mdsalManager.syncRemoveFlow(flowEntity, 1);
}
}
* so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
* wait indefinitely. */
- // FIXME:
- // mdsalManager.syncInstallFlow(flowEntity, 1);
- mdsalManager.installFlow(flowEntity);
+ mdsalManager.syncInstallFlow(flowEntity, 1);
} else {
- // FIXME:
- // mdsalManager.syncRemoveFlow(flowEntity, 1);
- mdsalManager.removeFlow(flowEntity);
+ mdsalManager.syncRemoveFlow(flowEntity, 1);
}
LOG.debug("LFIB Entry for dpID {} : label : {} group {} modified successfully {}",dpId, label, groupId );
}
public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
LOG.trace("New dpn {} for vpn {} : populateFibOnNewDpn", dpnId, rd);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
- Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
+ Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
if(vrfTable.isPresent()) {
for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
// Passing null as we don't know the dpn
public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
LOG.trace("Remove dpn {} for vpn {} : cleanUpDpnForVpn", dpnId, rd);
InstanceIdentifier<VrfTables> id = buildVrfId(rd);
- Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
+ Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
if(vrfTable.isPresent()) {
for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
// Passing null as we don't know the dpn
}
protected String resolveAdjacency(final BigInteger localDpnId, final BigInteger remoteDpnId,
- final long vpnId, final VrfEntry vrfEntry) {
+ final long vpnId, final VrfEntry vrfEntry, String rd) {
String adjacency = null;
- LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);;
+ boolean staticRoute = false;
+ LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);
try {
- adjacency =
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if(extra_route != null) {
+ staticRoute = true;
+ }
+
+ adjacency =
nextHopManager.getRemoteNextHopPointer(localDpnId, remoteDpnId, vpnId,
vrfEntry.getDestPrefix(),
- vrfEntry.getNextHopAddress());
+ (staticRoute == true) ? extra_route.getNexthopIp() : vrfEntry.getNextHopAddress());
} catch (NullPointerException e) {
LOG.trace("", e);
}
protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.create(VpnInstanceOpData.class).child(
VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
- Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
if(vpnInstanceOpData.isPresent()) {
return vpnInstanceOpData.get();
}
result.add(String.format(" %-7s %-20s %-20s %-7s", "RD", "Prefix", "Nexthop", "Label"));
result.add("-------------------------------------------------------------------");
InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
- Optional<FibEntries> fibEntries = read(LogicalDatastoreType.OPERATIONAL, id);
+ Optional<FibEntries> fibEntries = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
if (fibEntries.isPresent()) {
List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
for (VrfTables vrfTable : vrfTables) {
--- /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.vpnservice.fibmanager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class FibUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
+ static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path) {
+
+ ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return result;
+ }
+
+ static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ tx.submit();
+ }
+
+ static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+ }
+
+ static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+ .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey(ipAddress)).build();
+ }
+
+ static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+ .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies.class).build();
+ }
+
+ static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey(vpnId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
+ }
+
+ static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+ .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).build();
+ }
+
+ static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey(rd))
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey(dpnId)).build();
+ }
+
+ static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore operation");
+ }
+
+ public void onFailure(Throwable error) {
+ LOG.error("Error in Datastore operation", error);
+ };
+ };
+
+}
private static final short FIB_TABLE = 21;
private static final short DEFAULT_FLOW_PRIORITY = 10;
private static final String NEXTHOP_ID_POOL_NAME = "nextHopPointerPool";
+ private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
private static final FutureCallback<Void> DEFAULT_CALLBACK =
new FutureCallback<Void>() {
addVpnNexthopToDS(dpnId, vpnId, ipAddress, groupId);
// install Group
- // FIXME: mdsalManager.syncInstallGroup(groupEntity);
- mdsalManager.installGroup(groupEntity);
+ mdsalManager.syncInstallGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS);
} else {
//nexthop exists already; a new flow is going to point to it, increment the flowrefCount by 1
localDpnId, remoteDpnId, vpnId, prefixIp, nextHopIp);
LOG.trace("getRemoteNextHopPointer: Calling ITM with localDpnId {} ", localDpnId);
- try{
- // here use the config for tunnel type param
- tunnelIfName = getTunnelInterfaceName(remoteDpnId, IpAddressBuilder.getDefaultInstance(nextHopIp));
- }catch(Exception ex){
- LOG.error("Error while retrieving nexthop pointer for DC Gateway : ", ex.getMessage());
+ if (nextHopIp != null && !nextHopIp.isEmpty()) {
+ try{
+ // here use the config for tunnel type param
+ tunnelIfName = getTunnelInterfaceName(remoteDpnId, IpAddressBuilder.getDefaultInstance(nextHopIp));
+ }catch(Exception ex){
+ LOG.error("Error while retrieving nexthop pointer for nexthop {} : ", nextHopIp, ex.getMessage());
+ }
}
return tunnelIfName;
}
GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
// remove Group ...
- // FIXME: mdsalManager.syncRemoveGroup(groupEntity);
- mdsalManager.removeGroup(groupEntity);
+ mdsalManager.syncRemoveGroup(groupEntity);
//update MD-SAL DS
removeVpnNexthopFromDS(vpnId, ipAddress);
//release groupId
.child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
}
+
+ InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(VpnInterfaces.class)
+ .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ Adjacencies.class).build();
+ }
}
private static final int label = 10;
BigInteger Dpn;
private static final long vpnId = 101L;
+ private static final long vpnIntfCnt = 2;
private void SetupMocks() {
Dpn = BigInteger.valueOf(100000L);
return testRd;
}
+ @Override
+ public Long getVpnInterfaceCount() { return vpnIntfCnt; }
+
@Override
public List<VpnToDpnList> getVpnToDpnList() {
List <VpnToDpnList> vpnToDpnLists = new ArrayList<>();
type string;
}
}
+ }
+
+ container interface-monitor-id-map {
+ config false;
+ list interface-monitor-id {
+ key interface-name;
+ leaf interface-name {
+ type string;
+ }
+ leaf-list monitor-id {
+ type uint32;
+ }
+ }
+ }
+
+ container monitor-id-interface-map {
+ config false;
+ list monitor-id-interface {
+ key monitor-id;
+ leaf monitor-id {
+ type uint32;
+ }
+ leaf interface-name {
+ type string;
+ }
}
+ }
}
\ No newline at end of file
type inet:ip-address;
description "gateway IP address";
}
+
+ leaf monitor-enabled {
+ type boolean;
+ default false;
+ }
+
+ leaf monitor-interval {
+ type uint32;
+ default 10000;
+ }
}
augment "/if:interfaces/if:interface" {
description "gateway IP address";
}
}
+
/* MPLS logical port */
augment "/if:interfaces/if:interface" {
ext:augment-identifier "if-mpls";
<artifactId>idmanager-impl</artifactId>
<version>${vpnservices.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>alivenessmonitor-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.ovsdb</groupId>
<artifactId>southbound-api</artifactId>
<version>${vpns.ovsdb.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
</dependencies>
</project>
<capability>urn:opendaylight:params:xml:ns:yang:interfacemgr:impl?module=interfacemgr-impl&revision=2015-03-25</capability>
<capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28</capability>
</required-capabilities>
<configuration>
<type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
<name>mdsalutil-service</name>
</mdsalutil>
+ <notification-service>
+ <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-service</type>
+ <name>binding-notification-adapter</name>
+ </notification-service>
<rpc-registry>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
<name>binding-rpc-broker</name>
import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
import org.opendaylight.vpnservice.interfacemgr.globals.VlanInterfaceInfo;
import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeGre;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.InterfaceMonitorIdMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.MonitorIdInterfaceMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan.L2vlanMode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
}
return vlanInterfaceInfo;
}
-
-
-
}
import java.util.concurrent.Future;
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.NotificationService;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;
private RpcProviderRegistry rpcProviderRegistry;
private IdManagerService idManager;
+ private NotificationService notificationService;
+ private AlivenessMonitorService alivenessManager;
private IMdsalApiManager mdsalManager;
private InterfaceConfigListener interfaceConfigListener;
private InterfaceTopologyStateListener topologyStateListener;
private FlowBasedServicesInterfaceStateListener flowBasedServicesInterfaceStateListener;
private FlowBasedServicesConfigListener flowBasedServicesConfigListener;
private VlanMemberConfigListener vlanMemberConfigListener;
+ private org.opendaylight.vpnservice.interfacemgr.listeners.AlivenessMonitorListener alivenessMonitorListener;
private DataBroker dataBroker;
private InterfaceManagerRpcService interfaceManagerRpcService;
private BindingAwareBroker.RpcRegistration<OdlInterfaceRpcService> rpcRegistration;
this.mdsalManager = mdsalManager;
}
+ public void setNotificationService(NotificationService notificationService) {
+ this.notificationService = notificationService;
+ }
+
@Override
public void onSessionInitiated(ProviderContext session) {
LOG.info("InterfacemgrProvider Session Initiated");
idManager = rpcProviderRegistry.getRpcService(IdManagerService.class);
createIdPool();
+ alivenessManager = rpcProviderRegistry.getRpcService(AlivenessMonitorService.class);
interfaceManagerRpcService = new InterfaceManagerRpcService(dataBroker, mdsalManager);
rpcRegistration = getRpcProviderRegistry().addRpcImplementation(
OdlInterfaceRpcService.class, interfaceManagerRpcService);
- interfaceConfigListener = new InterfaceConfigListener(dataBroker, idManager);
+ interfaceConfigListener = new InterfaceConfigListener(dataBroker, idManager,alivenessManager, mdsalManager);
interfaceConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
- interfaceInventoryStateListener = new InterfaceInventoryStateListener(dataBroker, idManager, mdsalManager);
+ interfaceInventoryStateListener = new InterfaceInventoryStateListener(dataBroker, idManager, mdsalManager, alivenessManager);
interfaceInventoryStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
topologyStateListener = new InterfaceTopologyStateListener(dataBroker);
flowBasedServicesInterfaceStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
vlanMemberConfigListener =
- new VlanMemberConfigListener(dataBroker, idManager);
+ new VlanMemberConfigListener(dataBroker, idManager, alivenessManager,mdsalManager);
vlanMemberConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ alivenessMonitorListener = new org.opendaylight.vpnservice.interfacemgr.listeners.AlivenessMonitorListener(dataBroker);
+ notificationService.registerNotificationListener(alivenessMonitorListener);
} catch (Exception e) {
LOG.error("Error initializing services", e);
}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.vpnservice.interfacemgr.commons;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class AlivenessMonitorUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorUtils.class);
+ private static final int FAILURE_THRESHOLD = 4;
+ private static final int MONITORING_INTERVAL = 10;
+ private static final int MONITORING_WINDOW = 4;
+
+ public static void startLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ Interface trunkInterface) {
+ //LLDP monitoring for the trunk interface
+ /*String trunkInterfaceName = trunkInterface.getName();
+ IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
+ if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ MonitorStartInput lldpMonitorInput = new MonitorStartInputBuilder().setConfig(new ConfigBuilder()
+ .setSource(new SourceBuilder().setEndpointType(getInterfaceForMonitoring(trunkInterfaceName,
+ ifTunnel.getTunnelSource())).build())
+ .setMode(MonitoringMode.OneOne)
+ .setProfileId(allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, MONITORING_INTERVAL, MONITORING_WINDOW,
+ EtherTypes.Lldp)).build()).build();
+ try {
+ Future<RpcResult<MonitorStartOutput>> result = alivenessMonitorService.monitorStart(lldpMonitorInput);
+ RpcResult<MonitorStartOutput> rpcResult = result.get();
+ long monitorId;
+ if (rpcResult.isSuccessful()) {
+ monitorId = rpcResult.getResult().getMonitorId();
+ createOrUpdateInterfaceMonitorIdMap(dataBroker, trunkInterfaceName, monitorId);
+ createOrUpdateMonitorIdInterfaceMap(dataBroker, trunkInterfaceName, monitorId);
+ LOG.trace("Started LLDP monitoring with id {}", monitorId);
+ } else {
+ LOG.warn("RPC Call to start monitoring returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when starting monitoring", e);
+ }
+ }*/
+ }
+
+ public static void stopLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ Interface trunkInterface) {
+ /*IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
+ if(!ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)){
+ return;
+ }
+ List<Long> monitorIds = getMonitorIdForInterface(dataBroker, trunkInterface.getName());
+ if (monitorIds == null) {
+ LOG.error("Monitor Id doesn't exist for Interface {}", trunkInterface);
+ return;
+ }
+ for (Long monitorId : monitorIds) {
+ String interfaceName = getInterfaceFromMonitorId(dataBroker, monitorId);
+ if (interfaceName != null) {
+ MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(monitorId).build();
+ alivenessMonitorService.monitorStop(input);
+ removeMonitorIdInterfaceMap(dataBroker, monitorId);
+ removeMonitorIdFromInterfaceMonitorIdMap(dataBroker, interfaceName, monitorId);
+ return;
+ }
+ }*/
+ }
+
+ public static String getInterfaceFromMonitorId(DataBroker broker, Long monitorId) {
+ InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+ Optional<MonitorIdInterface> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(interfaceMonitorIdMap.isPresent()) {
+ return interfaceMonitorIdMap.get().getInterfaceName();
+ }
+ return null;
+ }
+
+ private static void removeMonitorIdInterfaceMap(DataBroker broker, long monitorId) {
+ InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+ Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(monitorIdInterfaceMap.isPresent()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ }
+ }
+
+ private static void removeMonitorIdFromInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
+ InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+ Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(interfaceMonitorIdMap.isPresent()) {
+ InterfaceMonitorId interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
+ List<Long> existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
+ if (existingMonitorIds != null && existingMonitorIds.contains(monitorId)) {
+ existingMonitorIds.remove(monitorId);
+ InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
+ interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+ }
+ }
+ }
+
+ private static org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface getInterfaceForMonitoring(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress ipAddress) {
+ return new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.
+ endpoint.type.InterfaceBuilder().setInterfaceIp(ipAddress).setInterfaceName(interfaceName).build();
+ }
+
+ protected void handleTunnelMonitorEnabledUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ List<String> interfaceNames, boolean origMonitorEnabled, boolean updatedMonitorEnabled) {
+ for (String interfaceName : interfaceNames) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface tunnelInterface =
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
+ IfTunnel ifTunnel = tunnelInterface.getAugmentation(IfTunnel.class);
+ InterfaceManagerCommonUtils.updateTunnelMonitorDetailsInConfigDS(dataBroker, interfaceName, updatedMonitorEnabled, 3);
+ // Check if monitoring is started already
+ if (getMonitorIdForInterface(dataBroker, interfaceName) != null) {
+ // Get updated Interface details from Config DS
+ if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ if (updatedMonitorEnabled) {
+ startLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
+ } else {
+ stopLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
+ }
+ }
+ }
+ }
+ }
+
+ protected void handleTunnelMonitorIntervalUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ List<String> interfaceNames, long origMonitorInterval, long updatedMonitorInterval) {
+ for (String interfaceName : interfaceNames) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface tunnelInterface =
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
+ IfTunnel ifTunnel = tunnelInterface.getAugmentation(IfTunnel.class);
+ InterfaceManagerCommonUtils.updateTunnelMonitorDetailsInConfigDS(dataBroker, interfaceName, ifTunnel.isMonitorEnabled(), updatedMonitorInterval);
+ // Restart LLDP monitoring only if it's started already
+ List<Long> monitorIds = getMonitorIdForInterface(dataBroker, interfaceName);
+ if (monitorIds != null && monitorIds.size() > 1) {
+ // Get updated Interface details from Config DS
+ if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ stopLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
+ startLLDPMonitoring(alivenessMonitorService, dataBroker,tunnelInterface);
+ }
+ }
+ }
+ // Delete old profile from Aliveness Manager
+ if (origMonitorInterval > 0) {
+ long profileId = allocateProfile(alivenessMonitorService, 4, origMonitorInterval, 4, EtherTypes.Lldp);
+ MonitorProfileDeleteInput profileDeleteInput = new MonitorProfileDeleteInputBuilder().setProfileId(profileId).build();
+ alivenessMonitorService.monitorProfileDelete(profileDeleteInput);
+ }
+ }
+
+
+ public static void createOrUpdateInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
+ InterfaceMonitorId interfaceMonitorIdInstance;
+ List<Long> existingMonitorIds;
+ InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
+ InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+ Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if (interfaceMonitorIdMap.isPresent()) {
+ interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
+ existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
+ if (existingMonitorIds == null) {
+ existingMonitorIds = new ArrayList<>();
+ }
+ if (!existingMonitorIds.contains(monitorId)) {
+ existingMonitorIds.add(monitorId);
+ interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+ }
+ } else {
+ existingMonitorIds = new ArrayList<>();
+ existingMonitorIds.add(monitorId);
+ interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setMonitorId(existingMonitorIds).setKey(new InterfaceMonitorIdKey(infName)).setInterfaceName(infName).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+ }
+ }
+
+ public static void createOrUpdateMonitorIdInterfaceMap(DataBroker broker,String infName, long monitorId) {
+ MonitorIdInterface monitorIdInterfaceInstance;
+ String existinginterfaceName;
+ MonitorIdInterfaceBuilder monitorIdInterfaceBuilder = new MonitorIdInterfaceBuilder();
+ InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+ Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(monitorIdInterfaceMap.isPresent()) {
+ monitorIdInterfaceInstance = monitorIdInterfaceMap.get();
+ existinginterfaceName = monitorIdInterfaceInstance.getInterfaceName();
+ if(!existinginterfaceName.equals(infName)) {
+ monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
+ }
+ } else {
+ monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setMonitorId(monitorId).setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
+ }
+ }
+
+ public static List<Long> getMonitorIdForInterface(DataBroker broker, String infName) {
+ InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+ Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(interfaceMonitorIdMap.isPresent()) {
+ return interfaceMonitorIdMap.get().getMonitorId();
+ }
+ return null;
+ }
+
+ public static long allocateProfile(AlivenessMonitorService alivenessMonitor, long failureThreshold, long interval, long window, EtherTypes etherType ) {
+ MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().setProfile(new ProfileBuilder().setFailureThreshold(failureThreshold)
+ .setMonitorInterval(interval).setMonitorWindow(window).setProtocolType(etherType).build()).build();
+ try {
+ Future<RpcResult<MonitorProfileCreateOutput>> result = alivenessMonitor.monitorProfileCreate(input);
+ RpcResult<MonitorProfileCreateOutput> rpcResult = result.get();
+ if(rpcResult.isSuccessful()) {
+ return rpcResult.getResult().getProfileId();
+ } else {
+ LOG.warn("RPC Call to Get Profile Id Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when allocating profile Id",e);
+ }
+ return 0;
+ }
+}
\ No newline at end of file
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
public static String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
}
+
+ public static void setOpStateForInterface(DataBroker broker, String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opStatus) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = IfmUtil.buildStateInterfaceId(interfaceName);
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceData = ifaceBuilder.setOperStatus(opStatus).build();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceData);
+ }
+
+ public static void updateTunnelMonitorDetailsInConfigDS(DataBroker broker, String interfaceName, boolean monitorEnabled, long monitorInterval) {
+ InstanceIdentifier<Interface> id = IfmUtil.buildId(interfaceName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder();
+ ifaceBuilder.setKey(new InterfaceKey(interfaceName));
+ IfTunnelBuilder ifTunnelBuilder = new IfTunnelBuilder();
+ ifTunnelBuilder.setMonitorEnabled(monitorEnabled);
+ ifTunnelBuilder.setMonitorInterval(monitorInterval);
+ ifaceBuilder.addAugmentation(IfTunnel.class, ifTunnelBuilder.build());
+
+ LOG.trace("Updating trunk interface {} in Config DS", interfaceName);
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, ifaceBuilder.build());
+ }
}
\ No newline at end of file
package org.opendaylight.vpnservice.interfacemgr.commons;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.eclipse.xtend.lib.annotations.Data;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.idmanager.IdManager;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.BridgeInterfaceInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.BridgeRefInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
public class InterfaceMetaUtils {
public static InstanceIdentifier<BridgeRefEntry> getBridgeRefEntryIdentifier(BridgeRefEntryKey bridgeRefEntryKey) {
InstanceIdentifier.InstanceIdentifierBuilder<BridgeRefEntry> bridgeRefEntryInstanceIdentifierBuilder =
}
IfmUtil.releaseId(idManager, IfmConstants.IFM_IDPOOL_NAME, infName);
}
+
+ public static void createBridgeRefEntry(BigInteger dpnId, InstanceIdentifier<?> bridgeIid,
+ WriteTransaction tx){
+ BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpnId);
+ InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
+ BridgeRefEntryBuilder tunnelDpnBridgeEntryBuilder =
+ new BridgeRefEntryBuilder().setKey(bridgeRefEntryKey).setDpid(dpnId)
+ .setBridgeReference(new OvsdbBridgeRef(bridgeIid));
+ tx.put(LogicalDatastoreType.OPERATIONAL, bridgeEntryId, tunnelDpnBridgeEntryBuilder.build(), true);
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.vpnservice.interfacemgr.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.LivenessState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * This class listens for interface creation/removal/update in Configuration DS.
+ * This is used to handle interfaces for base of-ports.
+ */
+public class AlivenessMonitorListener implements org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorListener {
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorListener.class);
+ private DataBroker dataBroker;
+
+ public AlivenessMonitorListener(final DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ public void onMonitorEvent(MonitorEvent notification) {
+ Long monitorId = notification.getEventData().getMonitorId();
+ String trunkInterfaceName = AlivenessMonitorUtils.getInterfaceFromMonitorId(dataBroker, monitorId);
+ if (trunkInterfaceName == null) {
+ LOG.debug("Either monitoring for interface - {} not started by Interfacemgr or it is not LLDP monitoring", trunkInterfaceName);
+ return;
+ }
+ LivenessState livenessState = notification.getEventData().getMonitorState();
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(trunkInterfaceName),
+ dataBroker);
+ IfTunnel tunnelInfo = interfaceInfo.getAugmentation(IfTunnel.class);
+ // Not handling monitoring event if it is GRE Trunk Interface.
+ if (tunnelInfo.getTunnelInterfaceType().isAssignableFrom(TunnelTypeGre.class)) {
+ return;
+ }
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState =
+ livenessState == LivenessState.Up ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up :
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ InterfaceManagerCommonUtils.setOpStateForInterface(dataBroker, trunkInterfaceName, opState);
+ }
+
+}
\ No newline at end of file
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
private static final Logger LOG = LoggerFactory.getLogger(InterfaceConfigListener.class);
private DataBroker dataBroker;
private IdManagerService idManager;
+ private AlivenessMonitorService alivenessMonitorService;
+ private IMdsalApiManager mdsalApiManager;
- public InterfaceConfigListener(final DataBroker dataBroker, final IdManagerService idManager) {
+ public InterfaceConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
+ final AlivenessMonitorService alivenessMonitorService,
+ final IMdsalApiManager mdsalApiManager) {
super(Interface.class, InterfaceConfigListener.class);
this.dataBroker = dataBroker;
this.idManager = idManager;
+ this.alivenessMonitorService = alivenessMonitorService;
+ this.mdsalApiManager = mdsalApiManager;
}
@Override
public List<ListenableFuture<Void>> call() throws Exception {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return OvsInterfaceConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew, idManager);
+ return OvsInterfaceConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew,
+ idManager, alivenessMonitorService, mdsalApiManager);
}
@Override
public List<ListenableFuture<Void>> call() throws Exception {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return OvsInterfaceConfigUpdateHelper.updateConfiguration(dataBroker, idManager, interfaceNew, interfaceOld);
+ return OvsInterfaceConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager,
+ mdsalApiManager, interfaceNew, interfaceOld);
}
@Override
public List<ListenableFuture<Void>> call() throws Exception {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, interfaceOld, idManager, parentRefs);
+ return OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService,
+ interfaceOld, idManager, mdsalApiManager, parentRefs);
}
@Override
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
private DataBroker dataBroker;
private IdManagerService idManager;
private IMdsalApiManager mdsalApiManager;
+ private AlivenessMonitorService alivenessMonitorService;
- public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager, final IMdsalApiManager mdsalApiManager) {
+ public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager,
+ final IMdsalApiManager mdsalApiManager, final AlivenessMonitorService alivenessMonitorService) {
super(FlowCapableNodeConnector.class, InterfaceInventoryStateListener.class);
this.dataBroker = dataBroker;
this.idManager = idManager;
this.mdsalApiManager = mdsalApiManager;
+ this.alivenessMonitorService = alivenessMonitorService;
}
@Override
FlowCapableNodeConnector flowCapableNodeConnectorOld) {
LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
String portName = flowCapableNodeConnectorOld.getName();
- NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
- InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, key,
- flowCapableNodeConnectorOld, portName);
+ InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
+ key, flowCapableNodeConnectorOld, portName);
coordinator.enqueueJob(portName, interfaceStateRemoveWorker);
}
public Object call() throws Exception {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, nodeConnectorId,
+ return OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, alivenessMonitorService, nodeConnectorId,
portName, fcNodeConnectorNew);
}
public Object call() throws Exception {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return OvsInterfaceStateUpdateHelper.updateState(key, dataBroker, portName,
+ return OvsInterfaceStateUpdateHelper.updateState(key, alivenessMonitorService, dataBroker, portName,
fcNodeConnectorNew, fcNodeConnectorOld);
}
public Object call() throws Exception {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return OvsInterfaceStateRemoveHelper.removeState(idManager, mdsalApiManager, key, dataBroker, portName, fcNodeConnectorOld);
+ return OvsInterfaceStateRemoveHelper.removeState(idManager, mdsalApiManager, alivenessMonitorService,
+ key, dataBroker, portName, fcNodeConnectorOld);
}
@Override
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigAddHelper;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigRemoveHelper;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
private static final Logger LOG = LoggerFactory.getLogger(VlanMemberConfigListener.class);
private DataBroker dataBroker;
private IdManagerService idManager;
+ private AlivenessMonitorService alivenessMonitorService;
+ private IMdsalApiManager mdsalApiManager;
- public VlanMemberConfigListener(final DataBroker dataBroker, final IdManagerService idManager) {
+ public VlanMemberConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
+ final AlivenessMonitorService alivenessMonitorService,
+ final IMdsalApiManager mdsalApiManager) {
super(Interface.class, VlanMemberConfigListener.class);
this.dataBroker = dataBroker;
this.idManager = idManager;
+ this.alivenessMonitorService = alivenessMonitorService;
+ this.mdsalApiManager = mdsalApiManager;
}
@Override
public List<ListenableFuture<Void>> call() throws Exception {
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
- return OvsVlanMemberConfigUpdateHelper.updateConfiguration(dataBroker, parentRefsNew, interfaceOld,
- ifL2vlanNew, interfaceNew, idManager);
+ return OvsVlanMemberConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService,
+ parentRefsNew, interfaceOld, ifL2vlanNew, interfaceNew, idManager, mdsalApiManager);
}
}
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
+import org.eclipse.xtend.lib.annotations.Data;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.idmanager.IdManager;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
public class OvsInterfaceConfigAddHelper {
private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigAddHelper.class);
public static List<ListenableFuture<Void>> addConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
- Interface interfaceNew, IdManagerService idManager) {
+ Interface interfaceNew, IdManagerService idManager,
+ AlivenessMonitorService alivenessMonitorService,
+ IMdsalApiManager mdsalApiManager) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
IfTunnel ifTunnel = interfaceNew.getAugmentation(IfTunnel.class);
if (ifTunnel != null) {
- addTunnelConfiguration(dataBroker, parentRefs, interfaceNew, idManager, futures);
+ addTunnelConfiguration(dataBroker, parentRefs, interfaceNew, idManager, alivenessMonitorService,
+ mdsalApiManager, futures);
return futures;
}
private static void addTunnelConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
Interface interfaceNew, IdManagerService idManager,
+ AlivenessMonitorService alivenessMonitorService,
+ IMdsalApiManager mdsalApiManager,
List<ListenableFuture<Void>> futures) {
LOG.debug("adding tunnel configuration for {}", interfaceNew.getName());
WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
return;
}
- //createBridgeEntryIfNotPresent(dpId, dataBroker, t);
-
BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpId);
BridgeInterfaceEntryKey bridgeInterfaceEntryKey = new BridgeInterfaceEntryKey(interfaceNew.getName());
String bridgeName = ovsdbBridgeAugmentation.getBridgeName().getValue();
SouthboundUtils.addPortToBridge(bridgeIid, interfaceNew,
ovsdbBridgeAugmentation, bridgeName, interfaceNew.getName(), dataBroker, futures);
+
+ // if TEP is already configured on switch, start LLDP monitoring and program tunnel ingress flow
+ NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(interfaceNew, dataBroker);
+ if(ncId != null){
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(ncId));
+ InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, interfaceNew.getAugmentation(IfTunnel.class),
+ dpId, portNo, interfaceNew, NwConstants.ADD_FLOW);
+ // start LLDP monitoring for the tunnel interface
+ AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
+ }
}
}
}
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.idmanager.IdManager;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
public class OvsInterfaceConfigRemoveHelper {
private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigRemoveHelper.class);
- public static List<ListenableFuture<Void>> removeConfiguration(DataBroker dataBroker, Interface interfaceOld,
- IdManagerService idManager, ParentRefs parentRefs) {
+ public static List<ListenableFuture<Void>> removeConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService,
+ Interface interfaceOld,
+ IdManagerService idManager,
+ IMdsalApiManager mdsalApiManager,
+ ParentRefs parentRefs) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
WriteTransaction t = dataBroker.newWriteOnlyTransaction();
IfTunnel ifTunnel = interfaceOld.getAugmentation(IfTunnel.class);
if (ifTunnel != null) {
- removeTunnelConfiguration(parentRefs, dataBroker, interfaceOld, idManager, t);
+ removeTunnelConfiguration(alivenessMonitorService, parentRefs, dataBroker, interfaceOld,
+ idManager, mdsalApiManager, futures);
}else {
removeVlanConfiguration(dataBroker, interfaceOld, t);
+ futures.add(t.submit());
}
- futures.add(t.submit());
return futures;
}
}
}
- private static void removeTunnelConfiguration(ParentRefs parentRefs, DataBroker dataBroker, Interface interfaceOld,
- IdManagerService idManager, WriteTransaction t) {
+ private static void removeTunnelConfiguration(AlivenessMonitorService alivenessMonitorService, ParentRefs parentRefs,
+ DataBroker dataBroker, Interface interfaceOld,
+ IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+ List<ListenableFuture<Void>> futures) {
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
BigInteger dpId = null;
if (parentRefs != null) {
dpId = parentRefs.getDatapathNodeIdentifier();
InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceOld.getName());
t.delete(LogicalDatastoreType.CONFIGURATION, tpIid);
+
+ // delete tunnel ingress flow
+ NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(interfaceOld, dataBroker);
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(ncId));
+ InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager,
+ interfaceOld.getAugmentation(IfTunnel.class),
+ dpId, portNo, interfaceOld,
+ NwConstants.DEL_FLOW);
}
BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpId);
bridgeInterfaceEntryKey);
t.delete(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryIid);
}
+ futures.add(t.submit());
+ // stop LLDP monitoring for the tunnel interface
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceOld);
}
}
\ No newline at end of file
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.idmanager.IdManager;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.LivenessState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
-public class OvsInterfaceConfigUpdateHelper {
+public class OvsInterfaceConfigUpdateHelper{
private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigUpdateHelper.class);
- public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, IdManagerService idManager,
+ public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService,
+ IdManagerService idManager, IMdsalApiManager mdsalApiManager,
Interface interfaceNew, Interface interfaceOld) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
if(portAttributesModified(interfaceOld, interfaceNew)) {
- futures.addAll(OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, interfaceOld, idManager,
- interfaceOld.getAugmentation(ParentRefs.class)));
+ futures.addAll(OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService, interfaceOld, idManager,
+ mdsalApiManager, interfaceOld.getAugmentation(ParentRefs.class)));
futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
- interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager));
+ interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager,alivenessMonitorService,mdsalApiManager));
return futures;
}
InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceNew.getName(), dataBroker);
if (ifState == null) {
futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
- interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager));
+ interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager, alivenessMonitorService, mdsalApiManager));
return futures;
}
IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
futures.add(t.submit());
+ // stop tunnel monitoring if admin state is disabled for a vxlan trunk interface
+ if(!interfaceNew.isEnabled()){
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
+ }
return futures;
}
return false;
}
+
}
\ No newline at end of file
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
public class OvsVlanMemberConfigUpdateHelper {
private static final Logger LOG = LoggerFactory.getLogger(OvsVlanMemberConfigUpdateHelper.class);
- public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, ParentRefs parentRefsNew,
+ public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService, ParentRefs parentRefsNew,
Interface interfaceOld, IfL2vlan ifL2vlanNew,
- Interface interfaceNew, IdManagerService idManager) {
+ Interface interfaceNew, IdManagerService idManager,
+ IMdsalApiManager mdsalApiManager) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
ParentRefs parentRefsOld = interfaceOld.getAugmentation(ParentRefs.class);
if (interfaceChildEntry == null) {
futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
- interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager));
+ interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager, alivenessMonitorService, mdsalApiManager));
return futures;
}
import org.opendaylight.vpnservice.VpnConstants;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
public class OvsInterfaceStateAddHelper {
private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateAddHelper.class);
- public static List<ListenableFuture<Void>> addState(DataBroker dataBroker, IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+ public static List<ListenableFuture<Void>> addState(DataBroker dataBroker, IdManagerService idManager,
+ IMdsalApiManager mdsalApiManager,AlivenessMonitorService alivenessMonitorService,
NodeConnectorId nodeConnectorId, String portName, FlowCapableNodeConnector fcNodeConnectorNew) {
LOG.debug("Adding Interface State to Oper DS for port: {}", portName);
List<ListenableFuture<Void>> futures = new ArrayList<>();
InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel,dpId, portNo, iface,
NwConstants.ADD_FLOW);
futures.add(transaction.submit());
+ AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
return futures;
}
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateRemoveHelper.class);
public static List<ListenableFuture<Void>> removeState(IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+ AlivenessMonitorService alivenessMonitorService,
InstanceIdentifier<FlowCapableNodeConnector> key,
DataBroker dataBroker, String portName, FlowCapableNodeConnector fcNodeConnectorOld) {
LOG.debug("Removing interface-state for port: {}", portName);
return futures;
}
- // If this interface is a tunnel interface, remove the tunnel ingress flow
+ // If this interface is a tunnel interface, remove the tunnel ingress flow and stop lldp monitoring
IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
if(tunnel != null){
NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel, dpId, portNo, iface,
NwConstants.DEL_FLOW);
+ futures.add(transaction.submit());
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
return futures;
}
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
public static List<ListenableFuture<Void>> updateState(InstanceIdentifier<FlowCapableNodeConnector> key,
+ AlivenessMonitorService alivenessMonitorService,
DataBroker dataBroker, String portName,
FlowCapableNodeConnector flowCapableNodeConnectorNew,
FlowCapableNodeConnector flowCapableNodeConnectorOld) {
InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(portName);
InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
-
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface = null;
boolean modified = false;
if (opstateModified) {
LOG.debug("Opstate Modified for Port: {}", portName);
InterfaceKey interfaceKey = new InterfaceKey(portName);
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
- InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
// If interface config admin state is disabled, set operstate of the Interface State entity to Down.
if (iface != null && !iface.isEnabled()) {
InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
if (interfaceParentEntry == null) {
futures.add(t.submit());
+ // start/stop monitoring based on opState
+ if(operStatusNew == Interface.OperStatus.Down )
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
+ else
+ AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService,dataBroker, iface);
return futures;
}
public static List<ListenableFuture<Void>> addPortToBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
OvsdbBridgeAugmentation bridgeNew, DataBroker dataBroker) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
- WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
if (bridgeNew.getDatapathId() == null) {
LOG.warn("DataPathId found as null for Bridge Augmentation: {}... retrying...", bridgeNew);
return futures;
}
- BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpnId);
- InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
- InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
- BridgeRefEntryBuilder tunnelDpnBridgeEntryBuilder =
- new BridgeRefEntryBuilder().setKey(bridgeRefEntryKey).setDpid(dpnId)
- .setBridgeReference(new OvsdbBridgeRef(bridgeIid));
- t.put(LogicalDatastoreType.OPERATIONAL, bridgeEntryId, tunnelDpnBridgeEntryBuilder.build(), true);
+ // create bridge reference entry in interface meta operational DS
+ InterfaceMetaUtils.createBridgeRefEntry(dpnId, bridgeIid, writeTransaction);
+
+ // FIX for OVSDB Bug - manually copying the bridge info from topology operational DS to config DS
+ SouthboundUtils.addBridge(bridgeIid, bridgeNew, dataBroker, futures);
BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpnId);
InstanceIdentifier<BridgeEntry> bridgeEntryInstanceIdentifier =
InterfaceMetaUtils.getBridgeEntryFromConfigDS(bridgeEntryInstanceIdentifier,
dataBroker);
if (bridgeEntry == null) {
- futures.add(t.submit());
+ futures.add(writeTransaction.submit());
return futures;
}
Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
if (iface.getAugmentation(IfTunnel.class) != null) {
SouthboundUtils.addPortToBridge(bridgeIid, iface, bridgeNew, bridgeName, portName, dataBroker, futures);
- InterfaceMetaUtils.createBridgeInterfaceEntryInConfigDS(bridgeEntryKey,
- new BridgeInterfaceEntryKey(portName), portName, t);
}
}
- futures.add(t.submit());
+ futures.add(writeTransaction.submit());
return futures;
}
}
\ No newline at end of file
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
t.delete(LogicalDatastoreType.OPERATIONAL, bridgeEntryId);
+ // FIX for ovsdb bug for delete TEP
+ SouthboundUtils.deleteBridge(bridgeIid, dataBroker, futures);
+
futures.add(t.submit());
return futures;
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
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;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
futures.add(tx.submit());
}
+ public static void addBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+ OvsdbBridgeAugmentation bridgeAugmentation,
+ DataBroker dataBroker, List<ListenableFuture<Void>> futures){
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ NodeId nodeId = InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)).getNodeId();
+ NodeBuilder bridgeNodeBuilder = new NodeBuilder();
+ bridgeNodeBuilder.setNodeId(nodeId);
+ bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentation);
+ tx.put(LogicalDatastoreType.CONFIGURATION, createNodeInstanceIdentifier(nodeId), bridgeNodeBuilder.build(), true);
+ futures.add(tx.submit());
+ }
+
+ public static void deleteBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+ DataBroker dataBroker, List<ListenableFuture<Void>> futures){
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ NodeId nodeId = InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)).getNodeId();
+ tx.delete(LogicalDatastoreType.CONFIGURATION, createNodeInstanceIdentifier(nodeId));
+ futures.add(tx.submit());
+ }
+
private static void addVlanPortToBridge(InstanceIdentifier<?> bridgeIid, IfL2vlan ifL2vlan,
OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName,
String portName, DataBroker dataBroker, WriteTransaction t) {
LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
return terminationPointPath;
}
+
+ public static InstanceIdentifier<Node> createNodeInstanceIdentifier(NodeId nodeId) {
+ return InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
+ .child(Node.class,new NodeKey(nodeId));
+ }
}
\ No newline at end of file
public java.lang.AutoCloseable createInstance() {
InterfacemgrProvider provider = new InterfacemgrProvider();
provider.setRpcProviderRegistry(getRpcRegistryDependency());
+ provider.setNotificationService(getNotificationServiceDependency());
provider.setMdsalManager(getMdsalutilDependency());
getBrokerDependency().registerProvider(provider);
return provider;
prefix "interfacemgr-impl";
import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28;}
import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
import odl-interface {prefix odlif; revision-date 2015-03-31;}
import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
}
}
}
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
}
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.IfIndexesInterfaceMap;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface;
@Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
@Mock ReadOnlyTransaction mockReadTx;
@Mock WriteTransaction mockWriteTx;
+ @Mock AlivenessMonitorService alivenessMonitorService;
OvsInterfaceStateAddHelper addHelper;
OvsInterfaceStateRemoveHelper removeHelper;
.setIdKey(InterfaceManagerTestUtil.interfaceName).build();
doReturn(idOutputOptional).when(idManager).allocateId(getIdInput);
- addHelper.addState(dataBroker, idManager, mdsalManager, nodeConnectorId, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+ addHelper.addState(dataBroker, idManager, mdsalManager, alivenessMonitorService,
+ nodeConnectorId, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
//Add some verifications
verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier,
doReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build())).when(idManager).releaseId(getIdInput);
- removeHelper.removeState(idManager, mdsalManager, fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+ removeHelper.removeState(idManager, mdsalManager, alivenessMonitorService, fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, ifIndexId);
fcNodeConnectorOldupdate.setState(b2.build());
fcNodeConnectorNewupdate.setState(b3.build());
- updateHelper.updateState(fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNewupdate.build(), fcNodeConnectorOldupdate.build());
+ updateHelper.updateState(fcNodeConnectorId, alivenessMonitorService, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNewupdate.build(), fcNodeConnectorOldupdate.build());
verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier,stateInterface);
}
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
@Mock DataBroker dataBroker;
@Mock IdManagerService idManager;
+ @Mock AlivenessMonitorService alivenessMonitorService;
@Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
@Mock ReadOnlyTransaction mockReadTx;
@Mock WriteTransaction mockWriteTx;
-
+ @Mock
+ IMdsalApiManager mdsalApiManager;
OvsInterfaceConfigAddHelper addHelper;
OvsInterfaceConfigRemoveHelper removeHelper;
OvsInterfaceConfigUpdateHelper updateHelper;
doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
- addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager);
+ addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
//Add some verifications
verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryInstanceIdentifier, bridgeInterfaceEntry, true);
public void testAddGreInterfaceWhenSwitchIsConnected() {
Optional<BridgeRefEntry> expectedBridgeRefEntry = Optional.of(bridgeRefEntry);
Optional<OvsdbBridgeAugmentation> expectedOvsdbBridgeAugmentation = Optional.of(ovsdbBridgeAugmentation);
-
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
doReturn(Futures.immediateCheckedFuture(expectedBridgeRefEntry)).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
doReturn(Futures.immediateCheckedFuture(expectedOvsdbBridgeAugmentation)).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, ovsdbBridgeAugmentationInstanceIdentifier);
- addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager);
+ addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
//Add some verifications
verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryInstanceIdentifier ,
public void testDeleteGreInterfaceWhenSwitchIsConnected() {
Optional<BridgeRefEntry> expectedBridgeRefEntry = Optional.of(bridgeRefEntry);
Optional<BridgeEntry> expectedBridgeEntry = Optional.of(bridgeEntry);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedInterfaceState = Optional.of(stateInterface);
doReturn(Futures.immediateCheckedFuture(expectedBridgeRefEntry)).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
doReturn(Futures.immediateCheckedFuture(expectedBridgeEntry)).when(mockReadTx).read(
LogicalDatastoreType.CONFIGURATION, bridgeEntryIid);
+ doReturn(Futures.immediateCheckedFuture(expectedInterfaceState)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
ifaceBuilder.setOperStatus(OperStatus.Down);
ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(tunnelInterfaceEnabled.getName()));
stateInterface = ifaceBuilder.build();
- removeHelper.removeConfiguration(dataBroker, tunnelInterfaceEnabled, idManager, parentRefs);
+ removeHelper.removeConfiguration(dataBroker, alivenessMonitorService, tunnelInterfaceEnabled, idManager,
+ mdsalApiManager, parentRefs);
//Add some verifications
verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION, bridgeEntryIid);
doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
- updateHelper.updateConfiguration(dataBroker,idManager,tunnelInterfaceDisabled,tunnelInterfaceEnabled);
+ updateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager, mdsalApiManager,
+ tunnelInterfaceDisabled,tunnelInterfaceEnabled);
//verify whether operational data store is updated with the new oper state.
InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
- updateHelper.updateConfiguration(dataBroker,idManager,tunnelInterfaceEnabled,tunnelInterfaceDisabled);
+ updateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager, mdsalApiManager,
+ tunnelInterfaceEnabled,tunnelInterfaceDisabled);
//verify whether operational data store is updated with the new oper state.
InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@Mock
DataBroker dataBroker;
+ @Mock
+ AlivenessMonitorService alivenessMonitorService;
@Mock IdManager idManager;
@Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
@Mock ReadOnlyTransaction mockReadTx;
@Mock WriteTransaction mockWriteTx;
-
+ @Mock IMdsalApiManager mdsalApiManager;
OvsInterfaceConfigAddHelper addHelper;
OvsInterfaceConfigRemoveHelper removeHelper;
doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
- addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager);
+ addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
//Nothing to verify, since when switch is not connected we don't do any datastore operation
doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
- addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager);
+ addHelper.addConfiguration(dataBroker, null, vlanInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
//Nothing to verify, since when adminstate is enabled and switch opstate is already up,
//we don't do any datastore operation
ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(vlanInterfaceEnabled.getName()));
stateInterface = ifaceBuilder.build();
- addHelper.addConfiguration(dataBroker, null, vlanInterfaceDisabled, idManager);
+ addHelper.addConfiguration(dataBroker, null, vlanInterfaceDisabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
//verification
verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier, stateInterface);
ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(vlanInterfaceEnabled.getName()));
stateInterface = ifaceBuilder.build();
- removeHelper.removeConfiguration(dataBroker, vlanInterfaceEnabled, idManager, null);
+ removeHelper.removeConfiguration(dataBroker,alivenessMonitorService, vlanInterfaceEnabled, idManager,
+ mdsalApiManager, null);
//verification
verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier, stateInterface);
* @param delayTime
*/
public void syncRemoveFlow(FlowEntity flowEntity, long delayTime);
+ public void syncInstallFlow(FlowEntity flowEntity, long delayTime);
/**
* API to install the Group on Data Plane Node synchronously. It internally waits for
mdSalMgr.syncSetUpFlow(flowEntity, delayTime, true);
}
+ @Override
+ public void syncInstallFlow(FlowEntity flowEntity, long delayTime) {
+ mdSalMgr.syncSetUpFlow(flowEntity, delayTime, false);
+ }
+
@Override
public void syncInstallGroup(GroupEntity groupEntity, long delayTime) {
mdSalMgr.syncSetUpGroup(groupEntity, delayTime, false);
import ietf-inet-types {
prefix inet;
+ revision-date "2010-09-24";
}
import ietf-yang-types {
prefix yang;
prefix "ericsson-bgp";
// import some basic inet types
- import ietf-inet-types { prefix inet; }
+ import ietf-inet-types { prefix inet; revision-date "2010-09-24"; }
// meta
organization
container ebgp-multihop {
leaf nhops {
type uint32;
- mandatory "true";
}
leaf peer-ip {
type leafref {
<dependency>
<groupId>org.opendaylight.mdsal</groupId>
<artifactId>yang-binding</artifactId>
- <version>${yangtools.version}</version>
+ <version>${mdsal.model.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>vpnmanager-api</artifactId>
<version>${vpnservices.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>elanmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.vpnservice</groupId>
<artifactId>mdsalutil-api</artifactId>
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
if (LOG.isTraceEnabled()) {
LOG.trace("Adding Network : key: " + identifier + ", value=" + input);
}
+ //Create ELAN instance for this network
+ createElanInstance(input.getUuid().getValue());
}
@Override
if (LOG.isTraceEnabled()) {
LOG.trace("Removing Network : key: " + identifier + ", value=" + input);
}
+ //Delete ELAN instance for this network
+ deleteElanInstance(input.getUuid().getValue());
}
@Override
}
}
+ private void createElanInstance(String elanInstanceName) {
+ ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setKey(new
+ ElanInstanceKey(elanInstanceName)).build();
+ InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
+ .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInstance);
+
+ }
+
+ private void deleteElanInstance(String elanInstanceName) {
+ InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
+ .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
+ }
+
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
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.neutron.ports.rev150712.port.attributes.FixedIps;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
.PortFixedipToPortNameBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
// Create of-port interface for this neutron port
createOfPortInterface(port, portVlanId);
+ LOG.debug("Creating ELAN Interface");
+ createElanInterface(port, portVlanId);
LOG.debug("Add port to subnet");
// add port to local Subnets DS
Uuid vpnId = addPortToSubnets(port);
}
int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
// Remove of-port interface for this neutron port
+ // ELAN interface is also implicitly deleted as part of this operation
deleteOfPortInterface(port, portVlanId);
}
.getUuid());
}
+ private void createElanInterface(Port port, int portVlanId) {
+ String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
+ String interfaceName = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
+ String elanInstanceName = port.getNetworkId().getValue();
+ List<PhysAddress> physAddresses = new ArrayList<>();
+ physAddresses.add(new PhysAddress(port.getMacAddress()));
+
+ InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
+ .class, new ElanInterfaceKey(interfaceName)).build();
+ ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
+ .setName(interfaceName).setStaticMacEntries(physAddresses).
+ setKey(new ElanInterfaceKey(interfaceName)).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInterface);
+ LOG.debug("Creating new ELan Interface {}", elanInterface);
+ }
+
// adds port to subnet list and creates vpnInterface
private Uuid addPortToSubnets(Port port) {
Uuid subnetId = null;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.Interfaces;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
if (LOG.isTraceEnabled()) {
LOG.trace("Removing router : key: " + identifier + ", value=" + input);
}
- // check if this router has internal-VPN
Uuid routerId = input.getUuid();
- VpnMap vpnmap = NeutronvpnUtils.getVpnMap(broker, routerId);
- if (vpnmap != null) {
- // if yes, remove corresponding internal vpn
- LOG.trace("removing internal-vpn for router {}", routerId);
- nvpnManager.removeL3Vpn(routerId);
- } else {
- // if not, it is associated with some VPN
- // remove VPN-router association
- Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId);
- LOG.trace("dissociating router {} from vpn {}", routerId, vpnId);
- nvpnManager.dissociateRouterFromVpn(vpnId, routerId);
+ // fetch subnets associated to router
+ List<Interfaces> routerInterfaces = input.getInterfaces();
+ List<Uuid> routerSubnetIds = new ArrayList<Uuid>();
+ if (routerInterfaces != null) {
+ for (Interfaces rtrIf : routerInterfaces) {
+ routerSubnetIds.add(rtrIf.getSubnetId());
+ }
}
-
+ nvpnManager.handleNeutronRouterDeleted(routerId, routerSubnetIds);
}
@Override
update);
}
Uuid routerId = update.getUuid();
- Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId);
+ Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
+ // internal vpn always present in case external vpn not found
+ if (vpnId == null) {
+ vpnId = routerId;
+ }
List<Interfaces> oldInterfaces = (original.getInterfaces() != null) ? original.getInterfaces() : new
ArrayList<Interfaces>();
List<Interfaces> newInterfaces = (update.getInterfaces() != null) ? update.getInterfaces() : new
return;
}
String portname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
- String name = new StringBuilder(portname).append(":0").toString();
List<Adjacency> adjList = new ArrayList<Adjacency>();
InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
- child(VpnInterface.class, new VpnInterfaceKey(name)).build();
+ child(VpnInterface.class, new VpnInterfaceKey(portname)).build();
// find router associated to vpn
Uuid routerId = NeutronvpnUtils.getRouterforVpn(broker, vpnId);
Router rtr = null;
// create extra route adjacency
if (rtr != null && rtr.getRoutes() != null) {
List<String> routeList = rtr.getRoutes();
- List<Adjacency> erAdjList = addAdjacencyforExtraRoute(routeList, false, name);
+ List<Adjacency> erAdjList = addAdjacencyforExtraRoute(routeList, false, portname);
if (erAdjList != null) {
adjList.addAll(erAdjList);
}
}
// create vpn-interface on this neutron port
Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
- VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(name)).
- setName(name).setVpnInstanceName(vpnId.getValue()).addAugmentation(Adjacencies.class, adjs);
+ VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(portname)).
+ setName(portname).setVpnInstanceName(vpnId.getValue()).addAugmentation(Adjacencies.class, adjs);
VpnInterface vpnIf = vpnb.build();
- NeutronvpnUtils.lockVpnInterface(lockManager, name);
+ NeutronvpnUtils.lockVpnInterface(lockManager, portname);
try {
logger.debug("Creating vpn interface {}", vpnIf);
MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
} catch (Exception ex) {
- logger.error("Creation of vpninterface {} failed due to {}", name, ex);
+ logger.error("Creation of vpninterface {} failed due to {}", portname, ex);
} finally {
- NeutronvpnUtils.unlockVpnInterface(lockManager, name);
+ NeutronvpnUtils.unlockVpnInterface(lockManager, portname);
}
}
if (port != null) {
String pname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
- String name = new StringBuilder(pname).append(":0").toString();
InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
- child(VpnInterface.class, new VpnInterfaceKey(name)).build();
+ child(VpnInterface.class, new VpnInterfaceKey(pname)).build();
- NeutronvpnUtils.lockVpnInterface(lockManager, name);
+ NeutronvpnUtils.lockVpnInterface(lockManager, pname);
try {
- logger.debug("Deleting vpn interface {}", name);
+ logger.debug("Deleting vpn interface {}", pname);
MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
} catch (Exception ex) {
- logger.error("Deletion of vpninterface {} failed due to {}", name, ex);
+ logger.error("Deletion of vpninterface {} failed due to {}", pname, ex);
} finally {
- NeutronvpnUtils.unlockVpnInterface(lockManager, name);
+ NeutronvpnUtils.unlockVpnInterface(lockManager, pname);
}
}
}
String destination = parts[1];
String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
- String ifname = new StringBuilder(tapPortName).append(":0").toString();
logger.trace("Adding extra route with nexthop {}, destination {}, ifName {}", nextHop,
- destination, ifname);
+ destination, tapPortName);
Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination).setNextHopIp(nextHop).setKey
(new AdjacencyKey(destination)).build();
if (rtrUp == false) {
- if (ifname.equals(vpnifname)) {
+ if (tapPortName.equals(vpnifname)) {
adjList.add(erAdj);
}
continue;
}
InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
- child(VpnInterface.class, new VpnInterfaceKey(ifname)).build();
+ child(VpnInterface.class, new VpnInterfaceKey(tapPortName)).build();
Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(broker, LogicalDatastoreType
.CONFIGURATION, vpnIfIdentifier);
if (optionalVpnInterface.isPresent()) {
Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(erAdj)).build();
- VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(ifname))
+ VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(tapPortName))
.addAugmentation(Adjacencies.class, erAdjs).build();
MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
logger.trace("extra route {} added successfully", route);
} else {
logger.error("VM adjacency for interface {} not present ; cannot add extra route adjacency",
- ifname);
+ tapPortName);
}
} else {
logger.error("Incorrect input received for extra route. {}", parts);
String destination = parts[1];
String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
- String ifname = new StringBuilder(tapPortName).append(":0").toString();
logger.trace("Removing extra route with nexthop {}, destination {}, ifName {}", nextHop,
- destination, ifname);
+ destination, tapPortName);
InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
- child(VpnInterface.class, new VpnInterfaceKey(ifname)).augmentation(Adjacencies.class)
+ child(VpnInterface.class, new VpnInterfaceKey(tapPortName)).augmentation(Adjacencies.class)
.child(Adjacency.class, new AdjacencyKey(destination)).build();
MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
logger.trace("extra route {} deleted successfully", route);
}
protected void removeL3Vpn(Uuid id) {
- // read VPN networks
+ // read VPNMaps
VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, id);
Uuid router = vpnMap.getRouterId();
// dissociate router
}
}
- protected void associateRouterToVpn(Uuid vpn, Uuid router) {
+ protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
- // remove existing Router-VPN
- if (!vpn.equals(router)) {
- removeL3Vpn(router);
- }
- updateVpnMaps(vpn, null, router, null, null);
+ List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
- List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
- logger.debug("Adding subnets...");
+ if (!vpnId.equals(routerId)) {
+ logger.debug("Removing subnets from internal vpn {}", routerId.getValue());
+ if (routerSubnets != null) {
+ for (Uuid subnet : routerSubnets) {
+ removeSubnetFromVpn(routerId, subnet);
+ }
+ }
+ }
+ logger.debug("Adding subnets to vpn {}", vpnId.getValue());
for (Uuid subnet : routerSubnets) {
- addSubnetToVpn(vpn, subnet);
+ addSubnetToVpn(vpnId, subnet);
}
+
+ updateVpnMaps(vpnId, null, routerId, null, null);
}
- protected void dissociateRouterFromVpn(Uuid vpn, Uuid router) {
- clearFromVpnMaps(vpn, router, null);
+ protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
- // fetching sn from SubnetmapDS for internal VPN because sn already deleted from RouterIf DS on router deletion
- List<Uuid> routerSubnets = (vpn.equals(router)) ? getSubnetsforVpn(vpn) :
- NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
+ // remove existing external vpn interfaces
+ List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
- logger.debug("dissociateRouter vpn {} router {} Removing subnets...", vpn.getValue(), router.getValue());
if (routerSubnets != null) {
for (Uuid subnet : routerSubnets) {
- removeSubnetFromVpn(vpn, subnet);
+ logger.debug("Removing subnets from external vpn {}", vpnId.getValue());
+ removeSubnetFromVpn(vpnId, subnet);
+ logger.debug("Adding subnets to internal vpn {}", routerId.getValue());
+ addSubnetToVpn(routerId, subnet);
}
}
- // create Router-VPN for this router
- if (!vpn.equals(router)) {
- logger.debug("Re-creating vpn-router...");
- createL3Vpn(router, null, null, null, null, null, router, null);
- }
+ clearFromVpnMaps(vpnId, routerId, null);
}
protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
return result;
}
+ protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
+ // check if the router is associated to some VPN
+ Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
+ if (vpnId != null) {
+ // remove existing external vpn interfaces
+ for (Uuid subnetId : routerSubnetIds) {
+ removeSubnetFromVpn(vpnId, subnetId);
+ }
+ clearFromVpnMaps(vpnId, routerId, null);
+ } else {
+ // remove existing internal vpn interfaces
+ for (Uuid subnetId : routerSubnetIds) {
+ removeSubnetFromVpn(routerId, subnetId);
+ }
+ }
+ // delete entire vpnMaps node for internal VPN
+ deleteVpnMapsNode(routerId);
+
+ // delete vpn-instance for internal VPN
+ deleteVpnInstance(routerId);
+ }
+
protected Subnet getNeutronSubnet(Uuid subnetId) {
InstanceIdentifier<Subnet> inst = InstanceIdentifier.create(Neutron.class).
child(Subnets.class).child(Subnet.class, new SubnetKey(subnetId));
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TimeUnits;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInput;
return null;
}
- protected static Uuid getVpnForRouter(DataBroker broker, Uuid router) {
+ // true for external vpn, false for internal vpn
+ protected static Uuid getVpnForRouter(DataBroker broker, Uuid routerId, Boolean externalVpn) {
InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
- Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
+ Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapsIdentifier);
if (optionalVpnMaps.isPresent()) {
VpnMaps vpnNets = optionalVpnMaps.get();
List<VpnMap> allMaps = vpnNets.getVpnMap();
- if (router != null) {
+ if (routerId != null) {
for (VpnMap vpnMap : allMaps) {
- if (router.equals(vpnMap.getRouterId())) {
- return vpnMap.getVpnId();
+ if (routerId.equals(vpnMap.getRouterId())) {
+ if (externalVpn == true) {
+ if (!routerId.equals(vpnMap.getVpnId())) {
+ return vpnMap.getVpnId();
+ }
+ } else {
+ if (routerId.equals(vpnMap.getVpnId())) {
+ return vpnMap.getVpnId();
+ }
+ }
}
}
}
protected static List<Uuid> getNeutronRouterSubnetIds(DataBroker broker, Uuid routerId) {
logger.info("getNeutronRouterSubnetIds for {}", routerId.getValue());
- List<Uuid> subnetNames = new ArrayList<Uuid>();
+ List<Uuid> subnetIdList = new ArrayList<Uuid>();
Router router = getNeutronRouter(broker, routerId);
if (router != null) {
List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router
- .Interfaces> ifs = router.getInterfaces();
- if (!ifs.isEmpty()) {
+ .Interfaces> interfacesList = router.getInterfaces();
+ if (!interfacesList.isEmpty()) {
for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers
- .router.Interfaces iff : ifs) {
- subnetNames.add(iff.getSubnetId());
+ .router.Interfaces interfaces : interfacesList) {
+ subnetIdList.add(interfaces.getSubnetId());
}
}
}
logger.info("returning from getNeutronRouterSubnetIds for {}", routerId.getValue());
- return subnetNames;
+ return subnetIdList;
}
protected static String uuidToTapPortName(Uuid id) {
try {
Uuid subnetUUID = port.getFixedIps().get(0).getSubnetId();
- org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets
- .SubnetKey subnetkey = new org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets
- .rev150712.subnets.attributes.subnets.SubnetKey(subnetUUID);
- InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
- .attributes.subnets.Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class).child(org
- .opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets
- .class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
- .attributes.subnets.Subnet.class, subnetkey);
- Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes
- .subnets.Subnet> subnet = read(broker, LogicalDatastoreType.CONFIGURATION, subnetidentifier);
-
+ SubnetKey subnetkey = new SubnetKey(subnetUUID);
+ InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class).child(Subnets
+ .class).child(Subnet.class, subnetkey);
+ Optional<Subnet> subnet = read(broker, LogicalDatastoreType.CONFIGURATION,subnetidentifier);
if (subnet.isPresent()) {
cidr = subnet.get().getCidr();
// Extract the prefix length from cidr
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 INTERNAL
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>org.opendaylight.vpnservice</groupId>
<artifactId>vpnservice</artifactId>
<version>0.3.0-SNAPSHOT</version>
<module>distribution/karaf</module>
<module>features</module>
<module>vpnservice-artifacts</module>
+ <module>vpnintent</module>
</modules>
<!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
<url>https://wiki.opendaylight.org/view/VPNService:Main</url>
<tag>HEAD</tag>
</scm>
-</project>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/binding-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnintent-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+ */
+module vpnintent {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:vpnintent";
+ prefix "vpnintent";
+
+ import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
+
+ revision "2015-01-05" {
+ description "Initial revision of VPN intent model.
+ Create VPN via Intent, keep VPN state and manage MPLS labels";
+ }
+
+ container vpns{
+ list vpn-intents {
+ key "vpn-name";
+ uses vpn-intent;
+ }
+ }
+
+ typedef failover-type {
+ type enumeration {
+ enum fast-reroute {
+ value 1;
+ }
+ enum slow-reroute {
+ value 2;
+ }
+ }
+ }
+
+ grouping vpn-intent {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ leaf path-protection {
+ type boolean;
+ }
+ leaf failover-type {
+ type failover-type;
+ }
+ list endpoint {
+ key "site-name";
+ uses endpoint-fields;
+ description "List to keep track site name and endpoint.";
+ }
+ }
+
+ grouping endpoint-fields {
+ leaf site-name{
+ type string;
+ description "VPN member site name.";
+ }
+
+ leaf ip-prefix {
+ type inet:ip-prefix;
+ description "VPN member IP prefix.";
+ }
+
+ leaf switch-port-id {
+ type string;
+ description "Switch and port ID that VPN member is connected to.";
+ }
+ }
+
+ grouping labels {
+ list label {
+ key "label-id";
+ leaf "label-id"{
+ type uint32 {
+ range "0 .. 524288";
+ }
+ description "20 bit MPLS label ID";
+ mandatory true;
+ }
+ uses endpoint-fields;
+ description "Keep track of MPLS/other label endpoint relation.";
+ }
+ }
+
+ container mpls-labels {
+ uses labels;
+ }
+
+ rpc add-vpn-endpoint{
+ description
+ "Add VPN endpoint.";
+ input {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ uses endpoint-fields;
+ }
+ }
+
+ rpc remove-vpn-endpoint{
+ description
+ "Remove VPN endpoint.";
+ input {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ leaf site-name{
+ type string;
+ description "VPN member site name.";
+ }
+ }
+ }
+
+ rpc remove-vpn{
+ description
+ "Remove VPN and its endpoints.";
+ input {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ }
+ }
+ }
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>vpnintent-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <nic.version>1.2.0-SNAPSHOT</nic.version>
+ <powermock.version>1.5.2</powermock.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- NIC dependency -->
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>intent-api</artifactId>
+ <version>${nic.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>intent-mapping-interface</artifactId>
+ <version>${nic.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>utils</artifactId>
+ <version>${nic.version}</version>
+ </dependency>
+
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2016 Inocybe Technologies 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
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:vpnintent:impl?module=vpnintent-impl&revision=2014-12-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ </required-capabilities>
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:vpnintent:impl">prefix:vpnintent-impl</type>
+ <name>vpnintent-impl-default</name>
+ <broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </broker>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.constraints.rev150122.FailoverType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Actions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Constraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Subjects;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.SubjectsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.allow.AllowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.block.BlockBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.failover.constraint.FailoverConstraintBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.protection.constraint.ProtectionConstraintBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * This class is used to build Intents object and
+ * write it to Network Intent Composition md-sal tree
+ * in order to create/delete intents between two endpoint groups.
+ */
+public class IntentServiceManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IntentServiceManager.class);
+ private static final short FIRST_SUBJECT = 1;
+ private static final short SECOND_SUBJECT = 2;
+ public static final String ACTION_ALLOW = "ALLOW";
+ public static final String ACTION_BLOCK = "BLOCK";
+ public static final String FAST_REROUTE = "fast-reroute";
+ public static final String SLOW_REROUTE = "slow-reroute";
+ private final DataBroker dataBroker;
+ private static final InstanceIdentifier<Intents> INTENTS_IID = IidFactory.getIntentsIid();
+ private final MdsalUtils mdsal;
+
+ public IntentServiceManager(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ this.mdsal = new MdsalUtils(dataBroker);
+ }
+
+ /**
+ * Create Intents object and write to to config tree to trigger intents
+ * @param src :Source Site Name
+ * @param dst :Destination Site Name
+ * @param intentAction :Intent verb: ALLOW or BLOCK
+ * @param failOverType
+ */
+ public void addIntent(String src, String dst, String intentAction, String failOverType) {
+ Preconditions.checkNotNull(src);
+ Preconditions.checkNotNull(dst);
+ Preconditions.checkNotNull(intentAction);
+
+ List<Intent> intentList = null;
+ List<Subjects> subjects = createSubjects(dst, src);
+ List<Actions> intentActions = createActions(intentAction);
+ List<Constraints> intentConstraints = createConstraints(failOverType);
+
+ Intent intent = new IntentBuilder().setId(new Uuid(UUID.randomUUID().toString()))
+ .setSubjects(subjects).setActions(intentActions)
+ .setConstraints(intentConstraints)
+ .build();
+
+ Intents currentIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID);
+ if (currentIntents == null) {
+ intentList = new ArrayList<>();
+ } else {
+ intentList = currentIntents.getIntent();
+ }
+ intentList.add(intent);
+ Intents intents = new IntentsBuilder().setIntent(intentList).build();
+ mdsal.put(LogicalDatastoreType.CONFIGURATION, INTENTS_IID, intents);
+ LOG.info("AddIntent: config populated: {}", intents);
+ }
+
+ /**
+ * Delete an Intent
+ * @param id :Uuid of the Intent to be deleted
+ */
+ public void removeIntent(Uuid id) {
+ Preconditions.checkNotNull(id);
+ InstanceIdentifier<Intent> iid = InstanceIdentifier.create(Intents.class).child(Intent.class, new IntentKey(id));
+ mdsal.delete(LogicalDatastoreType.CONFIGURATION, iid);
+ LOG.info("RemoveIntent succeeded");
+ }
+
+ /**
+ * Remove all associated intents by endpointGroupName
+ * @param endpointGroupName
+ */
+ public void removeIntentsByEndpoint(String endpointGroupName) {
+ Preconditions.checkNotNull(endpointGroupName);
+
+ Intents intents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID);
+
+ if (intents != null && intents.getIntent() != null) {
+ for (Intent intent : intents.getIntent()) {
+ if (intent.getSubjects() != null && intent.getSubjects().size() > 0) {
+ String endpointValue = "";
+ for (Subjects subject : intent.getSubjects()) {
+ if (subject
+ .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) subject
+ .getSubject();
+ endpointValue = epg.getEndPointGroup().getName();
+ } else if (subject
+ .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) subject
+ .getSubject();
+ endpointValue = epg.getEndPointSelector().getEndPointSelector();
+ } else if (subject
+ .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) subject
+ .getSubject();
+ endpointValue = epg.getEndPointGroupSelector().getEndPointGroupSelector();
+ }
+ if (endpointValue.equalsIgnoreCase(endpointGroupName)) {
+ removeIntent(intent.getId());
+ LOG.info("Deleted Intent ID : {} for endpoint: {}", intent.getId(), endpointGroupName);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a list of Intent actions
+ * @param intentAction
+ * @return :a list of Actions
+ */
+ private List<Actions> createActions(String intentAction) {
+ List<Actions> actionsList = new ArrayList<Actions>();
+ short order = 1;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.Action action = null;
+ if (intentAction.equalsIgnoreCase(ACTION_ALLOW)) {
+ action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action
+ .AllowBuilder().setAllow(new AllowBuilder().build()).build();
+ } else if (intentAction.equalsIgnoreCase(ACTION_BLOCK)) {
+ action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action
+ .BlockBuilder().setBlock(new BlockBuilder().build()).build();
+ }
+
+ Actions intentActions = new ActionsBuilder().setOrder(order).setAction(action).build();
+ actionsList.add(intentActions);
+ return actionsList;
+ }
+
+ /**
+ * Create a list of Intent subjects
+ * @param src :Source Site Name
+ * @param dst :Destination Site Name
+ * @return :a list of Subjects
+ */
+ private List<Subjects> createSubjects(String src, String dst) {
+ List<Subjects> subjectList = new ArrayList<Subjects>();
+
+ EndPointGroup endpointGroupFrom = new EndPointGroupBuilder().setName(src).build();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup fromEPG =
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject
+ .EndPointGroupBuilder().setEndPointGroup(endpointGroupFrom).build();
+ Subjects subjects1 = new SubjectsBuilder().setOrder(FIRST_SUBJECT).setSubject(fromEPG).build();
+
+ EndPointGroup endpointGroupTo = new EndPointGroupBuilder().setName(dst).build();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup toEPG =
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject
+ .EndPointGroupBuilder().setEndPointGroup(endpointGroupTo).build();
+ Subjects subjects2 = new SubjectsBuilder().setOrder(SECOND_SUBJECT).setSubject(toEPG).build();
+
+ subjectList.add(subjects1);
+ subjectList.add(subjects2);
+ return subjectList;
+ }
+
+ /**
+ * Create a list of Intent constraints
+ * @param failOverType :Type of failover, fast-reroute or slow-reroute
+ * @return
+ */
+ private List<Constraints> createConstraints(String failOverType) {
+ List<Constraints> intentConstraints = new ArrayList<Constraints>();
+ if (failOverType==null) {
+ return intentConstraints;
+ }
+ short order = 1;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints
+ protectionConstraint = null;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints
+ failoverConstraint = null;
+ if (failOverType.equals(FAST_REROUTE)) {
+ protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent
+ .constraints.constraints.ProtectionConstraintBuilder()
+ .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build();
+ failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints
+ .constraints.FailoverConstraintBuilder()
+ .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.FastReroute).build())
+ .build();
+ } else if (failOverType.equals(SLOW_REROUTE)) {
+ protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent
+ .constraints.constraints.ProtectionConstraintBuilder()
+ .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build();
+ failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints
+ .constraints.FailoverConstraintBuilder()
+ .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.SlowReroute).build())
+ .build();
+ }
+ Constraints constraint1 = new ConstraintsBuilder().setOrder(order).setConstraints(protectionConstraint).build();
+ Constraints constraint2 = new ConstraintsBuilder().setOrder(++order).setConstraints(failoverConstraint).build();
+ intentConstraints.add(constraint1);
+ intentConstraints.add(constraint2);
+ return intentConstraints;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class MappingServiceManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MappingServiceManager.class);
+ private IntentMappingService intentMappingService;
+ private String IP_PREFIX_PROPERTY = "ip_prefix";
+ private String SWITCH_PORT_ID_PROPERTY = "switch_port";
+ private String MPLS_LABEL_PROPERTY = "mpls_label";
+ private String NEXT_HOP_PROPERTY = "next_hop";
+
+ public MappingServiceManager(IntentMappingService intentMappingService) {
+ Preconditions.checkNotNull(intentMappingService);
+ this.intentMappingService = intentMappingService;
+ }
+
+ /**
+ * @param siteName
+ * Name of the member
+ * @param ipPrefix
+ * Ip prefix of the member
+ * @param switchPortId
+ * Switch ID and port ID (i.e. openflow:1:2)
+ * @param mplsLabel
+ * MPLS label, if needed
+ * @param nextHop
+ * Next hop in the route
+ */
+ public void add(final String siteName, final String ipPrefix, final String switchPortId, final Long mplsLabel,
+ final String nextHop) {
+ Preconditions.checkNotNull(siteName);
+ Preconditions.checkNotNull(ipPrefix);
+ Preconditions.checkNotNull(switchPortId);
+
+ Map<String, String> objs = new HashMap<>();
+ objs.put(IP_PREFIX_PROPERTY, ipPrefix);
+ objs.put(SWITCH_PORT_ID_PROPERTY, switchPortId);
+
+ if (mplsLabel != null)
+ objs.put(MPLS_LABEL_PROPERTY, String.valueOf(mplsLabel));
+ if (nextHop != null)
+ objs.put(NEXT_HOP_PROPERTY, nextHop);
+
+ intentMappingService.add(siteName, objs);
+ }
+
+ /**
+ * @param siteName
+ * Name of the member
+ * @return Map of parameters related to the member
+ */
+ public Map<String, String> get(String siteName) {
+ return intentMappingService.get(siteName);
+ }
+
+ /**
+ * @param siteName
+ * Name of the member
+ * @return Return true if transaction succeed, otherwise false
+ */
+ public boolean delete(String siteName) {
+ try {
+ // TODO: Implement delete() in mapping service
+ // By now, it's going to overwrite data for this key
+ intentMappingService.add(siteName, null);
+ return true;
+ } catch (Exception e) {
+ LOG.error("Error deleting from NIC's mapping service {}", e);
+ throw e;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MplsLabelManagerService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MplsLabelManagerService.class);
+ private static final Integer MAX_MPLS_LABEL = 524288;
+ private static InstanceIdentifier<Label> LABEL_IID = null;
+ public static final InstanceIdentifier<MplsLabels> MPLS_LABELS_IID = IidFactory.getMplsLabelsIid();
+ private final DataBroker dataBroker;
+ private final Random random = new Random();
+ private final MdsalUtils mdsal;
+
+ public MplsLabelManagerService(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ this.mdsal = new MdsalUtils(this.dataBroker);
+ }
+
+ /**
+ * Generate a unique Mpls Label
+ * Mpls label is of length 20 bits maximum
+ * @return :next unique Mpls label value
+ */
+ public Long getUniqueLabel(Endpoint endpoint) {
+ Long nextUniqueLabel = (long) random.nextInt(MAX_MPLS_LABEL);
+ while(checkIsLabelUsed(nextUniqueLabel)) {
+ nextUniqueLabel = (long) random.nextInt(MAX_MPLS_LABEL);
+ }
+ updateToLabelStore(nextUniqueLabel, endpoint, true);
+ return nextUniqueLabel;
+ }
+
+ /**
+ * Delete label from datastore
+ * @param endpoint :endpoint whose label needs to be deleted
+ */
+ public void deleteLabel(Endpoint endpoint) {
+ Map<Long, String> labelMap = getAllLabels();
+ for (Map.Entry<Long, String> labelEntry : labelMap.entrySet()) {
+ if(labelEntry.getValue().equalsIgnoreCase(endpoint.getSiteName())) {
+ updateToLabelStore(labelEntry.getKey(), endpoint, false);
+ }
+ }
+ }
+
+ /**
+ * Update the model for Labels with used Mpls label values
+ * @param label :mpls label allocated to an endpoint
+ * @param endpoint :endpoint to which mpls label is allocated to
+ * @param add :true if add label to datastore, false to delete label from datastore
+ */
+ private void updateToLabelStore(Long label, Endpoint endpoint, boolean add) {
+ LABEL_IID = IidFactory.getLabelIid(label);
+ Label mplsLabel = new LabelBuilder().
+ setKey(new LabelKey(label)).
+ setLabelId(label).
+ setSiteName(endpoint.getSiteName()).
+ setIpPrefix(endpoint.getIpPrefix()).
+ setSwitchPortId(endpoint.getSwitchPortId()).build();
+
+ if(add) {
+ mdsal.put(LogicalDatastoreType.OPERATIONAL, LABEL_IID, mplsLabel);
+ LOG.info("Add mpls label to operational datastore: {} for endpoint: {}", label, endpoint.getSiteName());
+ } else {
+ mdsal.delete(LogicalDatastoreType.OPERATIONAL, LABEL_IID);
+ LOG.info("Delete mpls label from operational datastore: {} for endpoint: {}", label, endpoint.getSiteName());
+ }
+ }
+
+ /**
+ * Check if label is already allocated to any endpoint
+ * @param nextUniqueLabel :value of mpls label
+ * @return :true is label is already used else false
+ */
+ private boolean checkIsLabelUsed(Long nextUniqueLabel) {
+ Map<Long, String> labelMap = getAllLabels();
+ if(labelMap.containsKey(nextUniqueLabel)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get a map of all the labels allocated to the endpoints
+ * @return :hashmap of labels as key, site names as value
+ */
+ private Map<Long, String> getAllLabels() {
+ Map<Long, String> labelMap = new HashMap<>();
+ MplsLabels mplsLabels = mdsal.read(LogicalDatastoreType.OPERATIONAL, MPLS_LABELS_IID);
+ if(mplsLabels != null) {
+ for (Label label : mplsLabels.getLabel()) {
+ labelMap.put(label.getLabelId(), label.getSiteName());
+ }
+ }
+ return labelMap;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.AddVpnEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.FailoverType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnintentService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntentsKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class VpnintentProvider implements VpnintentService, BindingAwareProvider, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VpnintentProvider.class);
+ public static final InstanceIdentifier<MplsLabels> LABELS_IID = IidFactory.getMplsLabelsIid();
+ public static final InstanceIdentifier<Vpns> VPN_IID = IidFactory.getVpnsIid();
+ public static final InstanceIdentifier<VpnIntents> VPN_INTENT_IID = IidFactory.getVpnIntentIid();
+ public static final InstanceIdentifier<Endpoint> ENDPOINT_IID = IidFactory.getEndpointIid();
+
+ private DataBroker dataBroker;
+ private IntentMappingService intentMappingService;
+ private BindingAwareBroker.RpcRegistration<VpnintentService> rpcRegistration = null;
+ private MdsalUtils mdsal;
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("VpnintentProvider Session Initiated");
+ dataBroker = session.getSALService(DataBroker.class);
+ rpcRegistration = session.addRpcImplementation(VpnintentService.class, this);
+ this.mdsal = new MdsalUtils(this.dataBroker);
+
+ // Load IntentMappingService Reference
+ loadIntentMappingServiceReference();
+
+ Vpns vpns = new VpnsBuilder().build();
+ MplsLabels labels = new MplsLabelsBuilder().build();
+
+ // Initialize MD-SAL data store for vpn-intents and mpls-labels
+ initDatastore(LogicalDatastoreType.CONFIGURATION, VPN_IID, vpns);
+ initDatastore(LogicalDatastoreType.OPERATIONAL, LABELS_IID, labels);
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("VpnintentProvider Closed");
+ }
+
+ private <T extends DataObject> void initDatastore(LogicalDatastoreType store, InstanceIdentifier<T> iid, T object) {
+ // Put data to MD-SAL data store
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ transaction.put(store, iid, object);
+
+ // Perform the tx.submit asynchronously
+ Futures.addCallback(transaction.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ LOG.info("initDatastore for VPN-Intents: transaction succeeded");
+ }
+
+ @Override
+ public void onFailure(final Throwable throwable) {
+ LOG.error("initDatastore for VPN-Intents: transaction failed");
+ }
+ });
+ LOG.info("initDatastore: data populated: {}, {}, {}", store, iid, object);
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeVpn(RemoveVpnInput input) {
+ InstanceIdentifier<VpnIntents> vpnIdentifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(input.getVpnName())).build();
+ MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
+ MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+
+ VpnIntents vpn = getVpn(input.getVpnName());
+
+ if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
+ for (Endpoint endpoint : vpn.getEndpoint()) {
+ // Release MPLS label
+ mplsManager.deleteLabel(endpoint);
+
+ // Remove all intents related to this endpoint
+ IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+ intentManager.removeIntentsByEndpoint(endpoint.getSiteName());
+
+ // Remove info from Mapping Service
+ msManager.delete(endpoint.getSiteName());
+ }
+ }
+
+ mdsal.delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+ LOG.info("Deleted VPN {}", input.getVpnName());
+ return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+ }
+
+ @Override
+ public Future<RpcResult<Void>> addVpnEndpoint(AddVpnEndpointInput input) {
+ Endpoint currentEndpoint = new EndpointBuilder().setIpPrefix(input.getIpPrefix())
+ .setSiteName(input.getSiteName()).setSwitchPortId(input.getSwitchPortId())
+ .setKey(new EndpointKey(input.getSiteName())).build();
+ VpnIntents vpn = getVpn(input.getVpnName());
+ String failOverType = null;
+ if (vpn.isPathProtection() && vpn.getFailoverType()!= null) {
+ if (vpn.getFailoverType().equals(FailoverType.FastReroute)) {
+ failOverType = IntentServiceManager.FAST_REROUTE;
+ } else if(vpn.getFailoverType().equals(FailoverType.SlowReroute)) {
+ failOverType = IntentServiceManager.SLOW_REROUTE;
+ }
+ }
+
+ MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+
+ // Get unique MPLS label
+ Long mplsLabel = mplsManager.getUniqueLabel(currentEndpoint);
+
+ // Add info into Mapping Service
+ MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
+ msManager.add(currentEndpoint.getSiteName(), extractIP(currentEndpoint.getIpPrefix()),
+ currentEndpoint.getSwitchPortId(), mplsLabel, null);
+
+ if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
+ IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+
+ for (Endpoint member : vpn.getEndpoint()) {
+ // Create mesh of Intents
+ intentManager.addIntent(member.getSiteName(), currentEndpoint.getSiteName(),
+ IntentServiceManager.ACTION_ALLOW, failOverType);
+ intentManager.addIntent(currentEndpoint.getSiteName(), member.getSiteName(),
+ IntentServiceManager.ACTION_ALLOW, failOverType);
+ }
+ }
+ // Associate endpoint with VPN
+ addEndpointToVpn(vpn, currentEndpoint);
+
+ return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+ }
+
+ /**
+ * @param IpPrefix
+ * object
+ * @return String representation of IP prefix
+ */
+ private String extractIP(IpPrefix ipPrefix) {
+ String ip = null;
+ if (ipPrefix.getIpv4Prefix() != null) {
+ ip = ipPrefix.getIpv4Prefix().getValue();
+ } else if (ipPrefix.getIpv6Prefix() != null) {
+ ip = ipPrefix.getIpv6Prefix().getValue();
+ }
+ return ip;
+ }
+
+ /**
+ * @param vpnName
+ * VPN name
+ * @return VPN instance
+ */
+ private VpnIntents getVpn(String vpnName) {
+ InstanceIdentifier<VpnIntents> identifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(vpnName)).build();
+
+ VpnIntents vpnIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, identifier);
+ Preconditions.checkNotNull(vpnIntents);
+ return vpnIntents;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeVpnEndpoint(RemoveVpnEndpointInput input) {
+ Endpoint endpoint = getEndpoint(input.getVpnName(), input.getSiteName());
+
+ // Release MPLS label
+ MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+ mplsManager.deleteLabel(endpoint);
+
+ // Remove all intents related to this endpoint
+ IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+ intentManager.removeIntentsByEndpoint(input.getSiteName());
+
+ // Remove endpoint from VPN
+ removeEndpointFromVpn(input.getVpnName(), input.getSiteName());
+
+ return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+ }
+
+ /**
+ * @param siteName
+ * Site name of the VPN member
+ * @return VPN member (Endpoint)
+ */
+ private Endpoint getEndpoint(String vpnName, String siteName) {
+ InstanceIdentifier<Endpoint> endpointID = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
+ .build();
+
+ return mdsal.read(LogicalDatastoreType.CONFIGURATION, endpointID);
+ }
+
+ /**
+ * @param vpnName
+ * VPN name
+ * @param siteName
+ * Site name
+ */
+ private void removeEndpointFromVpn(String vpnName, String siteName) {
+ InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
+ .build();
+
+ mdsal.delete(LogicalDatastoreType.CONFIGURATION, identifier);
+ LOG.info("Deleted VPN member : {} from VPN: {}", siteName, vpnName);
+ }
+
+ /**
+ * @param vpn
+ * VPN
+ * @param vpnMember
+ * VPN member (endpoint)
+ */
+ private void addEndpointToVpn(VpnIntents vpn, Endpoint vpnMember) {
+ InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, vpn.getKey())
+ .child(Endpoint.class, vpnMember.getKey()).build();
+
+ mdsal.put(LogicalDatastoreType.CONFIGURATION, identifier, vpnMember);
+ LOG.info("Added VPN member : {} to VPN: {}", vpnMember.getSiteName(), vpn.getVpnName());
+ }
+
+ /**
+ * Load IntentMappingService reference
+ */
+ private void loadIntentMappingServiceReference() {
+ ServiceReference<?> serviceReference = getBundleCtx().getServiceReference(IntentMappingService.class);
+ intentMappingService = (IntentMappingService) getBundleCtx().getService(serviceReference);
+ }
+
+ private BundleContext getBundleCtx() {
+ return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.utils;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IidFactory {
+
+ public static InstanceIdentifier<MplsLabels> getMplsLabelsIid() {
+ return InstanceIdentifier.builder(MplsLabels.class).build();
+ }
+
+ public static InstanceIdentifier<Label> getLabelIid(Long label) {
+ return InstanceIdentifier.create(MplsLabels.class).child(Label.class, new LabelKey(label));
+ }
+
+ public static InstanceIdentifier<Intents> getIntentsIid() {
+ return InstanceIdentifier.builder(Intents.class).build();
+ }
+
+ public static InstanceIdentifier<Vpns> getVpnsIid() {
+ return InstanceIdentifier.builder(Vpns.class).build();
+ }
+
+ public static InstanceIdentifier<VpnIntents> getVpnIntentIid() {
+ return InstanceIdentifier.builder(Vpns.class).child(VpnIntents.class).build();
+ }
+
+ public static InstanceIdentifier<Endpoint> getEndpointIid() {
+ return InstanceIdentifier.builder(Vpns.class).child(VpnIntents.class).child(Endpoint.class).build();
+ }
+}
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210;
+
+import org.opendaylight.vpnservice.impl.VpnintentProvider;
+
+public class VpnintentImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.AbstractVpnintentImplModule {
+ public VpnintentImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public VpnintentImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.VpnintentImplModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ VpnintentProvider provider = new VpnintentProvider();
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: vpnintent-impl yang module local name: vpnintent-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Dec 16 22:44:32 EST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210;
+public class VpnintentImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.AbstractVpnintentImplModuleFactory {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+ */
+module vpnintent-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:vpnintent:impl";
+ prefix "vpnintent-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+ description
+ "Service definition for vpnintent project";
+
+ revision "2014-12-10" {
+ description
+ "Initial revision";
+ }
+
+ identity vpnintent-impl {
+ base config:module-type;
+ config:java-name-prefix VpnintentImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case vpnintent-impl {
+ when "/config:modules/config:module/config:type = 'vpnintent-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@PrepareForTest({IntentServiceManager.class})
+@RunWith(PowerMockRunner.class)
+public class IntentServiceManagerTest {
+
+ private static final String SRC_SITE_NAME = "site a";
+ private static final String DST_SITE_NAME = "site b";
+ private static final String INTENT_ALLOW_ACTION = "ALLOW";
+ private IntentServiceManager intentServiceManager;
+ @Mock private MdsalUtils mdsal;
+
+ @Before
+ public void setUp() throws Exception {
+ intentServiceManager = mock(IntentServiceManager.class, Mockito.CALLS_REAL_METHODS);
+ MemberModifier.field(IntentServiceManager.class, "mdsal").set(intentServiceManager, mdsal);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testAddIntent() throws Exception {
+ IntentBuilder intentBldr = mock(IntentBuilder.class);
+ PowerMockito.whenNew(IntentBuilder.class).withNoArguments().thenReturn(intentBldr);
+ when(intentBldr.setId(any(Uuid.class))).thenReturn(intentBldr);
+ when(intentBldr.setSubjects(any(List.class))).thenReturn(intentBldr);
+ when(intentBldr.setActions(any(List.class))).thenReturn(intentBldr);
+ when(intentBldr.setConstraints(any(List.class))).thenReturn(intentBldr);
+ when(intentBldr.build()).thenReturn(mock(Intent.class));
+
+ Intents currentIntents = mock(Intents.class);
+ PowerMockito.when(mdsal.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(currentIntents);
+ IntentsBuilder intentsBldr = mock(IntentsBuilder.class);
+ PowerMockito.whenNew(IntentsBuilder.class).withNoArguments().thenReturn(intentsBldr);
+ when(intentsBldr.setIntent(any(List.class))).thenReturn(intentsBldr);
+ PowerMockito.when(mdsal.put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Intents.class))).thenReturn(true);
+
+ intentServiceManager.addIntent(SRC_SITE_NAME, DST_SITE_NAME, INTENT_ALLOW_ACTION, "fast-reroute");
+ verify(intentBldr).setId(any(Uuid.class));
+ verify(mdsal).read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+ verify(mdsal).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Intents.class));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRemoveIntents() {
+ Uuid id = mock(Uuid.class);
+ when(mdsal.delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(true);
+
+ intentServiceManager.removeIntent(id);
+ verify(mdsal).delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+
+public class MappingServiceManagerTests {
+
+ @Test
+ public void addInfo() {
+ // Arrange
+ String siteName = "UoR";
+ String ipPrefix = "16.101.233.2/8";
+ String switchPortId = "openflow:1:3";
+ long mplsLabel = 10L;
+ String nextHop = "16.101.233.1/8";
+
+ Map<String, String> map = new HashMap<>();
+ map.put("ip_prefix", ipPrefix);
+ map.put("switch_port", switchPortId);
+ map.put("mpls_label", String.valueOf(mplsLabel));
+ map.put("next_hop", nextHop);
+
+ IntentMappingService mapSvc = mock(IntentMappingService.class);
+ when(mapSvc.get(any(String.class))).thenReturn(map);
+
+ MappingServiceManager manager = new MappingServiceManager(mapSvc);
+
+ // Act
+ manager.add(siteName, ipPrefix, switchPortId, mplsLabel, nextHop);
+
+ Map<String, String> returnedObjs = manager.get(siteName);
+
+ // Assert
+ assertEquals(ipPrefix, returnedObjs.get("ip_prefix"));
+ assertEquals(switchPortId, returnedObjs.get("switch_port"));
+ assertEquals(mplsLabel, Long.parseLong(returnedObjs.get("mpls_label")));
+ assertEquals(nextHop, returnedObjs.get("next_hop"));
+ }
+
+ @Test
+ public void removeInfo() {
+ // Arrange
+ String siteName = "UoR";
+ String ipPrefix = "16.101.233.2/8";
+ String switchPortId = "openflow:1:3";
+
+ Map<String, String> map = new HashMap<>();
+ map.put("ip_prefix", ipPrefix);
+ map.put("switch_port", switchPortId);
+
+ IntentMappingService mapSvc = mock(IntentMappingService.class);
+
+ MappingServiceManager manager = new MappingServiceManager(mapSvc);
+
+ // Add first to delete next
+ manager.add(siteName, ipPrefix, switchPortId, null, null);
+
+ // Act
+ boolean result = manager.delete(siteName);
+
+ // Assert
+ assertTrue(result);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.vpnservice.impl;
+
+import static org.mockito.Mockito.mock;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+public class VpnintentProviderTest {
+ @Ignore
+ @Test
+ public void testOnSessionInitiated() {
+ VpnintentProvider provider = new VpnintentProvider();
+
+ // ensure no exceptions
+ // currently this method is empty
+ provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
+ }
+
+ @Ignore
+ @Test
+ public void testClose() throws Exception {
+ VpnintentProvider provider = new VpnintentProvider();
+
+ // ensure no exceptions
+ // currently this method is empty
+ provider.close();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnintent-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>vpnintent</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>api</module>
+ <module>impl</module>
+ </modules>
+ <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
--- /dev/null
+{
+ "id": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "name": "VPN Intents",
+ "description": "Apply protection and failover-type constraints to VpnService and NIC. When protections is set to true, and failover type is either soft-reroute or hard-reroute then the end-to-end connectivity is self-healing in case of link/node failure. VpnService shall create Intent object with constraints embedded in it (constraints are set by users) and NIC renders flows according based on the constraints.\n\nDisjoint Path Calculation using Suurballe Algorithm when soft-reroute constraint is applied to NIC, two disjoint paths are calculated. When one of the paths is non-usable due to a link/node failure the other disjoint path is automatically invoked to push required flows for all the intents that get affection by the failed path.\n\nDelete flows from the switch when an intent is removed: NIC did not support deleting flows from the nodes when an intent was removed, this was also fixed.",
+ "order": [],
+ "folders": [
+ {
+ "id": "d424223b-11b7-b00d-3875-70b5fb4e6e85",
+ "name": "Add Members to VPN",
+ "description": "",
+ "order": [
+ "bfcc70b5-208a-d64e-7277-f4174b5f9ff9",
+ "45328601-ed77-b7ff-0ae6-c5734c69c170",
+ "84f7e114-532c-02d4-45fa-6e335f2a7e5d",
+ "6421391f-20de-e31b-00a4-5cf36297c074"
+ ],
+ "owner": "255113",
+ "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+ },
+ {
+ "id": "2049f3c6-ebf5-a456-61de-ee9abd1811f4",
+ "name": "Create VPN",
+ "description": "",
+ "order": [
+ "e5f75d2a-c350-e601-5029-e6e5ea736eef",
+ "91d91020-d5e0-2aaf-6c09-ed9cdec077de",
+ "72ac6ee2-90a8-36b1-0dda-9eb886df197c"
+ ],
+ "owner": "255113",
+ "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+ },
+ {
+ "id": "a2deb454-a0e6-3870-0c64-ba7fdffaccba",
+ "name": "MPLS Label Management",
+ "description": "Includes a set of GET operations to access the labels assigned to each member",
+ "order": [
+ "e7ba99ee-7804-d411-e652-9d932687a35c"
+ ],
+ "owner": "255113",
+ "collectionId": "efd3dae9-0818-468a-0d86-86fcec008d22"
+ },
+ {
+ "id": "118a7d9f-7925-4e75-d59a-f9c151b1c4c4",
+ "name": "Network Intent Composition Operations",
+ "description": "GET operations to check the state of Intents",
+ "order": [
+ "109d1ae7-bdd4-907e-be5d-61b6f493640b"
+ ],
+ "owner": "255113",
+ "collectionId": "748af960-874f-028d-cbd0-74134a3c6db7"
+ },
+ {
+ "id": "3ab1d430-5cc5-f506-0619-b827cc6f645b",
+ "name": "Remove Member from VPN",
+ "description": "",
+ "order": [
+ "d3250d1d-ca8d-9a31-dec7-4ded8720e530",
+ "42034ad0-1789-a773-6be3-9b9b5c4881bf",
+ "13757df8-f5ea-c933-a991-b9a8e4d60b07",
+ "0063438d-94b1-5ca3-88f2-1d789f3d2251"
+ ],
+ "owner": "255113",
+ "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+ },
+ {
+ "id": "3958cf6c-b82e-f0d4-a5c3-ce0bb85464c7",
+ "name": "Remove VPN",
+ "description": "",
+ "order": [
+ "63050e81-9cac-5de5-2180-7ed5c6bd361a",
+ "b0ac20bf-7cad-e958-761c-a83a456afdd4"
+ ],
+ "owner": "255113"
+ }
+ ],
+ "timestamp": 1450878947771,
+ "owner": "255113",
+ "remoteLink": "",
+ "public": false,
+ "requests": [
+ {
+ "id": "0063438d-94b1-5ca3-88f2-1d789f3d2251",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741595237,
+ "name": "Remove Member 4 (site 4) from unprotected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 4\"\n }\n}"
+ },
+ {
+ "id": "109d1ae7-bdd4-907e-be5d-61b6f493640b",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/intent:intents/",
+ "pathVariables": {},
+ "preRequestScript": "",
+ "method": "GET",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "data": [],
+ "dataMode": "params",
+ "name": "GET intents",
+ "description": "Gets a list of intents added",
+ "descriptionFormat": "html",
+ "time": 1450721033712,
+ "version": 2,
+ "responses": [],
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "folder": "118a7d9f-7925-4e75-d59a-f9c151b1c4c4"
+ },
+ {
+ "id": "13757df8-f5ea-c933-a991-b9a8e4d60b07",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741569695,
+ "name": "Remove Member 3 (site 3) from unprotected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 3\"\n }\n}"
+ },
+ {
+ "id": "42034ad0-1789-a773-6be3-9b9b5c4881bf",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741544712,
+ "name": "Remove Member 2 (site 2) from protected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 2\"\n }\n}"
+ },
+ {
+ "id": "45328601-ed77-b7ff-0ae6-c5734c69c170",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741386479,
+ "name": "Add Member 2 (site 2) to protected VPN",
+ "description": "Add a Member to a protected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 2\",\n \"ip-prefix\": \"10.0.0.2/32\",\n \"switch-port-id\": \"openflow:2:1\"\n }\n}"
+ },
+ {
+ "id": "63050e81-9cac-5de5-2180-7ed5c6bd361a",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741509183,
+ "name": "Remove protected VPN",
+ "description": "Delete a VPN\n\nParameters description\nvpn-name: The VPN that needs to be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\"\n }\n}"
+ },
+ {
+ "id": "6421391f-20de-e31b-00a4-5cf36297c074",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741358417,
+ "name": "Add Member 4 (site 4) to unprotected VPN",
+ "description": "Add a Member to an unprotected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 4\",\n \"ip-prefix\": \"10.0.0.4/32\",\n \"switch-port-id\": \"openflow:4:1\"\n }\n}"
+ },
+ {
+ "id": "72ac6ee2-90a8-36b1-0dda-9eb886df197c",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+ "pathVariables": {},
+ "preRequestScript": "",
+ "method": "GET",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "data": [],
+ "dataMode": "params",
+ "name": "GET VPNs",
+ "description": "Gets a list of all the VPNs along with the list of members that belong to these VPNs",
+ "descriptionFormat": "html",
+ "time": 1450716801343,
+ "version": 2,
+ "responses": [],
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "folder": "2049f3c6-ebf5-a456-61de-ee9abd1811f4"
+ },
+ {
+ "id": "84f7e114-532c-02d4-45fa-6e335f2a7e5d",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741323406,
+ "name": "Add Member 3 (site 3) to unprotected VPN",
+ "description": "Add a Member to an unprotected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 3\",\n \"ip-prefix\": \"10.0.0.1/32\",\n \"switch-port-id\": \"openflow:3:1\"\n }\n}"
+ },
+ {
+ "id": "91d91020-d5e0-2aaf-6c09-ed9cdec077de",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741250149,
+ "name": "Create an unprotected VPN",
+ "description": "Create a protected VPN by pushing to config data tree to the Vpn-intents Yang model\n\nParameters description\nvpn-name: The name of the VPN that you intend to create\nprotection: True if path protection is needed\nfailover-type: Type of failover mechanism\n - slow-reroute\n - fast-reroute",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"vpn-intents\": [\n {\n \"vpn-name\": \"VPN unprotected\",\n \"path-protection\": \"false\",\n \"failover-type\": \"slow-reroute\"\n }\n ]\n}"
+ },
+ {
+ "id": "b0ac20bf-7cad-e958-761c-a83a456afdd4",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741501187,
+ "name": "Remove unprotected VPN",
+ "description": "Delete a VPN\n\nParameters description\nvpn-name: The VPN that needs to be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\"\n }\n}"
+ },
+ {
+ "id": "bfcc70b5-208a-d64e-7277-f4174b5f9ff9",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741369995,
+ "name": "Add Member 1 (site 1) to protected VPN",
+ "description": "Add a Member to a protected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 1\",\n \"ip-prefix\": \"10.0.0.1/32\",\n \"switch-port-id\": \"openflow:1:1\"\n }\n}"
+ },
+ {
+ "id": "d3250d1d-ca8d-9a31-dec7-4ded8720e530",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741522615,
+ "name": "Remove Member 1 (site 1) from protected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 1\"\n }\n}"
+ },
+ {
+ "id": "e5f75d2a-c350-e601-5029-e6e5ea736eef",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741238916,
+ "name": "Create a protected VPN",
+ "description": "Create a protected VPN by pushing to config data tree to the Vpn-intents Yang model\n\nParameters description\nvpn-name: The name of the VPN that you intend to create\nprotection: True if path protection is needed\nfailover-type: Type of failover mechanism\n - slow-reroute\n - fast-reroute",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"vpn-intents\": [\n {\n \"vpn-name\": \"VPN protected\",\n \"path-protection\": \"true\",\n \"failover-type\": \"slow-reroute\"\n }\n ]\n}"
+ },
+ {
+ "id": "e7ba99ee-7804-d411-e652-9d932687a35c",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operational/vpnintent:mpls-labels",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "GET",
+ "data": [],
+ "dataMode": "params",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452282516268,
+ "name": "GET all unique MPLS Labels",
+ "description": "Gets a list of unique labels assigned to every Member in the VPN",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "folder": "a2deb454-a0e6-3870-0c64-ba7fdffaccba"
+ }
+ ]
+}
\ No newline at end of file
}
}
+ container vpn-to-extraroute {
+ config false;
+ list vpn {
+ key vrf-id;
+ leaf vrf-id {
+ description
+ "The vrf-id command configures a route distinguisher (RD)
+ for the IPv4 or IPv6 address family of a VPN instance or
+ vpn instance name for internal vpn case.";
+ type string;
+ }
+ list extraroute {
+ key prefix;
+ leaf prefix {type string;}
+ leaf nexthop-ip {
+ type string;
+ }
+ }
+ }
+ }
+
/* Data models to adhere to restart requirements */
container vpn-instance-to-vpn-id {
list vpn-instance {
type string;
}
+ leaf vpn-interface-count { type uint32; }
uses vpn-route-list;
list vpn-to-dpn-list {
key dpnId;
LOG.info("Received port UP event for interface {} ", interfaceName);
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
configInterface = InterfaceUtils.getInterface(broker, interfaceName);
+ BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
if (configInterface != null && configInterface.getType().equals(Tunnel.class)) {
- BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
if(intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
//advertise all prefixes in all vpns for this dpn to bgp
vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
}
} else {
- vpnInterfaceManager.processVpnInterfaceUp(interfaceName, intrf.getIfIndex());
+ vpnInterfaceManager.processVpnInterfaceUp(dpnId, interfaceName, intrf.getIfIndex());
}
} catch (Exception e) {
LOG.error("Exception caught in Interface Operational State Up event", e);
LOG.info("Received port DOWN event for interface {} ", interfaceName);
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
intf = InterfaceUtils.getInterface(broker, interfaceName);
+ BigInteger dpId = InterfaceUtils.getDpIdFromInterface(intrf);
if (intf != null && intf.getType().equals(Tunnel.class)) {
- // Get the dpId from del reference itself. Because interfaceManager.getDpnForInterface returns
- // NPE because entry is already deleted in operational data store
- BigInteger dpId = getDpIdFromInterface(intrf);
- if (dpId == null) {
- return;
- }
if(intrf.getOperStatus().equals(Interface.OperStatus.Down)) {
//withdraw all prefixes in all vpns for this dpn from bgp
vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
}
} else {
if (VpnUtil.isVpnInterfaceConfigured(broker, interfaceName)) {
- vpnInterfaceManager.processVpnInterfaceDown(interfaceName, intrf.getIfIndex(), true);
+ vpnInterfaceManager.processVpnInterfaceDown(dpId, interfaceName, intrf.getIfIndex(), true);
}
}
} catch (Exception e) {
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
intf = InterfaceUtils.getInterface(broker, interfaceName);
if (intf != null && intf.getType().equals(Tunnel.class)) {
- BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
+ BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
if(update.getOperStatus().equals(Interface.OperStatus.Up)) {
//advertise all prefixes in all vpns for this dpn to bgp
vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
}
- public BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface infState) {
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
- InterfaceUtils.getInterfaceStateFromOperDS(broker, infState.getName());
- String lowerLayerIf = ifState.getLowerLayerIf().get(0);
- NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
- return new BigInteger(InterfaceUtils.getDpnFromNodeConnectorId(nodeConnectorId));
- }
-
}
public static final BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
public static final BigInteger COOKIE_L3_BASE = new BigInteger("8000000", 16);
public static final String FLOWID_PREFIX = "L3.";
+ public static final long WAIT_TIME_IN_MILLISECONDS = 5000;
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
-import java.util.concurrent.Future;
+import java.util.concurrent.*;
import com.google.common.base.Optional;
public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration;
+ private ConcurrentMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
+ private ExecutorService executorService = Executors.newSingleThreadExecutor();
private final DataBroker broker;
private final IBgpManager bgpManager;
private IFibManager fibManager;
private IdManagerService idManager;
private OdlArputilService arpManager;
private InterfaceStateChangeListener interfaceListener;
+ private VpnInterfaceOpListener vpnInterfaceOpListener;
private ArpNotificationHandler arpNotificationHandler;
protected enum UpdateRouteAction {
ADVERTISE_ROUTE, WITHDRAW_ROUTE
broker = db;
this.bgpManager = bgpManager;
interfaceListener = new InterfaceStateChangeListener(db, this);
+ vpnInterfaceOpListener = new VpnInterfaceOpListener();
arpNotificationHandler = new ArpNotificationHandler(this, broker);
notificationService.registerNotificationListener(arpNotificationHandler);
registerListener(db);
if (listenerRegistration != null) {
try {
listenerRegistration.close();
+ opListenerRegistration.close();
} catch (final Exception e) {
LOG.error("Error when cleaning up DataChangeListener.", e);
}
listenerRegistration = null;
+ opListenerRegistration = null;
}
LOG.info("VPN Interface Manager Closed");
}
try {
listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
+ opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
} catch (final Exception e) {
LOG.error("VPN Service DataChange listener registration fail!", e);
throw new IllegalStateException("VPN Service registration Listener failed.", e);
@Override
protected void add(final InstanceIdentifier<VpnInterface> identifier,
final VpnInterface vpnInterface) {
- LOG.trace("key: {} , value: {}", identifier, vpnInterface );
+ LOG.trace("VPN Interface key: {} , value: {}", identifier, vpnInterface );
addInterface(identifier, vpnInterface);
}
private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
final VpnInterface vpnInterface) {
- LOG.trace("Add event - key: {}, value: {}" ,identifier, vpnInterface );
+ LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
String interfaceName = key.getName();
InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
if (interfaceState != null) {
// Interface state is up
- processVpnInterfaceUp(interfaceName, interfaceState.getIfIndex());
+ processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex());
+ } else {
+ LOG.trace("VPN interfaces are not yet operational.");
}
}
- protected synchronized void processVpnInterfaceUp(String interfaceName, int lPortTag) {
+ protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag) {
VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
if(vpnInterface == null) {
}
String vpnName = vpnInterface.getVpnInstanceName();
LOG.info("Binding vpn service to interface {} ", interfaceName);
- bindService(vpnName, interfaceName, lPortTag);
- updateDpnDbs(vpnName, interfaceName, true);
- processVpnInterfaceAdjacencies(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+ long vpnId = VpnUtil.getVpnId(broker, vpnName);
+ if (vpnId == VpnConstants.INVALID_ID) {
+ LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
+ return;
+ }
+ if (VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName()) != null) {
+ LOG.trace("VPN Interface already provisioned , bailing out from here.");
+ return;
+ }
+ synchronized (interfaceName.intern()) {
+
+ bindService(dpId, vpnName, interfaceName, lPortTag);
+ updateDpnDbs(vpnName, interfaceName, true);
+ processVpnInterfaceAdjacencies(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+ }
}
}
- private void bindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+ private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
- makeArpFlow(VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName, vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
+ makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+ vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
}
}
}
- private void makeArpFlow(short sIndex, int lPortTag, String vpnInterfaceName, long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
+ private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
+ long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
List<MatchInfo> matches = new ArrayList<MatchInfo>();
BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
// Install the flow entry in L3_INTERFACE_TABLE
- BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
FlowEntity flowEntity;
} else {
VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
VpnUtil.getVpnInstanceOpDataIdentifier(rd),
- VpnUtil.getVpnInstanceOpData(rd, vpnId));
+ VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId));
VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
if (existingVpnInterface.isPresent() && interfaceState != null) {
- processVpnInterfaceDown(interfaceName, interfaceState.getIfIndex(), false);
+ processVpnInterfaceDown(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex(), false);
} else {
LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
}
}
- protected synchronized void processVpnInterfaceDown(String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
+ protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
if(vpnInterface == null) {
LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
String vpnName = vpnInterface.getVpnInstanceName();
InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
- removeAdjacenciesFromVpn(identifier, vpnInterface);
- LOG.info("Unbinding vpn service from interface {} ", interfaceName);
- unbindService(vpnName, interfaceName, lPortTag, isInterfaceStateDown);
- updateDpnDbs(vpnName, interfaceName, false);
- VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, identifier, VpnUtil.DEFAULT_CALLBACK);
+ synchronized (interfaceName.intern()) {
+ removeAdjacenciesFromVpn(identifier, vpnInterface);
+ LOG.info("Unbinding vpn service from interface {} ", interfaceName);
+ unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown);
+
+ //wait till DCN for removal of vpn interface in operational DS arrives
+ Runnable notifyTask = new VpnNotifyTask();
+ synchronized (interfaceName.intern()) {
+ vpnIntfMap.put(interfaceName, notifyTask);
+ synchronized (notifyTask) {
+ try {
+ notifyTask.wait(VpnConstants.WAIT_TIME_IN_MILLISECONDS);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ }
}
private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
for (Adjacency nextHop : nextHops) {
VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
- VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ /*VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
VpnUtil.getPrefixToInterfaceIdentifier(
VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
nextHop.getIpAddress()),
- VpnUtil.DEFAULT_CALLBACK);
+ VpnUtil.DEFAULT_CALLBACK);*/
if (rd.equals(intf.getVpnInstanceName())) {
//this is an internal vpn - the rd is assigned to the vpn instance name;
//remove from FIB directly
}
- private void unbindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag, boolean isInterfaceStateDown) {
+ private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
+ int lPortTag, boolean isInterfaceStateDown) {
if (!isInterfaceStateDown) {
VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
InterfaceUtils.buildServiceId(vpnInterfaceName,
VpnUtil.DEFAULT_CALLBACK);
}
long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
- makeArpFlow(VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+ makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
}
VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
setVrfEntry(vrfEntryList).build();
- VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, vrfTableNew);
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
}
public synchronized void removeFibEntryFromDS(String rd, String prefix) {
InstanceIdentifierBuilder<VrfEntry> idBuilder =
InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
- VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
+ VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
}
InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
- VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
+ VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
}
VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
- addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label);
+ addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label, currVpnIntf.getName());
}
}
- protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label) {
+ protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label, String intfName) {
+
+ //add extra route to vpn mapping; advertise with nexthop as tunnel ip
+ VpnUtil.syncUpdate(
+ broker,
+ LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnToExtrarouteIdentifier(
+ (rd != null) ? rd : routerID, destination),
+ VpnUtil.getVpnToExtraroute(destination, nextHop));
+
+ if(intfName != null && !intfName.isEmpty()) {
+ BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
+ String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
+ if (nextHopIp == null && !nextHopIp.isEmpty()) {
+ LOG.error("NextHop for interface {} is null. Failed adding extra route for prefix {}", intfName, destination);
+ return;
+ }
+ nextHop = nextHopIp;
+ }
if (rd != null) {
addPrefixToBGP(rd, destination, nextHop, label);
} else {
}
}
+ class VpnInterfaceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInterface> {
+
+ public VpnInterfaceOpListener() {
+ super(VpnInterface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
+ final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+ String interfaceName = key.getName();
+
+ //increment the vpn interface count in Vpn Instance Op Data
+ Long ifCnt = 0L;
+ String rd = getRouteDistinguisher(del.getVpnInstanceName());
+ if(rd.isEmpty()) rd = del.getVpnInstanceName();
+ VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
+ if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
+ ifCnt = vpnInstOp.getVpnInterfaceCount();
+ }
+
+ LOG.trace("VpnInterfaceOpListener remove: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
+
+ VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
+
+ //TODO: Clean up the DPN List in Vpn Instance Op if ifCnt is zero
+
+ notifyTaskIfRequired(interfaceName);
+ }
+
+ private void notifyTaskIfRequired(String intfName) {
+ Runnable notifyTask = vpnIntfMap.remove(intfName);
+ if (notifyTask == null) {
+ return;
+ }
+ executorService.execute(notifyTask);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
+ final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+ String interfaceName = key.getName();
+
+ //increment the vpn interface count in Vpn Instance Op Data
+ Long ifCnt = 0L;
+ String rd = getRouteDistinguisher(add.getVpnInstanceName());
+ if(rd.isEmpty()) rd = add.getVpnInstanceName();
+ VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
+ if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
+ ifCnt = vpnInstOp.getVpnInterfaceCount();
+ }
+
+ LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
+
+ VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
+
+
+ }
+ }
+
protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.*;
+import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.bgpmanager.api.IBgpManager;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnIdBuilder;
public class VpnManager extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(VpnManager.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration, fibListenerRegistration;
+ private ListenerRegistration<DataChangeListener> listenerRegistration, fibListenerRegistration, opListenerRegistration;
+ private ConcurrentMap<String, Runnable> vpnOpMap = new ConcurrentHashMap<String, Runnable>();
+ private ExecutorService executorService = Executors.newSingleThreadExecutor();
private final DataBroker broker;
private final IBgpManager bgpManager;
private IdManagerService idManager;
private VpnInterfaceManager vpnInterfaceManager;
private final FibEntriesListener fibListener;
+ private final VpnInstanceOpListener vpnInstOpListener;
private static final FutureCallback<Void> DEFAULT_CALLBACK =
new FutureCallback<Void>() {
broker = db;
this.bgpManager = bgpManager;
this.fibListener = new FibEntriesListener();
+ this.vpnInstOpListener = new VpnInstanceOpListener();
registerListener(db);
}
getWildCardPath(), VpnManager.this, DataChangeScope.SUBTREE);
fibListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
getFibEntryListenerPath(), fibListener, DataChangeScope.BASE);
+ opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getVpnInstanceOpListenerPath(), vpnInstOpListener, DataChangeScope.SUBTREE);
+
} catch (final Exception e) {
LOG.error("VPN Service DataChange listener registration fail !", e);
throw new IllegalStateException("VPN Service registration Listener failed.", e);
this.vpnInterfaceManager = vpnInterfaceManager;
}
+ private void waitForOpDataRemoval(String id) {
+ //wait till DCN for removal of all DPNs in VPN arrivaes
+ Runnable notifyTask = new VpnNotifyTask();
+ synchronized (id.intern()) {
+ vpnOpMap.put(id, notifyTask);
+ synchronized (notifyTask) {
+ try {
+ notifyTask.wait(VpnConstants.WAIT_TIME_IN_MILLISECONDS);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ }
+
@Override
protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
LOG.trace("Remove VPN event - Key: {}, value: {}", identifier, del);
if (rd !=null) {
- delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd));
try {
bgpManager.deleteVrf(rd);
- } catch(Exception e) {
+ } catch (Exception e) {
LOG.error("Exception when removing VRF from BGP", e);
}
+ waitForOpDataRemoval(rd);
+ delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd));
} else {
+ waitForOpDataRemoval(vpnName);
delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
}
}
@Override
protected void add(InstanceIdentifier<VpnInstance> identifier,
VpnInstance value) {
- LOG.trace("key: {}, value: {}", identifier, value);
+ LOG.trace("VPN Instance key: {}, value: {}", identifier, value);
VpnAfConfig config = value.getIpv4Family();
String rd = config.getRouteDistinguisher();
long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, value.getVpnInstanceName());
-
+ LOG.trace("VPN instance to ID generated.");
org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(value.getVpnInstanceName(), vpnId,
(rd != null) ? rd : value.getVpnInstanceName());
- asyncWrite(LogicalDatastoreType.CONFIGURATION,
+ syncWrite(LogicalDatastoreType.CONFIGURATION,
VpnUtil.getVpnInstanceToVpnIdIdentifier(value.getVpnInstanceName()),
vpnInstanceToVpnId, DEFAULT_CALLBACK);
if(rd == null) {
- asyncWrite(LogicalDatastoreType.OPERATIONAL,
+ syncWrite(LogicalDatastoreType.OPERATIONAL,
VpnUtil.getVpnInstanceOpDataIdentifier(value.getVpnInstanceName()),
- VpnUtil.getVpnInstanceOpData(value.getVpnInstanceName(), vpnId), DEFAULT_CALLBACK);
+ VpnUtil.getVpnInstanceOpDataBuilder(value.getVpnInstanceName(), vpnId), DEFAULT_CALLBACK);
} else {
- asyncWrite(LogicalDatastoreType.OPERATIONAL,
+ syncWrite(LogicalDatastoreType.OPERATIONAL,
VpnUtil.getVpnInstanceOpDataIdentifier(rd),
- VpnUtil.getVpnInstanceOpData(rd, vpnId), DEFAULT_CALLBACK);
+ VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId), DEFAULT_CALLBACK);
List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
LOG.error("Exception when adding VRF to BGP", e);
}
}
+ //Try to add up vpn Interfaces if already in Operational Datastore
+ LOG.trace("Trying to add the vpn interfaces -1.");
+ InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
+ Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, vpnInterfacesId);
+
+ if(optionalVpnInterfaces.isPresent()) {
+ List<VpnInterface> vpnInterfaces = optionalVpnInterfaces.get().getVpnInterface();
+ for(VpnInterface vpnInterface : vpnInterfaces) {
+ if(vpnInterface.getVpnInstanceName().equals(value.getVpnInstanceName())) {
+ LOG.debug("VpnInterface {} will be added from VPN {}", vpnInterface.getName(), value.getVpnInstanceName());
+ vpnInterfaceManager.add(
+ VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+
+ }
+ }
+ }
}
private InstanceIdentifier<?> getWildCardPath() {
.child(VrfEntry.class);
}
+ private InstanceIdentifier<?> getVpnInstanceOpListenerPath() {
+ return InstanceIdentifier.create(VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class);
+
+ }
+
@Override
public void close() throws Exception {
if (listenerRegistration != null) {
}
fibListenerRegistration = null;
}
+ if (opListenerRegistration != null) {
+ try {
+ opListenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up VPN Instance Operational entries DataChangeListener.", e);
+ }
+ opListenerRegistration = null;
+ }
+
LOG.trace("VPN Manager Closed");
}
Futures.addCallback(tx.submit(), callback);
}
+ private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error writing VPN instance to ID info to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
}
}
}
+
+ class VpnInstanceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInstanceOpDataEntry> {
+
+ public VpnInstanceOpListener() {
+ super(VpnInstanceOpDataEntry.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry del) {
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry original, VpnInstanceOpDataEntry update) {
+ final VpnInstanceOpDataEntryKey key = identifier.firstKeyOf(VpnInstanceOpDataEntry.class, VpnInstanceOpDataEntryKey.class);
+ String vpnName = key.getVrfId();
+
+ LOG.trace("VpnInstanceOpListener update: vpn name {} interface count in Old VpnOp Instance {} in New VpnOp Instance {}" ,
+ vpnName, original.getVpnInterfaceCount(), update.getVpnInterfaceCount() );
+
+ //if((original.getVpnToDpnList().size() != update.getVpnToDpnList().size()) && (update.getVpnToDpnList().size() == 0)) {
+ if((original.getVpnInterfaceCount() != update.getVpnInterfaceCount()) && (update.getVpnInterfaceCount() == 0)) {
+ notifyTaskIfRequired(vpnName);
+ }
+ }
+
+ private void notifyTaskIfRequired(String vpnName) {
+ Runnable notifyTask = vpnOpMap.remove(vpnName);
+ if (notifyTask == null) {
+ return;
+ }
+ executorService.execute(notifyTask);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry add) {
+ }
+ }
}
--- /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.vpnservice;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class VpnNotifyTask implements Runnable{
+ private static final Logger logger = LoggerFactory.getLogger(VpnNotifyTask.class);
+
+ @Override
+ public void run() {
+ logger.debug("Notify Task is running for the task {}", this);
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
vpnInterfaceName).setIpAddress(ipPrefix).build();
}
+ static InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
+ return InstanceIdentifier.builder(VpnToExtraroute.class)
+ .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
+ new ExtrarouteKey(ipPrefix)).build();
+ }
+
+ static Extraroute getVpnToExtraroute(String ipPrefix, String nextHop) {
+ return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIp(nextHop).build();
+ }
+
static Adjacencies
getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
return new AdjacenciesBuilder().setAdjacency(nextHops).build();
.child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
}
- static VpnInstanceOpDataEntry getVpnInstanceOpData(String rd, long vpnId) {
+ static VpnInstanceOpDataEntry getVpnInstanceOpDataBuilder(String rd, long vpnId) {
return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).build();
}
+ static VpnInstanceOpDataEntry updateIntfCntInVpnInstOpData(Long count, String vrfId) {
+ return new VpnInstanceOpDataEntryBuilder().setVpnInterfaceCount(count).setVrfId(vrfId).build();
+ }
+
+ static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if(vpnInstanceOpData.isPresent()) {
+ return vpnInstanceOpData.get();
+ }
+ return null;
+ }
+
static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
@Override
public void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label) {
LOG.info("Adding extra route with destination {} and nexthop {}", destination, nextHop);
- vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label);
+ vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label, null);
}
@Override
String[] split = portId.getValue().split(OF_URI_SEPARATOR);
return split[1];
}
+
+ public static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
+ }
+
}