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.ITMBatchingUtils;
19 import org.opendaylight.genius.itm.impl.ItmUtils;
20 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpointsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 public class ItmInternalTunnelAddWorker {
39 private static final Logger logger = LoggerFactory.getLogger(ItmInternalTunnelAddWorker.class) ;
40 private static Boolean monitorEnabled;
41 private static Integer monitorInterval;
42 private static Class<? extends TunnelMonitoringTypeBase> monitorProtocol;
43 private static final FutureCallback<Void> DEFAULT_CALLBACK =
44 new FutureCallback<Void>() {
46 public void onSuccess(Void result) {
47 logger.debug("Success in Datastore operation");
51 public void onFailure(Throwable error) {
52 logger.error("Error in Datastore operation", error);
57 public static List<ListenableFuture<Void>> build_all_tunnels(DataBroker dataBroker, IdManagerService idManagerService,IMdsalApiManager mdsalManager,
58 List<DPNTEPsInfo> cfgdDpnList, List<DPNTEPsInfo> meshedDpnList) {
59 logger.trace( "Building tunnels with DPN List {} " , cfgdDpnList );
60 monitorInterval = ItmUtils.determineMonitorInterval(dataBroker);
61 monitorProtocol = ItmUtils.determineMonitorProtocol(dataBroker);
62 monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
63 List<ListenableFuture<Void>> futures = new ArrayList<>();
64 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
65 if( null == cfgdDpnList || cfgdDpnList.isEmpty()) {
66 logger.error(" Build Tunnels was invoked with empty list");
70 for( DPNTEPsInfo dpn : cfgdDpnList) {
71 //#####if dpn is not in meshedDpnList
72 build_tunnel_from(dpn, meshedDpnList, dataBroker, idManagerService, mdsalManager, t, futures);
73 if(null == meshedDpnList) {
74 meshedDpnList = new ArrayList<>() ;
76 meshedDpnList.add(dpn) ;
77 // Update the operational datastore -- FIXME -- Error Handling
78 updateOperationalDatastore(dataBroker, dpn, t, futures) ;
80 futures.add( t.submit()) ;
84 private static void updateOperationalDatastore(DataBroker dataBroker, DPNTEPsInfo dpn, WriteTransaction t, List<ListenableFuture<Void>> futures) {
85 logger.debug("Updating CONFIGURATION datastore with DPN {} ", dpn);
86 InstanceIdentifier<DpnEndpoints> dep = InstanceIdentifier.builder( DpnEndpoints.class).build() ;
87 List<DPNTEPsInfo> dpnList = new ArrayList<>() ;
89 DpnEndpoints tnlBuilder = new DpnEndpointsBuilder().setDPNTEPsInfo(dpnList).build() ;
90 ITMBatchingUtils.update(dep,tnlBuilder , ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
93 private static void build_tunnel_from( DPNTEPsInfo srcDpn,List<DPNTEPsInfo> meshedDpnList, DataBroker dataBroker, IdManagerService idManagerService, IMdsalApiManager mdsalManager, WriteTransaction t, List<ListenableFuture<Void>> futures) {
94 logger.trace( "Building tunnels from DPN {} " , srcDpn );
96 if( null == meshedDpnList || 0 == meshedDpnList.size()) {
97 logger.debug( "No DPN in the mesh ");
100 for( DPNTEPsInfo dstDpn: meshedDpnList) {
101 if ( ! srcDpn.equals(dstDpn) ) {
102 wireUpWithinTransportZone(srcDpn, dstDpn, dataBroker, idManagerService, mdsalManager, t, futures) ;
108 private static void wireUpWithinTransportZone( DPNTEPsInfo srcDpn, DPNTEPsInfo dstDpn, DataBroker dataBroker,
109 IdManagerService idManagerService, IMdsalApiManager mdsalManager,WriteTransaction t, List<ListenableFuture<Void>> futures) {
110 logger.trace( "Wiring up within Transport Zone for Dpns {}, {} " , srcDpn, dstDpn );
111 List<TunnelEndPoints> srcEndPts = srcDpn.getTunnelEndPoints();
112 List<TunnelEndPoints> dstEndPts = dstDpn.getTunnelEndPoints();
114 for( TunnelEndPoints srcte : srcEndPts) {
115 for( TunnelEndPoints dstte : dstEndPts ) {
116 // Compare the Transport zones
117 if (!srcDpn.getDPNID().equals(dstDpn.getDPNID())) {
118 if( !ItmUtils.getIntersection(srcte.getTzMembership(), dstte.getTzMembership()).isEmpty()) {
120 wireUpBidirectionalTunnel( srcte, dstte, srcDpn.getDPNID(), dstDpn.getDPNID(), dataBroker, idManagerService, mdsalManager, t, futures );
121 // CHECK THIS -- Assumption -- One end point per Dpn per transport zone
129 private static void wireUpBidirectionalTunnel( TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId,
130 DataBroker dataBroker, IdManagerService idManagerService, IMdsalApiManager mdsalManager, WriteTransaction t, List<ListenableFuture<Void>> futures) {
131 // Setup the flow for LLDP monitoring -- PUNT TO CONTROLLER
133 if(monitorProtocol.isAssignableFrom(TunnelMonitoringTypeLldp.class)) {
134 ItmUtils.setUpOrRemoveTerminatingServiceTable(srcDpnId, mdsalManager, true);
135 ItmUtils.setUpOrRemoveTerminatingServiceTable(dstDpnId, mdsalManager, true);
137 // Create the forward direction tunnel
138 if(!wireUp( srcte, dstte, srcDpnId, dstDpnId, dataBroker, idManagerService, t, futures )) {
139 logger.error("Could not build tunnel between end points {}, {} " , srcte, dstte );
142 // CHECK IF FORWARD IS NOT BUILT , REVERSE CAN BE BUILT
143 // Create the tunnel for the reverse direction
144 if(! wireUp( dstte, srcte, dstDpnId, srcDpnId, dataBroker, idManagerService, t, futures )) {
145 logger.error("Could not build tunnel between end points {}, {} " , dstte, srcte);
149 private static boolean wireUp(TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId ,
150 DataBroker dataBroker, IdManagerService idManagerService, WriteTransaction t, List<ListenableFuture<Void>> futures) {
152 logger.trace( "Wiring between source tunnel end points {}, destination tunnel end points {} " , srcte, dstte );
153 String interfaceName = srcte.getInterfaceName() ;
154 Class<? extends TunnelTypeBase> tunType = srcte.getTunnelType();
155 String tunTypeStr = srcte.getTunnelType().getName();
156 // Form the trunk Interface Name
158 String trunkInterfaceName = ItmUtils.getTrunkInterfaceName( idManagerService, interfaceName,
159 new String(srcte.getIpAddress().getValue()),
160 new String(dstte.getIpAddress().getValue()),
163 String gateway = srcte.getIpAddress().getIpv4Address() != null ? "0.0.0.0" : "::";
164 IpAddress gatewayIpObj = new IpAddress(gateway.toCharArray());
165 IpAddress gwyIpAddress = srcte.getSubnetMask().equals(dstte.getSubnetMask()) ? gatewayIpObj : srcte.getGwIpAddress() ;
166 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 ) ;
167 boolean useOfTunnel = ItmUtils.falseIfNull(srcte.isOptionOfTunnel());
168 Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName,
169 String.format( "%s %s",ItmUtils.convertTunnelTypetoString(srcte.getTunnelType()), "Trunk Interface"),
170 true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress, srcte.getVLANID(), true,
171 monitorEnabled, monitorProtocol, monitorInterval, useOfTunnel);
172 logger.debug( " Trunk Interface builder - {} ", iface ) ;
173 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
174 logger.debug( " Trunk Interface Identifier - {} ", trunkIdentifier ) ;
175 logger.trace( " Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface ) ;
176 ITMBatchingUtils.update(trunkIdentifier, iface, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
177 ItmUtils.itmCache.addInterface(iface);
178 // also update itm-state ds?
179 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
181 .child(InternalTunnel.class, new InternalTunnelKey( dstDpnId, srcDpnId, tunType));
182 InternalTunnel tnl = ItmUtils.buildInternalTunnel(srcDpnId, dstDpnId, tunType, trunkInterfaceName);
183 ITMBatchingUtils.update(path, tnl, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
184 ItmUtils.itmCache.addInternalTunnel(tnl);