From 50bb8cd056ca25114a412398c4df672eac891b28 Mon Sep 17 00:00:00 2001 From: HemaTG Date: Wed, 23 Dec 2015 17:46:45 +0530 Subject: [PATCH] Adding ITM internal/external tunnel build logic Change-Id: I190052ce3a5d5da8f315f9e7787a95c96d12ad62 Signed-off-by: HemaTG --- .../src/main/yang/odl-interface.yang | 1 + itm/itm-api/pom.xml | 5 +- itm/itm-api/src/main/yang/itm-rpc.yang | 61 ++++++ itm/itm-api/src/main/yang/itm-state.yang | 1 + itm/itm-api/src/main/yang/itm.yang | 1 + itm/itm-impl/pom.xml | 15 -- .../ItmExternalTunnelAddWorker.java | 80 ++++++++ .../ItmExternalTunnelDeleteWorker.java | 50 +++++ .../ItmInternalTunnelAddWorker.java | 138 +++++++++++++ .../ItmInternalTunnelDeleteWorker.java | 130 ++++++++++++ .../itm/confighelpers/ItmTepAddWorker.java | 51 +++++ .../itm/confighelpers/ItmTepRemoveWorker.java | 49 +++++ .../vpnservice/itm/impl/ITMManager.java | 19 +- .../vpnservice/itm/impl/ItmProvider.java | 35 ++-- .../vpnservice/itm/impl/ItmUtils.java | 188 ++++++++++++++++++ .../itm/listeners/TransportZoneListener.java | 179 +++++++++++++++++ .../itm/rpc/ItmManagerRpcService.java | 111 +++++++++++ .../vpnmanager-api/src/main/yang/l3vpn.yang | 1 + 18 files changed, 1084 insertions(+), 31 deletions(-) create mode 100644 itm/itm-api/src/main/yang/itm-rpc.yang create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java create mode 100644 itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java diff --git a/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang b/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang index 828ede50..db04860f 100644 --- a/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang +++ b/interfacemgr/interfacemgr-api/src/main/yang/odl-interface.yang @@ -17,6 +17,7 @@ module odl-interface { import ietf-inet-types { prefix inet; + revision-date "2010-09-24"; } import opendaylight-inventory { diff --git a/itm/itm-api/pom.xml b/itm/itm-api/pom.xml index 4003b968..479728de 100644 --- a/itm/itm-api/pom.xml +++ b/itm/itm-api/pom.xml @@ -8,7 +8,7 @@ 0.2.0-SNAPSHOT ../../commons/config-parent - + 4.0.0 org.opendaylight.vpnservice itm-api @@ -21,14 +21,17 @@ interfacemgr-api ${vpnservices.version} + org.opendaylight.mdsal.model ietf-interfaces diff --git a/itm/itm-api/src/main/yang/itm-rpc.yang b/itm/itm-api/src/main/yang/itm-rpc.yang new file mode 100644 index 00000000..4779a265 --- /dev/null +++ b/itm/itm-api/src/main/yang/itm-rpc.yang @@ -0,0 +1,61 @@ +module itm-rpc { + namespace "urn:opendaylight:params:xml:ns:yang:itm:rpcs"; + prefix "itmrpcs"; + + import ietf-inet-types { + prefix inet; + revision-date "2010-09-24"; + } + + import ietf-yang-types { + prefix yang; + } + + import ietf-interfaces { + prefix if; revision-date 2014-05-08; + } + + revision "2015-12-17" { + description "ODL Specific Itm Manager Rpcs Module"; + } + + /* RPCs */ + + rpc get-tunnel-interface-id { + description "used to retrieve tunnel interface id between Dpns"; + input { + leaf source-dpid { + type uint64; + } + leaf destination-dpid { + type uint64; + } + } + output { + leaf interfaceid { + type uint16; + } + } + } + + rpc build-tunnel-from-dpn-to-dcgateway { + description "used for building tunnels between a Dpn and DC Gateway"; + input { + leaf dpid { + type uint64; + } + leaf dcgwyid { + type inet:ip-address; + } + } + } + + rpc build-tunnel-to-dcgateway { + description "used for building tunnels between teps on all Dpns and DC Gateway"; + input { + leaf dcgwyid { + type inet:ip-address; + } + } + } +} \ No newline at end of file diff --git a/itm/itm-api/src/main/yang/itm-state.yang b/itm/itm-api/src/main/yang/itm-state.yang index f3951241..a1a1ce29 100644 --- a/itm/itm-api/src/main/yang/itm-state.yang +++ b/itm/itm-api/src/main/yang/itm-state.yang @@ -14,6 +14,7 @@ module itm-state { import ietf-inet-types { prefix inet; + revision-date "2010-09-24"; } description "This YANG module defines operation part of the model."; diff --git a/itm/itm-api/src/main/yang/itm.yang b/itm/itm-api/src/main/yang/itm.yang index bbc1273b..3dd4ba1f 100644 --- a/itm/itm-api/src/main/yang/itm.yang +++ b/itm/itm-api/src/main/yang/itm.yang @@ -12,6 +12,7 @@ module itm { } import ietf-inet-types { prefix inet; + revision-date "2010-09-24"; } import config { prefix config; revision-date 2013-04-05; } diff --git a/itm/itm-impl/pom.xml b/itm/itm-impl/pom.xml index ca5e9074..10463d8a 100644 --- a/itm/itm-impl/pom.xml +++ b/itm/itm-impl/pom.xml @@ -28,11 +28,6 @@ interfacemgr-api ${vpnservices.version} - - org.opendaylight.vpnservice - interfacemgr-impl - ${vpnservices.version} - org.opendaylight.vpnservice mdsalutil-api @@ -58,16 +53,6 @@ test - org.opendaylight.vpnservice - interfacemgr-api - ${vpnservices.version} - - - org.opendaylight.vpnservice - mdsalutil-api - ${vpnservices.version} - - com.google.guava guava 18.0 diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java new file mode 100644 index 00000000..49b882fb --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelAddWorker.java @@ -0,0 +1,80 @@ +/* + * 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.itm.confighelpers; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +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.interfaces.rev140508.interfaces.Interface; +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.dpn.teps.info.TunnelEndPoints; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.commons.net.util.SubnetUtils; + +import com.google.common.util.concurrent.ListenableFuture; + +public class ItmExternalTunnelAddWorker { + private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class ) ; + + public static List> buildTunnelsToExternalEndPoint(DataBroker dataBroker,List meshedDpnList, IpAddress extIp) { + List> futures = new ArrayList<>(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if( null == meshedDpnList) + ItmUtils.getTunnelMeshInfo(dataBroker) ; + if( null != meshedDpnList) { + for( DPNTEPsInfo teps : meshedDpnList ) { + // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels + TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0) ; + String interfaceName = firstEndPt.getInterfaceName() ; + String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue()) ; + char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue() ; + String subnetMaskStr = String.valueOf(subnetMaskArray) ; + SubnetUtils utils = new SubnetUtils(subnetMaskStr); + String dcGwyIpStr = String.valueOf(extIp.getValue()); + IpAddress gwyIpAddress = (utils.getInfo().isInRange(dcGwyIpStr) ) ? null : firstEndPt.getGwIpAddress() ; + Class tunType = (teps.getTunnelEndPoints().get(0).getTunnelType().equals("GRE") ) ? TunnelTypeGre.class :TunnelTypeVxlan.class ; + String ifDescription = (tunType.equals("GRE") ) ? "GRE" : "VxLan" ; + logger.debug( " Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, DC Gateway IP - {} gateway IP - {}",trunkInterfaceName, interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress ) ; + Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName, String.format( "%s %s",ifDescription, "Trunk Interface"), true, tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress) ; + logger.debug( " Trunk Interface builder - {} ", iface ) ; + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(trunkInterfaceName); + logger.debug( " Trunk Interface Identifier - {} ", trunkIdentifier ) ; + logger.trace( " Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface ) ; + //ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION,trunkIdentifier, iface , dataBroker, ItmUtils.DEFAULT_CALLBACK); + t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true); + } + futures.add( t.submit()) ; + } + return futures ; + } + + public static List> buildTunnelsFromDpnToExternalEndPoint(DataBroker dataBroker,BigInteger dpnId,List meshedDpnList, IpAddress extIp) { + List> futures = new ArrayList<>(); + List cfgDpnList = new ArrayList() ; + if( null != meshedDpnList) { + for( DPNTEPsInfo teps : meshedDpnList ) { + if( teps.getDPNID().equals(dpnId)) { + cfgDpnList.add(teps) ; + } + } + futures = buildTunnelsToExternalEndPoint( dataBroker, cfgDpnList, extIp) ; + } + return futures ; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java new file mode 100644 index 00000000..13a6329e --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmExternalTunnelDeleteWorker.java @@ -0,0 +1,50 @@ +/* + * 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.itm.confighelpers; + +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +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.interfaces.rev140508.interfaces.Interface; +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.dpn.teps.info.TunnelEndPoints; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.ListenableFuture; + +public class ItmExternalTunnelDeleteWorker { + private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelDeleteWorker.class ) ; + + public static List> deleteTunnels(DataBroker dataBroker, List dpnTepsList,IpAddress extIp ) { + logger.trace( " Delete Tunnels towards DC Gateway with Ip {}", extIp ) ; + List> futures = new ArrayList<>(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + + if (dpnTepsList == null || dpnTepsList.size() == 0) { + logger.debug("no vtep to delete"); + return null ; + } + for( DPNTEPsInfo teps : dpnTepsList) { + TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0) ; + String interfaceName = firstEndPt.getInterfaceName() ; + String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue()) ; + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(trunkInterfaceName); + t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier); + } + futures.add(t.submit()) ; + return futures ; + } + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java new file mode 100644 index 00000000..8a914df3 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelAddWorker.java @@ -0,0 +1,138 @@ +/* + * 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.itm.confighelpers; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import com.google.common.util.concurrent.ListenableFuture; + +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +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.interfaces.rev140508.interfaces.Interface; +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.TunnelsBuilder; +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.dpn.teps.info.TunnelEndPoints; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ItmInternalTunnelAddWorker { + private static final Logger logger = LoggerFactory.getLogger(ItmInternalTunnelAddWorker.class) ; + + public static List> build_all_tunnels(DataBroker dataBroker, List cfgdDpnList, List meshedDpnList) { + logger.trace( "Building tunnels with DPN List {} " , cfgdDpnList ); + List> futures = new ArrayList<>(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if( null == cfgdDpnList || cfgdDpnList.isEmpty()) { + logger.error(" Build Tunnels was invoked with empty list"); + return null; + } + + for( DPNTEPsInfo dpn : cfgdDpnList) { + build_tunnel_from(dpn, meshedDpnList, dataBroker, t, futures); + if(null == meshedDpnList) { + meshedDpnList = new ArrayList() ; + } + meshedDpnList.add(dpn) ; + // Update the operational datastore -- FIXME -- Error Handling + updateOperationalDatastore(dataBroker, dpn, t, futures) ; + } + futures.add( t.submit()) ; + return futures ; + } + + private static void updateOperationalDatastore(DataBroker dataBroker, DPNTEPsInfo dpn, WriteTransaction t, List> futures) { + logger.debug("Updating CONFIGURATION datastore with DPN {} ", dpn); + InstanceIdentifier tnId = InstanceIdentifier.builder( Tunnels.class).build() ; + List dpnList = new ArrayList() ; + dpnList.add(dpn) ; + Tunnels tnlBuilder = new TunnelsBuilder().setDPNTEPsInfo(dpnList).build() ; + t.merge(LogicalDatastoreType.CONFIGURATION, tnId, tnlBuilder, true); + } + + private static void build_tunnel_from( DPNTEPsInfo srcDpn,List meshedDpnList, DataBroker dataBroker, WriteTransaction t, List> futures) { + logger.trace( "Building tunnels from DPN {} " , srcDpn ); + + if( null == meshedDpnList || 0 == meshedDpnList.size()) { + logger.debug( "No DPN in the mesh "); + return ; + } + for( DPNTEPsInfo dstDpn: meshedDpnList) { + if ( ! srcDpn.equals(dstDpn) ) + wireUpWithinTransportZone(srcDpn, dstDpn, dataBroker, t, futures) ; + } + + } + + private static void wireUpWithinTransportZone( DPNTEPsInfo srcDpn, DPNTEPsInfo dstDpn, DataBroker dataBroker, WriteTransaction t, List> futures) { + logger.trace( "Wiring up within Transport Zone for Dpns {}, {} " , srcDpn, dstDpn ); + List srcEndPts = srcDpn.getTunnelEndPoints(); + List dstEndPts = dstDpn.getTunnelEndPoints(); + + for( TunnelEndPoints srcte : srcEndPts) { + for( TunnelEndPoints dstte : dstEndPts ) { + // Compare the Transport zones + if (!srcDpn.getDPNID().equals(dstDpn.getDPNID())) { + if( (srcte.getTransportZone().equals(dstte.getTransportZone()))) { + // wire them up + wireUpBidirectionalTunnel( srcte, dstte, srcDpn.getDPNID(), dstDpn.getDPNID(), dataBroker, t, futures ); + // CHECK THIS -- Assumption -- One end point per Dpn per transport zone + break ; + } + } + } + } + } + + private static void wireUpBidirectionalTunnel( TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId, + DataBroker dataBroker, WriteTransaction t, List> futures) { + // Setup the flow for LLDP monitoring -- PUNT TO CONTROLLER + // setUpOrRemoveTerminatingServiceTable(srcDpnId, true); + // setUpOrRemoveTerminatingServiceTable(dstDpnId, true); + + // Create the forward direction tunnel + if(!wireUp( srcte, dstte, srcDpnId, dstDpnId, dataBroker, t, futures )) + logger.error("Could not build tunnel between end points {}, {} " , srcte, dstte ); + + // CHECK IF FORWARD IS NOT BUILT , REVERSE CAN BE BUILT + // Create the tunnel for the reverse direction + if(! wireUp( dstte, srcte, dstDpnId, srcDpnId, dataBroker, t, futures )) + logger.error("Could not build tunnel between end points {}, {} " , dstte, srcte); + } + + private static boolean wireUp( TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId , + DataBroker dataBroker, WriteTransaction t, List> futures) { + // Wire Up logic + logger.trace( "Wiring between source tunnel end points {}, destination tunnel end points {} " , srcte, dstte ); + String interfaceName = srcte.getInterfaceName() ; + Class tunType = (srcte.getTunnelType().equals("GRE") ) ? TunnelTypeGre.class :TunnelTypeVxlan.class ; + String ifDescription = (srcte.getTunnelType().equals("GRE") ) ? "GRE" : "VxLan" ; + // Form the trunk Interface Name + String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(interfaceName,srcte.getIpAddress().getIpv4Address().getValue(), dstte.getIpAddress().getIpv4Address().getValue()) ; + IpAddress gwyIpAddress = ( srcte.getSubnetMask().equals(dstte.getSubnetMask()) ) ? null : srcte.getGwIpAddress() ; + logger.debug( " Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}",trunkInterfaceName, interfaceName, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress ) ; + Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName, String.format( "%s %s",ifDescription, "Trunk Interface"), true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress) ; + logger.debug( " Trunk Interface builder - {} ", iface ) ; + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(trunkInterfaceName); + logger.debug( " Trunk Interface Identifier - {} ", trunkIdentifier ) ; + logger.trace( " Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface ) ; + t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true); + return true; + } + +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java new file mode 100644 index 00000000..8922fd93 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmInternalTunnelDeleteWorker.java @@ -0,0 +1,130 @@ +/* + * 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.itm.confighelpers; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +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.dpn.teps.info.TunnelEndPoints; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.ListenableFuture; + +public class ItmInternalTunnelDeleteWorker { + private static final Logger logger = LoggerFactory.getLogger(ItmInternalTunnelDeleteWorker.class) ; + + public static List> deleteTunnels(DataBroker dataBroker, List dpnTepsList, List meshedDpnList) + { + List> futures = new ArrayList<>(); + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + try { + if (dpnTepsList == null || dpnTepsList.size() == 0) { + logger.debug("no vtep to delete"); + return null ; + } + + if (meshedDpnList == null || meshedDpnList.size() == 0) { + logger.debug("No Meshed Vteps"); + return null ; + } + for (DPNTEPsInfo srcDpn : dpnTepsList) { + logger.trace("Processing srcDpn " + srcDpn); + for (TunnelEndPoints srcTep : srcDpn.getTunnelEndPoints()) { + logger.trace("Processing srcTep " + srcTep); + String srcTZone = srcTep.getTransportZone(); + + // run through all other DPNS other than srcDpn + for (DPNTEPsInfo dstDpn : meshedDpnList) { + if (!(srcDpn.getDPNID().equals(dstDpn.getDPNID()))) { + for (TunnelEndPoints dstTep : dstDpn.getTunnelEndPoints()) { + logger.trace("Processing dstTep " + dstTep); + if (dstTep.getTransportZone().equals(srcTZone)) { + // remove all trunk interfaces + logger.trace("Invoking removeTrunkInterface between source TEP {} , Destination TEP {} " ,srcTep , dstTep); + removeTrunkInterface(dataBroker, srcTep, dstTep, srcDpn.getDPNID(), dstDpn.getDPNID(), t, futures); + } + } + } + } + + // removing vtep / dpn from Tunnels OpDs. + InstanceIdentifier tepPath = + InstanceIdentifier.builder(Tunnels.class).child(DPNTEPsInfo.class, srcDpn.getKey()) + .child(TunnelEndPoints.class, srcTep.getKey()).build(); + + logger.trace("Tep Removal from DPNTEPSINFO CONFIG DS " + srcTep); + t.delete(LogicalDatastoreType.CONFIGURATION, tepPath); + InstanceIdentifier dpnPath = + InstanceIdentifier.builder(Tunnels.class).child(DPNTEPsInfo.class, srcDpn.getKey()) + .build(); + Optional dpnOptional = + ItmUtils.read(LogicalDatastoreType.CONFIGURATION, dpnPath, dataBroker); + if (dpnOptional.isPresent()) { + DPNTEPsInfo dpnRead = dpnOptional.get(); + // remove dpn if no vteps exist on dpn + if (dpnRead.getTunnelEndPoints() == null || dpnRead.getTunnelEndPoints().size() == 0) { + logger.debug( "Removing Terminating Service Table Flow ") ; + // setUpOrRemoveTerminatingServiceTable(dpnRead.getDPNID(), false); + logger.trace("DPN Removal from DPNTEPSINFO CONFIG DS " + dpnRead); + t.delete(LogicalDatastoreType.CONFIGURATION, dpnPath); + InstanceIdentifier tnlContainerPath = + InstanceIdentifier.builder(Tunnels.class).build(); + Optional containerOptional = + ItmUtils.read(LogicalDatastoreType.CONFIGURATION, + tnlContainerPath, dataBroker); + // remove container if no DPNs are present + if (containerOptional.isPresent()) { + Tunnels tnls = containerOptional.get(); + if (tnls.getDPNTEPsInfo() == null || tnls.getDPNTEPsInfo().isEmpty()) { + logger.trace("Container Removal from DPNTEPSINFO CONFIG DS"); + t.delete(LogicalDatastoreType.CONFIGURATION, tnlContainerPath); + } + } + } + } + } + } + futures.add( t.submit() ); + } catch (Exception e1) { + logger.error("exception while deleting tep", e1); + } + return futures ; + } + + private static void removeTrunkInterface(DataBroker dataBroker, TunnelEndPoints srcTep, TunnelEndPoints dstTep, BigInteger srcDpnId, BigInteger dstDpnId, + WriteTransaction t, List> futures) { + String trunkfwdIfName = + ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(), srcTep.getIpAddress() + .getIpv4Address().getValue(), dstTep.getIpAddress().getIpv4Address() + .getValue()); + logger.trace("Removing forward Trunk Interface " + trunkfwdIfName); + InstanceIdentifier trunkIdentifier = ItmUtils.buildId(trunkfwdIfName); + logger.debug( " Removing Trunk Interface Name - {} , Id - {} from Config DS {}, {} ", trunkfwdIfName, trunkIdentifier ) ; + t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier); + String trunkRevIfName = + ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(), dstTep.getIpAddress() + .getIpv4Address().getValue(), srcTep.getIpAddress().getIpv4Address() + .getValue()); + logger.trace("Removing Reverse Trunk Interface " + trunkRevIfName); + trunkIdentifier = ItmUtils.buildId(trunkfwdIfName); + logger.debug( " Removing Trunk Interface Name - {} , Id - {} from Config DS {}, {} ", trunkfwdIfName, trunkIdentifier ) ; + t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier); + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java new file mode 100644 index 00000000..21bce967 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepAddWorker.java @@ -0,0 +1,51 @@ +/* + * 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.itm.confighelpers; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import com.google.common.util.concurrent.ListenableFuture; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.DPNTEPsInfo; +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; + +public class ItmTepAddWorker implements Callable>> { + private static final Logger logger = LoggerFactory.getLogger(ItmTepAddWorker.class ) ; + private DataBroker dataBroker; + private List meshedDpnList; + private List cfgdDpnList ; + + public ItmTepAddWorker( List cfgdDpnList, DataBroker broker) { + this.cfgdDpnList = cfgdDpnList ; + this.dataBroker = broker ; + logger.trace("ItmTepAddWorker initialized with DpnList {}",cfgdDpnList ); + } + + @Override + public List> call() throws Exception { + List> futures = new ArrayList<>() ; + this.meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ; + logger.debug("Invoking Internal Tunnel build method with Configured DpnList {} ; Meshed DpnList {} ",cfgdDpnList, meshedDpnList ); + futures.addAll( ItmInternalTunnelAddWorker.build_all_tunnels(dataBroker, cfgdDpnList, meshedDpnList) ) ; + // IF EXTERNAL TUNNELS NEEDS TO BE BUILT, DO IT HERE. IT COULD BE TO DC GATEWAY OR TOR SWITCH + //futures.addAll(ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker,meshedDpnList, extIp) ; + return futures ; + } + + @Override + public String toString() { + return "ItmTepAddWorker { " + + "Configured Dpn List : " + cfgdDpnList + + " Meshed Dpn List : " + meshedDpnList + " }" ; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java new file mode 100644 index 00000000..087da587 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/confighelpers/ItmTepRemoveWorker.java @@ -0,0 +1,49 @@ +/* + * 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.itm.confighelpers; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import com.google.common.util.concurrent.ListenableFuture; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.DPNTEPsInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ItmTepRemoveWorker implements Callable>> { + private static final Logger logger = LoggerFactory.getLogger(ItmTepRemoveWorker.class ) ; + private DataBroker dataBroker; + private List delDpnList ; + private List meshedDpnList ; + + public ItmTepRemoveWorker( List delDpnList, DataBroker broker) { + this.delDpnList = delDpnList ; + this.dataBroker = broker ; + logger.trace("ItmTepRemoveWorker initialized with DpnList {}",delDpnList ); + } + + @Override + public List> call() throws Exception { + List> futures = new ArrayList<>() ; + this.meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ; + futures.addAll( ItmInternalTunnelDeleteWorker.deleteTunnels(dataBroker, delDpnList, meshedDpnList)); + logger.debug("Invoking Internal Tunnel delete method with DpnList to be deleted {} ; Meshed DpnList {} ",delDpnList, meshedDpnList ); + // IF EXTERNAL TUNNELS NEEDS TO BE DELETED, DO IT HERE, IT COULD BE TO DC GATEWAY OR TOR SWITCH + return futures ; + } + + @Override + public String toString() { + return "ItmTepRemoveWorker { " + + "Delete Dpn List : " + delDpnList + " }" ; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java index 7aa7ead9..07947391 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ITMManager.java @@ -14,18 +14,31 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.Future; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; import org.apache.commons.net.util.SubnetUtils; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; import org.opendaylight.controller.md.sal.binding.api.NotificationService; - +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +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.interfaces.rev140508.interfaces.Interface; +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.TunnelsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan ; import org.opendaylight.vpnservice.itm.globals.ITMConstants; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +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.dpn.teps.info.TunnelEndPoints; + +import com.google.common.base.Optional; public class ITMManager implements AutoCloseable { @@ -35,6 +48,8 @@ public class ITMManager implements AutoCloseable { private IMdsalApiManager mdsalManager; private NotificationPublishService notificationPublishService; + List meshedDpnList; + @Override public void close() throws Exception { LOG.info("ITMManager Closed"); diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java index a53b760e..441979ea 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmProvider.java @@ -19,13 +19,14 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderCo import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; import org.opendaylight.vpnservice.itm.api.IITMProvider; - +import org.opendaylight.vpnservice.itm.listeners.TransportZoneListener; +import org.opendaylight.vpnservice.itm.rpc.ItmManagerRpcService; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.GetTunnelIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.GetTunnelIdOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.ItmStateService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.TunnelsState; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rev150701.TransportZones; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rev150701.transport.zones.transport.zone.*;; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,20 +39,25 @@ public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMPro private IMdsalApiManager mdsalManager; private DataBroker dataBroker; private NotificationPublishService notificationPublishService; + private ItmManagerRpcService itmRpcService ; private NotificationService notificationService; - + private TransportZoneListener tzChangeListener; + @Override public void onSessionInitiated(ProviderContext session) { LOG.info("ItmProvider Session Initiated"); try { dataBroker = session.getSALService(DataBroker.class); - + itmManager = new ITMManager(dataBroker); - + tzChangeListener = new TransportZoneListener(dataBroker) ; + itmRpcService = new ItmManagerRpcService(dataBroker); + itmManager.setMdsalManager(mdsalManager); itmManager.setNotificationPublishService(notificationPublishService); itmManager.setMdsalManager(mdsalManager); - + tzChangeListener.setItmManager(itmManager); + tzChangeListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker); } catch (Exception e) { LOG.error("Error initializing services", e); } @@ -77,15 +83,18 @@ public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMPro if (itmManager != null) { itmManager.close(); } - + if (tzChangeListener != null) { + tzChangeListener.close(); + } + LOG.info("ItmProvider Closed"); } - @Override - public Future> getTunnelId( - GetTunnelIdInput input) { - // TODO Auto-generated method stub - return null; - } + @Override + public Future> getTunnelId( + GetTunnelIdInput input) { + // TODO Auto-generated method stub + return null; + } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java new file mode 100644 index 00000000..f1eaaed4 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/impl/ItmUtils.java @@ -0,0 +1,188 @@ +/* + * 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.itm.impl; + +import java.math.BigInteger; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.net.util.SubnetUtils; +import org.apache.commons.net.util.SubnetUtils.SubnetInfo; +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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder; +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.iana._if.type.rev140508.Tunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*; +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.vpnservice.mdsalutil.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.inet.types.rev100924.IpPrefix; +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.Interface; +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.itm.op.rev150701.Tunnels; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.TunnelsBuilder; +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.DPNTEPsInfoBuilder; +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.itm.op.rev150701.tunnels.dpn.teps.info.TunnelEndPointsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.dpn.teps.info.TunnelEndPointsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels_state.StateTunnelListKey; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice._interface.service.rev150602._interface.service.info.ServiceInfo; +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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.net.InetAddresses; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; + +public class ItmUtils { + + public static final String DUMMY_IP_ADDRESS = "0.0.0.0"; + public static final String TUNNEL_TYPE_VXLAN = "VXLAN"; + public static final String TUNNEL_TYPE_GRE = "GRE"; + + private static final Logger LOG = LoggerFactory.getLogger(ItmUtils.class); + + public static final FutureCallback DEFAULT_CALLBACK = new FutureCallback() { + 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); + } + }; + + public static Optional read(LogicalDatastoreType datastoreType, + InstanceIdentifier path, DataBroker broker) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional result = Optional.absent(); + try { + result = tx.read(datastoreType, path).get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return result; + } + + public static void asyncWrite(LogicalDatastoreType datastoreType, + InstanceIdentifier path, T data, DataBroker broker, FutureCallback callback) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.put(datastoreType, path, data, true); + Futures.addCallback(tx.submit(), callback); + } + + public static void asyncUpdate(LogicalDatastoreType datastoreType, + InstanceIdentifier path, T data, DataBroker broker, FutureCallback callback) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.merge(datastoreType, path, data, true); + Futures.addCallback(tx.submit(), callback); + } + + public static void asyncDelete(LogicalDatastoreType datastoreType, + InstanceIdentifier path, DataBroker broker, FutureCallback callback) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.delete(datastoreType, path); + Futures.addCallback(tx.submit(), callback); + } + + public static String getInterfaceName(final BigInteger datapathid, final String portName, final Integer vlanId) { + return String.format("%s:%s:%s", datapathid, portName, vlanId); + } + + public static BigInteger getDpnIdFromInterfaceName(String interfaceName) { + String[] dpnStr = interfaceName.split(":"); + BigInteger dpnId = new BigInteger(dpnStr[0]); + return dpnId; + } + + public static String getTrunkInterfaceName(String parentInterfaceName, String localHostName, String remoteHostName) { + String trunkInterfaceName = String.format("%s:%s:%s", parentInterfaceName, localHostName, remoteHostName); + return trunkInterfaceName; + } + + public static InetAddress getInetAddressFromIpAddress(IpAddress ip) { + return InetAddresses.forString(ip.getIpv4Address().getValue()); + } + + public static InstanceIdentifier getDPNTEPInstance(BigInteger dpIdKey) { + InstanceIdentifier.InstanceIdentifierBuilder dpnTepInfoBuilder = + InstanceIdentifier.builder(Tunnels.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpIdKey)); + InstanceIdentifier dpnInfo = dpnTepInfoBuilder.build(); + return dpnInfo; + } + + public static DPNTEPsInfo createDPNTepInfo(BigInteger dpId, List endpoints) { + + return new DPNTEPsInfoBuilder().setKey(new DPNTEPsInfoKey(dpId)).setTunnelEndPoints(endpoints).build(); + } + + public static TunnelEndPoints createTunnelEndPoints(BigInteger dpnId, IpAddress ipAddress, String portName, int vlanId, + IpPrefix prefix, IpAddress gwAddress, String zoneName, String tunnel_type) { + // when Interface Mgr provides support to take in Dpn Id + return new TunnelEndPointsBuilder().setKey(new TunnelEndPointsKey(ipAddress, portName, vlanId)) + .setSubnetMask(prefix).setGwIpAddress(gwAddress).setTransportZone(zoneName) + .setInterfaceName(ItmUtils.getInterfaceName(dpnId, portName, vlanId)).setTunnelType(tunnel_type).build(); + } + + public static Tunnels createTunnel(List dpnTepInfo) { + return new TunnelsBuilder().setDPNTEPsInfo(dpnTepInfo).build(); + } + + public static InstanceIdentifier buildId(String interfaceName) { + InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName)); + InstanceIdentifier id = idBuilder.build(); + return id; + } + + public static Interface buildTunnelInterface(BigInteger dpn, String ifName, String desc, boolean enabled, Class tunType, + IpAddress localIp, IpAddress remoteIp, IpAddress gatewayIp) { + InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(ifName)).setName(ifName) + .setDescription(desc).setEnabled(enabled).setType(Tunnel.class); + ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dpn).build(); + builder.addAugmentation(ParentRefs.class, parentRefs); + IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(remoteIp).setTunnelGateway(gatewayIp).setTunnelSource(localIp) + .setTunnelInterfaceType( tunType).build(); + builder.addAugmentation(IfTunnel.class, tunnel); + return builder.build(); + } + + public static List getTunnelMeshInfo(DataBroker dataBroker) { + List dpnTEPs= null ; + + // Read the EndPoint Info from the operational database + InstanceIdentifierBuilder tnlBuilder = InstanceIdentifier.builder( Tunnels.class) ; + InstanceIdentifier tnls = tnlBuilder.build() ; + Optional tunnels = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tnls, dataBroker); + if( tunnels.isPresent()) { + Tunnels tn= tunnels.get() ; + dpnTEPs = tn.getDPNTEPsInfo() ; + LOG.debug( "Read from CONFIGURATION datastore - No. of Dpns " , dpnTEPs.size() ); + }else + LOG.debug( "No Dpn information in CONFIGURATION datastore " ); + return dpnTEPs ; + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java new file mode 100644 index 00000000..2878d850 --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/listeners/TransportZoneListener.java @@ -0,0 +1,179 @@ +/* + * 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.itm.listeners; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ListenableFuture; + +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +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.inet.types.rev100924.IpPrefix; +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.dpn.teps.info.TunnelEndPoints; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rev150701.TransportZones; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rev150701.TransportZonesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rev150701.transport.zones.TransportZone; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rev150701.transport.zones.transport.zone.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rev150701.transport.zones.transport.zone.subnets.Vteps; +import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase; +import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator; +import org.opendaylight.vpnservice.itm.impl.ITMManager; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.vpnservice.itm.confighelpers.ItmTepAddWorker ; +import org.opendaylight.vpnservice.itm.confighelpers.ItmTepRemoveWorker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class listens for interface creation/removal/update in Configuration DS. + * This is used to handle interfaces for base of-ports. + */ +public class TransportZoneListener extends AsyncDataTreeChangeListenerBase implements AutoCloseable{ + private static final Logger LOG = LoggerFactory.getLogger(TransportZoneListener.class); + private DataBroker dataBroker; + private ITMManager itmManager; + + public TransportZoneListener(final DataBroker dataBroker) { + super(TransportZone.class, TransportZoneListener.class); + this.dataBroker = dataBroker; + initializeTZNode(dataBroker); + } + + public void setItmManager(ITMManager itmManager) { + this.itmManager = itmManager; + } + + private void initializeTZNode(DataBroker db) { + ReadWriteTransaction transaction = db.newReadWriteTransaction(); + InstanceIdentifier path = InstanceIdentifier.create(TransportZones.class); + CheckedFuture, ReadFailedException> tzones = + transaction.read(LogicalDatastoreType.CONFIGURATION,path); + try { + if (!tzones.get().isPresent()) { + TransportZonesBuilder tzb = new TransportZonesBuilder(); + transaction.put(LogicalDatastoreType.CONFIGURATION,path,tzb.build()); + transaction.submit(); + } else { + transaction.cancel(); + } + } catch (Exception e) { + LOG.error("Error initializing TransportZones {}",e); + } + } + + @Override + public void close() throws Exception { + LOG.info("tzChangeListener Closed"); + } + @Override + protected InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(TransportZones.class).child(TransportZone.class); + } + + @Override + protected TransportZoneListener getDataTreeChangeListener() { + return TransportZoneListener.this; + } + + @Override + protected void remove(InstanceIdentifier key, TransportZone tzOld) { + LOG.debug("Received Transport Zone Remove Event: {}, {}", key, tzOld); + List opDpnList = createDPNTepInfo(tzOld); + LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList); + if(opDpnList.size()>0) { + LOG.trace("Delete: Invoking ItmManager"); + // itmManager.deleteTunnels(opDpnList); + DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance(); + ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(opDpnList, dataBroker); + coordinator.enqueueJob(tzOld.getZoneName(), removeWorker); + } + } + + @Override + protected void update(InstanceIdentifier key, TransportZone tzOld, TransportZone tzNew) { + LOG.debug("Received Transport Zone Update Event: {}, {}, {}", key, tzOld, tzNew); + if( !(tzOld.equals(tzNew))) { + add(key, tzNew); + } + } + + @Override + protected void add(InstanceIdentifier key, TransportZone tzNew) { + LOG.debug("Received Transport Zone Add Event: {}, {}", key, tzNew); + List opDpnList = createDPNTepInfo(tzNew); + LOG.trace("Add: Operational dpnTepInfo - Before invoking ItmManager {}", opDpnList); + if(opDpnList.size()>0) { + LOG.trace("Add: Invoking ItmManager with DPN List {} " , opDpnList); + //itmManager.build_all_tunnels(opDpnList); + DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance(); + ItmTepAddWorker addWorker = new ItmTepAddWorker(opDpnList,dataBroker); + coordinator.enqueueJob(tzNew.getZoneName(), addWorker); + } + } + + private List createDPNTepInfo(TransportZone transportZone){ + + Map> mapDPNToTunnelEndpt = new ConcurrentHashMap<>(); + List dpnTepInfo = new ArrayList(); + // List transportZoneList = transportZones.getTransportZone(); + // for(TransportZone transportZone : transportZoneList) { + String zone_name = transportZone.getZoneName(); + String tunnel_type = transportZone.getTunnelType(); + LOG.trace("Transport Zone_name: {}", zone_name); + List subnetsList = transportZone.getSubnets(); + if(subnetsList!=null){ + for (Subnets subnet : subnetsList) { + IpPrefix ipPrefix = subnet.getPrefix(); + IpAddress gatewayIP = subnet.getGatewayIp(); + int vlanID = subnet.getVlanId(); + LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID); + List vtepsList = subnet.getVteps(); + for (Vteps vteps : vtepsList) { + BigInteger dpnID = vteps.getDpnId(); + String port = vteps.getPortname(); + IpAddress ipAddress = vteps.getIpAddress(); + LOG.trace("DpnID: {}, port: {}, ipAddress: {}", dpnID, port, ipAddress); + TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port, vlanID, ipPrefix, gatewayIP, zone_name, tunnel_type); + List tunnelEndPointsList = mapDPNToTunnelEndpt.get(dpnID); + if (tunnelEndPointsList != null) { + LOG.trace("Existing DPN info list in the Map: {} ", dpnID); + tunnelEndPointsList.add(tunnelEndPoints); + } else { + LOG.trace("Adding new DPN info list to the Map: {} ", dpnID); + tunnelEndPointsList = new ArrayList(); + tunnelEndPointsList.add(tunnelEndPoints); + mapDPNToTunnelEndpt.put(dpnID, tunnelEndPointsList); + } + } + } + } + //} + if(mapDPNToTunnelEndpt.size()>0){ + Set keys = mapDPNToTunnelEndpt.keySet(); + LOG.trace("List of dpns in the Map: {} ", keys); + for(BigInteger key: keys){ + DPNTEPsInfo newDpnTepsInfo = ItmUtils.createDPNTepInfo(key, mapDPNToTunnelEndpt.get(key)); + dpnTepInfo.add(newDpnTepsInfo); + } + } + return dpnTepInfo; + } +} \ No newline at end of file diff --git a/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java new file mode 100644 index 00000000..dad264df --- /dev/null +++ b/itm/itm-impl/src/main/java/org/opendaylight/vpnservice/itm/rpc/ItmManagerRpcService.java @@ -0,0 +1,111 @@ +/* + * 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.itm.rpc; + +import java.math.BigInteger; +import java.util.List; +import java.util.concurrent.Future; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelAddWorker; +import org.opendaylight.vpnservice.itm.impl.ItmUtils; +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.itm.op.rev150701.tunnels.DPNTEPsInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.BuildTunnelFromDpnToDcgatewayInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.BuildTunnelToDcgatewayInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.GetTunnelInterfaceIdInput; +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.GetTunnelInterfaceIdOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.rpcs.rev151217.ItmRpcService; +import org.opendaylight.yangtools.yang.common.RpcResult; +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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; + +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import com.google.common.base.Optional; + +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; + +public class ItmManagerRpcService implements ItmRpcService { + + private static final Logger LOG = LoggerFactory.getLogger(ItmRpcService.class); + DataBroker dataBroker; + public ItmManagerRpcService(DataBroker dataBroker) { + this.dataBroker = dataBroker; + } + + @Override + public Future> buildTunnelFromDpnToDcgateway(BuildTunnelFromDpnToDcgatewayInput input) { + //Ignore the Futures for now + final SettableFuture> result = SettableFuture.create(); + ItmExternalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, input.getDpid(), null, input.getDcgwyid()); + result.set(RpcResultBuilder.success().build()); + return result ; + } + + @Override + public Future> getTunnelInterfaceId(GetTunnelInterfaceIdInput input) { + final SettableFuture> result = SettableFuture.create() ; + RpcResultBuilder resultBld = null; + BigInteger sourceDpn = input.getSourceDpid() ; + BigInteger destinationDpn = input.getDestinationDpid() ; + String parentName = null; + IpAddress srcIp = null ; + IpAddress destIp = null ; + List meshDpnList = ItmUtils.getTunnelMeshInfo(dataBroker); + for ( DPNTEPsInfo dpn : meshDpnList) { + if( (dpn.getDPNID()).equals(sourceDpn) ){ + parentName = dpn.getTunnelEndPoints().get(0).getInterfaceName(); + srcIp = dpn.getTunnelEndPoints().get(0).getIpAddress() ; + }else if( (dpn.getDPNID()).equals(destinationDpn)) { + destIp = dpn.getTunnelEndPoints().get(0).getIpAddress() ; + } + } + if( srcIp != null && destIp != null ) + { + String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(parentName, srcIp.getIpv4Address().getValue(), destIp.getIpv4Address().getValue()) ; + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(InterfacesState.class) + .child(Interface.class, new InterfaceKey(trunkInterfaceName)); + InstanceIdentifier id = idBuilder.build(); + Optional stateIf = ItmUtils.read(LogicalDatastoreType.OPERATIONAL, id, dataBroker); + if(stateIf.isPresent()){ + GetTunnelInterfaceIdOutputBuilder output = new GetTunnelInterfaceIdOutputBuilder() ; + output.setInterfaceid(stateIf.get().getIfIndex()) ; + resultBld.withResult(output.build()) ; + result.set(resultBld.build()) ; + }else { + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "Interface Not found ").build()) ; + } + }else { + result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "Source or Destination Dpn Id not found ").build()) ; + } + return result ; + } + + @Override + public Future> buildTunnelToDcgateway(BuildTunnelToDcgatewayInput input) { + //Ignore the Futures for now + final SettableFuture> result = SettableFuture.create(); + ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, null, input.getDcgwyid()) ; + result.set(RpcResultBuilder.success().build()); + return result ; + } +} diff --git a/vpnmanager/vpnmanager-api/src/main/yang/l3vpn.yang b/vpnmanager/vpnmanager-api/src/main/yang/l3vpn.yang index 534b7742..f8db3ca0 100644 --- a/vpnmanager/vpnmanager-api/src/main/yang/l3vpn.yang +++ b/vpnmanager/vpnmanager-api/src/main/yang/l3vpn.yang @@ -14,6 +14,7 @@ module l3vpn { import ietf-inet-types { prefix inet; + revision-date "2010-09-24"; //RFC6991 } -- 2.36.6