2 * Copyright (c) 2016, 2017 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.base.Optional;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.apache.commons.net.util.SubnetUtils;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.itm.globals.ITMConstants;
21 import org.opendaylight.genius.itm.impl.ItmUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class ItmExternalTunnelAddWorker {
48 private static final Logger LOG = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class);
50 private static Boolean monitorEnabled;
51 private static Integer monitorInterval;
52 private static Class<? extends TunnelMonitoringTypeBase> monitorProtocol;
54 private static final FutureCallback<Void> DEFAULT_CALLBACK =
55 new FutureCallback<Void>() {
57 public void onSuccess(Void result) {
58 LOG.debug("Success in Datastore operation");
62 public void onFailure(Throwable error) {
63 LOG.error("Error in Datastore operation", error);
68 public static List<ListenableFuture<Void>> buildTunnelsToExternalEndPoint(DataBroker dataBroker,
69 IdManagerService idManagerService,
70 List<DPNTEPsInfo> cfgDpnList,
72 Class<? extends TunnelTypeBase> tunType) {
73 List<ListenableFuture<Void>> futures = new ArrayList<>();
74 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
75 if (null != cfgDpnList) {
76 for (DPNTEPsInfo teps : cfgDpnList) {
77 // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels
78 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
79 String interfaceName = firstEndPt.getInterfaceName();
80 String tunTypeStr = tunType.getName();
81 String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName,
82 new String(firstEndPt.getIpAddress().getValue()),
83 new String(extIp.getValue()), tunTypeStr);
84 char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue();
85 boolean useOfTunnel = ItmUtils.falseIfNull(firstEndPt.isOptionOfTunnel());
86 String subnetMaskStr = String.valueOf(subnetMaskArray);
87 SubnetUtils utils = new SubnetUtils(subnetMaskStr);
88 String dcGwyIpStr = String.valueOf(extIp.getValue());
89 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
90 IpAddress gwyIpAddress =
91 utils.getInfo().isInRange(dcGwyIpStr) ? gatewayIpObj : firstEndPt.getGwIpAddress();
92 LOG.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {},"
93 + " source IP - {}, DC Gateway IP - {} gateway IP - {}", trunkInterfaceName, interfaceName,
94 firstEndPt.getIpAddress(), extIp, gwyIpAddress);
95 Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName,
96 String.format("%s %s", ItmUtils.convertTunnelTypetoString(tunType), "Trunk Interface"), true,
97 tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress, firstEndPt.getVLANID(), false, false,
98 ITMConstants.DEFAULT_MONITOR_PROTOCOL, null, useOfTunnel);
100 LOG.debug(" Trunk Interface builder - {} ", iface);
101 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
102 LOG.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
103 LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
104 transaction.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
105 // update external_tunnel_list ds
106 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(ExternalTunnelList.class)
107 .child(ExternalTunnel.class, new ExternalTunnelKey(extIp.toString(),
108 teps.getDPNID().toString(), tunType));
109 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(teps.getDPNID().toString(), extIp.toString(),
110 tunType, trunkInterfaceName);
111 transaction.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
113 futures.add(transaction.submit());
118 public static List<ListenableFuture<Void>> buildTunnelsFromDpnToExternalEndPoint(DataBroker dataBroker,
119 IdManagerService idManagerService,
120 List<BigInteger> dpnId,
122 Class<? extends TunnelTypeBase>
124 List<ListenableFuture<Void>> futures = new ArrayList<>();
125 List<DPNTEPsInfo> cfgDpnList = dpnId == null ? ItmUtils.getTunnelMeshInfo(dataBroker)
126 : ItmUtils.getDpnTepListFromDpnId(dataBroker, dpnId);
127 futures = buildTunnelsToExternalEndPoint(dataBroker, idManagerService, cfgDpnList, extIp, tunType);
131 public static List<ListenableFuture<Void>> buildHwVtepsTunnels(DataBroker dataBroker,
132 IdManagerService idManagerService,
133 List<DPNTEPsInfo> cfgdDpnList,
134 List<HwVtep> cfgdHwVteps) {
135 List<ListenableFuture<Void>> futures = new ArrayList<>();
136 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
137 monitorInterval = ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL;
138 monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
139 monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
140 if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
141 LOG.trace("calling tunnels from css {}",cfgdDpnList);
142 tunnelsFromCSS(cfgdDpnList, idManagerService , futures, writeTransaction , dataBroker);
144 if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty()) {
145 LOG.trace("calling tunnels from hwTep {}",cfgdHwVteps);
146 tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, writeTransaction, dataBroker);
149 if (cfgdDpnList != null && !cfgdDpnList.isEmpty() || cfgdHwVteps != null && !cfgdHwVteps.isEmpty()) {
150 futures.add(writeTransaction.submit());
155 private static void tunnelsFromCSS(List<DPNTEPsInfo> cfgdDpnList, IdManagerService idManagerService,
156 List<ListenableFuture<Void>> futures, WriteTransaction transaction,
157 DataBroker dataBroker) {
158 Boolean monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
159 Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
160 for (DPNTEPsInfo dpn : cfgdDpnList) {
161 LOG.trace("processing dpn {}" , dpn);
162 if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty()) {
163 for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) {
164 for (TzMembership zone: tep.getTzMembership()) {
165 createTunnelsFromOVSinTransportZone(zone.getZoneName(), dpn, tep, idManagerService,
166 futures, transaction, dataBroker);
173 private static void createTunnelsFromOVSinTransportZone(String zoneName, DPNTEPsInfo dpn, TunnelEndPoints tep,
174 IdManagerService idManagerService,
175 List<ListenableFuture<Void>> futures,
176 WriteTransaction transaction, DataBroker dataBroker) {
177 InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
178 .child(TransportZone.class, new TransportZoneKey(zoneName)).build();
179 Optional<TransportZone> transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
180 tzonePath, dataBroker);
181 if (transportZoneOptional.isPresent()) {
182 TransportZone transportZone = transportZoneOptional.get();
183 //do we need to check tunnel type?
184 if (transportZone.getSubnets() != null && !transportZone.getSubnets().isEmpty()) {
185 for (Subnets sub : transportZone.getSubnets()) {
186 if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
187 for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
188 //dont mesh if hwVteps and OVS-tep have same ip-address
189 if (hwVtepDS.getIpAddress().equals(tep.getIpAddress())) {
192 final String cssID = dpn.getDPNID().toString();
193 String nodeId = hwVtepDS.getNodeId();
194 boolean useOfTunnel = ItmUtils.falseIfNull(tep.isOptionOfTunnel());
195 LOG.trace("wire up {} and {}",tep, hwVtepDS);
196 if (!wireUp(dpn.getDPNID(), tep.getPortname(), sub.getVlanId(),
197 tep.getIpAddress(), useOfTunnel, nodeId, hwVtepDS.getIpAddress(),
198 tep.getSubnetMask(), sub.getGatewayIp(), sub.getPrefix(),
199 transportZone.getTunnelType(), false, monitorProtocol, monitorInterval,
200 idManagerService, dataBroker, futures, transaction)) {
201 LOG.error("Unable to build tunnel {} -- {}",
202 tep.getIpAddress(), hwVtepDS.getIpAddress());
205 LOG.trace("wire up {} and {}", hwVtepDS,tep);
206 if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
207 cssID, tep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(),
208 tep.getSubnetMask(), transportZone.getTunnelType(), false, monitorProtocol,
209 monitorInterval, idManagerService, dataBroker, futures, transaction)) {
210 LOG.error("Unable to build tunnel {} -- {}",
211 hwVtepDS.getIpAddress(), tep.getIpAddress());
221 private static void tunnelsFromhWVtep(List<HwVtep> cfgdHwVteps, IdManagerService idManagerService,
222 List<ListenableFuture<Void>> futures, WriteTransaction transaction,
223 DataBroker dataBroker) {
224 for (HwVtep hwTep : cfgdHwVteps) {
225 InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
226 .child(TransportZone.class, new TransportZoneKey(hwTep.getTransportZone())).build();
227 Optional<TransportZone> transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
228 tzonePath, dataBroker);
229 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
230 Boolean monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
231 Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
232 if (transportZoneOptional.isPresent()) {
233 TransportZone tzone = transportZoneOptional.get();
234 //do we need to check tunnel type?
235 if (tzone.getSubnets() != null && !tzone.getSubnets().isEmpty()) {
236 for (Subnets sub : tzone.getSubnets()) {
237 if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
238 for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
239 if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp())) {
240 continue;//dont mesh with self
242 LOG.trace("wire up {} and {}",hwTep, hwVtepDS);
243 if (!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(),
244 hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), hwTep.getIpPrefix(),
245 hwTep.getGatewayIP(), sub.getPrefix(), tunType,false,monitorProtocol,
246 monitorInterval, idManagerService, dataBroker, futures, transaction)) {
247 LOG.error("Unable to build tunnel {} -- {}",
248 hwTep.getHwIp(), hwVtepDS.getIpAddress());
251 LOG.trace("wire up {} and {}", hwVtepDS,hwTep);
252 if (!wireUp(hwTep.getTopo_id(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
253 hwTep.getNode_id(), hwTep.getHwIp(), sub.getPrefix(), sub.getGatewayIp(),
254 hwTep.getIpPrefix(), tunType, false, monitorProtocol, monitorInterval,
255 idManagerService, dataBroker, futures, transaction)) {
256 LOG.error("Unable to build tunnel {} -- {}",
257 hwVtepDS.getIpAddress(), hwTep.getHwIp());
261 if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
262 for (Vteps vtep : sub.getVteps()) {
263 if (vtep.getIpAddress().equals(hwTep.getHwIp())) {
267 String cssID = vtep.getDpnId().toString();
268 LOG.trace("wire up {} and {}",hwTep, vtep);
269 if (!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), cssID,
270 vtep.getIpAddress(), hwTep.getIpPrefix(), hwTep.getGatewayIP(),
271 sub.getPrefix(), tunType,false, monitorProtocol, monitorInterval,
272 idManagerService, dataBroker, futures, transaction)) {
273 LOG.error("Unable to build tunnel {} -- {}",
274 hwTep.getHwIp(), vtep.getIpAddress());
277 LOG.trace("wire up {} and {}", vtep,hwTep);
278 boolean useOfTunnel = ItmUtils.falseIfNull(vtep.isOptionOfTunnel());
279 if (!wireUp(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId(), vtep.getIpAddress(),
280 useOfTunnel, hwTep.getNode_id(),hwTep.getHwIp(),sub.getPrefix(),
281 sub.getGatewayIp(),hwTep.getIpPrefix(), tunType,false,monitorProtocol,
282 monitorInterval, idManagerService, dataBroker, futures, transaction)) {
294 //for tunnels from TOR device
295 private static boolean wireUp(String topoId, String srcNodeid, IpAddress srcIp, String dstNodeId, IpAddress dstIp,
296 IpPrefix srcSubnet, IpAddress gwIp, IpPrefix dstSubnet,
297 Class<? extends TunnelTypeBase> tunType,Boolean monitorEnabled,
298 Class<? extends TunnelMonitoringTypeBase> monitorProtocol, Integer monitorInterval,
299 IdManagerService idManagerService, DataBroker dataBroker,
300 List<ListenableFuture<Void>> futures, WriteTransaction transaction) {
301 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
302 IpAddress gwyIpAddress = srcSubnet.equals(dstSubnet) ? gatewayIpObj : gwIp;
303 String parentIf = ItmUtils.getHwParentIf(topoId, srcNodeid);
304 String tunTypeStr = tunType.getName();
305 String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
306 new String(srcIp.getValue()), new String(dstIp.getValue()), tunTypeStr);
307 LOG.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, "
308 + "source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp,
309 dstIp, gwyIpAddress);
310 Interface hwTunnelIf = ItmUtils.buildHwTunnelInterface(tunnelIfName,
311 String.format("%s %s", tunType.getName(), "Trunk Interface"), true, topoId, srcNodeid, tunType, srcIp,
312 dstIp, gwyIpAddress, monitorEnabled, monitorProtocol, monitorInterval);
313 InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class)
314 .child(Interface.class, new InterfaceKey(tunnelIfName)).build();
315 LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf);
316 ItmUtils.itmCache.addInterface(hwTunnelIf);
317 transaction.merge(LogicalDatastoreType.CONFIGURATION, ifIID, hwTunnelIf, true);
318 // also update itm-state ds?
319 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(ExternalTunnelList.class)
320 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId),
321 getExternalTunnelKey(srcNodeid), tunType));
322 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(getExternalTunnelKey(srcNodeid),
323 getExternalTunnelKey(dstNodeId), tunType, tunnelIfName);
324 transaction.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
325 ItmUtils.itmCache.addExternalTunnel(tnl);
329 //for tunnels from OVS
330 private static boolean wireUp(BigInteger dpnId, String portname, Integer vlanId, IpAddress srcIp,
331 Boolean remoteIpFlow, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
332 IpAddress gwIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType,
333 Boolean monitorEnabled, Class<? extends TunnelMonitoringTypeBase> monitorProtocol,
334 Integer monitorInterval, IdManagerService idManagerService, DataBroker dataBroker,
335 List<ListenableFuture<Void>> futures, WriteTransaction transaction) {
336 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
337 IpAddress gwyIpAddress = srcSubnet.equals(dstSubnet) ? gatewayIpObj : gwIp;
338 String parentIf = ItmUtils.getInterfaceName(dpnId, portname, vlanId);
339 String tunTypeStr = tunType.getName();
340 String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
341 new String(srcIp.getValue()), new String(dstIp.getValue()), tunTypeStr);
342 LOG.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, "
343 + "source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp,
344 dstIp, gwyIpAddress);
345 Interface extTunnelIf = ItmUtils.buildTunnelInterface(dpnId, tunnelIfName,
346 String.format("%s %s", tunType.getName(), "Trunk Interface"), true, tunType, srcIp, dstIp, gwyIpAddress,
347 vlanId, false,monitorEnabled, monitorProtocol, monitorInterval, remoteIpFlow);
348 InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class,
349 new InterfaceKey(tunnelIfName)).build();
350 LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf);
351 transaction.merge(LogicalDatastoreType.CONFIGURATION, ifIID, extTunnelIf, true);
352 ItmUtils.itmCache.addInterface(extTunnelIf);
353 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(ExternalTunnelList.class)
354 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId),
355 dpnId.toString(), tunType));
356 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(dpnId.toString(),
357 getExternalTunnelKey(dstNodeId),
358 tunType, tunnelIfName);
359 transaction.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
360 ItmUtils.itmCache.addExternalTunnel(tnl);
364 static String getExternalTunnelKey(String nodeid) {
365 if (nodeid.indexOf("physicalswitch") > 0) {
366 nodeid = nodeid.substring(0, nodeid.indexOf("physicalswitch") - 1);