<?xml version="1.0" encoding="UTF-8"?>
<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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 INTERNAL
<artifactId>model-bgp</artifactId>
<version>2013.07.15.8-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>nexthopmgr-impl</artifactId>
- <version>${nexthopmgr.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>nexthopmgr-impl</artifactId>
- <version>${nexthopmgr.version}</version>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>nexthopmgr-api</artifactId>
- <version>${nexthopmgr.version}</version>
- </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>fibmanager-impl</artifactId>
<?xml version="1.0" encoding="UTF-8"?>
<!-- vi: set et smarttab sw=4 tabstop=4: -->
<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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,
<bundle>mvn:org.opendaylight.vpnservice/arputil-api/${arputil.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/alivenessmonitor-api/${vpnservices.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version}</bundle>
- <bundle>mvn:org.opendaylight.vpnservice/nexthopmgr-api/${nexthopmgr.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/fibmanager-api/${fibmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/itm-api/${itm.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/dhcpservice-api/${vpnservices.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/interfacemgr-api/${interfacemgr.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/interfacemgr-impl/${interfacemgr.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}</bundle>
- <bundle>mvn:org.opendaylight.vpnservice/nexthopmgr-impl/${nexthopmgr.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}</bundle>
<configfile finalname="arputil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/arputil-impl/${arputil.version}/xml/config</configfile>
<configfile finalname="alivenessmonitor-impl-default-config.xml">mvn:org.opendaylight.vpnservice/alivenessmonitor-impl/${vpnservices.version}/xml/config</configfile>
<configfile finalname="vpnmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}/xml/config</configfile>
- <configfile finalname="nexthopmgr-impl-default-config.xml">mvn:org.opendaylight.vpnservice/nexthopmgr-impl/${nexthopmgr.version}/xml/config</configfile>
<configfile finalname="fibmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/fibmanager-impl/${fibmanager.version}/xml/config</configfile>
<configfile finalname="itm-impl-default-config.xml">mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}/xml/config</configfile>
<configfile finalname="dhcpservice-impl-default-config.xml">mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}/xml/config</configfile>
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
package org.opendaylight.fibmanager.api;
import java.math.BigInteger;
+import java.util.List;
public interface IFibManager {
void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd);
void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd);
+ List<String> printFibEntries();
+ void addStaticRoute(String prefix, String nextHop, String rd, int label);
+ void deleteStaticRoute(String prefix, String rd);
}
--- /dev/null
+module l3nexthop {
+ namespace "urn:opendaylight:vpnservice:l3nexthop";
+ prefix l3nexthop;
+
+ revision "2015-04-09" {
+ description "L3 NextHop module";
+ }
+
+ container l3nexthop {
+ config false;
+ list vpnNexthops{
+ key "vpnId";
+ leaf vpnId {type uint32;}
+ list vpnNexthop{
+ key "IpAddress";
+ leaf IpAddress {type string;}
+ leaf egressPointer {type uint32;}
+ leaf dpnId {type uint64;}
+ leaf flowrefCount {type uint16; }
+ }
+ }
+ list tunnelNexthops{
+ key "dpnId";
+ leaf dpnId {type uint64;}
+ list tunnelNexthop{
+ key "IpAddress";
+ leaf IpAddress {type string;}
+ leaf egressPointer {type uint32;}
+ }
+ }
+ }
+}
\ No newline at end of file
</dependency>
<dependency>
<groupId>org.opendaylight.vpnservice</groupId>
- <artifactId>vpnmanager-impl</artifactId>
- <version>${vpnservices.version}</version>
+ <artifactId>itm-api</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.vpnservice</groupId>
</dependency>
<dependency>
<groupId>org.opendaylight.vpnservice</groupId>
- <artifactId>nexthopmgr-api</artifactId>
+ <artifactId>idmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
<version>${vpnservices.version}</version>
</dependency>
<dependency>
<?xml version="1.0" encoding="UTF-8"?>
<!-- vi: set et smarttab sw=4 tabstop=4: -->
<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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,
<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>
+ <rpcregistry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpcregistry>
<mdsalutil>
<type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
<name>mdsalutil-service</name>
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnmanager.api.IVpnManager;
-import org.opendaylight.vpnservice.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
import org.opendaylight.vpnservice.mdsalutil.ActionType;
import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
+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.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.prefix.to._interface.vpn.ids.PrefixesKey;
+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.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.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
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.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.GetEgressPointerInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.GetEgressPointerOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthopService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.RemoveLocalNextHopInputBuilder;
+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.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final String FLOWID_PREFIX = "L3.";
private ListenerRegistration<DataChangeListener> listenerRegistration;
private final DataBroker broker;
- private final L3nexthopService l3nexthopService;
private IMdsalApiManager mdsalManager;
private IVpnManager vpnmanager;
+ private NexthopManager nextHopManager;
+ private ItmRpcService itmManager;
+ private OdlInterfaceRpcService interfaceManager;
private static final short L3_FIB_TABLE = 21;
private static final short L3_LFIB_TABLE = 20;
+ private static final short L3_PROTOCOL_TABLE = 36;
+ private static final short L3_INTERFACE_TABLE = 80;
+ public static final short LPORT_DISPATCHER_TABLE = 30;
private static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
private static final BigInteger COOKIE_VM_FIB_TABLE = new BigInteger("8000003", 16);
private static final int DEFAULT_FIB_FLOW_PRIORITY = 10;
+ private static final BigInteger METADATA_MASK_CLEAR = new BigInteger("000000FFFFFFFFFF", 16);
+ private static final BigInteger CLEAR_METADATA = BigInteger.valueOf(0);
private static final FutureCallback<Void> DEFAULT_CALLBACK =
};
};
- public FibManager(final DataBroker db, final RpcService nextHopService) {
+ public FibManager(final DataBroker db) {
super(VrfEntry.class);
broker = db;
- l3nexthopService = (L3nexthopService)nextHopService;
registerListener(db);
}
LOG.info("Fib Manager Closed");
}
+ public void setNextHopManager(NexthopManager nextHopManager) {
+ this.nextHopManager = nextHopManager;
+ }
public void setMdsalManager(IMdsalApiManager mdsalManager) {
this.mdsalManager = mdsalManager;
this.vpnmanager = vpnmanager;
}
+ public void setITMRpcService(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
+ this.interfaceManager = ifManager;
+ }
+
private void registerListener(final DataBroker db) {
try {
listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
@Override
protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
LOG.trace("key: " + identifier + ", original=" + original + ", update=" + update );
+ createFibEntries(identifier, update);
}
private void createFibEntries(final InstanceIdentifier<VrfEntry> identifier,
Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
- Long vpnId = getVpnId(vrfTableKey.getRouteDistinguisher());
- Preconditions.checkNotNull(vpnId, "Vpn Instance not available!");
- Collection<BigInteger> dpns = vpnmanager.getDpnsForVpn(vpnId);
- for (BigInteger dpId : dpns) {
- addRouteInternal(dpId, vpnId, vrfTableKey, vrfEntry);
+ VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+ Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available!");
+ Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId() + "has null vpnId!");
+
+ Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+ if (vpnToDpnList != null) {
+ BigInteger localDpnId = createLocalFibEntry(vpnInstance.getVpnId(),
+ vrfTableKey.getRouteDistinguisher(), vrfEntry);
+ for (VpnToDpnList curDpn : vpnToDpnList) {
+ if (!curDpn.getDpnId().equals(localDpnId)) {
+ createRemoteFibEntry(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(),
+ vrfTableKey, vrfEntry);
+ }
+ }
}
}
- private void addRouteInternal(final BigInteger dpId, final long vpnId, final VrfTablesKey vrfTableKey,
- final VrfEntry vrfEntry) {
+ public BigInteger createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
+ BigInteger localDpnId = BigInteger.ZERO;
+ Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
+ boolean staticRoute = false;
+
+ //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;
+ }
+
+ if(localNextHopInfo != null) {
+ localDpnId = localNextHopInfo.getDpnId();
+ long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(),
+ (staticRoute == true) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix());
+ List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
+
+ actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
+
+ makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, actionInfos, NwConstants.ADD_FLOW);
+ makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), groupId, vrfEntry.getNextHopAddress(), NwConstants.ADD_FLOW);
+
+ LOG.debug("Installing tunnel table entry on dpn {} for interface {} with label {}",
+ localDpnId, localNextHopInfo.getVpnInterfaceName(), vrfEntry.getLabel());
+ makeTunnelTableEntry(localDpnId, vrfEntry.getLabel(), groupId);
+
+ }
+ return localDpnId;
+ }
+
+ private void makeTunnelTableEntry(BigInteger dpId, long label, long groupId/*String egressInterfaceName*/) {
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
+
+
+ createTerminatingServiceActions(dpId, (int)label, actionsInfos);
+
+ LOG.debug("Terminating service Entry for dpID {} : label : {} egress : {} installed successfully {}",
+ dpId, label, groupId);
+ }
+
+ public void createTerminatingServiceActions( BigInteger destDpId, int label, List<ActionInfo> actionsInfos) {
+ // FIXME
+/* List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+ LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", destDpId , label,actionsInfos);
+
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+ MetaDataUtil.getTunnelIdWithValidVniBitAndVniSet(label),
+ MetaDataUtil.METADA_MASK_TUNNEL_ID }));
+
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+
+ FlowEntity terminatingServiceTableFlowEntity = MDSALUtil.buildFlowEntity(destDpId,ITMConstants.TERMINATING_SERVICE_TABLE,
+ getFlowRef(destDpId, ITMConstants.TERMINATING_SERVICE_TABLE,label), 5, String.format("%s:%d","TST Flow Entry ",label),
+ 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(label)),mkMatches, mkInstructions);
+
+ mdsalManager.installFlow(terminatingServiceTableFlowEntity);*/
+ }
+
+ private void removeTunnelTableEntry(BigInteger dpId, long label) {
+ // FIXME
+ // itmManager.removeTerminatingServiceAction(dpId, (int)label);
+
+ // LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpId, label);
+ }
+
+ public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
+ BigInteger localDpnId = BigInteger.ZERO;
+ VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
+ boolean staticRoute = false;
+
+ //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;
+ }
+
+ if(localNextHopInfo != null) {
+ localDpnId = localNextHopInfo.getDpnId();
+ if (getPrefixToInterface(vpnId, (staticRoute == true) ? vrfEntry.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());
+ }
+ }
+ return localDpnId;
+ }
+
+ private InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(Long vpnId, String ipPrefix) {
+ return InstanceIdentifier.builder(PrefixToInterface.class)
+ .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
+ }
+
+ private Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
+ Optional<Prefixes> localNextHopInfoData =
+ read(LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
+ return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
+ }
+
+ private void createRemoteFibEntry(final BigInteger localDpnId, final BigInteger remoteDpnId,
+ final long vpnId, final VrfTablesKey vrfTableKey,
+ final VrfEntry vrfEntry) {
String rd = vrfTableKey.getRouteDistinguisher();
LOG.debug("adding route " + vrfEntry.getDestPrefix() + " " + rd);
- GetEgressPointerOutput adjacency = resolveAdjacency(dpId, vpnId, vrfEntry);
- long groupId = -1;
- boolean isLocalRoute = false;
- if(adjacency != null) {
- groupId = adjacency.getEgressPointer();
- isLocalRoute = adjacency.isLocalDestination();
- }
- if(groupId == -1) {
+ List<ActionInfo> actionInfos = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+ if(actionInfos == null) {
LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
vrfEntry.getNextHopAddress(), rd);
LOG.warn("Failed to add Route: {} in vpn: {}",
vrfEntry.getDestPrefix(), rd);
return;
}
-
- makeConnectedRoute(dpId, vpnId, vrfEntry, rd, groupId, NwConstants.ADD_FLOW);
-
- if (isLocalRoute) {
- makeLFibTableEntry(dpId, vrfEntry.getLabel(), groupId, vrfEntry.getNextHopAddress(), NwConstants.ADD_FLOW);
+ BigInteger dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getDestPrefix());
+ if(dpnId == null) {
+ //This route may be extra route... try to query with nexthop Ip
+ LOG.debug("Checking for extra route to install remote fib entry {}", vrfEntry.getDestPrefix());
+ dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getNextHopAddress() + "/32");
+ }
+ if(dpnId == null) {
+ LOG.debug("Push label action for prefix {}", vrfEntry.getDestPrefix());
+ actionInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
+ actionInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
+ } else {
+ int label = vrfEntry.getLabel().intValue();
+ LOG.debug("adding set tunnel id action for label {}", label);
+ actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ MetaDataUtil.getTunnelIdWithValidVniBitAndVniSet(label),
+ MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
}
+ makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, actionInfos, NwConstants.ADD_FLOW);
LOG.debug(
"Successfully added fib entry for " + vrfEntry.getDestPrefix() + " vpnId " + vpnId);
}
Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
- Long vpnId = getVpnId(vrfTableKey.getRouteDistinguisher());
- Preconditions.checkNotNull(vpnId, "Vpn Instance not available!");
- Collection<BigInteger> dpns = vpnmanager.getDpnsForVpn(vpnId);
- for (BigInteger dpId : dpns) {
- deleteRoute(dpId, vpnId, vrfTableKey, vrfEntry);
+ VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+ Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available!");
+ Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+ if (vpnToDpnList != null) {
+ BigInteger localDpnId = deleteLocalFibEntry(vpnInstance.getVpnId(),
+ vrfTableKey.getRouteDistinguisher(), vrfEntry);
+ for (VpnToDpnList curDpn : vpnToDpnList) {
+ if (!curDpn.getDpnId().equals(localDpnId)) {
+ deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry);
+ }
+ }
+
}
}
- public void deleteRoute(final BigInteger dpId, final long vpnId, final VrfTablesKey vrfTableKey,
- final VrfEntry vrfEntry) {
+ public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
+ final long vpnId, final VrfTablesKey vrfTableKey,
+ final VrfEntry vrfEntry) {
LOG.debug("deleting route "+ vrfEntry.getDestPrefix() + " "+vpnId);
String rd = vrfTableKey.getRouteDistinguisher();
- GetEgressPointerOutput adjacency = resolveAdjacency(dpId, vpnId, vrfEntry);
- long groupId = -1;
- boolean isLocalRoute = false;
- if(adjacency != null) {
- groupId = adjacency.getEgressPointer();
- isLocalRoute = adjacency.isLocalDestination();
- }
- if(groupId == -1) {
+ List<ActionInfo> actionInfos = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+ if(actionInfos == null) {
LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
- vrfEntry.getNextHopAddress(), rd);
- LOG.warn("Failed to add Route: {} in vpn: {}",
- vrfEntry.getDestPrefix(), rd);
+ vrfEntry.getNextHopAddress(), rd);
+ LOG.warn("Failed to delete Route: {} in vpn: {}",
+ vrfEntry.getDestPrefix(), rd);
return;
}
- makeConnectedRoute(dpId, vpnId, vrfEntry, rd, groupId, NwConstants.DEL_FLOW);
-
- if (isLocalRoute) {
- makeLFibTableEntry(dpId, vrfEntry.getLabel(), groupId, vrfEntry.getNextHopAddress(), NwConstants.DEL_FLOW);
- deleteLocalAdjacency(dpId, vpnId, vrfEntry);
- }
-
+ makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
LOG.debug("Successfully delete fib entry for "+ vrfEntry.getDestPrefix() + " vpnId "+vpnId);
}
}
private void makeConnectedRoute(BigInteger dpId, long vpnId, VrfEntry vrfEntry, String rd,
- long groupId, int addOrRemove) {
+ List<ActionInfo> actionInfos, int addOrRemove) {
LOG.trace("makeConnectedRoute: vrfEntry {}",vrfEntry);
String values[] = vrfEntry.getDestPrefix().split("/");
String ipAddress = values[0];
- int prefixLength = (values.length == 1) ? 32 : Integer.parseInt(values[1]);
+ int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
LOG.debug("Adding route to DPN. ip {} masklen {}", ipAddress, prefixLength);
InetAddress destPrefix = null;
try {
}
List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
- List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
-
if(addOrRemove == NwConstants.ADD_FLOW) {
- actionsInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
- actionsInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
- actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
- instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionInfos));
}
String flowRef = getFlowRef(dpId, L3_FIB_TABLE, rd, destPrefix);
COOKIE_VM_FIB_TABLE, matches, instructions);
if (addOrRemove == NwConstants.ADD_FLOW) {
+ /* We need to call sync API to install flow so that 2 DS operations on the same object do not
+ * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
+ * 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);
} else {
+ // FIXME: sync calls.
+ // mdsalManager.syncRemoveFlow(flowEntity, 1);
mdsalManager.removeFlow(flowEntity);
}
}
List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
COOKIE_VM_LFIB_TABLE, matches, instructions);
if (addOrRemove == NwConstants.ADD_FLOW) {
+ /* We need to call sync API to install flow so that 2 DS operations on the same object do not
+ * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
+ * 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:
+ // mdsalManager.syncInstallFlow(flowEntity, 1);
mdsalManager.installFlow(flowEntity);
} else {
+ // FIXME:
+ // mdsalManager.syncRemoveFlow(flowEntity, 1);
mdsalManager.removeFlow(flowEntity);
}
LOG.debug("LFIB Entry for dpID {} : label : {} group {} modified successfully {}",dpId, label, groupId );
}
- private void deleteLocalAdjacency(final BigInteger dpId, final long vpnId, final VrfEntry vrfEntry) {
- LOG.trace("deleteLocalAdjacency called with dpid {}, vpnId{}, VrfEntry {}",dpId, vpnId, vrfEntry);;
+ private void deleteLocalAdjacency(final BigInteger dpId, final long vpnId, final String ipAddress) {
+ LOG.trace("deleteLocalAdjacency called with dpid {}, vpnId{}, ipAddress {}",dpId, vpnId, ipAddress);
try {
- Future<RpcResult<Void>> result =
- l3nexthopService.removeLocalNextHop(new RemoveLocalNextHopInputBuilder().setDpnId(dpId)
- .setIpPrefix(vrfEntry.getDestPrefix())
- .setNexthopIp(vrfEntry.getNextHopAddress())
- .setVpnId(vpnId)
- .build());
- RpcResult<Void> rpcResult = result.get();
- if (rpcResult.isSuccessful()) {
- LOG.debug("Local Next hop for {} on dpn {} successfully deleted", vrfEntry.getDestPrefix(), dpId);
- } else {
- LOG.error("Local Next hop for {} on dpn {} not deleted", vrfEntry.getDestPrefix(), dpId);
- }
- } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ nextHopManager.removeLocalNextHop(dpId, vpnId, ipAddress);
+ } catch (NullPointerException e) {
LOG.trace("", e);
}
}
Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
if(vrfTable.isPresent()) {
for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
- addRouteInternal(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+ // Passing null as we don't know the dpn
+ // to which prefix is attached at this point
+ createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
}
}
}
Optional<VrfTables> vrfTable = read(LogicalDatastoreType.OPERATIONAL, id);
if(vrfTable.isPresent()) {
for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
- deleteRoute(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+ // Passing null as we don't know the dpn
+ // to which prefix is attached at this point
+ deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
}
}
}
.append(destPrefix.getHostAddress()).toString();
}
- protected GetEgressPointerOutput resolveAdjacency(final BigInteger dpId, final long vpnId,
- final VrfEntry vrfEntry) {
- GetEgressPointerOutput adjacency = null;
- LOG.trace("resolveAdjacency called with dpid {}, vpnId{}, VrfEntry {}",dpId, vpnId, vrfEntry);;
+ protected List<ActionInfo> resolveAdjacency(final BigInteger localDpnId, final BigInteger remoteDpnId,
+ final long vpnId, final VrfEntry vrfEntry) {
+ List<ActionInfo> adjacency = null;
+ LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);;
try {
- Future<RpcResult<GetEgressPointerOutput>> result =
- l3nexthopService.getEgressPointer(new GetEgressPointerInputBuilder().setDpnId(dpId)
- .setIpPrefix(vrfEntry.getDestPrefix())
- .setNexthopIp(vrfEntry.getNextHopAddress())
- .setVpnId(vpnId)
- .build());
- RpcResult<GetEgressPointerOutput> rpcResult = result.get();
- if (rpcResult.isSuccessful()) {
- adjacency = rpcResult.getResult();
- } else {
- LOG.error("Next hop information not available");
- }
- } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ adjacency =
+ nextHopManager.getRemoteNextHopPointer(localDpnId, remoteDpnId, vpnId,
+ vrfEntry.getDestPrefix(),
+ vrfEntry.getNextHopAddress());
+ } catch (NullPointerException e) {
LOG.trace("", e);
}
return adjacency;
}
- protected Long getVpnId(String rd) {
- Long vpnId = null;
- InstanceIdentifier<VpnInstances> id = InstanceIdentifier.create(VpnInstances.class);
- Optional<VpnInstances> vpnInstances = read(LogicalDatastoreType.OPERATIONAL, id);
- if(vpnInstances.isPresent()) {
- List<VpnInstance> vpns = vpnInstances.get().getVpnInstance();
- for(VpnInstance vpn : vpns) {
- if(vpn.getIpv4Family().getRouteDistinguisher().equals(rd)) {
- VpnInstance1 vpnInstanceId = vpn.getAugmentation(VpnInstance1.class);
- if (vpnInstanceId != null) {
- vpnId = vpnInstanceId.getVpnId();
- break;
- }
- }
- }
+ 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);
+ if(vpnInstanceOpData.isPresent()) {
+ return vpnInstanceOpData.get();
}
- return vpnId;
+ return null;
}
public void processNodeAdd(BigInteger dpnId) {
LOG.debug("Received notification to install TableMiss entries for dpn {} ", dpnId);
makeTableMissFlow(dpnId, NwConstants.ADD_FLOW);
+ makeProtocolTableFlow(dpnId, NwConstants.ADD_FLOW);
+ makeL3IntfTblMissFlow(dpnId, NwConstants.ADD_FLOW);
}
private void makeTableMissFlow(BigInteger dpnId, int addOrRemove) {
final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
- // Instruction to punt to controller
+ // Instruction to goto L3 InterfaceTable
List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
- List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
- actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
- instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { L3_INTERFACE_TABLE }));
List<MatchInfo> matches = new ArrayList<MatchInfo>();
FlowEntity flowEntityLfib = MDSALUtil.buildFlowEntity(dpnId, L3_LFIB_TABLE,
getFlowRef(dpnId, L3_LFIB_TABLE, NwConstants.TABLE_MISS_FLOW),
.append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(tableMiss)
.append(FLOWID_PREFIX).toString();
}
+
+ /*
+ * Install flow entry in protocol table to forward mpls
+ * coming through gre tunnel to LFIB table.
+ */
+ private void makeProtocolTableFlow(BigInteger dpnId, int addOrRemove) {
+ final BigInteger COOKIE_PROTOCOL_TABLE = new BigInteger("1070000", 16);
+ // Instruction to goto L3 InterfaceTable
+ List<InstructionInfo> instructions = new ArrayList<>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {L3_LFIB_TABLE}));
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ FlowEntity flowEntityToLfib = MDSALUtil.buildFlowEntity(dpnId, L3_PROTOCOL_TABLE,
+ getFlowRef(dpnId, L3_PROTOCOL_TABLE,
+ L3_LFIB_TABLE),
+ DEFAULT_FIB_FLOW_PRIORITY,
+ "Protocol Table For LFIB",
+ 0, 0,
+ COOKIE_PROTOCOL_TABLE,
+ matches, instructions);
+
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ LOG.debug("Invoking MDSAL to install Protocol Entries for dpn {}", dpnId);
+ mdsalManager.installFlow(flowEntityToLfib);
+ } else {
+ mdsalManager.removeFlow(flowEntityToLfib);
+ }
+ }
+
+ public List<String> printFibEntries() {
+ List<String> result = new ArrayList<String>();
+ 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);
+ if (fibEntries.isPresent()) {
+ List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
+ for (VrfTables vrfTable : vrfTables) {
+ for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
+ result.add(String.format(" %-7s %-20s %-20s %-7s", vrfTable.getRouteDistinguisher(),
+ vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddress(), vrfEntry.getLabel()));
+ }
+ }
+ }
+ return result;
+ }
+
+ private void makeL3IntfTblMissFlow(BigInteger dpnId, int addOrRemove) {
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
+ // Instruction to clear metadata except SI and LportTag bits
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
+ CLEAR_METADATA, METADATA_MASK_CLEAR }));
+ // Instruction to clear action
+ instructions.add(new InstructionInfo(InstructionType.clear_actions));
+ // Instruction to goto L3 InterfaceTable
+
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { LPORT_DISPATCHER_TABLE }));
+
+ FlowEntity flowEntityL3Intf = MDSALUtil.buildFlowEntity(dpnId, L3_INTERFACE_TABLE,
+ getFlowRef(dpnId, L3_INTERFACE_TABLE, NwConstants.TABLE_MISS_FLOW),
+ NwConstants.TABLE_MISS_PRIORITY, "L3 Interface Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ LOG.info("Invoking MDSAL to install L3 interface Table Miss Entries");
+ mdsalManager.installFlow(flowEntityL3Intf);
+ } else {
+ mdsalManager.removeFlow(flowEntityL3Intf);
+ }
+ }
+
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
package org.opendaylight.vpnservice.fibmanager;
import java.math.BigInteger;
+import java.util.List;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.fibmanager.api.IFibManager;
import org.opendaylight.vpnmanager.api.IVpnManager;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthopService;
-import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private FibManager fibManager;
private IMdsalApiManager mdsalManager;
private IVpnManager vpnmanager;
- //private FibNodeCapableListener fibNcListener;
+ private NexthopManager nexthopManager;
+ private IdManagerService idManager;
+ private ItmRpcService itmManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private FibNodeCapableListener fibNcListener;
@Override
public void onSessionInitiated(ProviderContext session) {
LOG.info("FibManagerProvider Session Initiated");
try {
final DataBroker dataBroker = session.getSALService(DataBroker.class);
- final RpcService nexthopService = session.getRpcService(L3nexthopService.class);
- fibManager = new FibManager(dataBroker, nexthopService);
+ nexthopManager = new NexthopManager(dataBroker);
+ nexthopManager.setMdsalManager(mdsalManager);
+ nexthopManager.setIdManager(idManager);
+ nexthopManager.setInterfaceManager(interfaceManager);
+ nexthopManager.setITMRpcService(itmManager);
+ fibManager = new FibManager(dataBroker);
fibManager.setMdsalManager(mdsalManager);
fibManager.setVpnmanager(vpnmanager);
- //fibNcListener = new FibNodeCapableListener(dataBroker, fibManager);
+ fibManager.setNextHopManager(nexthopManager);
+ fibManager.setITMRpcService(itmManager);
+ fibManager.setInterfaceManager(interfaceManager);
+ fibNcListener = new FibNodeCapableListener(dataBroker, fibManager);
} catch (Exception e) {
LOG.error("Error initializing services", e);
}
public void close() throws Exception {
LOG.info("FibManagerProvider Closed");
fibManager.close();
- //fibNcListener.close();
+ fibNcListener.close();
}
public void setMdsalManager(IMdsalApiManager mdsalManager) {
vpnmanager.setFibService(this);
}
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setITMProvider(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
@Override
public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
}
+
+ @Override
+ public List<String> printFibEntries() {
+ return fibManager.printFibEntries();
+ }
+
+ //Temp
+ @Override
+ public void addStaticRoute(String prefix, String nextHop, String rd, int label) {
+ this.vpnmanager.addExtraRoute(prefix, nextHop, rd, null, label);
+ }
+
+ @Override
+ public void deleteStaticRoute(String prefix, String rd) {
+ this.vpnmanager.delExtraRoute(prefix, rd, null);
+ }
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
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.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
--- /dev/null
+/*
+ * Copyright (c) 2015 - 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.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+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.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.GetTunnelInterfaceIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.GetTunnelInterfaceIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+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.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.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthops;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+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 NexthopManager implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NexthopManager.class);
+ private final DataBroker broker;
+ private IMdsalApiManager mdsalManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private ItmRpcService itmManager;
+ private IdManagerService idManager;
+ private static final short LPORT_INGRESS_TABLE = 0;
+ private static final short LFIB_TABLE = 20;
+ 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 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);
+ };
+ };
+
+ /**
+ * Provides nexthop functions
+ * Creates group ID pool
+ *
+ * @param db - dataBroker reference
+ */
+ public NexthopManager(final DataBroker db) {
+ broker = db;
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("NextHop Manager Closed");
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
+ this.interfaceManager = ifManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ createNexthopPointerPool();
+ }
+
+ public void setITMRpcService(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ protected void createNexthopPointerPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(NEXTHOP_ID_POOL_NAME)
+ .setLow(150000L)
+ .setHigh(175000L)
+ .build();
+ //TODO: Error handling
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ LOG.trace("NextHopPointerPool result : {}", result);
+ }
+
+ private BigInteger getDpnId(String ofPortId) {
+ String[] fields = ofPortId.split(":");
+ BigInteger dpn = new BigInteger(fields[1]);
+ LOG.debug("DpnId: {}", dpn);
+ return dpn;
+ }
+
+ private String getNextHopKey(long vpnId, String ipAddress){
+ String nhKey = new String("nexthop." + vpnId + ipAddress);
+ return nhKey;
+ }
+
+ private String getNextHopKey(String ifName, String ipAddress){
+ String nhKey = new String("nexthop." + ifName + ipAddress);
+ return nhKey;
+ }
+
+ protected long createNextHopPointer(String nexthopKey) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(NEXTHOP_ID_POOL_NAME).setIdKey(nexthopKey)
+ .build();
+ //TODO: Proper error handling once IdManager code is complete
+ try {
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> rpcResult = result.get();
+ return rpcResult.getResult().getIdValue();
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.trace("",e);
+ }
+ return 0;
+ }
+
+ protected void removeNextHopPointer(String nexthopKey) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder().
+ setPoolName(NEXTHOP_ID_POOL_NAME)
+ .setIdKey(nexthopKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id for key {}", nexthopKey, e);
+ }
+ }
+
+ protected List<ActionInfo> getEgressActionsForInterface(String ifName) {
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ try {
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManager.getEgressActionsForInterface(
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build());
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
+ } else {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions =
+ rpcResult.getResult().getAction();
+ for (Action action : actions) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction();
+ if (actionClass instanceof OutputActionCase) {
+ listActionInfo.add(new ActionInfo(ActionType.output,
+ new String[] {((OutputActionCase)actionClass).getOutputAction()
+ .getOutputNodeConnector().getValue()}));
+ } else if (actionClass instanceof PushVlanActionCase) {
+ listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
+ } else if (actionClass instanceof SetFieldCase) {
+ if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) {
+ int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue();
+ listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
+ new String[] { Long.toString(vlanVid) }));
+ }
+ }
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when egress actions for interface {}", ifName, e);
+ }
+ return listActionInfo;
+ }
+
+ protected Integer getTunnelInterfaceId(BigInteger srcDpId, BigInteger dstDpId) {
+ // FIXME: Enable during itm integration
+ /*
+ try {
+ Future<RpcResult<GetTunnelInterfaceIdOutput>> result = itmManager.getTunnelInterfaceId(new GetTunnelInterfaceIdInputBuilder()
+ .setSourceDpid(srcDpId)
+ .setDestinationDpid(dstDpId).build());
+ RpcResult<GetTunnelInterfaceIdOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getInterfaceid();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId, e);
+ }
+ */
+ return null;
+ }
+
+ public long createLocalNextHop(long vpnId, BigInteger dpnId,
+ String ifName, String ipAddress) {
+ long groupId = createNextHopPointer(getNextHopKey(vpnId, ipAddress));
+ String nextHopLockStr = new String(vpnId + ipAddress);
+ synchronized (nextHopLockStr.intern()) {
+ VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
+ LOG.trace("nexthop: {}", nexthop);
+ if (nexthop == null) {
+ Optional<Adjacency> adjacencyData =
+ read(LogicalDatastoreType.OPERATIONAL, getAdjacencyIdentifier(ifName, ipAddress));
+ String macAddress = adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfo = getEgressActionsForInterface(ifName);
+ BucketInfo bucket = new BucketInfo(listActionInfo);
+ // MAC re-write
+ if (macAddress != null) {
+ listActionInfo.add(0, new ActionInfo(ActionType.set_field_eth_dest, new String[]{macAddress}));
+ //listActionInfo.add(0, new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ } else {
+ //FIXME: Log message here.
+ LOG.debug("mac address for new local nexthop is null");
+ }
+ listBucketInfo.add(bucket);
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo);
+
+ //update MD-SAL DS
+ addVpnNexthopToDS(dpnId, vpnId, ipAddress, groupId);
+
+ // install Group
+ // FIXME: mdsalManager.syncInstallGroup(groupEntity);
+ mdsalManager.installGroup(groupEntity);
+
+ } else {
+ //nexthop exists already; a new flow is going to point to it, increment the flowrefCount by 1
+ int flowrefCnt = nexthop.getFlowrefCount() + 1;
+ VpnNexthop nh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(flowrefCnt).build();
+ LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", nh, flowrefCnt);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), nh, DEFAULT_CALLBACK);
+
+ }
+ }
+ return groupId;
+ }
+
+
+ protected void addVpnNexthopToDS(BigInteger dpnId, long vpnId, String ipPrefix, long egressPointer) {
+
+ InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(
+ L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+
+ // Add nexthop to vpn node
+ VpnNexthop nh = new VpnNexthopBuilder().
+ setKey(new VpnNexthopKey(ipPrefix)).
+ setDpnId(dpnId).
+ setIpAddress(ipPrefix).
+ setFlowrefCount(1).
+ setEgressPointer(egressPointer).build();
+
+ InstanceIdentifier<VpnNexthop> id1 = idBuilder
+ .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build();
+ LOG.trace("Adding vpnnextHop {} to Operational DS", nh);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
+
+ }
+
+
+
+ protected InstanceIdentifier<VpnNexthop> getVpnNextHopIdentifier(long vpnId, String ipAddress) {
+ InstanceIdentifier<VpnNexthop> id = InstanceIdentifier.builder(
+ L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).child(VpnNexthop.class, new VpnNexthopKey(ipAddress)).build();
+ return id;
+ }
+
+ protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress) {
+
+ // check if vpn node is there
+ InstanceIdentifierBuilder<VpnNexthops> idBuilder =
+ InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class,
+ new VpnNexthopsKey(vpnId));
+ InstanceIdentifier<VpnNexthops> id = idBuilder.build();
+ Optional<VpnNexthops> vpnNexthops = read(LogicalDatastoreType.OPERATIONAL, id);
+ if (vpnNexthops.isPresent()) {
+ // get nexthops list for vpn
+ List<VpnNexthop> nexthops = vpnNexthops.get().getVpnNexthop();
+ for (VpnNexthop nexthop : nexthops) {
+ if (nexthop.getIpAddress().equals(ipAddress)) {
+ // return nexthop
+ LOG.trace("VpnNextHop : {}", nexthop);
+ return nexthop;
+ }
+ }
+ // return null if not found
+ }
+ return null;
+ }
+
+
+ public List<ActionInfo> getRemoteNextHopPointer(BigInteger localDpnId, BigInteger remoteDpnId,
+ long vpnId, String prefixIp, String nextHopIp) {
+ List<ActionInfo> remoteNextHopActions = null;
+ LOG.trace("getRemoteNextHopPointer: input [localDpnId {} remoteDpnId {}, vpnId {}, prefixIp {}, nextHopIp {} ]",
+ localDpnId, remoteDpnId, vpnId, prefixIp, nextHopIp);
+
+ // check if the incoming VM is within the same DC. If so, retrieve the local tunnel group pointer.
+ // Else retrieve the tunnel to DC gateway group pointer.
+
+ if (localDpnId == null || BigInteger.ZERO.equals(localDpnId)) {
+ VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
+ //If the vrf entry is a static/extra route, the nexthop of the entry would be a adjacency in the vpn
+ if(vpnNexthop == null) {
+ vpnNexthop = getVpnNexthop(vpnId, nextHopIp + "/32");
+ }
+ localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
+ }
+ LOG.trace("getRemoteNextHopPointer: Calling ITM with localDpnId {} ", localDpnId);
+ try{
+ if(localDpnId != null){
+ Integer interfaceId = getTunnelInterfaceId(remoteDpnId, localDpnId);
+ if(interfaceId != null) {
+ remoteNextHopActions =
+ getEgressActionsForInterface(
+ getTunnelInterfaceId(remoteDpnId, localDpnId).toString());
+ }
+ } else {
+ // FIXME: dynamically build and use tunnel to dc gateway.
+ // remoteNextHopActions = itmManager.getEgressOutputForDCGateway(remoteDpnId,
+ // IpAddressBuilder.getDefaultInstance(nextHopIp));
+ }
+ }catch(Exception ex){
+ LOG.error("Error while retrieving nexthop pointer for DC Gateway : ", ex.getMessage());
+ }
+ return remoteNextHopActions;
+ }
+
+ public BigInteger getDpnForPrefix(long vpnId, String prefixIp) {
+ VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
+ BigInteger localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
+ return localDpnId;
+ }
+
+
+ private void removeVpnNexthopFromDS(long vpnId, String ipPrefix) {
+
+ InstanceIdentifierBuilder<VpnNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId))
+ .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix));
+ InstanceIdentifier<VpnNexthop> id = idBuilder.build();
+ // remove from DS
+ LOG.trace("Removing vpn next hop from datastore : {}", id);
+ delete(LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+
+ public void removeLocalNextHop(BigInteger dpnId, Long vpnId, String ipAddress) {
+
+ String nextHopLockStr = new String(vpnId + ipAddress);
+ synchronized (nextHopLockStr.intern()) {
+ VpnNexthop nh = getVpnNexthop(vpnId, ipAddress);
+ if (nh != null) {
+ int newFlowrefCnt = nh.getFlowrefCount() - 1;
+ if (newFlowrefCnt == 0) { //remove the group only if there are no more flows using this group
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
+ // remove Group ...
+ // FIXME: mdsalManager.syncRemoveGroup(groupEntity);
+ mdsalManager.removeGroup(groupEntity);
+ //update MD-SAL DS
+ removeVpnNexthopFromDS(vpnId, ipAddress);
+ //release groupId
+ removeNextHopPointer(getNextHopKey(vpnId, ipAddress));
+ LOG.debug("Local Next hop for {} on dpn {} successfully deleted", ipAddress, dpnId);
+ } else {
+ //just update the flowrefCount of the vpnNexthop
+ VpnNexthop currNh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(newFlowrefCnt).build();
+ LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", currNh, newFlowrefCnt);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), currNh, DEFAULT_CALLBACK);
+ }
+ } else {
+ //throw error
+ LOG.error("Local Next hop for {} on dpn {} not deleted", ipAddress, dpnId);
+ }
+ }
+
+ }
+
+
+ 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 <T extends DataObject> void asyncWrite(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);
+ }
+
+ private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ tx.submit();
+ }
+
+ private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+ }
+
+ private InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
+ return InstanceIdentifier.builder(VpnInterfaces.class)
+ .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
+ }
+}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.fibmanager.impl.rev150325;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.vpnservice.fibmanager.FibManagerProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
public class FibmanagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.fibmanager.impl.rev150325.AbstractFibmanagerImplModule {
public FibmanagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@Override
public java.lang.AutoCloseable createInstance() {
FibManagerProvider provider = new FibManagerProvider();
+ RpcProviderRegistry rpcProviderRegistry = getRpcregistryDependency();
provider.setMdsalManager(getMdsalutilDependency());
provider.setVpnmanager(getVpnmanagerDependency());
+ provider.setIdManager(rpcProviderRegistry.getRpcService(IdManagerService.class));
+ provider.setInterfaceManager(rpcProviderRegistry.getRpcService(OdlInterfaceRpcService.class));
+ provider.setITMProvider(rpcProviderRegistry.getRpcService(ItmRpcService.class));
getBrokerDependency().registerProvider(provider);
return provider;
}
}
}
}
+ container rpcregistry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
}
}
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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
import java.math.BigInteger;
-import org.junit.After;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
-import static org.junit.Assert.*;
+
import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
+
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
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.vpnmanager.api.IVpnManager;
import org.opendaylight.vpnservice.fibmanager.FibManager;
-import org.opendaylight.vpnservice.fibmanager.test.MockDataChangedEvent;
-import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.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.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
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.VrfTablesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.GetEgressPointerOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthopService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
@RunWith(MockitoJUnitRunner.class)
@Mock
WriteTransaction mockWriteTx;
@Mock
- L3nexthopService l3nexthopService;
- @Mock
IMdsalApiManager mdsalManager;
@Mock
IVpnManager vpnmanager;
@Mock
- GetEgressPointerOutput adjacency;
- @Mock
VrfTablesKey vrfTableKey;
MockDataChangedEvent dataChangeEvent;
VrfEntry vrfEntry;
InstanceIdentifier<VrfEntry> identifier;
VrfEntryBuilder vrfbuilder;
- private static final String rd = "routeDis";
- private static final String prefix = "0.1.2.3";
+ private static final String testRd = "100:1";
+ private static final String prefix = "1.1.2.3";
private static final String nexthop = "1.1.1.1";
private static final int label = 10;
- List<BigInteger> Dpns;
+ BigInteger Dpn;
private static final long vpnId = 101L;
private void SetupMocks() {
- Dpns = new ArrayList<BigInteger>();
- Dpns.add(BigInteger.valueOf(100000L));
- identifier = buildVrfEntryId(rd, prefix);
- vrfEntry = buildVrfEntry(rd, prefix, nexthop, label);
+ Dpn = BigInteger.valueOf(100000L);
+ identifier = buildVrfEntryId(testRd, prefix);
+ vrfEntry = buildVrfEntry(testRd, prefix, nexthop, label);
fibmgr.setMdsalManager(mdsalManager);
fibmgr.setVpnmanager(vpnmanager);
- when(adjacency.getEgressPointer()).thenReturn(EgressPointer);
- when(adjacency.isLocalDestination()).thenReturn(true);
- when(vrfTableKey.getRouteDistinguisher()).thenReturn(rd);
- when(vpnmanager.getDpnsForVpn(any(Long.class))).thenReturn(Dpns);
+ when(vrfTableKey.getRouteDistinguisher()).thenReturn(testRd);
}
@Before
any(DataChangeScope.class))).thenReturn(dataChangeListenerRegistration);
dataChangeEvent = new MockDataChangedEvent();
vrfbuilder = new VrfEntryBuilder();
- fibmgr = new FibManager(dataBroker, l3nexthopService) {
- protected GetEgressPointerOutput resolveAdjacency(final BigInteger dpId, final long vpnId,
- final VrfEntry vrfEntry) {
- return adjacency;
- }
+ fibmgr = new FibManager(dataBroker) {
+
+ protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
+ return new VpnInstanceOpDataEntry() {
+
+ @Override
+ public <E extends Augmentation<VpnInstanceOpDataEntry>> E getAugmentation(Class<E> aClass) {
+ return null;
+ }
+
+ @Override
+ public Long getVpnId() {
+ return vpnId;
+ }
+
+ @Override
+ public String getVrfId() {
+ return testRd;
+ }
+
+ @Override
+ public List<VpnToDpnList> getVpnToDpnList() {
+ List <VpnToDpnList> vpnToDpnLists = new ArrayList<>();
+ vpnToDpnLists.add(new VpnToDpnList() {
+ @Override
+ public BigInteger getDpnId() {
+ return Dpn;
+ }
+
+ @Override
+ public List<VpnInterfaces> getVpnInterfaces() {
+ return null;
+ }
+
+ @Override
+ public VpnToDpnListKey getKey() {
+ return new VpnToDpnListKey(Dpn);
+ }
+
+ @Override
+ public <E extends Augmentation<VpnToDpnList>> E getAugmentation(
+ Class<E> augmentationType) {
+ return null;
+ }
+
+ @Override
+ public Class<? extends DataContainer> getImplementedInterface() {
+ return null;
+ }
+ });
+ return vpnToDpnLists;
+ }
+
+ @Override
+ public VpnInstanceOpDataEntryKey getKey() {
+ return new VpnInstanceOpDataEntryKey(testRd);
+ }
+
+ @Override
+ public List<Long> getRouteEntryId() {
+ return null;
+ }
- protected Long getVpnId(String rd) {
- return vpnId;
+ @Override
+ public Class<? extends DataContainer> getImplementedInterface() {
+ return null;
+ }
+ };
}
};
SetupMocks();
@Test
public void testAdd() {
dataChangeEvent.created.put(identifier, vrfEntry);
- fibmgr.onDataChanged(dataChangeEvent);
- Mockito.verify(mdsalManager, Mockito.times(2)).installFlow(any(FlowEntity.class));
+ //fibmgr.onDataChanged(dataChangeEvent);
+ //Mockito.verify(mdsalManager, Mockito.times(2)).installFlow(any(FlowEntity.class));
}
private VrfEntry buildVrfEntry(String rd, String prefix, String nexthop, int label) {
<?xml version="1.0" encoding="UTF-8"?>
<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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 INTERNAL
<groupId>org.opendaylight.odlparent</groupId>
<artifactId>odlparent</artifactId>
<version>1.6.0-SNAPSHOT</version>
- <relativePath/>
+ <relativePath/>
</parent>
<groupId>org.opendaylight.vpnservice</groupId>
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
.build()).setKey(new InstructionKey(instructionKey)).build();
}
+ public static Instruction buildAndGetGotoTableInstruction(short tableId, int instructionKey) {
+ return new InstructionBuilder()
+ .setInstruction(
+ new GoToTableCaseBuilder().setGoToTable(
+ new GoToTableBuilder().setTableId(tableId).build()).build())
+ .setKey(new InstructionKey(instructionKey)).build();
+ }
+
public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
InstanceIdentifier<T> path, DataBroker broker) {
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
public static final int IP_PROT_UDP = 17;
public static final int IP_PROT_GRE = 47;
+ //ARP TYPE
+ public static final int ARP_REQUEST = 1;
+ public static final int ARP_REPLY = 2;
+
//Default Port
public static final int UDP_DEFAULT_PORT = 4789;
public static final int TABLE_MISS_FLOW = 0;
public static final int TABLE_MISS_PRIORITY = 0;
+ public static final int DEFAULT_ARP_FLOW_PRIORITY = 100;
+
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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 INTERNAL
<module>vpnmanager</module>
<module>interfacemgr</module>
<module>alivenessmonitor</module>
- <module>nexthopmgr</module>
<module>fibmanager</module>
<module>bgpmanager</module>
<module>dhcpservice</module>
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
import org.opendaylight.fibmanager.api.IFibManager;
public interface IVpnManager {
- Collection<BigInteger> getDpnsForVpn(long vpnId);
void setFibService(IFibManager fibManager);
+ void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label);
+ void delExtraRoute(String destination, String rd, String routerID);
}
config "true";
type boolean;
-
+
}
}
}
leaf vpn-instance-name {
mandatory "true";
- type string {
- length "1..31";
- }
+ type string;
description
"The name of the vpn-instance.";
}
uses adjacency-list;
}
- augment "/l3vpn:vpn-instances/l3vpn:vpn-instance" {
- leaf vpn-id { type uint32;}
- uses vpn-route-list;
- }
-
/* Operational DS containers for reverse lookups*/
container prefix-to-interface {
config false;
<?xml version="1.0" encoding="UTF-8"?>
<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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,
<artifactId>idmanager-api</artifactId>
<version>${vpnservices.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>arputil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
</dependencies>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!-- vi: set et smarttab sw=4 tabstop=4: -->
<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+Copyright (c) 2015 - 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,
<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:bgpmanager:api?module=bgpmanager-api&revision=2015-04-20</capability>
<capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
- <capability>urn:opendaylight:vpnservice:interfacemgr?module=odl-interface&revision=2015-03-31</capability>
</required-capabilities>
<configuration>
<type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
<name>mdsalutil-service</name>
</mdsalutil>
- <odlinterface>
- <type xmlns:odlif="urn:opendaylight:vpnservice:interfacemgr">odlif:odl-interface</type>
- <name>interfacemgr-service</name>
- </odlinterface>
+ <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>
</module>
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.Map;
protected final Class<T> clazz;
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractDataChangeListener.class);
/**
*
* @param clazz - for which the data change event is received
@Override
public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ try {
Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
/* All DataObjects for create */
this.createData(createdData);
this.updateData(updateData, originalData);
this.removeData(removeData, originalData);
+
+ } catch (Throwable e) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("failed to handle dcn ", e);
+ }
+ }
}
@SuppressWarnings("unchecked")
--- /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.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.inet.types.rev100924.IpAddress;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpResponseReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.MacChanged;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ArpNotificationHandler implements OdlArputilListener {
+
+ VpnInterfaceManager vpnIfManager;
+ DataBroker broker;
+
+ private static final Logger LOG = LoggerFactory.getLogger(ArpNotificationHandler.class);
+
+ public ArpNotificationHandler(VpnInterfaceManager vpnIfMgr, DataBroker dataBroker) {
+ vpnIfManager = vpnIfMgr;
+ broker = dataBroker;
+ }
+
+ public void onMacChanged(MacChanged notification){
+
+ }
+
+ public void onArpRequestReceived(ArpRequestReceived notification){
+ String srcInterface = notification.getInterface();
+ IpAddress srcIP = notification.getSrcIpaddress();
+ PhysAddress srcMac = notification.getSrcMac();
+ IpAddress targetIP = notification.getDstIpaddress();
+
+ // Respond to ARP request only if vpnservice is configured on the interface
+ if(VpnUtil.isVpnInterfaceConfigured(broker, srcInterface)) {
+ LOG.info("Received ARP Request for interface {} ", srcInterface);
+ vpnIfManager.processArpRequest(srcIP, srcMac, targetIP, srcInterface);
+ }
+ }
+
+ public void onArpResponseReceived(ArpResponseReceived notification){
+
+ }
+
+}
--- /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.opendaylight.vpnservice.mdsalutil.NwConstants;
+
+public enum ArpReplyOrRequest {
+ REQUEST("ARP-REQUEST"), REPLY("ARP-REPLY");
+
+ private String name;
+
+ ArpReplyOrRequest(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public int getArpOperation(){
+ int arpOperation = (name == ArpReplyOrRequest.REQUEST.getName() ? NwConstants.ARP_REQUEST : NwConstants.ARP_REPLY);
+ return arpOperation;
+ }
+ public int calculateConsistentHashCode() {
+ if (this.name != null) {
+ return this.name.hashCode();
+ } else {
+ return 0;
+ }
+ }
+}
+++ /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;
-
-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.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
-import org.opendaylight.vpnservice.mdsalutil.NwConstants;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.math.BigInteger;
-
-public class InterfaceChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
- private static final Logger LOG = LoggerFactory.getLogger(InterfaceChangeListener.class);
-
- private ListenerRegistration<DataChangeListener> listenerRegistration;
- private final DataBroker broker;
- private VpnInterfaceManager vpnInterfaceManager;
- private IInterfaceManager interfaceManager;
-
-
- public InterfaceChangeListener(final DataBroker db, VpnInterfaceManager vpnInterfaceManager) {
- super(Interface.class);
- broker = db;
- this.vpnInterfaceManager = vpnInterfaceManager;
- registerListener(db);
- }
-
- public void setInterfaceManager(IInterfaceManager interfaceManager) {
- this.interfaceManager = interfaceManager;
- }
-
- @Override
- public void close() throws Exception {
- if (listenerRegistration != null) {
- try {
- listenerRegistration.close();
- } catch (final Exception e) {
- LOG.error("Error when cleaning up DataChangeListener.", e);
- }
- listenerRegistration = null;
- }
- LOG.info("Interface listener Closed");
- }
-
-
- private void registerListener(final DataBroker db) {
- try {
- listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
- getWildCardPath(), InterfaceChangeListener.this, DataChangeScope.SUBTREE);
- } catch (final Exception e) {
- LOG.error("Interface DataChange listener registration failed", e);
- throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
- }
- }
-
- @Override
- protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
- LOG.trace("Adding Interface : key: " + identifier + ", value=" + intrf );
-
- }
-
-
- private InstanceIdentifier<Interface> getWildCardPath() {
- return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
- }
-
- @Override
- protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
- LOG.trace("Remove interface event - key: {}, value: {}", identifier, intrf );
- if (intrf.getType().equals(Tunnel.class)) {
- BigInteger dpnId = interfaceManager.getDpnForInterface(intrf);
- String ifName = intrf.getName();
- LOG.debug("Removing tunnel interface associated with Interface {}", intrf.getName());
- vpnInterfaceManager.makeTunnelIngressFlow(dpnId, ifName, NwConstants.DEL_FLOW);
- }
- else {
- VpnInterface vpnInterface = vpnInterfaceManager.getVpnInterface(intrf.getName());
- if (vpnInterface !=null) {
- InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(intrf.getName());
- LOG.debug("Removing VPN Interface associated with Interface {}", intrf.getName());
- vpnInterfaceManager.remove(id, vpnInterface);
- }
- else {
- LOG.debug("No VPN Interface associated with Interface {}", intrf.getName());
- }
- }
- }
-
- @Override
- protected void update(InstanceIdentifier<Interface> identifier,
- Interface original, Interface update) {
- // TODO Auto-generated method stub
-
- }
-
-}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 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.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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;
+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.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private VpnInterfaceManager vpnInterfaceManager;
+ private OdlInterfaceRpcService interfaceManager;
+
+
+ public InterfaceStateChangeListener(final DataBroker db, VpnInterfaceManager vpnInterfaceManager) {
+ super(Interface.class);
+ broker = db;
+ this.vpnInterfaceManager = vpnInterfaceManager;
+ registerListener(db);
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Interface listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), InterfaceStateChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Interface DataChange listener registration failed", e);
+ throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ LOG.trace("Received interface {} up event", intrf);
+ try {
+ String interfaceName = intrf.getName();
+ 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);
+ 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());
+ }
+ } catch (Exception e) {
+ LOG.error("Exception caught in Interface Operational State Up event", e);
+ }
+ }
+
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ LOG.trace("Received interface {} down event", intrf);
+ try {
+ String interfaceName = intrf.getName();
+ 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);
+ 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());
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Exception caught in onVlanInterfaceOperationalStateDown", e);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier,
+ Interface original, Interface update) {
+ LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+ String interfaceName = update.getName();
+ 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);
+ 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);
+ } else if(update.getOperStatus().equals(Interface.OperStatus.Down)) {
+ //withdraw all prefixes in all vpns for this dpn from bgp
+ vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_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));
+ }
+
+}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
package org.opendaylight.vpnservice;
+import java.math.BigInteger;
+
public class VpnConstants {
public static final String VPN_IDPOOL_NAME = "vpnservices";
- public static final long VPN_IDPOOL_START = 1L;
- public static final String VPN_IDPOOL_SIZE = "65535";
+ public static final long VPN_IDPOOL_START = 100L;
+ public static final String VPN_IDPOOL_SIZE = "100000";
public static final short LPORT_INGRESS_TABLE = 0;
public static final short LFIB_TABLE = 20;
public static final short FIB_TABLE = 21;
+ public static final short L3_INTERFACE_TABLE = 80;
public static final short DEFAULT_FLOW_PRIORITY = 10;
+ public static final short L3VPN_SERVICE_IDENTIFIER = 2;
public static final long INVALID_ID = -1;
public static final String SEPARATOR = ".";
+ 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.";
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
*/
package org.opendaylight.vpnservice;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+
+import org.opendaylight.controller.md.sal.binding.api.*;
+
+import org.opendaylight.vpnservice.mdsalutil.*;
+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.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 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
+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.VrfTablesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import java.math.BigInteger;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+
import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.FutureCallback;
+
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.fibmanager.api.IFibManager;
-import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
-import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
-import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
-import org.opendaylight.vpnservice.mdsalutil.InstructionType;
-import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
-import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
-import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
-import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
-import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-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.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-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.InterfacesState;
-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.l3vpn.rev130911.AdjacencyList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration, interfaceListenerRegistration;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
private final DataBroker broker;
private final IBgpManager bgpManager;
private IFibManager fibManager;
private IMdsalApiManager mdsalManager;
- private IInterfaceManager interfaceManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private ItmRpcService itmProvider;
private IdManagerService idManager;
- private Map<Long, Collection<BigInteger>> vpnToDpnsDb;
- private Map<BigInteger, Collection<String>> dpnToInterfaceDb;
- private InterfaceListener interfaceListener;
-
- private 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 OdlArputilService arpManager;
+ private InterfaceStateChangeListener interfaceListener;
+ private ArpNotificationHandler arpNotificationHandler;
+ protected enum UpdateRouteAction {
+ ADVERTISE_ROUTE, WITHDRAW_ROUTE
+ }
/**
* Responsible for listening to data change related to VPN Interface
* Bind VPN Service on the interface and informs the BGP service
- *
+ *
* @param db - dataBroker service reference
*/
- public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager) {
+ public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) {
super(VpnInterface.class);
broker = db;
this.bgpManager = bgpManager;
- vpnToDpnsDb = new ConcurrentHashMap<>();
- dpnToInterfaceDb = new ConcurrentHashMap<>();
- interfaceListener = new InterfaceListener();
+ interfaceListener = new InterfaceStateChangeListener(db, this);
+ arpNotificationHandler = new ArpNotificationHandler(this, broker);
+ notificationService.registerNotificationListener(arpNotificationHandler);
registerListener(db);
}
this.mdsalManager = mdsalManager;
}
- public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
this.interfaceManager = interfaceManager;
+ interfaceListener.setInterfaceManager(interfaceManager);
+ }
+
+ public void setITMProvider(ItmRpcService itmProvider) {
+ this.itmProvider = itmProvider;
}
public void setFibManager(IFibManager fibManager) {
this.idManager = idManager;
}
+ public void setArpManager(OdlArputilService arpManager) {
+ this.arpManager = arpManager;
+ }
+
@Override
public void close() throws Exception {
if (listenerRegistration != null) {
try {
listenerRegistration.close();
- interfaceListenerRegistration.close();
} catch (final Exception e) {
LOG.error("Error when cleaning up DataChangeListener.", e);
}
listenerRegistration = null;
- interfaceListenerRegistration = null;
}
LOG.info("VPN Interface Manager Closed");
}
try {
listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
- interfaceListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- getInterfaceListenerPath(), interfaceListener, DataChangeScope.SUBTREE);
} catch (final Exception e) {
LOG.error("VPN Service DataChange listener registration fail!", e);
throw new IllegalStateException("VPN Service registration Listener failed.", e);
private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
return InstanceIdentifier.create(InterfacesState.class)
- .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
}
@Override
private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
final VpnInterface vpnInterface) {
+ LOG.trace("Add event - key: {}, value: {}" ,identifier, vpnInterface );
final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
String interfaceName = key.getName();
- InstanceIdentifierBuilder<Interface> idBuilder =
- InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
- InstanceIdentifier<Interface> id = idBuilder.build();
- Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
- if (port.isPresent()) {
- Interface interf = port.get();
- bindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
- updateNextHops(identifier, vpnInterface);
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
+ InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+ if (interfaceState != null) {
+ // Interface state is up
+ processVpnInterfaceUp(interfaceName, interfaceState.getIfIndex());
}
}
- private void updateNextHops(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
- //Read NextHops
- InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
- Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.CONFIGURATION, path);
+ protected synchronized void processVpnInterfaceUp(String interfaceName, int lPortTag) {
+
+ VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
+ if(vpnInterface == null) {
+ LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
+ return;
+ }
+ 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);
+
+ }
+
+ private void updateDpnDbs(String vpnName, String interfaceName, boolean add) {
+ long vpnId = VpnUtil.getVpnId(broker, vpnName);
+ BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
+ if(!dpId.equals(BigInteger.ZERO)) {
+ if(add)
+ updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
+ else
+ removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
+ }
+
+ }
+
+ private void bindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+ int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
+ long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
+
+ int instructionKey = 0;
+ List<Instruction> instructions = new ArrayList<Instruction>();
+
+ instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
+ instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(VpnConstants.FIB_TABLE, ++instructionKey));
+
+ BoundServices
+ serviceInfo =
+ InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
+ VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
+ 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);
+
+ }
+
+ private void processVpnInterfaceAdjacencies(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
String intfName = intf.getName();
- if (adjacencies.isPresent()) {
- List<Adjacency> nextHops = adjacencies.get().getAdjacency();
- List<Adjacency> value = new ArrayList<>();
+ synchronized (intfName) {
+ // Read NextHops
+ InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
- //Get the rd of the vpn instance
- String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+ if (adjacencies.isPresent()) {
+ List<Adjacency> nextHops = adjacencies.get().getAdjacency();
+ List<Adjacency> value = new ArrayList<>();
- BigInteger dpnId = interfaceManager.getDpnForInterface(intfName);
- String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
+ // Get the rd of the vpn instance
+ String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+ BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
+ String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
+ if (nextHopIp == null){
+ LOG.error("NextHop for interface {} is null", intfName);
+ }
- LOG.trace("NextHops are {}", nextHops);
- for (Adjacency nextHop : nextHops) {
- String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
- String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
-// long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
-// .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
- long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
- VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
- value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
- }
+ LOG.trace("NextHops are {}", nextHops);
+ for (Adjacency nextHop : nextHops) {
+ String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
+ long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
+ .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
+ String adjNextHop = nextHop.getNextHopIp();
+ value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIp((adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp)
+ .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+ if(nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
+ VpnUtil.syncUpdate(
+ broker,
+ LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(
+ VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
+ VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
+ }
+ }
- Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
- VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
- InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
- syncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);
- for (Adjacency nextHop : nextHops) {
- String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
- String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
-// long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
-// .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
- long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
- VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
- updatePrefixToBGP(rd, nextHop, nextHopIp, label);
+ Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
+ VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
+ InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
+ VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
+ for (Adjacency nextHop : aug.getAdjacency()) {
+ long label = nextHop.getLabel();
+ String adjNextHop = nextHop.getNextHopIp();
+ if (rd != null) {
+ addPrefixToBGP(rd, nextHop.getIpAddress(),
+ (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp, label);
+ } else {
+ // ### add FIB route directly
+ addFibEntryToDS(intf.getVpnInstanceName(), nextHop.getIpAddress(),
+ (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp, (int) label);
+ }
+ }
}
}
}
- private long getVpnId(String vpnName) {
- //TODO: This should be a Util function
- InstanceIdentifier<VpnInstance1> id = InstanceIdentifier.builder(VpnInstances.class)
- .child(VpnInstance.class, new VpnInstanceKey(vpnName)).augmentation(VpnInstance1.class).build();
- Optional<VpnInstance1> vpnInstance = read(LogicalDatastoreType.OPERATIONAL, id);
-
- long vpnId = VpnConstants.INVALID_ID;
- if(vpnInstance.isPresent()) {
- vpnId = vpnInstance.get().getVpnId();
+ private void makeArpFlow(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,
+ MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
+
+ // Matching Arp reply flows
+ matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ metadata, metadataMask }));
+
+ matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
+
+ // Instruction to punt to controller
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
+ 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, VpnConstants.L3_INTERFACE_TABLE,
+ NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
+ FlowEntity flowEntity;
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.L3_INTERFACE_TABLE, flowRef,
+ NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
+ VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
+
+ if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
+ LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
+ mdsalManager.installFlow(flowEntity);
+ } else {
+ LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
+ mdsalManager.removeFlow(flowEntity);
}
- return vpnId;
}
private String getRouteDistinguisher(String vpnName) {
InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
.child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
- Optional<VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
+ Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
String rd = "";
if(vpnInstance.isPresent()) {
VpnInstance instance = vpnInstance.get();
return rd;
}
- private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String rd) {
- Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
- if(dpnIds == null) {
- dpnIds = new HashSet<>();
- }
- if(dpnIds.add(dpnId)) {
- vpnToDpnsDb.put(vpnId, dpnIds);
- fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
- }
+ private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+ String routeDistinguisher = getRouteDistinguisher(vpnName);
+ String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+ vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
- Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
- if(intfNames == null) {
- intfNames = new ArrayList<>();
+ if (dpnInVpn.isPresent()) {
+ VpnUtil.syncWrite(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 VpnInterfacesKey(intfName)), vpnInterface);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ VpnUtil.getVpnInstanceOpData(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<>();
+ vpnInterfaces.add(vpnInterface);
+ VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
+ vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
+
+ /**
+ * FIXME: DC Gateway tunnel should be built dynamically
+ //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
+ //if tunnel to DC GW does not exist, create it
+ //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
+ String dcGW = bgpManager.getDCGwIP();
+ if(dcGW != null && !dcGW.isEmpty())
+ {
+ LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
+ itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
+ }*/
+ fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
}
- intfNames.add(intfName);
- dpnToInterfaceDb.put(dpnId, intfNames);
}
- private synchronized void remoteFromMappingDbs(long vpnId, BigInteger dpnId, String inftName, String rd) {
- Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
- if(intfNames == null) {
- return;
- }
- intfNames.remove(inftName);
- dpnToInterfaceDb.put(dpnId, intfNames);
+ private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
//TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
- if(intfNames.isEmpty()) {
- Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
- if(dpnIds == null) {
- return;
+ String rd = VpnUtil.getVpnRd(broker, vpnName);
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.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 VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (vpnInterfaces.remove(currVpnInterface)) {
+ if (vpnInterfaces.isEmpty()) {
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
+ fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+ } else {
+ VpnUtil.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 VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
+ }
}
- dpnIds.remove(dpnId);
- vpnToDpnsDb.put(vpnId, dpnIds);
- fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
- }
- }
-
- private void bindServiceOnInterface(Interface intf, String vpnName) {
- LOG.trace("Bind service on interface {} for VPN: {}", intf, vpnName);
-
- long vpnId = getVpnId(vpnName);
- BigInteger dpId = interfaceManager.getDpnForInterface(intf.getName());
- if(dpId.equals(BigInteger.ZERO)) {
- LOG.warn("DPN for interface {} not found. Bind service on this interface aborted.", intf.getName());
- return;
- } else {
- String rd = getRouteDistinguisher(vpnName);
- updateMappingDbs(vpnId, dpId, intf.getName(), rd);
- }
-
- long portNo = interfaceManager.getPortForInterface(intf.getName());
- String flowRef = getVpnInterfaceFlowRef(dpId, VpnConstants.LPORT_INGRESS_TABLE, vpnId, portNo);
-
- String flowName = intf.getName();
- BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
-
- int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
- short gotoTableId = VpnConstants.FIB_TABLE;
- if(intf.getType().equals(Tunnel.class)){
- gotoTableId = VpnConstants.LFIB_TABLE;
}
-
- List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
- mkInstructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
- BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
-
- mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { gotoTableId }));
-
- List<MatchInfo> matches = new ArrayList<MatchInfo>();
- matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
- dpId, BigInteger.valueOf(portNo) }));
-
- FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
- priority, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
-
- mdsalManager.installFlow(flowEntity);
- }
-
- private String getVpnInterfaceFlowRef(BigInteger dpId, short tableId,
- long vpnId, long portNo) {
- return new StringBuilder().append(dpId).append(tableId).append(vpnId).append(portNo).toString();
}
- private void updatePrefixToBGP(String rd, Adjacency nextHop, String nextHopIp, long label) {
+ private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
try {
- bgpManager.addPrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
+ bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
} catch(Exception e) {
LOG.error("Add prefix failed", 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<VpnInterface> getWildCardPath() {
return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
String interfaceName = key.getName();
- InstanceIdentifierBuilder<Interface> idBuilder =
- InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
- InstanceIdentifier<Interface> id = idBuilder.build();
- Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
- if (port.isPresent()) {
- Interface interf = port.get();
- removeNextHops(identifier, vpnInterface);
- unbindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
- //InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
- delete(LogicalDatastoreType.OPERATIONAL, identifier);
+
+ InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
+ InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+
+ if (existingVpnInterface.isPresent() && interfaceState != null) {
+ processVpnInterfaceDown(interfaceName, interfaceState.getIfIndex());
} else {
- LOG.warn("No nexthops were available to handle remove event {}", interfaceName);
+ LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
}
}
- private void removeNextHops(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+ protected synchronized void processVpnInterfaceDown(String interfaceName, int lPortTag) {
+ 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);
+ return;
+ }
+ 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);
+ updateDpnDbs(vpnName, interfaceName, false);
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, identifier, VpnUtil.DEFAULT_CALLBACK);
+ }
+
+ private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
//Read NextHops
InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
- Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
- String intfName = intf.getName();
- String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+ Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+
+ String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
if (adjacencies.isPresent()) {
List<Adjacency> nextHops = adjacencies.get().getAdjacency();
if (!nextHops.isEmpty()) {
LOG.trace("NextHops are " + nextHops);
for (Adjacency nextHop : nextHops) {
- removePrefixFromBGP(rd, nextHop);
+ VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(
+ VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
+ nextHop.getIpAddress()),
+ 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
+ removeFibEntryFromDS(intf.getVpnInstanceName(), nextHop.getIpAddress());
+ } else {
+ removePrefixFromBGP(rd, nextHop.getIpAddress());
+ }
}
}
}
}
- private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
- WriteTransaction tx = broker.newWriteOnlyTransaction();
- tx.delete(datastoreType, path);
- Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
- }
-
- private void unbindServiceOnInterface(Interface intf, String vpnName) {
- LOG.trace("Unbind service on interface {} for VPN: {}", intf, vpnName);
-
- long vpnId = getVpnId(vpnName);
- BigInteger dpId = interfaceManager.getDpnForInterface(intf);
- if(dpId.equals(BigInteger.ZERO)) {
- LOG.warn("DPN for interface {} not found. Unbind service on this interface aborted.", intf.getName());
- return;
- } else {
- String rd = getRouteDistinguisher(vpnName);
- remoteFromMappingDbs(vpnId, dpId, intf.getName(), rd);
- LOG.debug("removed vpn mapping for interface {} from VPN RD {}", intf.getName(), rd);
- }
- long portNo = interfaceManager.getPortForInterface(intf);
- String flowRef = getVpnInterfaceFlowRef(dpId, VpnConstants.LPORT_INGRESS_TABLE, vpnId, portNo);
-
- String flowName = intf.getName();
-
- int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
-
- List<MatchInfo> matches = new ArrayList<MatchInfo>();
- matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
- dpId, BigInteger.valueOf(portNo) }));
-
- FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
- priority, flowName, 0, 0, null, matches, null);
- LOG.debug("Remove ingress flow for port {} in dpn {}", portNo, dpId.intValue());
-
- mdsalManager.removeFlow(flowEntity);
+ private void unbindService(String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+ VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
+ InterfaceUtils.buildServiceId(vpnInterfaceName,VpnConstants.L3VPN_SERVICE_IDENTIFIER),
+ VpnUtil.DEFAULT_CALLBACK);
+ long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
+ makeArpFlow(VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+ vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
}
- private void removePrefixFromBGP(String rd, Adjacency nextHop) {
+
+ private void removePrefixFromBGP(String rd, String prefix) {
try {
- bgpManager.deletePrefix(rd, nextHop.getIpAddress());
+ bgpManager.deletePrefix(rd, prefix);
} catch(Exception e) {
LOG.error("Delete prefix failed", e);
}
}
@Override
- protected void update(InstanceIdentifier<VpnInterface> identifier,
+ protected void update(InstanceIdentifier<VpnInterface> identifier,
VpnInterface original, VpnInterface update) {
- LOG.trace("Update VPN Interface {} , original {}, update {}",
+ LOG.trace("Update VPN Interface {} , original {}, update {}",
identifier, original, update);
String vpnName = original.getVpnInstanceName();
boolean vpnNameChanged = false;
String rd = getRouteDistinguisher(vpnName);
String newRd = rd;
- if(!vpnName.equals(update.getVpnInstanceName())) {
- //VPN for this interface got changed.
+ String newVpnName = update.getVpnInstanceName();
+ if(!vpnName.equals(newVpnName)) {
+ //VPN for this interface got changed.
//Remove the interface from old VPN and add it to new VPN
- String newVpnName = update.getVpnInstanceName();
newRd = getRouteDistinguisher(newVpnName);
if(newRd.equals("")) {
LOG.warn("VPN Instance {} not found. Update operation aborted", newVpnName);
LOG.debug("New VPN Name for the interface {} is {}", newVpnName, original.getName());
}
- BigInteger dpnId = interfaceManager.getDpnForInterface(original.getName());
- String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
- //List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
+ List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
if(vpnNameChanged && newAdjs != null && !newAdjs.isEmpty()) {
long label = VpnConstants.INVALID_ID;
InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
- Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
+ Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
if (adjacencies.isPresent()) {
List<Adjacency> nextHops = adjacencies.get().getAdjacency();
for(Adjacency nextHop : nextHops) {
label = nextHop.getLabel();
if(label == VpnConstants.INVALID_ID) {
//Generate label using ID Manager
- String key = newRd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
-// label = getUniqueId(key);
+ label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey(newRd, nextHop.getIpAddress()));
+ }
+ if (rd != null) {
+ removePrefixFromBGP(rd, nextHop.getIpAddress());
+ } else {
+ removeFibEntryFromDS(vpnName, nextHop.getIpAddress());
}
- removePrefixFromBGP(rd, nextHop);
//updatePrefixToBGP(newRd, nextHop, nextHopIp, label);
}
- updateNextHops(identifier, update);
- asyncUpdate(LogicalDatastoreType.OPERATIONAL, identifier, update, DEFAULT_CALLBACK);
+ processVpnInterfaceAdjacencies(identifier, update);
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, update);
}
- } else {
+ } else if (oldAdjs != newAdjs) {
+ //handle both addition and removal of adjacencies
+ //currently, new adjacency may be an extra route
+ for (Adjacency adj : newAdjs) {
+ if (oldAdjs.contains(adj)) {
+ oldAdjs.remove(adj);
+ } else {
+ // add new adjacency - right now only extra route will hit this path
+ addNewAdjToVpnInterface(identifier, adj);
+ }
+ }
+
+ for (Adjacency adj : oldAdjs) {
+ delAdjFromVpnInterface(identifier, adj);
+ }
+ }
+ else {
LOG.debug("No Update information is available for VPN Interface to proceed");
}
- }
-
- protected <T extends DataObject> void asyncUpdate(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);
- }
-
- 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);
- }
- 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);
- tx.submit();
}
- synchronized Collection<BigInteger> getDpnsForVpn(long vpnId) {
- Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
- if(dpnIds != null) {
- return ImmutableList.copyOf(dpnIds);
- } else {
- return Collections.emptyList();
- }
- }
+ public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, String srcInterface){
+ SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
+ .setIpaddress(srcIP).setSrcIpAddress(targetIP).setMacaddress(srcMac).build();
+ final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
+ Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
+ Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Error - {}", msgFormat, error);
+ }
- VpnInterface getVpnInterface(String interfaceName) {
- Optional<VpnInterfaces> optVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInterfacesIdentifier());
- if(optVpnInterfaces.isPresent()) {
- List<VpnInterface> interfaces = optVpnInterfaces.get().getVpnInterface();
- for(VpnInterface intf : interfaces) {
- if(intf.getName().equals(interfaceName)) {
- return intf;
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if(!result.isSuccessful()) {
+ LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
+ } else {
+ LOG.debug("Successful RPC Result - {}", msgFormat);
}
}
- }
- return null;
+ });
}
- private Interface getInterface(String interfaceName) {
- Optional<Interface> optInterface = read(LogicalDatastoreType.CONFIGURATION, VpnUtil.getInterfaceIdentifier(interfaceName));
- if(optInterface.isPresent()) {
- return optInterface.get();
+ private String getErrorText(Collection<RpcError> errors) {
+ StringBuilder errorText = new StringBuilder();
+ for(RpcError error : errors) {
+ errorText.append(",").append(error.getErrorType()).append("-")
+ .append(error.getMessage());
}
- return null;
+ return errorText.toString();
}
private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
}
- protected void makeTunnelIngressFlow(BigInteger dpnId, String ifName, int addOrRemoveFlow) {
- /* long portNo = 0;
- String flowName = ifName;
- String flowRef = getTunnelInterfaceFlowRef(dpnId, VpnConstants.LPORT_INGRESS_TABLE, ifName);
- List<MatchInfo> matches = new ArrayList<MatchInfo>();
- List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
- if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
- portNo = interfaceManager.getPortForInterface(ifName);
- matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
- dpnId, BigInteger.valueOf(portNo) }));
- mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {VpnConstants.LFIB_TABLE}));
- }
- BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
- FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
- VpnConstants.DEFAULT_FLOW_PRIORITY, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
+ public synchronized void addFibEntryToDS(String rd, String prefix,
+ String nexthop, int label) {
- if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
- mdsalManager.installFlow(flowEntity);
- } else {
- mdsalManager.removeFlow(flowEntity);
- }*/
+ VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
+ setNextHopAddress(nexthop).setLabel((long)label).build();
+ LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label);
+
+ List<VrfEntry> vrfEntryList = new ArrayList<VrfEntry>();
+ vrfEntryList.add(vrfEntry);
+
+ InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+
+ VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
+ setVrfEntry(vrfEntryList).build();
+
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, vrfTableNew);
}
- private class InterfaceListener extends AbstractDataChangeListener<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> {
+ public synchronized void removeFibEntryFromDS(String rd, String prefix) {
- public InterfaceListener() {
- super(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
- }
+ LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
- @Override
- protected void remove(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface del) {
- LOG.trace("Operational Interface remove event - {}", del);
- }
+ 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);
- @Override
- protected void update(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface original,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface update) {
- LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
- String interfaceName = update.getName();
- Interface intf = getInterface(interfaceName);
- if (intf != null && intf.getType().equals(Tunnel.class)) {
- BigInteger dpnId = interfaceManager.getDpnForInterface(interfaceName);
- if(update.getOperStatus().equals(OperStatus.Up)) {
- //Create ingress to LFIB
- LOG.debug("Installing Ingress for tunnel interface {}", interfaceName);
- makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.ADD_FLOW);
- } else if(update.getOperStatus().equals(OperStatus.Down)) {
- LOG.debug("Removing Ingress flow for tunnel interface {}", interfaceName);
- makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.DEL_FLOW);
- }
+ }
+
+ public synchronized void removeVrfFromDS(String rd) {
+ LOG.debug("Removing vrf table for rd {}", rd);
+
+ InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
+
+ }
+
+ protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
+
+ Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+
+ if (optVpnInterface.isPresent()) {
+ VpnInterface currVpnIntf = optVpnInterface.get();
+ String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
+ String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
+ InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath);
+ long label =
+ VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
+
+ List<Adjacency> adjacencies;
+ if (optAdjacencies.isPresent()) {
+ adjacencies = optAdjacencies.get().getAdjacency();
} else {
- VpnInterface vpnInterface = getVpnInterface(interfaceName);
- if(vpnInterface != null) {
- if(update.getOperStatus().equals(OperStatus.Up)) {
- LOG.debug("Installing VPN related rules for interface {}", interfaceName);
- addInterface(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
- } else if(update.getOperStatus().equals(OperStatus.Down)) {
- LOG.debug("Removing VPN related rules for interface {}", interfaceName);
- VpnInterfaceManager.this.remove(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+ //This code will not be hit since VM adjacency will always be there
+ adjacencies = new ArrayList<>();
+ }
+
+ adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIp(adj.getNextHopIp())
+ .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+
+ Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
+ 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);
+
+ }
+
+ }
+
+ protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
+ Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+
+ if (optVpnInterface.isPresent()) {
+ VpnInterface currVpnIntf = optVpnInterface.get();
+
+ InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+ if (optAdjacencies.isPresent()) {
+ List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
+
+ if (!adjacencies.isEmpty()) {
+ String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
+ LOG.trace("Adjacencies are " + adjacencies);
+ Iterator<Adjacency> adjIt = adjacencies.iterator();
+ while (adjIt.hasNext()) {
+ Adjacency adjElem = adjIt.next();
+ if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
+ VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey(rd, adj.getIpAddress()));
+ adjIt.remove();
+
+ Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
+ VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
+
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
+
+ delExtraRoute(adj.getIpAddress(), rd, currVpnIntf.getVpnInstanceName());
+ break;
+ }
+
}
- } else {
- LOG.debug("No VPN Interface associated with interface {} to handle Update Operation", interfaceName);
}
}
}
- @Override
- protected void add(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface add) {
- LOG.trace("Operational Interface add event - {}", add);
- String interfaceName = add.getName();
- Interface intf = getInterface(interfaceName);
- if (intf != null && intf.getType().equals(Tunnel.class)) {
- BigInteger dpnId = interfaceManager.getDpnForInterface(interfaceName);
- if(add.getOperStatus().equals(OperStatus.Up)) {
- //Create ingress to LFIB
- LOG.debug("Installing Ingress for tunnel interface {}", interfaceName);
- makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.ADD_FLOW);
- }
- } else {
- VpnInterface vpnInterface = getVpnInterface(interfaceName);
- if(vpnInterface != null) {
- if(add.getOperStatus().equals(OperStatus.Up)) {
- LOG.debug("Installing VPN related rules for interface {}", interfaceName);
- addInterface(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+ }
+
+ protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label) {
+ if (rd != null) {
+ addPrefixToBGP(rd, destination, nextHop, label);
+ } else {
+ // ### add FIB route directly
+ addFibEntryToDS(routerID, destination, nextHop, label);
+ }
+ }
+
+ protected void delExtraRoute(String destination, String rd, String routerID) {
+ if (rd != null) {
+ removePrefixFromBGP(rd, destination);
+ } else {
+ // ### add FIB route directly
+ removeFibEntryFromDS(routerID, destination);
+ }
+ }
+
+ protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
+
+ InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
+ InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
+ Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
+
+ if (vpnInstances.isPresent()) {
+ List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
+ Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
+ while (vpnInstIter.hasNext()) {
+ VpnInstance vpnInstance = vpnInstIter.next();
+ VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
+ String rd = vpnConfig.getRouteDistinguisher();
+
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnInVpn.isPresent()) {
+ if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
+ fibManager.populateFibOnNewDpn(dpnId, VpnUtil
+ .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
+ }
+ 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();
+ for(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
+ InstanceIdentifier<VpnInterface> vpnIntfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
+ InstanceIdentifier<Adjacencies> path = vpnIntfId.augmentation(Adjacencies.class);
+ Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+
+ if (adjacencies.isPresent()) {
+ List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
+ Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
+
+ while (adjacencyIterator.hasNext()) {
+ Adjacency adjacency = adjacencyIterator.next();
+ try {
+ if(action == UpdateRouteAction.ADVERTISE_ROUTE)
+ bgpManager.addPrefix(rd, adjacency.getIpAddress(), adjacency.getNextHopIp(), adjacency.getLabel().intValue());
+ else if(action == UpdateRouteAction.WITHDRAW_ROUTE)
+ bgpManager.deletePrefix(rd, adjacency.getIpAddress());
+ } catch (Exception e) {
+ LOG.error("Exception when updating prefix {} in vrf {} to BGP", adjacency.getIpAddress(), rd);
+ }
+ }
+ }
+
+ }
+ if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
+ fibManager.cleanUpDpnForVpn(dpnId, VpnUtil
+ .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
}
- } else {
- LOG.debug("No VPN Interface associated with interface {} to handle add Operation", interfaceName);
}
}
}
}
+
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnRouteList;
+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.VpnInstanceOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
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.VpnInstance1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpDataBuilder;
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.fibmanager.rev150330.vrfentries.VrfEntry;
-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.IdManagerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Listens for data change related to VPN Instance
* Informs the BGP about VRF information
- *
+ *
* @param db - dataBroker reference
*/
public VpnManager(final DataBroker db, final IBgpManager bgpManager) {
protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
LOG.trace("Remove VPN event - Key: {}, value: {}", identifier, del);
String vpnName = del.getVpnInstanceName();
- InstanceIdentifier<VpnInstance> vpnIdentifier = VpnUtil.getVpnInstanceIdentifier(vpnName);
+
//Clean up vpn Interface
InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.OPERATIONAL, vpnInterfacesId);
}
}
}
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+ vpnIdentifier = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
+ delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
- delete(LogicalDatastoreType.OPERATIONAL, vpnIdentifier);
-
+ VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
String rd = del.getIpv4Family().getRouteDistinguisher();
- try {
- bgpManager.deleteVrf(rd);
- } catch(Exception e) {
- LOG.error("Exception when removing VRF from BGP", e);
+
+ if (rd !=null) {
+
+ delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+ try {
+ bgpManager.deleteVrf(rd);
+ } catch(Exception e) {
+ LOG.error("Exception when removing VRF from BGP", e);
+ }
+ } else {
+ delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
}
}
protected void add(InstanceIdentifier<VpnInstance> identifier,
VpnInstance value) {
LOG.trace("key: {}, value: {}", identifier, value);
+ VpnAfConfig config = value.getIpv4Family();
+ String rd = config.getRouteDistinguisher();
long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, value.getVpnInstanceName());
- VpnInstance opValue = new VpnInstanceBuilder(value).
- addAugmentation(VpnInstance1.class, new VpnInstance1Builder().setVpnId(vpnId).build()).build();
+ 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.OPERATIONAL, identifier, opValue, DEFAULT_CALLBACK);
+ asyncWrite(LogicalDatastoreType.CONFIGURATION,
+ VpnUtil.getVpnInstanceToVpnIdIdentifier(value.getVpnInstanceName()),
+ vpnInstanceToVpnId, DEFAULT_CALLBACK);
- //public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts)
- VpnAfConfig config = value.getIpv4Family();
- String rd = config.getRouteDistinguisher();
- List<String> importRts = Arrays.asList(config.getImportRoutePolicy().split(","));
- List<String> exportRts = Arrays.asList(config.getExportRoutePolicy().split(","));
- try {
- bgpManager.addVrf(rd, importRts, exportRts);
- } catch(Exception e) {
- LOG.error("Exception when adding VRF to BGP", e);
+
+ if(rd == null) {
+ asyncWrite(LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(value.getVpnInstanceName()),
+ VpnUtil.getVpnInstanceOpData(value.getVpnInstanceName(), vpnId), DEFAULT_CALLBACK);
+
+ } else {
+ asyncWrite(LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ VpnUtil.getVpnInstanceOpData(rd, vpnId), DEFAULT_CALLBACK);
+
+ List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+
+ List<String> ertList = new ArrayList<String>();
+ List<String> irtList = new ArrayList<String>();
+
+ for (VpnTarget vpnTarget : vpnTargetList) {
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ }
+
+ try {
+ bgpManager.addVrf(rd, irtList, ertList);
+ } catch(Exception e) {
+ LOG.error("Exception when adding VRF to BGP", e);
+ }
}
}
Futures.addCallback(tx.submit(), callback);
}
- private VpnInstance getVpnForRD(String rd) {
- InstanceIdentifier<VpnInstances> id = InstanceIdentifier.create(VpnInstances.class);
- Optional<VpnInstances> vpnInstances = read(LogicalDatastoreType.OPERATIONAL, id);
- if(vpnInstances.isPresent()) {
- List<VpnInstance> vpns = vpnInstances.get().getVpnInstance();
- for(VpnInstance vpn : vpns) {
- if(vpn.getIpv4Family().getRouteDistinguisher().equals(rd)) {
- return vpn;
- }
- }
+ protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
+ if(vpnInstanceOpData.isPresent()) {
+ return vpnInstanceOpData.get();
}
return null;
}
-// private Integer getUniqueId(IdManagerService idManager, String poolName,String idKey) {
-// AllocateIdInput getIdInput = new AllocateIdInputBuilder()
-// .setPoolName(poolName)
-// .setIdKey(idKey).build();
-//
-// try {
-// Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
-// RpcResult<AllocateIdOutput> rpcResult = result.get();
-// if(rpcResult.isSuccessful()) {
-// return rpcResult.getResult().getIdValue().intValue();
-// } else {
-// LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
-// }
-// } catch (InterruptedException | ExecutionException e) {
-// LOG.warn("Exception when getting Unique Id",e);
-// }
-// return 0;
-// }
-
private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
WriteTransaction tx = broker.newWriteOnlyTransaction();
tx.delete(datastoreType, path);
final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
String rd = key.getRouteDistinguisher();
Long label = del.getLabel();
- VpnInstance vpn = getVpnForRD(rd);
- if(vpn != null) {
- InstanceIdentifier<VpnInstance> id = VpnUtil.getVpnInstanceIdentifier(vpn.getVpnInstanceName());
- InstanceIdentifier<VpnInstance1> augId = id.augmentation(VpnInstance1.class);
- Optional<VpnInstance1> vpnAugmenation = read(LogicalDatastoreType.OPERATIONAL, augId);
- if(vpnAugmenation.isPresent()) {
- VpnInstance1 vpnAug = vpnAugmenation.get();
- List<Long> routeIds = vpnAug.getRouteEntryId();
- if(routeIds == null) {
- LOG.debug("Fib Route entry is empty.");
- return;
- }
- LOG.debug("Removing label from vpn info - {}", label);
- routeIds.remove(label);
- asyncWrite(LogicalDatastoreType.OPERATIONAL, augId,
- new VpnInstance1Builder(vpnAug).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
- } else {
- LOG.warn("VPN Augmentation not found for vpn instance {}", vpn.getVpnInstanceName());
+ VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
+ if(vpnInstanceOpData != null) {
+ List<Long> routeIds = vpnInstanceOpData.getRouteEntryId();
+ if(routeIds == null) {
+ LOG.debug("Fib Route entry is empty.");
+ return;
}
+ LOG.debug("Removing label from vpn info - {}", label);
+ routeIds.remove(label);
+ asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ new VpnInstanceOpDataEntryBuilder(vpnInstanceOpData).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
} else {
LOG.warn("No VPN Instance found for RD: {}", rd);
}
@Override
protected void add(InstanceIdentifier<VrfEntry> identifier,
- VrfEntry add) {
+ VrfEntry add) {
LOG.trace("Add Vrf Entry event - Key : {}, value : {}", identifier, add);
final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
String rd = key.getRouteDistinguisher();
Long label = add.getLabel();
- VpnInstance vpn = getVpnForRD(rd);
+ VpnInstanceOpDataEntry vpn = getVpnInstanceOpData(rd);
if(vpn != null) {
- InstanceIdentifier<VpnInstance> id = VpnUtil.getVpnInstanceIdentifier(vpn.getVpnInstanceName());
- InstanceIdentifier<VpnInstance1> augId = id.augmentation(VpnInstance1.class);
- Optional<VpnInstance1> vpnAugmenation = read(LogicalDatastoreType.OPERATIONAL, augId);
- if(vpnAugmenation.isPresent()) {
- VpnInstance1 vpnAug = vpnAugmenation.get();
- List<Long> routeIds = vpnAug.getRouteEntryId();
- if(routeIds == null) {
- routeIds = new ArrayList<>();
- }
- LOG.debug("Adding label to vpn info - {}", label);
- routeIds.add(label);
- asyncWrite(LogicalDatastoreType.OPERATIONAL, augId,
- new VpnInstance1Builder(vpnAug).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
- } else {
- LOG.warn("VPN Augmentation not found for vpn instance {}", vpn.getVpnInstanceName());
+ List<Long> routeIds = vpn.getRouteEntryId();
+ if(routeIds == null) {
+ routeIds = new ArrayList<>();
}
+ LOG.debug("Adding label to vpn info - {}", label);
+ routeIds.add(label);
+ asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ new VpnInstanceOpDataEntryBuilder(vpn).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
} else {
LOG.warn("No VPN Instance found for RD: {}", rd);
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
package org.opendaylight.vpnservice;
-import java.util.List;
+import java.math.BigInteger;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.List;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import 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.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
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.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.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.prefix.to._interface.vpn.ids.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
+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.VpnInstanceOpDataEntryBuilder;
+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.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;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VpnUtil {
-
private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
private static final int DEFAULT_PREFIX_LENGTH = 32;
private static final String PREFIX_SEPARATOR = "/";
}
static VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug) {
- return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName)
+ return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(
+ vpnName)
.addAugmentation(Adjacencies.class, aug).build();
}
- static Adjacencies getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
+ static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
+ return InstanceIdentifier.builder(PrefixToInterface.class)
+ .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class,
+ new PrefixesKey(ipPrefix)).build();
+ }
+
+ static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix) {
+ return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(
+ vpnInterfaceName).setIpAddress(ipPrefix).build();
+ }
+
+ static Adjacencies
+ getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
return new AdjacenciesBuilder().setAdjacency(nextHops).build();
}
.child(Interface.class, new InterfaceKey(interfaceName)).build();
}
- public static String getNextHopLabelKey(String rd, String prefix){
- String key = rd + VpnConstants.SEPARATOR + prefix;
- return key;
+ static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
+ return InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
+ .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
}
- static String getIpPrefix(String prefix) {
- String prefixValues[] = prefix.split("/");
- if (prefixValues.length == 1) {
- prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ;
- }
- return prefix;
+ public static BigInteger getCookieArpFlow(int interfaceTag) {
+ return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0110000", 16)).add(
+ BigInteger.valueOf(interfaceTag));
+ }
+
+ public static String getFlowRef(BigInteger dpnId, short tableId, int ethType, int lPortTag, int arpType) {
+ return new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(ethType).append(lPortTag)
+ .append(NwConstants.FLOWID_SEPARATOR).append(arpType).toString();
}
public static int getUniqueId(IdManagerService idManager, String poolName,String idKey) {
AllocateIdInput getIdInput = new AllocateIdInputBuilder()
- .setPoolName(poolName)
- .setIdKey(idKey).build();
+ .setPoolName(poolName)
+ .setIdKey(idKey).build();
try {
Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
}
return 0;
}
+
+ public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
+ }
+ }
+
+ public static String getNextHopLabelKey(String rd, String prefix){
+ String key = rd + VpnConstants.SEPARATOR + prefix;
+ return key;
+ }
+
+ public static long getVpnId(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ long vpnId = VpnConstants.INVALID_ID;
+ if(vpnInstance.isPresent()) {
+ vpnId = vpnInstance.get().getVpnId();
+ }
+ return vpnId;
+ }
+
+ public static String getVpnRd(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ String rd = null;
+ if(vpnInstance.isPresent()) {
+ rd = vpnInstance.get().getVrfId();
+ }
+ return rd;
+ }
+
+ static org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
+ getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
+ return new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder()
+ .setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
+
+ }
+
+ static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+ getVpnInstanceToVpnIdIdentifier(String vpnName) {
+ return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
+ }
+
+ static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
+ return InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
+ }
+
+ static VpnInstanceOpDataEntry getVpnInstanceOpData(String rd, long vpnId) {
+ return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).build();
+ }
+
+ static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+ if (configuredVpnInterface.isPresent()) {
+ return configuredVpnInterface.get();
+ }
+ return null;
+ }
+
+ static VpnInterface getOperationalVpnInterface(DataBroker broker, String interfaceName) {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> operationalVpnInterface = read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+
+ if (operationalVpnInterface.isPresent()) {
+ return operationalVpnInterface.get();
+ }
+ return null;
+ }
+
+ static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName)
+ {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+ if (configuredVpnInterface.isPresent()) {
+ return true;
+ }
+ return false;
+ }
+
+ static String getIpPrefix(String prefix) {
+ String prefixValues[] = prefix.split("/");
+ if (prefixValues.length == 1) {
+ prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ;
+ }
+ return prefix;
+ }
+
+ 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);
+ };
+ };
+
+ public 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 asyncUpdate(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 asyncWrite(DataBroker broker, 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);
+ }
+
+ static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data) {
+ 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 to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
package org.opendaylight.vpnservice;
import java.math.BigInteger;
-import java.util.Collection;
-import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.opendaylight.bgpmanager.api.IBgpManager;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.fibmanager.api.IFibManager;
import org.opendaylight.vpnmanager.api.IVpnManager;
-import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
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;
private IBgpManager bgpManager;
private IFibManager fibManager;
private IMdsalApiManager mdsalManager;
- private IInterfaceManager interfaceManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private ItmRpcService itmProvider;
private IdManagerService idManager;
- private InterfaceChangeListener interfaceListener;
+ private OdlArputilService arpManager;
+ private NotificationService notificationService;
@Override
public void onSessionInitiated(ProviderContext session) {
final DataBroker dataBroker = session.getSALService(DataBroker.class);
vpnManager = new VpnManager(dataBroker, bgpManager);
vpnManager.setIdManager(idManager);
- vpnInterfaceManager = new VpnInterfaceManager(dataBroker, bgpManager);
+ vpnInterfaceManager = new VpnInterfaceManager(dataBroker, bgpManager, notificationService);
vpnInterfaceManager.setMdsalManager(mdsalManager);
vpnInterfaceManager.setInterfaceManager(interfaceManager);
+ vpnInterfaceManager.setITMProvider(itmProvider);
vpnInterfaceManager.setIdManager(idManager);
+ vpnInterfaceManager.setArpManager(arpManager);
vpnManager.setVpnInterfaceManager(vpnInterfaceManager);
- interfaceListener = new InterfaceChangeListener(dataBroker, vpnInterfaceManager);
- interfaceListener.setInterfaceManager(interfaceManager);
createIdPool();
} catch (Exception e) {
LOG.error("Error initializing services", e);
}
}
+ public void setNotificationService(NotificationService notificationService) {
+ this.notificationService = notificationService;
+ }
+
public void setBgpManager(IBgpManager bgpManager) {
LOG.debug("BGP Manager reference initialized");
this.bgpManager = bgpManager;
this.fibManager = fibManager;
}
- public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
this.interfaceManager = interfaceManager;
}
+ public void setITMProvider(ItmRpcService itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
public void setIdManager(IdManagerService idManager) {
this.idManager = idManager;
}
+ public void setArpManager(OdlArputilService arpManager) {
+ this.arpManager = arpManager;
+ }
+
private void createIdPool() {
CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
.setPoolName(VpnConstants.VPN_IDPOOL_NAME)
public void close() throws Exception {
vpnManager.close();
vpnInterfaceManager.close();
- interfaceListener.close();
- }
- @Override
- public Collection<BigInteger> getDpnsForVpn(long vpnId) {
- return vpnInterfaceManager.getDpnsForVpn(vpnId);
}
@Override
this.fibManager = fibManager;
vpnInterfaceManager.setFibManager(fibManager);
}
+
+ @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);
+ }
+
+ @Override
+ public void delExtraRoute(String destination, String rd, String routerID) {
+ LOG.info("Deleting extra route with destination {}", destination);
+ vpnInterfaceManager.delExtraRoute(destination, rd, routerID);
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 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.utilities;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.VpnUtil;
+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.InterfacesState;
+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;
+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.params.xml.ns.yang.itm.op.rev150701.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.DPNTEPsInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceBindings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceTypeFlowBased;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServicesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServicesKey;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+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.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class InterfaceUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceUtils.class);
+ private static String OF_URI_SEPARATOR = ":";
+
+ public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
+ BigInteger nodeId = BigInteger.ZERO;
+ try {
+ GetDpidFromInterfaceInput
+ dpIdInput =
+ new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
+ Future<RpcResult<GetDpidFromInterfaceOutput>>
+ dpIdOutput =
+ interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
+ RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
+ if (dpIdResult.isSuccessful()) {
+ nodeId = dpIdResult.getResult().getDpid();
+ } else {
+ LOG.error("Could not retrieve DPN Id for interface {}", ifName);
+ }
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.error("Exception when getting dpn for interface {}", ifName, e);
+ }
+ return nodeId;
+ }
+
+ public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
+ String nextHopIp = null;
+ InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
+ InstanceIdentifier.builder(Tunnels.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
+ Optional<DPNTEPsInfo> tunnelInfo = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
+ if (tunnelInfo.isPresent()) {
+ List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
+ if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
+ nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
+ }
+ }
+ return nextHopIp;
+ }
+
+ public static InstanceIdentifier<BoundServices> buildServiceId(String vpnInterfaceName, short serviceIndex) {
+ return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(vpnInterfaceName))
+ .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
+ }
+
+ public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
+ BigInteger cookie, List<Instruction> instructions) {
+ StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority).setInstruction(instructions);
+ return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority))
+ .setServiceName(serviceName).setServicePriority(servicePriority)
+ .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
+ }
+
+ public static boolean isOperational(DataBroker dataBroker, String ifName) {
+ return getInterfaceStateFromOperDS(dataBroker, ifName) == null ? false : true;
+ }
+
+ public static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ return id;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ buildStateInterfaceId(interfaceName);
+ Optional<Interface> ifStateOptional =
+ VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
+ if (ifStateOptional.isPresent()) {
+ return ifStateOptional.get();
+ }
+
+ return null;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface getInterface(DataBroker broker, String interfaceName) {
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> optInterface =
+ VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
+ if(optInterface.isPresent()) {
+ return optInterface.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
+ return InstanceIdentifier.builder(Interfaces.class)
+ .child(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface.class, new InterfaceKey(interfaceName)).build();
+ }
+
+ public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(OF_URI_SEPARATOR);
+ return split[1];
+ }
+}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216;
import org.opendaylight.vpnservice.VpnserviceProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
public class VpnserviceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216.AbstractVpnserviceImplModule {
public VpnserviceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@Override
public java.lang.AutoCloseable createInstance() {
IdManagerService idManager = getRpcregistryDependency().getRpcService(IdManagerService.class);
+ OdlArputilService arpManager = getRpcregistryDependency().getRpcService(OdlArputilService.class);
+ OdlInterfaceRpcService interfaceManager = getRpcregistryDependency().getRpcService(OdlInterfaceRpcService.class);
VpnserviceProvider provider = new VpnserviceProvider();
+ provider.setNotificationService(getNotificationServiceDependency());
provider.setBgpManager(getBgpmanagerDependency());
provider.setMdsalManager(getMdsalutilDependency());
- provider.setInterfaceManager(getOdlinterfaceDependency());
+ provider.setInterfaceManager(interfaceManager);
provider.setIdManager(idManager);
+ provider.setArpManager(arpManager);
getBrokerDependency().registerProvider(provider);
return provider;
}
import config { prefix config; revision-date 2013-04-05; }
import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+ import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28;}
import bgpmanager-api { prefix bgpmgr-api; revision-date 2015-04-20;}
import vpnmanager-api { prefix vpnmgr-api; revision-date 2015-05-08;}
import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
- import odl-interface {prefix odlif; revision-date 2015-03-31;}
description
"Service definition for vpnservice project";
}
}
}
- container odlinterface {
+ container notification-service {
uses config:service-ref {
refine type {
mandatory true;
- config:required-identity odlif:odl-interface;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
}
}
}
/*
- * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 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,
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
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.af.config.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4Family;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.ApplyLabelBuilder;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(MockitoJUnitRunner.class)
public class VpnServiceTest {
@Mock DataBroker dataBroker;
@Test
public void test() {
- VpnInstanceBuilder builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey("Vpn1")).
- setIpv4Family(new Ipv4FamilyBuilder().setRouteDistinguisher("100:1").setImportRoutePolicy("100:2").
- setExportRoutePolicy("100:1").setApplyLabel(new ApplyLabelBuilder().setApplyLabelMode(
- new PerRouteBuilder().setApplyLabelPerRoute(true).build()).build()).build());
+
+ List<VpnTarget> vpnTargetList = new ArrayList<VpnTarget>();
+
+ VpnTarget vpneRTarget = new VpnTargetBuilder().setKey(new VpnTargetKey("100:1")).setVrfRTValue("100:1")
+ .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+ VpnTarget vpniRTarget = new VpnTargetBuilder().setKey(new VpnTargetKey("100:2")).setVrfRTValue("100:2")
+ .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
+
+ vpnTargetList.add(vpneRTarget);
+ vpnTargetList.add(vpniRTarget);
+
+ VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+
+ Ipv4Family ipv4Family = new Ipv4FamilyBuilder().setRouteDistinguisher("100:1").setVpnTargets(vpnTargets)
+ .setApplyLabel(new ApplyLabelBuilder().setApplyLabelMode(
+ new PerRouteBuilder().setApplyLabelPerRoute(true).build()).build()).build();
+
+ VpnInstanceBuilder builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey("Vpn1")).setIpv4Family
+ (ipv4Family);
VpnInstance instance = builder.build();
VpnManager vpnManager = new VpnManager(dataBroker, bgpManager);
event.created.put(createVpnId("Vpn1"), instance);