*/
package org.opendaylight.vpnservice.nexthopmgr;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
-
import com.google.common.base.Optional;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.FutureCallback;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.idmanager.IdManager;
-
import java.util.concurrent.ExecutionException;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private IMdsalApiManager mdsalManager;
private IInterfaceManager interfaceManager;
private IdManager 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 FutureCallback<Void> DEFAULT_CALLBACK =
new FutureCallback<Void>() {
.build();
//TODO: Error handling
Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ LOG.trace("NextHopPointerPool result : {}", result);
// try {
// LOG.info("Result2: {}",result.get());
// } catch (InterruptedException | ExecutionException e) {
}
- private long getVpnId(String vpnName) {
+ protected long getVpnId(String vpnName) {
InstanceIdentifierBuilder<VpnInstance> idBuilder = InstanceIdentifier.builder(VpnInstances.class)
.child(VpnInstance.class, new VpnInstanceKey(vpnName));
Optional<VpnInstance1> vpn = read(LogicalDatastoreType.OPERATIONAL, idx);
if (vpn.isPresent()) {
+ LOG.debug("VPN id returned: {}", vpn.get().getVpnId());
return vpn.get().getVpnId();
} else {
return -1;
}
}
- private long getDpnId(String ifName) {
- String[] fields = ifName.split(":");
- long dpn = Integer.parseInt(fields[1]);
+ private BigInteger getDpnId(String ofPortId) {
+ String[] fields = ofPortId.split(":");
+ BigInteger dpn = new BigInteger(fields[1]);
+ LOG.debug("DpnId: {}", dpn);
return dpn;
}
- private int createNextHopPointer(String nexthopKey) {
+ protected int createNextHopPointer(String nexthopKey) {
GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder()
.setPoolName("nextHopPointerPool").setIdKey(nexthopKey)
.build();
int groupId = createNextHopPointer(nhKey);
long vpnId = getVpnId(vpnName);
- long dpnId = interfaceManager.getDpnForInterface(ifName);
- VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
+ BigInteger dpnId = interfaceManager.getDpnForInterface(ifName);
+ VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress, 0);
LOG.trace("nexthop: {}", nexthop);
if (nexthop == null) {
List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
// MAC re-write
if (macAddress != null) {
listActionInfo.add(0, new ActionInfo(ActionType.set_field_eth_dest, new String[]{macAddress}));
- listActionInfo.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ 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(
String nhKey = new String("nexthop." + ifName + ipAddress);
int groupId = createNextHopPointer(nhKey);
- long dpnId = getDpnId(ofPortId);
+ BigInteger dpnId = getDpnId(ofPortId);
TunnelNexthop nexthop = getTunnelNexthop(dpnId, ipAddress);
if (nexthop == null) {
-
List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
List<ActionInfo> listActionInfo = interfaceManager.getInterfaceEgressActions(ifName);
BucketInfo bucket = new BucketInfo(listActionInfo);
GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo);
mdsalManager.installGroup(groupEntity);
+ //makeRemoteFlow(dpnId, ifName, NwConstants.ADD_FLOW);
//update MD-SAL DS
addTunnelNexthopToDS(dpnId, ipAddress, groupId);
}
}
- private void addVpnNexthopToDS(long vpnId, String ipPrefix, long egressPointer) {
+ private void makeRemoteFlow(BigInteger dpnId, String ifName, int addOrRemoveFlow) {
+ long portNo = 0;
+ String flowName = ifName;
+ String flowRef = getTunnelInterfaceFlowRef(dpnId, 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[] {LFIB_TABLE}));
+ }
- InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
- .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+ BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, LPORT_INGRESS_TABLE, flowRef,
+ DEFAULT_FLOW_PRIORITY, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
- // check if vpn node is there or to be created
- InstanceIdentifier<VpnNexthops> id = idBuilder.build();
- Optional<VpnNexthops> nexthops = read(LogicalDatastoreType.OPERATIONAL, id);
- if (!nexthops.isPresent()) {
- // create a new node
- VpnNexthops node = new VpnNexthopsBuilder().setKey(new VpnNexthopsKey(vpnId)).setVpnId(vpnId).build();
- asyncWrite(LogicalDatastoreType.OPERATIONAL, id, node, DEFAULT_CALLBACK);
+ if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
+ mdsalManager.installFlow(flowEntity);
+ } else {
+ mdsalManager.removeFlow(flowEntity);
}
+ }
+
+ private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
+ return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
+ }
+
+ protected void addVpnNexthopToDS(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().
InstanceIdentifier<VpnNexthop> id1 = idBuilder
.child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build();
- LOG.trace("Adding nextHop {} to Operational DS", nh);
- asyncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
+ LOG.trace("Adding vpnnextHop {} to Operational DS", nh);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
}
- private void addTunnelNexthopToDS(long dpnId, String ipPrefix, long egressPointer) {
+ private void addTunnelNexthopToDS(BigInteger dpnId, String ipPrefix, long egressPointer) {
InstanceIdentifierBuilder<TunnelNexthops> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
.child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId));
- // check if dpn node is there or to be created
- InstanceIdentifier<TunnelNexthops> id = idBuilder.build();
- Optional<TunnelNexthops> nexthops = read(LogicalDatastoreType.OPERATIONAL, id);
- if (!nexthops.isPresent()) {
- // create a new node
- TunnelNexthops node = new TunnelNexthopsBuilder()
- .setKey(new TunnelNexthopsKey(dpnId))
- .setDpnId(dpnId)
- .build();
- asyncWrite(LogicalDatastoreType.OPERATIONAL, id, node, DEFAULT_CALLBACK);
- }
-
// Add nexthop to dpn node
TunnelNexthop nh = new TunnelNexthopBuilder().
setKey(new TunnelNexthopKey(ipPrefix)).
InstanceIdentifier<TunnelNexthop> id1 = idBuilder
.child(TunnelNexthop.class, new TunnelNexthopKey(ipPrefix)).build();
-
+ LOG.trace("Adding tunnelnextHop {} to Operational DS for a dpn node", nh);
asyncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
}
- private VpnNexthop getVpnNexthop(long vpnId, String ipAddress) {
+ protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress, int retryCount) {
- // check if vpn node is there
- InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
- .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+ // 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
- return nexthop;
+ try {
+ for (int retry = 0; retry <= retryCount; retry++) {
+ 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;
+ }
+ }
}
+ Thread.sleep(100L);
}
+ } catch (InterruptedException e) {
+ LOG.trace("", e);
}
- //return null if not found
+ // return null if not found
return null;
}
- private TunnelNexthop getTunnelNexthop(long dpnId, String ipAddress) {
+ private TunnelNexthop getTunnelNexthop(BigInteger dpnId, String ipAddress) {
InstanceIdentifierBuilder<TunnelNexthops> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
.child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId));
List<TunnelNexthop> nexthops = dpnNexthops.get().getTunnelNexthop();
for (TunnelNexthop nexthop : nexthops) {
if (nexthop.getIpAddress().equals(ipAddress)) {
+ LOG.trace("TunnelNextHop : {}",nexthop);
return nexthop;
}
}
return null;
}
- public long getNextHopPointer(long dpnId, long vpnId, String prefixIp, String nextHopIp) {
+ public long getNextHopPointer(BigInteger dpnId, long vpnId, String prefixIp, String nextHopIp) {
String endpointIp = interfaceManager.getEndpointIpForDpn(dpnId);
if (nextHopIp.equals(endpointIp)) {
- VpnNexthop vpnNextHop = getVpnNexthop(vpnId, prefixIp);
+ VpnNexthop vpnNextHop = getVpnNexthop(vpnId, prefixIp, 0);
return vpnNextHop.getEgressPointer();
} else {
TunnelNexthop tunnelNextHop = getTunnelNexthop(dpnId, nextHopIp);
+ LOG.trace("NExtHopPointer : {}", tunnelNextHop.getEgressPointer());
return tunnelNextHop.getEgressPointer();
}
}
- private void removeTunnelNexthopFromDS(long dpnId, String ipPrefix) {
+ private void removeTunnelNexthopFromDS(BigInteger dpnId, String ipPrefix) {
InstanceIdentifierBuilder<TunnelNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
.child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId))
.child(TunnelNexthop.class, new TunnelNexthopKey(ipPrefix));
InstanceIdentifier<TunnelNexthop> id = idBuilder.build();
// remove from DS
+ LOG.trace("Removing tunnel next hop from datastore : {}", id);
delete(LogicalDatastoreType.OPERATIONAL, id);
}
.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(Long dpId, Long vpnId, String ipAddress) {
+ public void removeLocalNextHop(BigInteger dpnId, Long vpnId, String ipAddress) {
- VpnNexthop nh = getVpnNexthop(vpnId, ipAddress);
+ VpnNexthop nh = getVpnNexthop(vpnId, ipAddress, 0);
if (nh != null) {
// how to inform and remove dependent FIB entries??
// we need to do it before the group is removed
GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
- dpId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
+ dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
// remove Group ...
mdsalManager.removeGroup(groupEntity);
//update MD-SAL DS
removeVpnNexthopFromDS(vpnId, ipAddress);
} else {
//throw error
+ LOG.error("removal of local next hop failed");
}
}
- public void removeRemoteNextHop(long dpnId, String ipAddress) {
+ public void removeRemoteNextHop(BigInteger dpnId, String ifName, String ipAddress) {
TunnelNexthop nh = getTunnelNexthop(dpnId, ipAddress);
if (nh != null) {
dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
// remove Group ...
mdsalManager.removeGroup(groupEntity);
+ //makeRemoteFlow(dpnId, ifName, NwConstants.DEL_FLOW);
//update MD-SAL DS
removeTunnelNexthopFromDS(dpnId, ipAddress);
} else {
//throw error
+ LOG.error("removal of remote next hop failed : dpnid : {}, ipaddress : {}", dpnId, ipAddress);
}
}
String endpointIp = interfaceManager.getEndpointIpForDpn(input.getDpnId());
LOG.trace("getEgressPointer: input {}, endpointIp {}", input, endpointIp);
- if (input.getNexthopIp().equals(endpointIp)) {
- VpnNexthop vpnNextHop = getVpnNexthop(input.getVpnId(), input.getIpPrefix());
+ if (input.getNexthopIp() == null || input.getNexthopIp().equals(endpointIp)) {
+ VpnNexthop vpnNextHop = getVpnNexthop(input.getVpnId(), input.getIpPrefix(), 5);
output.setEgressPointer(vpnNextHop.getEgressPointer());
output.setLocalDestination(true);
} else {
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);
+ 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();
@Override
public Future<RpcResult<Void>> removeLocalNextHop(RemoveLocalNextHopInput input) {
- VpnNexthop vpnNextHop = getVpnNexthop(input.getVpnId(), input.getIpPrefix());
+ VpnNexthop vpnNextHop = getVpnNexthop(input.getVpnId(), input.getIpPrefix(), 0);
RpcResultBuilder<Void> rpcResultBuilder;
LOG.debug("vpnnexthop is: {}", vpnNextHop);
try {