*/
package org.opendaylight.vpnservice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.L3tunnel;
+
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
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;
private ListenerRegistration<DataChangeListener> listenerRegistration;
private final DataBroker broker;
private final IBgpManager bgpManager;
+ private IFibManager fibManager;
private IMdsalApiManager mdsalManager;
private IInterfaceManager interfaceManager;
private IdManagerService idManager;
- private Map<Long, Collection<Long>> vpnToDpnsDb;
- private Map<Long, Collection<String>> dpnToInterfaceDb;
+ private Map<Long, Collection<BigInteger>> vpnToDpnsDb;
+ private Map<BigInteger, Collection<String>> dpnToInterfaceDb;
private static final FutureCallback<Void> DEFAULT_CALLBACK =
new FutureCallback<Void>() {
this.interfaceManager = interfaceManager;
}
+ public void setFibManager(IFibManager fibManager) {
+ this.fibManager = fibManager;
+ }
+
public void setIdManager(IdManagerService idManager) {
this.idManager = idManager;
}
Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
if (port.isPresent()) {
Interface interf = port.get();
- bindServiceOnInterface(interf, getVpnId(vpnInterface.getVpnInstanceName()));
+ bindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
updateNextHops(identifier, vpnInterface);
}
}
//Get the rd of the vpn instance
String rd = getRouteDistinguisher(intf.getVpnInstanceName());
- long dpnId = interfaceManager.getDpnForInterface(intfName);
+ BigInteger dpnId = interfaceManager.getDpnForInterface(intfName);
String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
- if (!nextHops.isEmpty()) {
- LOG.trace("NextHops are {}", nextHops);
- for (Adjacency nextHop : nextHops) {
- String key = nextHop.getIpAddress();
- long label = getUniqueId(key);
- updatePrefixToBGP(rd, nextHop, nextHopIp, label);
- value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
- }
+ LOG.trace("NextHops are {}", nextHops);
+ for (Adjacency nextHop : nextHops) {
+ String key = nextHop.getIpAddress();
+ long label = getUniqueId(key);
+ value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
}
+
Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
- asyncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);
+ for (Adjacency nextHop : nextHops) {
+ String key = nextHop.getIpAddress();
+ long label = getUniqueId(key);
+ updatePrefixToBGP(rd, nextHop, nextHopIp, label);
+ }
}
}
InstanceIdentifier<VpnInstance1> id = InstanceIdentifier.builder(VpnInstances.class)
.child(VpnInstance.class, new VpnInstanceKey(vpnName)).augmentation(VpnInstance1.class).build();
Optional<VpnInstance1> vpnInstance = read(LogicalDatastoreType.OPERATIONAL, id);
- //TODO: Default vpnid should be a constant.
- long vpnId = -1;
+
+ long vpnId = VpnConstants.INVALID_ID;
if(vpnInstance.isPresent()) {
vpnId = vpnInstance.get().getVpnId();
}
return rd;
}
- private synchronized void updateMappingDbs(long vpnId, long dpnId, String intfName) {
- Collection<Long> dpnIds = vpnToDpnsDb.get(vpnId);
+ 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);
- //TODO: Send an Event that new DPN added...
+ fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
}
Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
dpnToInterfaceDb.put(dpnId, intfNames);
}
- private synchronized void remoteFromMappingDbs(long vpnId, long dpnId, String inftName) {
+ 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);
+ //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
if(intfNames.isEmpty()) {
- Collection<Long> dpnIds = vpnToDpnsDb.get(vpnId);
+ Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
if(dpnIds == null) {
return;
}
dpnIds.remove(dpnId);
vpnToDpnsDb.put(vpnId, dpnIds);
+ fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
}
}
- private void bindServiceOnInterface(Interface intf, long vpnId) {
- LOG.trace("Bind service on interface {} for VPN: {}", intf, vpnId);
+ private void bindServiceOnInterface(Interface intf, String vpnName) {
+ LOG.trace("Bind service on interface {} for VPN: {}", intf, vpnName);
- long dpId = interfaceManager.getDpnForInterface(intf.getName());
- if(dpId == 0L) {
+ 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 {
- updateMappingDbs(vpnId, dpId, intf.getName());
+ String rd = getRouteDistinguisher(vpnName);
+ updateMappingDbs(vpnId, dpId, intf.getName(), rd);
}
long portNo = interfaceManager.getPortForInterface(intf.getName());
int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
short gotoTableId = VpnConstants.FIB_TABLE;
+ if(intf.getType().equals(L3tunnel.class)){
+ gotoTableId = VpnConstants.LFIB_TABLE;
+ }
List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
mkInstructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { gotoTableId }));
List<MatchInfo> matches = new ArrayList<MatchInfo>();
- matches.add(new MatchInfo(MatchFieldType.in_port, new long[] {
- dpId, portNo }));
+ 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(long dpId, short tableId,
+ private String getVpnInterfaceFlowRef(BigInteger dpId, short tableId,
long vpnId, long portNo) {
return new StringBuilder().append(dpId).append(tableId).append(vpnId).append(portNo).toString();
}
if (port.isPresent()) {
Interface interf = port.get();
removeNextHops(identifier, vpnInterface);
- unbindServiceOnInterface(interf, getVpnId(vpnInterface.getVpnInstanceName()));
+ unbindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
+ //InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+ delete(LogicalDatastoreType.OPERATIONAL, identifier);
} else {
LOG.warn("No nexthops were available to handle remove event {}", interfaceName);
}
}
}
}
- InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
- delete(LogicalDatastoreType.OPERATIONAL, interfaceId);
}
private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
}
- private void unbindServiceOnInterface(Interface intf, long vpnId) {
- LOG.trace("Unbind service on interface {} for VPN: {}", intf, vpnId);
+ private void unbindServiceOnInterface(Interface intf, String vpnName) {
+ LOG.trace("Unbind service on interface {} for VPN: {}", intf, vpnName);
- long dpId = interfaceManager.getDpnForInterface(intf.getName());
- if(dpId == 0L) {
+ long vpnId = getVpnId(vpnName);
+ BigInteger dpId = interfaceManager.getDpnForInterface(intf.getName());
+ if(dpId.equals(BigInteger.ZERO)) {
LOG.warn("DPN for interface {} not found. Unbind service on this interface aborted.", intf.getName());
return;
} else {
- remoteFromMappingDbs(vpnId, dpId, intf.getName());
+ String rd = getRouteDistinguisher(vpnName);
+ remoteFromMappingDbs(vpnId, dpId, intf.getName(), rd);
}
long portNo = interfaceManager.getPortForInterface(intf.getName());
int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
List<MatchInfo> matches = new ArrayList<MatchInfo>();
- matches.add(new MatchInfo(MatchFieldType.in_port, new long[] {
- dpId, portNo }));
+ 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);
}
private void removePrefixFromBGP(String rd, Adjacency nextHop) {
- //public void deletePrefix(String rd, String prefix) throws Exception;
try {
bgpManager.deletePrefix(rd, nextHop.getIpAddress());
} catch(Exception e) {
@Override
protected void update(InstanceIdentifier<VpnInterface> identifier,
VpnInterface original, VpnInterface update) {
- // TODO Auto-generated method stub
+ 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.
+ //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);
+ return;
+ }
+ vpnNameChanged = true;
+ 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> 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);
+ 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
+ label = getUniqueId(nextHop.getIpAddress());
+ }
+ removePrefixFromBGP(rd, nextHop);
+ updatePrefixToBGP(newRd, nextHop, nextHopIp, label);
+ }
+ asyncUpdate(LogicalDatastoreType.OPERATIONAL, identifier, update, DEFAULT_CALLBACK);
+ }
+ } 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,
Futures.addCallback(tx.submit(), callback);
}
- synchronized Collection<Long> getDpnsForVpn(long vpnId) {
- Collection<Long> dpnIds = vpnToDpnsDb.get(vpnId);
+ 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 {