X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=nexthopmgr%2Fnexthopmgr-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fvpnservice%2Fnexthopmgr%2FNexthopManager.java;h=8e1a4fc2e37d7cdf0d1eeec7af8d750baa389570;hb=cd331f15ad231c081bf3725fd10e8cfd39f58241;hp=71cfad7888ab8fdbea0b0bb16ba2c391caa8b7a9;hpb=2bfbbe0cf9942ff975dc82fc298c603fd9cef6a6;p=vpnservice.git diff --git a/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java b/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java index 71cfad78..8e1a4fc2 100644 --- a/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java +++ b/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java @@ -6,175 +6,413 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.vpnservice.nexthopmgr; -/********************************************************************************** -** NextHop MD-SAL DS -** ------------------------------------------------ -** DP_ID | VPN | IP Address | GroupId | -** ------------------------------------------------ -** -** Listen to DCNs from vpn-inetrfaces -** if a next-hop is added/removed in vpn-interfaces DS -** call add/removeNextHop(interface.dpn, interface.port, vpn_instance.vpnId, AdjacencyIpAddress); -** -** if a tunnel-interface is added inn interfaces DS -- -** call add/removeNextHop(interface.dpn, interface.port, 00, RemoteIpAddress); -*************************************************************************************/ -import java.util.Collections; -import java.util.Map; -import java.util.Set; + +import java.math.BigInteger; +import java.util.ArrayList; import java.util.List; -import com.google.common.base.Optional; -import com.google.common.collect.FluentIterable; +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.netconf.confignetconfconnector.mapping.rpc.Rpcs; import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; -import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; 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.common.api.data.LogicalDatastoreType; -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.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.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1; +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.GetUniqueIdOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.tunnelnexthops.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.*; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +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.idmanager.IdManager; -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.NextHopList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.next.hop.list.L3NextHops; -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.VpnInterface1; -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.opendaylight.vpnservice.l3nexthop.rev150330.L3nexthop; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150330.l3nexthop.VpnNexthops; +import java.util.concurrent.ExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class NexthopManager extends AbstractDataChangeListener implements AutoCloseable{ - private static final Logger LOG = LoggerFactory.getLogger(L3nexthop.class); - private ListenerRegistration listenerRegistration; +public class NexthopManager implements L3nexthopService, AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(NexthopManager.class); private final DataBroker broker; + private IMdsalApiManager mdsalManager; + private IInterfaceManager interfaceManager; + private IdManager idManager; + private static final FutureCallback DEFAULT_CALLBACK = + new FutureCallback() { + public void onSuccess(Void result) { + LOG.info("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) { - super(L3nexthop.class); broker = db; - registerListener(db); + createNexthopPointerPool(); } - @Override + @Override public void close() throws Exception { - if (listenerRegistration != null) { - try { - listenerRegistration.close(); - } catch (final Exception e) { - LOG.error("Error when cleaning up DataChangeListener.", e); + LOG.info("NextHop Manager Closed"); + } + + public void setInterfaceManager(IInterfaceManager ifManager) { + this.interfaceManager = ifManager; + } + + public void setMdsalManager(IMdsalApiManager mdsalManager) { + this.mdsalManager = mdsalManager; + } + + public void setIdManager(IdManager idManager) { + this.idManager = idManager; + } + + private void createNexthopPointerPool() { + CreateIdPoolInput createPool = new CreateIdPoolInputBuilder() + .setPoolName("nextHopPointerPool") + .setIdStart(1L) + .setPoolSize(new BigInteger("65535")) + .build(); + //TODO: Error handling + Future> result = idManager.createIdPool(createPool); +// try { +// LOG.info("Result2: {}",result.get()); +// } catch (InterruptedException | ExecutionException e) { +// // TODO Auto-generated catch block +// LOG.error("Error in result.get"); +// } + + } + + + private long getVpnId(String vpnName) { + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(VpnInstances.class) + .child(VpnInstance.class, new VpnInstanceKey(vpnName)); + + InstanceIdentifier id = idBuilder.build(); + InstanceIdentifier idx = id.augmentation(VpnInstance1.class); + Optional vpn = read(LogicalDatastoreType.CONFIGURATION, idx); + + if (vpn.isPresent()) { + return vpn.get().getVpnId(); + } else { + return 0; + } + } + + private long getDpnId(String ifName) { + String[] fields = ifName.split(":"); + long dpn = Integer.parseInt(fields[1]); + return dpn; + } + + private int createNextHopPointer(String nexthopKey) { + GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder() + .setPoolName("nextHopPointerPool").setIdKey(nexthopKey) + .build(); + //TODO: Proper error handling once IdManager code is complete + try { + Future> result = idManager.getUniqueId(getIdInput); + RpcResult rpcResult = result.get(); + return rpcResult.getResult().getIdValue().intValue(); + } catch (NullPointerException | InterruptedException | ExecutionException e) { + LOG.trace("",e); + } + return 0; + } + + public void createLocalNextHop(String ifName, String vpnName, String ipAddress, String macAddress) { + String nhKey = new String("nexthop." + vpnName + ipAddress); + int groupId = createNextHopPointer(nhKey); + + long vpnId = getVpnId(vpnName); + long dpnId = interfaceManager.getDpnForInterface(ifName); + VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress); + if (nexthop == null) { + List listBucketInfo = new ArrayList(); + List listActionInfo = interfaceManager.getInterfaceEgressActions(ifName); + BucketInfo bucket = new BucketInfo(listActionInfo); + // MAC re-write + if (macAddress != null) { + listActionInfo.add(new ActionInfo(ActionType.set_field_eth_dest, new String[]{macAddress})); + } else { + //FIXME: Log message here. + } + listBucketInfo.add(bucket); + GroupEntity groupEntity = MDSALUtil.buildGroupEntity( + dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo); + + // install Group + mdsalManager.installGroup(groupEntity); + + //update MD-SAL DS + addVpnNexthopToDS(vpnId, ipAddress, groupId); + } else { + //check update + } + } + + public void createRemoteNextHop(String ifName, String ofPortId, String ipAddress) { + String nhKey = new String("nexthop." + ifName + ipAddress); + int groupId = createNextHopPointer(nhKey); + + long dpnId = getDpnId(ofPortId); + TunnelNexthop nexthop = getTunnelNexthop(dpnId, ipAddress); + if (nexthop == null) { + + List listBucketInfo = new ArrayList(); + List listActionInfo = interfaceManager.getInterfaceEgressActions(ifName); + BucketInfo bucket = new BucketInfo(listActionInfo); + // MAC re-write?? + listBucketInfo.add(bucket); + GroupEntity groupEntity = MDSALUtil.buildGroupEntity( + dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo); + mdsalManager.installGroup(groupEntity); + + //update MD-SAL DS + addTunnelNexthopToDS(dpnId, ipAddress, groupId); + } else { + //check update + } + } + + private void addVpnNexthopToDS(long vpnId, String ipPrefix, long egressPointer) { + + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(L3nexthop.class) + .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)); + + // check if vpn node is there or to be created + InstanceIdentifier id = idBuilder.build(); + Optional nexthops = read(LogicalDatastoreType.CONFIGURATION, 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); + } + + // Add nexthop to vpn node + VpnNexthop nh = new VpnNexthopBuilder(). + setKey(new VpnNexthopKey(ipPrefix)). + setIpAddress(ipPrefix). + setEgressPointer(egressPointer).build(); + + InstanceIdentifier id1 = idBuilder + .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build(); + + asyncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK); + + } + + private void addTunnelNexthopToDS(long dpnId, String ipPrefix, long egressPointer) { + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(L3nexthop.class) + .child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId)); + + // check if dpn node is there or to be created + InstanceIdentifier id = idBuilder.build(); + Optional nexthops = read(LogicalDatastoreType.CONFIGURATION, 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)). + setIpAddress(ipPrefix). + setEgressPointer(egressPointer).build(); + + InstanceIdentifier id1 = idBuilder + .child(TunnelNexthop.class, new TunnelNexthopKey(ipPrefix)).build(); + + asyncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK); + + } + + private VpnNexthop getVpnNexthop(long vpnId, String ipAddress) { + + // check if vpn node is there + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(L3nexthop.class) + .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)); + InstanceIdentifier id = idBuilder.build(); + Optional vpnNexthops = read(LogicalDatastoreType.CONFIGURATION, id); + if (!vpnNexthops.isPresent()) { + + // get nexthops list for vpn + List nexthops = vpnNexthops.get().getVpnNexthop(); + for (VpnNexthop nexthop : nexthops) { + if (nexthop.getIpAddress().equals(ipAddress)) { + // return nexthop + return nexthop; + } } - listenerRegistration = null; } - LOG.info("VPN Interface Manager Closed"); + //return null if not found + return null; } + private TunnelNexthop getTunnelNexthop(long dpnId, String ipAddress) { + + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(L3nexthop.class) + .child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId)); + + // check if vpn node is there + InstanceIdentifier id = idBuilder.build(); + Optional dpnNexthops = read(LogicalDatastoreType.CONFIGURATION, id); + if (!dpnNexthops.isPresent()) { + List nexthops = dpnNexthops.get().getTunnelNexthop(); + for (TunnelNexthop nexthop : nexthops) { + if (nexthop.getIpAddress().equals(ipAddress)) { + return nexthop; + } + } + } + return null; + } + + public long getNextHopPointer(long dpnId, long vpnId, String prefixIp, String nextHopIp) { + String endpointIp = interfaceManager.getEndpointIpForDpn(dpnId); + if (nextHopIp.equals(endpointIp)) { + VpnNexthop vpnNextHop = getVpnNexthop(vpnId, prefixIp); + return vpnNextHop.getEgressPointer(); + } else { + TunnelNexthop tunnelNextHop = getTunnelNexthop(dpnId, nextHopIp); + return tunnelNextHop.getEgressPointer(); + } + } + + private void removeTunnelNexthopFromDS(long dpnId, String ipPrefix) { + + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(L3nexthop.class) + .child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId)) + .child(TunnelNexthop.class, new TunnelNexthopKey(ipPrefix)); + InstanceIdentifier id = idBuilder.build(); + // remove from DS + delete(LogicalDatastoreType.OPERATIONAL, id); + } + + private void removeVpnNexthopFromDS(long vpnId, String ipPrefix) { + + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(L3nexthop.class) + .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)) + .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)); + InstanceIdentifier id = idBuilder.build(); + // remove from DS + delete(LogicalDatastoreType.OPERATIONAL, id); + } - private void registerListener(final DataBroker db) { + + public void removeLocalNextHop(String vpnName, String ipAddress) { + + long vpnId = getVpnId(vpnName); + + VpnNexthop nh = getVpnNexthop(vpnId, ipAddress); + if (nh != null) { + // how to inform and remove dependent FIB entries?? + // we need to do it before the group is removed + + // remove Group ... + + //update MD-SAL DS + removeVpnNexthopFromDS(vpnId, ipAddress); + } else { + //throw error + } + + } + + public void removeRemoteNextHop(long dpnId, String ipAddress) { + + TunnelNexthop nh = getTunnelNexthop(dpnId, ipAddress); + if (nh != null) { + // how to inform and remove dependent FIB entries?? + // we need to do it before the group is removed + + // remove Group ... + //update MD-SAL DS + removeTunnelNexthopFromDS(dpnId, ipAddress); + } else { + //throw error + } + + } + + @Override + public Future> getEgressPointer( + GetEgressPointerInput input) { + long egressGroupId = + getNextHopPointer(input.getDpnId(), input.getVpnId(), input.getIpPrefix(), input.getNexthopIp()); + + GetEgressPointerOutputBuilder output = new GetEgressPointerOutputBuilder(); + output.setEgressPointer(egressGroupId); + + RpcResult result = null; + //Rpcs. getRpcResult(false, output.build()); + return Futures.immediateFuture(result); + } + + private Optional read(LogicalDatastoreType datastoreType, + InstanceIdentifier path) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional result = Optional.absent(); try { - listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, - getWildCardPath(), NexthopManager.this, DataChangeScope.SUBTREE); - } catch (final Exception e) { - LOG.error("Nexthop Manager DataChange listener registration fail!", e); - throw new IllegalStateException("Nexthop Manager registration Listener failed.", e); + result = tx.read(datastoreType, path).get(); + } catch (Exception e) { + throw new RuntimeException(e); } + + return result; + } + + private void asyncWrite(LogicalDatastoreType datastoreType, + InstanceIdentifier path, T data, FutureCallback callback) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.put(datastoreType, path, data, true); + Futures.addCallback(tx.submit(), callback); + } + + + private void delete(LogicalDatastoreType datastoreType, InstanceIdentifier path) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.delete(datastoreType, path); + Futures.addCallback(tx.submit(), DEFAULT_CALLBACK); } - - public void addNextHop(long dpnId, int port, String vpnRD, String IpAddress) - { - String nhKey = new String("nexthop"+vpnRD+IpAddress); - - int groupId = 1;//getIdManager().getUniqueId("nextHopGroupIdPool", nhKey); - -/* if (getNextHop(groupId) == Null){ - List listBucketInfo = new ArrayList(); - List listActionInfo = null;//nextHop.getActions({output to port}); - BucketInfo bucket = new BucketInfo(listActionInfo); - listBucketInfo.add(bucket); - //GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpId, groupId, IPAddress, GroupTypes.GroupIndirect, listBucketInfo); - //getMdsalApiManager().installGroup(groupEntity, objTransaction???); - - //update MD-SAL DS - addNextHopToDS(dpId, vpn, ipAddress, groupId); - }else{ - //check update - }*/ - } - - public void removeNextHop(long dpnId, int port, String vpnRD, String IpAddress) - { - String nhKey = new String("nexthop"+vpnRD+IpAddress); - int groupId = 1;//getIdManager().getUniqueId(L3Constants.L3NEXTHOP_GROUPID_POOL, nhKey); - -/* if (getNextHop(groupId) != Null){ - List listBucketInfo = new ArrayList(); - List listActionInfo = null;//nextHop.getActions({output to port}); - BucketInfo bucket = new BucketInfo(listActionInfo); - listBucketInfo.add(bucket); - //GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpId, groupId, IPAddress, GroupTypes.GroupIndirect, listBucketInfo); - //getMdsalApiManager().removeGroup(groupEntity, objTransaction???); - - //update MD-SAL DS - removeNextHopFromDS(dpId, vpn, ipAddress); - }else{ - //check update - }*/ - } - - public long getNextHopPointer(long dpnId, int vpnId, String prefixIp, String nxetHopIp) - { -/* String endpointIp = interfaceManager.getLocalEndpointIp(dpnId); - if (nextHopIp.equals(endpointIp)) { - return getGidFromDS(dpnId, vpnId, prefixIp); - } else { - return getGidFromDS(dpnId, 00, nextHopIp); - }*/ - return 0; - } - - private InstanceIdentifier getWildCardPath() { - return InstanceIdentifier.create(L3nexthop.class);//.child(l3nexthop.vpnNexthops.class); - } - - private void addNextHopToDS(long dpId, int vpnId, String ipAddress, long groupId) - { - - } - - private long getGidFromDS(String ipaddress) - { - return 0; - - } - - @Override - protected void remove(InstanceIdentifier identifier, - L3nexthop del) { - // TODO Auto-generated method stub - - } - - @Override - protected void update(InstanceIdentifier identifier, - L3nexthop original, L3nexthop update) { - // TODO Auto-generated method stub - - } - - @Override - protected void add(InstanceIdentifier identifier, L3nexthop add) { - // TODO Auto-generated method stub - - } } \ No newline at end of file