2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.itm.confighelpers;
10 import com.google.common.util.concurrent.FutureCallback;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.itm.impl.ItmUtils;
19 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.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.genius.idmanager.rev160406.IdManagerService;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpointsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 public class ItmInternalTunnelAddWorker {
38 private static final Logger logger = LoggerFactory.getLogger(ItmInternalTunnelAddWorker.class) ;
39 private static Boolean monitorEnabled;
40 private static Integer monitorInterval;
41 private static Class<? extends TunnelMonitoringTypeBase> monitorProtocol;
42 private static final FutureCallback<Void> DEFAULT_CALLBACK =
43 new FutureCallback<Void>() {
45 public void onSuccess(Void result) {
46 logger.debug("Success in Datastore operation");
50 public void onFailure(Throwable error) {
51 logger.error("Error in Datastore operation", error);
56 public static List<ListenableFuture<Void>> build_all_tunnels(DataBroker dataBroker, IdManagerService idManagerService,IMdsalApiManager mdsalManager,
57 List<DPNTEPsInfo> cfgdDpnList, List<DPNTEPsInfo> meshedDpnList) {
58 logger.trace( "Building tunnels with DPN List {} " , cfgdDpnList );
59 monitorInterval = ItmUtils.determineMonitorInterval(dataBroker);
60 monitorProtocol = ItmUtils.determineMonitorProtocol(dataBroker);
61 monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
62 List<ListenableFuture<Void>> futures = new ArrayList<>();
63 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
64 if( null == cfgdDpnList || cfgdDpnList.isEmpty()) {
65 logger.error(" Build Tunnels was invoked with empty list");
69 for( DPNTEPsInfo dpn : cfgdDpnList) {
70 //#####if dpn is not in meshedDpnList
71 build_tunnel_from(dpn, meshedDpnList, dataBroker, idManagerService, mdsalManager, t, futures);
72 if(null == meshedDpnList) {
73 meshedDpnList = new ArrayList<>() ;
75 meshedDpnList.add(dpn) ;
76 // Update the operational datastore -- FIXME -- Error Handling
77 updateOperationalDatastore(dataBroker, dpn, t, futures) ;
79 futures.add( t.submit()) ;
83 private static void updateOperationalDatastore(DataBroker dataBroker, DPNTEPsInfo dpn, WriteTransaction t, List<ListenableFuture<Void>> futures) {
84 logger.debug("Updating CONFIGURATION datastore with DPN {} ", dpn);
85 InstanceIdentifier<DpnEndpoints> dep = InstanceIdentifier.builder( DpnEndpoints.class).build() ;
86 List<DPNTEPsInfo> dpnList = new ArrayList<>() ;
88 DpnEndpoints tnlBuilder = new DpnEndpointsBuilder().setDPNTEPsInfo(dpnList).build() ;
89 t.merge(LogicalDatastoreType.CONFIGURATION, dep, tnlBuilder, true);
92 private static void build_tunnel_from( DPNTEPsInfo srcDpn,List<DPNTEPsInfo> meshedDpnList, DataBroker dataBroker, IdManagerService idManagerService, IMdsalApiManager mdsalManager, WriteTransaction t, List<ListenableFuture<Void>> futures) {
93 logger.trace( "Building tunnels from DPN {} " , srcDpn );
95 if( null == meshedDpnList || 0 == meshedDpnList.size()) {
96 logger.debug( "No DPN in the mesh ");
99 for( DPNTEPsInfo dstDpn: meshedDpnList) {
100 if ( ! srcDpn.equals(dstDpn) ) {
101 wireUpWithinTransportZone(srcDpn, dstDpn, dataBroker, idManagerService, mdsalManager, t, futures) ;
107 private static void wireUpWithinTransportZone( DPNTEPsInfo srcDpn, DPNTEPsInfo dstDpn, DataBroker dataBroker,
108 IdManagerService idManagerService, IMdsalApiManager mdsalManager,WriteTransaction t, List<ListenableFuture<Void>> futures) {
109 logger.trace( "Wiring up within Transport Zone for Dpns {}, {} " , srcDpn, dstDpn );
110 List<TunnelEndPoints> srcEndPts = srcDpn.getTunnelEndPoints();
111 List<TunnelEndPoints> dstEndPts = dstDpn.getTunnelEndPoints();
113 for( TunnelEndPoints srcte : srcEndPts) {
114 for( TunnelEndPoints dstte : dstEndPts ) {
115 // Compare the Transport zones
116 if (!srcDpn.getDPNID().equals(dstDpn.getDPNID())) {
117 if( !ItmUtils.getIntersection(srcte.getTzMembership(), dstte.getTzMembership()).isEmpty()) {
119 wireUpBidirectionalTunnel( srcte, dstte, srcDpn.getDPNID(), dstDpn.getDPNID(), dataBroker, idManagerService, mdsalManager, t, futures );
120 // CHECK THIS -- Assumption -- One end point per Dpn per transport zone
128 private static void wireUpBidirectionalTunnel( TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId,
129 DataBroker dataBroker, IdManagerService idManagerService, IMdsalApiManager mdsalManager, WriteTransaction t, List<ListenableFuture<Void>> futures) {
130 // Setup the flow for LLDP monitoring -- PUNT TO CONTROLLER
132 if(monitorProtocol.isAssignableFrom(TunnelMonitoringTypeLldp.class)) {
133 ItmUtils.setUpOrRemoveTerminatingServiceTable(srcDpnId, mdsalManager, true);
134 ItmUtils.setUpOrRemoveTerminatingServiceTable(dstDpnId, mdsalManager, true);
136 // Create the forward direction tunnel
137 if(!wireUp( srcte, dstte, srcDpnId, dstDpnId, dataBroker, idManagerService, t, futures )) {
138 logger.error("Could not build tunnel between end points {}, {} " , srcte, dstte );
141 // CHECK IF FORWARD IS NOT BUILT , REVERSE CAN BE BUILT
142 // Create the tunnel for the reverse direction
143 if(! wireUp( dstte, srcte, dstDpnId, srcDpnId, dataBroker, idManagerService, t, futures )) {
144 logger.error("Could not build tunnel between end points {}, {} " , dstte, srcte);
148 private static boolean wireUp(TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId ,
149 DataBroker dataBroker, IdManagerService idManagerService, WriteTransaction t, List<ListenableFuture<Void>> futures) {
151 logger.trace( "Wiring between source tunnel end points {}, destination tunnel end points {} " , srcte, dstte );
152 String interfaceName = srcte.getInterfaceName() ;
153 Class<? extends TunnelTypeBase> tunType = srcte.getTunnelType();
154 String tunTypeStr = srcte.getTunnelType().getName();
155 // Form the trunk Interface Name
156 String trunkInterfaceName = ItmUtils.getTrunkInterfaceName( idManagerService, interfaceName,
157 srcte.getIpAddress().getIpv4Address().getValue(),
158 dstte.getIpAddress().getIpv4Address().getValue(),
160 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
161 IpAddress gwyIpAddress = srcte.getSubnetMask().equals(dstte.getSubnetMask()) ? gatewayIpObj : srcte.getGwIpAddress() ;
162 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 ) ;
163 boolean useOfTunnel = ItmUtils.falseIfNull(srcte.isOptionOfTunnel());
164 Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName,
165 String.format( "%s %s",ItmUtils.convertTunnelTypetoString(srcte.getTunnelType()), "Trunk Interface"),
166 true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress, srcte.getVLANID(), true,
167 monitorEnabled, monitorProtocol, monitorInterval, useOfTunnel);
168 logger.debug( " Trunk Interface builder - {} ", iface ) ;
169 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
170 logger.debug( " Trunk Interface Identifier - {} ", trunkIdentifier ) ;
171 logger.trace( " Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface ) ;
172 t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
173 ItmUtils.itmCache.addInterface(iface);
174 // also update itm-state ds?
175 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
177 .child(InternalTunnel.class, new InternalTunnelKey( dstDpnId, srcDpnId, tunType));
178 InternalTunnel tnl = ItmUtils.buildInternalTunnel(srcDpnId, dstDpnId, tunType, trunkInterfaceName);
179 //ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tnl, dataBroker, DEFAULT_CALLBACK);
180 t.merge(LogicalDatastoreType.CONFIGURATION,path, tnl, true) ;
181 ItmUtils.itmCache.addInternalTunnel(tnl);