X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=interfacemgr%2Finterfacemgr-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fvpnservice%2Finterfacemgr%2FInterfaceManager.java;h=8f0a4aa381c96369ef4d46952e6d783ad497e407;hb=cd331f15ad231c081bf3725fd10e8cfd39f58241;hp=3ba00f57b5891a180bcfc7b82ff0b11689efb7fd;hpb=99b25a646fcff77b4e4705a05c2a16f2cf380c1e;p=vpnservice.git diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java index 3ba00f57..8f0a4aa3 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfaceManager.java @@ -7,47 +7,76 @@ */ package org.opendaylight.vpnservice.interfacemgr; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder; - -import java.math.BigInteger; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state._interface.StatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state._interface.Statistics; + +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.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +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.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.idmanager.IdManager; +import org.opendaylight.vpnservice.AbstractDataChangeListener; +import org.opendaylight.vpnservice.mdsalutil.ActionInfo; +import org.opendaylight.vpnservice.mdsalutil.ActionType; +import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; +import org.opendaylight.vpnservice.mdsalutil.MatchInfo; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; +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 com.google.common.util.concurrent.FutureCallback; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; -import org.opendaylight.vpnservice.AbstractDataChangeListener; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.id.pool.GeneratedIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL3tunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfMpls; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfStackedVlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.L3tunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.Mpls; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.StackedVlan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; 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.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.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.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Optional; -public class InterfaceManager extends AbstractDataChangeListener implements AutoCloseable{ +public class InterfaceManager extends AbstractDataChangeListener implements AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class); private ListenerRegistration listenerRegistration; private final DataBroker broker; + private final IdManager idManager; + private final Map mapNcToInterfaceName = new ConcurrentHashMap<>(); + private final Map dbDpnEndpoints = new ConcurrentHashMap<>(); private static final FutureCallback DEFAULT_CALLBACK = new FutureCallback() { @@ -57,12 +86,13 @@ public class InterfaceManager extends AbstractDataChangeListener impl public void onFailure(Throwable error) { LOG.error("Error in Datastore write operation", error); - }; + } }; - public InterfaceManager(final DataBroker db) { + public InterfaceManager(final DataBroker db, final IdManager idmgr) { super(Interface.class); broker = db; + idManager = idmgr; registerListener(db); } @@ -78,7 +108,7 @@ public class InterfaceManager extends AbstractDataChangeListener impl } LOG.info("Interface Manager Closed"); } - + private void registerListener(final DataBroker db) { try { listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, @@ -92,24 +122,31 @@ public class InterfaceManager extends AbstractDataChangeListener impl @Override protected void add(final InstanceIdentifier identifier, final Interface imgrInterface) { - LOG.trace("key: " + identifier + ", value=" + imgrInterface ); + LOG.trace("Adding interface key: " + identifier + ", value=" + imgrInterface ); addInterface(identifier, imgrInterface); } private InstanceIdentifier buildId(final InstanceIdentifier identifier) { //TODO Make this generic and move to AbstractDataChangeListener or Utils. final InterfaceKey key = identifier.firstKeyOf(Interface.class, InterfaceKey.class); - String interfaceName = key.getName(); + return buildId(key.getName()); + } + + private InstanceIdentifier buildId(String interfaceName) { + //TODO Make this generic and move to AbstractDataChangeListener or Utils. InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName)); InstanceIdentifier id = idBuilder.build(); return id; } - private InstanceIdentifier buildStateInterfaceId(String interfaceName) { + private InstanceIdentifier + + buildStateInterfaceId(String interfaceName) { //TODO Make this generic and move to AbstractDataChangeListener or Utils. - InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(InterfacesState.class) + InstanceIdentifierBuilder + + 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 id = idBuilder.build(); @@ -117,27 +154,26 @@ public class InterfaceManager extends AbstractDataChangeListener impl } private void addInterface(final InstanceIdentifier identifier, - final Interface imgrInterface) { - InstanceIdentifier id = buildId(identifier); - Optional port = read(LogicalDatastoreType.CONFIGURATION, id); - if(port.isPresent()) { - Interface interf = port.get(); - NodeConnector nodeConn = getNodeConnectorFromInterface(interf); - updateInterfaceState(interf, nodeConn); - /* TODO: - * 1. Get interface-id from id manager - * 2. Update interface-state with following: - * admin-status = set to enable value - * oper-status = Down [?] - * if-index = interface-id - * FIXME: - * 1. Get operational data from node-connector-id? - * - */ + final Interface interf) { + NodeConnector nodeConn = getNodeConnectorFromDataStore(interf); + NodeConnectorId ncId = null; + updateInterfaceState(identifier, interf, nodeConn); + if (nodeConn == null) { + ncId = getNodeConnectorIdFromInterface(interf); + } else { + ncId = nodeConn.getId(); + } + mapNcToInterfaceName.put(ncId, interf.getName()); + if(interf.getType().getClass().isInstance(L3tunnel.class)) { + NodeId nodeId = getNodeIdFromNodeConnectorId(ncId); + IfL3tunnel l3Tunnel = interf.getAugmentation(IfL3tunnel.class); + dbDpnEndpoints.put(nodeId, l3Tunnel.getLocalIp().getIpv4Address().getValue()); + LOG.trace("dbDpnEndpoints: {}",dbDpnEndpoints); } } - private void updateInterfaceState(Interface interf, NodeConnector nodeConn) { + private void updateInterfaceState(InstanceIdentifier identifier, + Interface interf, NodeConnector nodeConn) { /* Update InterfaceState * 1. Get interfaces-state Identifier * 2. Add interface to interfaces-state/interface @@ -152,31 +188,81 @@ public class InterfaceManager extends AbstractDataChangeListener impl Optional stateIf = read(LogicalDatastoreType.OPERATIONAL, id); org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateIface; + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder(); if(!stateIf.isPresent()) { - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder(); // TODO: Get interface-id from IdManager + String ifName = interf.getName(); ifaceBuilder.setAdminStatus((interf.isEnabled()) ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up : org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Down); - ifaceBuilder.setOperStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down); - ifaceBuilder.setIfIndex(200).setName(interf.getName()).setType(interf.getType()); - ifaceBuilder.setKey(getStateInterfaceKeyFromName(interf.getName())); - //ifaceBuilder.setStatistics(createStatistics(interf.getName(), nodeConn)); + ifaceBuilder.setOperStatus(getOperStatus(nodeConn)); + + ifaceBuilder.setIfIndex(getIfIndex(ifName)).setName(ifName).setType(interf.getType()); + ifaceBuilder.setKey(getStateInterfaceKeyFromName(ifName)); stateIface = ifaceBuilder.build(); - LOG.trace("updating OPERATIONAL data store with stateIface {} and id {}", stateIface, id); + LOG.trace("Adding stateIface {} and id {} to OPERATIONAL DS", stateIface, id); asyncWrite(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK); + } else { + if(interf.isEnabled() != null) { + ifaceBuilder.setAdminStatus((interf.isEnabled()) ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up : + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Down); + } + if(interf.getType() != null) { + ifaceBuilder.setType(interf.getType()); + } + ifaceBuilder.setOperStatus(getOperStatus(nodeConn)); + stateIface = ifaceBuilder.build(); + LOG.trace("updating OPERATIONAL data store with stateIface {} and id {}", stateIface, id); + asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK); + } + } + + private Integer getIfIndex(String ifName) { + GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder() + .setPoolName(IfmConstants.IFM_IDPOOL_NAME).setIdKey(ifName) + .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); + } + /* This currently returns null, so let us get it from IdManager DS + * TODO: Start-delete-me + */ + + InstanceIdentifier.InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey("interfaces")); + InstanceIdentifier id = idBuilder.build(); + Optional globalPool = read(LogicalDatastoreType.OPERATIONAL, id); + Long newIdValue = null; + if (globalPool.isPresent()) { + IdPool pool = globalPool.get(); + List generatedIds = pool.getGeneratedIds(); + if ((generatedIds != null) && !generatedIds.isEmpty()) { + for (GeneratedIds gen_id : generatedIds) { + if (gen_id.getIdKey().equals(ifName)) { + newIdValue = gen_id.getIdValue(); + LOG.debug("Id {} found for interface %s ", newIdValue, ifName); + return newIdValue.intValue(); + } + } + } } + //TODO: End-delete-me + LOG.debug("Unable to get valid ifIndex for interface {}", ifName); + return IfmConstants.DEFAULT_IFINDEX; } - private Statistics createStatistics(String name, NodeConnector nodeConn) { - Counter64 init64 = new Counter64(new BigInteger("0000000000000000")); - Counter32 init32 = new Counter32((long) 0); - StatisticsBuilder statBuilder = new StatisticsBuilder(); - statBuilder.setDiscontinuityTime(new DateAndTime("2015-04-04T00:00:00Z")) - .setInBroadcastPkts(init64).setInDiscards(init32).setInErrors(init32).setInMulticastPkts(init64) - .setInOctets(init64).setInUnicastPkts(init64).setInUnknownProtos(init32).setOutBroadcastPkts(init64) - .setOutDiscards(init32).setOutErrors(init32).setOutMulticastPkts(init64).setOutOctets(init64) - .setOutUnicastPkts(init64); - return statBuilder.build(); + private OperStatus getOperStatus(NodeConnector nodeConn) { + LOG.trace("nodeConn is {}", nodeConn); + if(nodeConn == null) { + return OperStatus.Down; + }else { + return OperStatus.Up; + } } private org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey getStateInterfaceKeyFromName( @@ -184,9 +270,10 @@ public class InterfaceManager extends AbstractDataChangeListener impl return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(name); } - private NodeConnector getNodeConnectorFromInterface(Interface interf) { + private NodeConnector getNodeConnectorFromDataStore(Interface interf) { NodeConnectorId ncId = interf.getAugmentation(BaseIds.class).getOfPortId(); - NodeId nodeId = new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":"))); + //TODO: Replace with MDSAL Util method + NodeId nodeId = getNodeIdFromNodeConnectorId(ncId); InstanceIdentifier ncIdentifier = InstanceIdentifier.builder(Nodes.class) .child(Node.class, new NodeKey(nodeId)) .child(NodeConnector.class, new NodeConnectorKey(ncId)).build(); @@ -200,23 +287,69 @@ public class InterfaceManager extends AbstractDataChangeListener impl return null; } + private NodeConnectorId getNodeConnectorIdFromInterface(Interface interf) { + return interf.getAugmentation(BaseIds.class).getOfPortId(); + } + private void delInterface(final InstanceIdentifier identifier, - final Interface del) { - InstanceIdentifier id = buildId(identifier); - Optional port = read(LogicalDatastoreType.CONFIGURATION, id); - if(port.isPresent()) { - Interface interf = port.get(); - // TODO: Update operational data + final Interface delInterface) { + InstanceIdentifier id = + buildStateInterfaceId(delInterface.getName()); + Optional stateIf = + read(LogicalDatastoreType.OPERATIONAL, id); + if(stateIf.isPresent()) { + LOG.trace("deleting interfaces:state OPERATIONAL data store with id {}", id); + asyncRemove(LogicalDatastoreType.OPERATIONAL, id, DEFAULT_CALLBACK); + NodeConnectorId ncId = getNodeConnectorIdFromInterface(delInterface); + if(ncId != null) { + mapNcToInterfaceName.remove(ncId); + if(delInterface.getType().getClass().isInstance(L3tunnel.class)) { + Node node = getNodeFromDataStore(delInterface); + if((node != null) &&(node.getNodeConnector().isEmpty())) { + dbDpnEndpoints.remove(node.getId()); + } + } + } } } + private Node getNodeFromDataStore(Interface interf) { + NodeConnectorId ncId = interf.getAugmentation(BaseIds.class).getOfPortId(); + //TODO: Replace with MDSAL Util method + NodeId nodeId = getNodeIdFromNodeConnectorId(ncId); + InstanceIdentifier ncIdentifier = InstanceIdentifier.builder(Nodes.class) + .child(Node.class, new NodeKey(nodeId)).build(); + + Optional dpn = read(LogicalDatastoreType.OPERATIONAL, ncIdentifier); + if(dpn.isPresent()) { + Node node = dpn.get(); + LOG.trace("node: {}",node); + return node; + } + return null; + } + private void updateInterface(final InstanceIdentifier identifier, - final Interface original, final Interface udpate) { + final Interface original, final Interface update) { InstanceIdentifier id = buildId(identifier); Optional port = read(LogicalDatastoreType.CONFIGURATION, id); if(port.isPresent()) { Interface interf = port.get(); - //TODO: Update operational data + NodeConnector nc = getNodeConnectorFromDataStore(update); + updateInterfaceState(identifier, update, nc); + /* + * Alternative is to get from interf and update map irrespective if NCID changed or not. + */ + if(nc != null) { + // Name doesn't change. Is it present in update? + mapNcToInterfaceName.put(nc.getId(), original.getName()); + if(interf.getType().getClass().isInstance(L3tunnel.class)) { + NodeId nodeId = getNodeIdFromNodeConnectorId(nc.getId()); + IfL3tunnel l3Tunnel = interf.getAugmentation(IfL3tunnel.class); + dbDpnEndpoints.put(nodeId, l3Tunnel.getLocalIp().getIpv4Address().getValue()); + LOG.trace("dbEndpoints: {}",dbDpnEndpoints); + } + } } } @@ -241,13 +374,13 @@ public class InterfaceManager extends AbstractDataChangeListener impl @Override protected void remove(InstanceIdentifier identifier, Interface del) { - LOG.trace("key: " + identifier + ", value=" + del ); + LOG.trace("remove - key: " + identifier + ", value=" + del ); delInterface(identifier, del); } @Override protected void update(InstanceIdentifier identifier, Interface original, Interface update) { - LOG.trace("key: " + identifier + ", original=" + original + ", update=" + update ); + LOG.trace("update - key: " + identifier + ", original=" + original + ", update=" + update ); updateInterface(identifier, original, update); } @@ -257,4 +390,177 @@ public class InterfaceManager extends AbstractDataChangeListener impl tx.put(datastoreType, path, data, true); Futures.addCallback(tx.submit(), callback); } + + private void asyncUpdate(LogicalDatastoreType datastoreType, + InstanceIdentifier path, T data, FutureCallback callback) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.merge(datastoreType, path, data, true); + Futures.addCallback(tx.submit(), callback); + } + + private void asyncRemove(LogicalDatastoreType datastoreType, + InstanceIdentifier path, FutureCallback callback) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.delete(datastoreType, path); + Futures.addCallback(tx.submit(), callback); + } + + void processPortAdd(NodeConnector port) { + NodeConnectorId portId = port.getId(); + FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class); + LOG.debug("PortAdd: PortId { "+portId.getValue()+"} PortName {"+ofPort.getName()+"}"); + String ifName = this.mapNcToInterfaceName.get(portId); + setInterfaceOperStatus(ifName, OperStatus.Up); + } + + void processPortUpdate(NodeConnector oldPort, NodeConnector update) { + //TODO: Currently nothing to do here. + LOG.trace("ifMap: {}, dpnMap: {}", mapNcToInterfaceName, dbDpnEndpoints); + } + + void processPortDelete(NodeConnector port) { + NodeConnectorId portId = port.getId(); + FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class); + LOG.debug("PortDelete: PortId { "+portId.getValue()+"} PortName {"+ofPort.getName()+"}"); + String ifName = this.mapNcToInterfaceName.get(portId); + setInterfaceOperStatus(ifName, OperStatus.Down); + } + + private void setInterfaceOperStatus(String ifName, OperStatus opStatus) { + if (ifName != null) { + InstanceIdentifier id = + buildStateInterfaceId(ifName); + Optional stateIf = + read(LogicalDatastoreType.OPERATIONAL, id); + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateIface; + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder(); + if (stateIf.isPresent()) { + stateIface = ifaceBuilder.setOperStatus(opStatus).build(); + LOG.trace("Setting OperStatus for {} to {} in OPERATIONAL DS", ifName, opStatus); + asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, stateIface, DEFAULT_CALLBACK); + } + } + } + + private Interface getInterfaceByIfName(String ifName) { + InstanceIdentifier id = buildId(ifName); + Optional port = read(LogicalDatastoreType.CONFIGURATION, id); + if(port.isPresent()) { + return port.get(); + } + return null; + } + + Long getPortForInterface(String ifName) { + Interface iface = getInterfaceByIfName(ifName); + return getPortNumForInterface(iface); + } + + long getDpnForInterface(String ifName) { + Interface iface = getInterfaceByIfName(ifName); + try { + NodeConnector port = getNodeConnectorFromDataStore(iface); + //TODO: This should be an MDSAL Util method + return Long.parseLong(IfmUtil.getDpnFromNodeConnectorId(port.getId())); + } catch (NullPointerException e) { + LOG.error("OFPort for Interface {} not found", ifName); + } + return 0L; + } + + String getEndpointIpForDpn(long dpnId) { + //TODO: This should be MDSAL Util function + NodeId dpnNodeId = IfmUtil.buildDpnNodeId(dpnId); + return dbDpnEndpoints.get(dpnNodeId); + } + + List getInterfaceIngressRule(String ifName) { + Interface iface = getInterfaceByIfName(ifName); + List matches = new ArrayList(); + Class ifType = iface.getType(); + long dpn = this.getDpnForInterface(ifName); + long portNo = this.getPortNumForInterface(iface).longValue(); + matches.add(new MatchInfo(MatchFieldType.in_port, new long[] {dpn, portNo})); + if (ifType.isInstance(L2vlan.class)) { + IfL2vlan vlanIface = iface.getAugmentation(IfL2vlan.class); + long vlanVid = vlanIface.getVlanId().longValue(); + if (vlanVid != 0) { + matches.add(new MatchInfo(MatchFieldType.vlan_vid, + new long[] {vlanVid})); + LOG.trace("L2Vlan: {}",vlanIface); + } + } else if (ifType.isInstance(L3tunnel.class)) { + //TODO: Handle different tunnel types + IfL3tunnel ifL3Tunnel = iface.getAugmentation(IfL3tunnel.class); + Class tunnType = ifL3Tunnel.getTunnelType(); + LOG.trace("L3Tunnel: {}",ifL3Tunnel); + } else if (ifType.getClass().isInstance(StackedVlan.class)) { + IfStackedVlan ifStackedVlan = iface.getAugmentation(IfStackedVlan.class); + LOG.trace("StackedVlan: {}",ifStackedVlan); + } else if (ifType.getClass().isInstance(Mpls.class)) { + IfMpls ifMpls = iface.getAugmentation(IfMpls.class); + LOG.trace("Mpls: {}",ifMpls); + } + return matches; + } + + public List getInterfaceEgressActions(String ifName) { + Interface iface = getInterfaceByIfName(ifName); + + List listActionInfo = new ArrayList(); + Class ifType = iface.getType(); + long dpn = this.getDpnForInterface(ifName); + long portNo = this.getPortNumForInterface(iface).longValue(); + + if (iface.isEnabled()) { + + if(ifType.isInstance(L2vlan.class)) { + IfL2vlan vlanIface = iface.getAugmentation(IfL2vlan.class); + long vlanVid = vlanIface.getVlanId(); + LOG.trace("L2Vlan: {}",vlanIface); + if (vlanVid != 0) { + listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {})); + listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid, + new String[] { Long.toString(vlanVid) })); + } + listActionInfo.add(new ActionInfo(ActionType.output, new String[] { Long.toString(portNo)})); + + } else if (ifType.isInstance(L3tunnel.class)) { + //TODO: Handle different tunnel types + IfL3tunnel ifL3Tunnel = iface.getAugmentation(IfL3tunnel.class); + Class tunnType = ifL3Tunnel.getTunnelType(); + LOG.trace("L3Tunnel: {}",ifL3Tunnel); + //TODO: check switch_type and configure accordingly + listActionInfo.add(new ActionInfo(ActionType.output, new String[] { Long.toString(portNo)})); + + } else if (ifType.isInstance(StackedVlan.class)) { + IfStackedVlan ifStackedVlan = iface.getAugmentation(IfStackedVlan.class); + LOG.trace("StackedVlan: {}",ifStackedVlan); + // TBD + } else if (ifType.isInstance(Mpls.class)) { + IfMpls ifMpls = iface.getAugmentation(IfMpls.class); + LOG.trace("Mpls: {}",ifMpls); + // TBD + } + } + return listActionInfo; + + } + + private NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) { + return new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":"))); + } + + private Long getPortNumForInterface(Interface iface) { + try { + NodeConnector port = getNodeConnectorFromDataStore(iface); + FlowCapableNodeConnector ofPort = port.getAugmentation(FlowCapableNodeConnector.class); + return ofPort.getPortNumber().getUint32(); + } catch (Exception e) { + LOG.error("OFPort for Interface {} not found", iface.getName()); + } + return null; + } + }