Fixing issues with ARP integration of VpnService
[vpnservice.git] / itm / itm-impl / src / main / java / org / opendaylight / vpnservice / itm / confighelpers / ItmInternalTunnelAddWorker.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.vpnservice.itm.confighelpers;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.Callable;
14
15 import com.google.common.util.concurrent.ListenableFuture;
16
17 import org.opendaylight.vpnservice.itm.impl.ItmUtils;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.Tunnels;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.TunnelsBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.DPNTEPsInfo;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels.dpn.teps.info.TunnelEndPoints;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 public class ItmInternalTunnelAddWorker {
35      private static final Logger logger = LoggerFactory.getLogger(ItmInternalTunnelAddWorker.class) ;
36
37     public static List<ListenableFuture<Void>> build_all_tunnels(DataBroker dataBroker, List<DPNTEPsInfo> cfgdDpnList, List<DPNTEPsInfo> meshedDpnList) {
38         logger.trace( "Building tunnels with DPN List {} " , cfgdDpnList );
39         List<ListenableFuture<Void>> futures = new ArrayList<>();
40         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
41         if( null == cfgdDpnList || cfgdDpnList.isEmpty()) {
42             logger.error(" Build Tunnels was invoked with empty list");
43             return null;
44          }
45
46         for( DPNTEPsInfo dpn : cfgdDpnList) {
47             build_tunnel_from(dpn, meshedDpnList, dataBroker, t, futures);
48             if(null == meshedDpnList) {
49                 meshedDpnList = new ArrayList<DPNTEPsInfo>() ;
50             }
51             meshedDpnList.add(dpn) ;
52             // Update the operational datastore -- FIXME -- Error Handling
53             updateOperationalDatastore(dataBroker, dpn, t, futures) ;
54         }
55         futures.add( t.submit()) ;
56         return futures ;
57     }
58
59     private static void updateOperationalDatastore(DataBroker dataBroker, DPNTEPsInfo dpn, WriteTransaction t, List<ListenableFuture<Void>> futures) {
60         logger.debug("Updating CONFIGURATION datastore with DPN {} ", dpn);
61         InstanceIdentifier<Tunnels> tnId = InstanceIdentifier.builder( Tunnels.class).build() ;
62         List<DPNTEPsInfo> dpnList = new ArrayList<DPNTEPsInfo>() ;
63         dpnList.add(dpn) ;
64         Tunnels tnlBuilder = new TunnelsBuilder().setDPNTEPsInfo(dpnList).build() ;
65         t.merge(LogicalDatastoreType.CONFIGURATION, tnId, tnlBuilder, true);
66     }
67
68     private static void build_tunnel_from( DPNTEPsInfo srcDpn,List<DPNTEPsInfo> meshedDpnList, DataBroker dataBroker,  WriteTransaction t, List<ListenableFuture<Void>> futures) {
69         logger.trace( "Building tunnels from DPN {} " , srcDpn );
70
71         if( null == meshedDpnList || 0 == meshedDpnList.size()) {
72             logger.debug( "No DPN in the mesh ");
73             return ;
74         }
75         for( DPNTEPsInfo dstDpn: meshedDpnList) {
76             if ( ! srcDpn.equals(dstDpn) )
77                     wireUpWithinTransportZone(srcDpn, dstDpn, dataBroker, t, futures) ;
78         }
79
80    }
81
82     private static void wireUpWithinTransportZone( DPNTEPsInfo srcDpn, DPNTEPsInfo dstDpn, DataBroker dataBroker,  WriteTransaction t, List<ListenableFuture<Void>> futures) {
83         logger.trace( "Wiring up within Transport Zone for Dpns {}, {} " , srcDpn, dstDpn );
84         List<TunnelEndPoints> srcEndPts = srcDpn.getTunnelEndPoints();
85         List<TunnelEndPoints> dstEndPts = dstDpn.getTunnelEndPoints();
86
87         for( TunnelEndPoints srcte : srcEndPts) {
88             for( TunnelEndPoints dstte : dstEndPts ) {
89                 // Compare the Transport zones
90               if (!srcDpn.getDPNID().equals(dstDpn.getDPNID())) {
91                 if( (srcte.getTransportZone().equals(dstte.getTransportZone()))) {
92                      // wire them up
93                      wireUpBidirectionalTunnel( srcte, dstte, srcDpn.getDPNID(), dstDpn.getDPNID(), dataBroker, t, futures );
94                      // CHECK THIS -- Assumption -- One end point per Dpn per transport zone
95                      break ;
96                 }
97               }
98             }
99          }
100     }
101
102     private static void wireUpBidirectionalTunnel( TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId,
103         DataBroker dataBroker,  WriteTransaction t, List<ListenableFuture<Void>> futures) {
104        // Setup the flow for LLDP monitoring -- PUNT TO CONTROLLER
105        //  setUpOrRemoveTerminatingServiceTable(srcDpnId, true);
106        //  setUpOrRemoveTerminatingServiceTable(dstDpnId, true);
107
108         // Create the forward direction tunnel
109         if(!wireUp( srcte, dstte, srcDpnId, dstDpnId, dataBroker, t, futures ))
110            logger.error("Could not build tunnel between end points {}, {} " , srcte, dstte );
111
112         // CHECK IF FORWARD IS NOT BUILT , REVERSE CAN BE BUILT
113       // Create the tunnel for the reverse direction
114        if(! wireUp( dstte, srcte, dstDpnId, srcDpnId, dataBroker, t, futures ))
115           logger.error("Could not build tunnel between end points {}, {} " , dstte, srcte);
116     }
117
118     private static boolean wireUp( TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId ,
119           DataBroker dataBroker,  WriteTransaction t, List<ListenableFuture<Void>> futures) {
120         // Wire Up logic
121         logger.trace( "Wiring between source tunnel end points {}, destination tunnel end points {} " , srcte, dstte );
122         String interfaceName = srcte.getInterfaceName() ;
123         Class<? extends TunnelTypeBase> tunType = (srcte.getTunnelType().equals("GRE") ) ? TunnelTypeGre.class :TunnelTypeVxlan.class ;
124         String ifDescription = (srcte.getTunnelType().equals("GRE") ) ? "GRE" : "VxLan" ;
125         // Form the trunk Interface Name
126         String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(interfaceName,srcte.getIpAddress().getIpv4Address().getValue(), dstte.getIpAddress().getIpv4Address().getValue()) ;
127         IpAddress gwyIpAddress = ( srcte.getSubnetMask().equals(dstte.getSubnetMask()) ) ? null : srcte.getGwIpAddress() ;
128         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 ) ;
129         Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName, String.format( "%s %s",ifDescription, "Trunk Interface"), true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress) ;
130         logger.debug(  " Trunk Interface builder - {} ", iface ) ;
131         InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
132         logger.debug(  " Trunk Interface Identifier - {} ", trunkIdentifier ) ;
133         logger.trace(  " Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface ) ;
134         t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
135         return true;
136     }
137
138 }