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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Objects;
14 import java.util.Optional;
15 import java.util.concurrent.ExecutionException;
16 import org.opendaylight.genius.infra.Datastore.Configuration;
17 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
18 import org.opendaylight.genius.infra.TypedWriteTransaction;
19 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
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.IpAddressBuilder;
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.interfacemanager.rev160406.TunnelMonitoringTypeBase;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.tunnel.optional.params.TunnelOptions;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVteps;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.opendaylight.yangtools.yang.common.Uint64;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public class ItmExternalTunnelAddWorker {
49 private static final Logger LOG = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class);
50 private static final IpAddress GATEWAY_IP_OBJ = IpAddressBuilder.getDefaultInstance("0.0.0.0");
52 private final ItmConfig itmConfig;
53 private final DPNTEPsInfoCache dpnTEPsInfoCache;
55 public ItmExternalTunnelAddWorker(ItmConfig itmConfig, DPNTEPsInfoCache dpnTEPsInfoCache) {
56 this.itmConfig = itmConfig;
57 this.dpnTEPsInfoCache = dpnTEPsInfoCache;
60 public void buildTunnelsToExternalEndPoint(Collection<DPNTEPsInfo> cfgDpnList, IpAddress extIp,
61 Class<? extends TunnelTypeBase> tunType,
62 TypedWriteTransaction<Configuration> tx) {
63 if (null != cfgDpnList) {
64 for (DPNTEPsInfo teps : cfgDpnList) {
65 // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels
66 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
67 String interfaceName = firstEndPt.getInterfaceName();
68 String tunTypeStr = tunType.getName();
69 String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(interfaceName,
70 firstEndPt.getIpAddress().stringValue(), extIp.stringValue(), tunTypeStr);
71 boolean useOfTunnel = ItmUtils.falseIfNull(firstEndPt.isOptionOfTunnel());
72 List<TunnelOptions> tunOptions = ItmUtils.buildTunnelOptions(firstEndPt, itmConfig);
73 IpAddress gatewayIpObj = IpAddressBuilder.getDefaultInstance("0.0.0.0");
74 IpAddress gwyIpAddress = gatewayIpObj;
75 LOG.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {},"
76 + " source IP - {}, DC Gateway IP - {} gateway IP - {}", trunkInterfaceName,
77 interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress);
78 Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName,
79 trunkInterface(ItmUtils.convertTunnelTypetoString(tunType)),
80 true, tunType, firstEndPt.getIpAddress(), extIp, false, false,
81 ITMConstants.DEFAULT_MONITOR_PROTOCOL, null, useOfTunnel, tunOptions);
83 LOG.debug(" Trunk Interface builder - {} ", iface);
84 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
85 LOG.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
86 LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
87 tx.mergeParentStructureMerge(trunkIdentifier, iface);
88 // update external_tunnel_list ds
89 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(ExternalTunnelList.class)
90 .child(ExternalTunnel.class, new ExternalTunnelKey(extIp.stringValue(),
91 teps.getDPNID().toString(), tunType));
92 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(teps.getDPNID().toString(),
93 extIp.stringValue(), tunType, trunkInterfaceName);
94 tx.mergeParentStructureMerge(path, tnl);
95 ItmUtils.ITM_CACHE.addExternalTunnel(tnl);
101 public void buildTunnelsFromDpnToExternalEndPoint(List<Uint64> dpnId, IpAddress extIp,
102 Class<? extends TunnelTypeBase> tunType,
103 TypedWriteTransaction<Configuration> tx) {
104 Collection<DPNTEPsInfo> cfgDpnList = dpnId == null ? dpnTEPsInfoCache.getAllPresent()
105 : ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, dpnId);
106 buildTunnelsToExternalEndPoint(cfgDpnList, extIp, tunType, tx);
109 public void buildHwVtepsTunnels(List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> cfgdHwVteps,
110 TypedReadWriteTransaction<Configuration> tx) {
112 Integer monitorInterval = ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL;
113 Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
115 if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
116 LOG.trace("calling tunnels from OVS {}",cfgdDpnList);
117 tunnelsFromOVS(cfgdDpnList, tx, monitorInterval, monitorProtocol);
119 if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty()) {
120 LOG.trace("calling tunnels from hwTep {}",cfgdHwVteps);
121 cfgdHwVteps.forEach(hwVtep -> {
123 tunnelsFromhWVtep(hwVtep, tx, monitorInterval, monitorProtocol);
124 } catch (ExecutionException | InterruptedException e) {
125 LOG.error("Tunnel Creation failed for {} due to ", hwVtep.getTransportZone(), e);
131 private void tunnelsFromOVS(List<DPNTEPsInfo> cfgdDpnList, TypedReadWriteTransaction<Configuration> tx,
132 Integer monitorInterval, Class<? extends TunnelMonitoringTypeBase> monitorProtocol) {
133 for (DPNTEPsInfo dpn : cfgdDpnList) {
134 LOG.trace("processing dpn {}", dpn);
135 if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty()) {
136 for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) {
137 for (TzMembership zone : tep.nonnullTzMembership().values()) {
139 createTunnelsFromOVSinTransportZone(zone.getZoneName(), dpn, tep, tx, monitorInterval,
141 } catch (ExecutionException | InterruptedException e) {
142 LOG.error("Tunnel Creation failed for {} due to ", zone.getZoneName(), e);
150 private void createTunnelsFromOVSinTransportZone(String zoneName, DPNTEPsInfo dpn, TunnelEndPoints tep,
151 TypedReadWriteTransaction<Configuration> tx, Integer monitorInterval,
152 Class<? extends TunnelMonitoringTypeBase> monitorProtocol)
153 throws ExecutionException, InterruptedException {
154 Optional<TransportZone> transportZoneOptional = tx.read(InstanceIdentifier.builder(TransportZones.class)
155 .child(TransportZone.class, new TransportZoneKey(zoneName)).build()).get();
156 if (transportZoneOptional.isPresent()) {
157 TransportZone transportZone = transportZoneOptional.get();
158 //do we need to check tunnel type?
159 if (transportZone.getDeviceVteps() != null && !transportZone.getDeviceVteps().isEmpty()) {
160 String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
161 int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava()
162 : ITMConstants.DUMMY_VLANID;
163 for (DeviceVteps hwVtepDS : transportZone.getDeviceVteps().values()) {
164 //dont mesh if hwVteps and OVS-tep have same ip-address
165 if (Objects.equals(hwVtepDS.getIpAddress(), tep.getIpAddress())) {
168 final String cssID = dpn.getDPNID().toString();
169 String nodeId = hwVtepDS.getNodeId();
170 boolean useOfTunnel = ItmUtils.falseIfNull(tep.isOptionOfTunnel());
171 LOG.trace("wire up {} and {}",tep, hwVtepDS);
172 if (!wireUp(dpn.getDPNID(), portName, vlanId, tep.getIpAddress(), useOfTunnel, nodeId,
173 hwVtepDS.getIpAddress(), transportZone.getTunnelType(), false,
174 monitorInterval, monitorProtocol, tx)) {
175 LOG.error("Unable to build tunnel {} -- {}",
176 tep.getIpAddress(), hwVtepDS.getIpAddress());
179 LOG.trace("wire up {} and {}", hwVtepDS,tep);
180 if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
181 cssID, tep.getIpAddress(),
182 transportZone.getTunnelType(), false, monitorInterval,
183 monitorProtocol, tx)) {
184 LOG.error("Unable to build tunnel {} -- {}",
185 hwVtepDS.getIpAddress(), tep.getIpAddress());
193 private void tunnelsFromhWVtep(HwVtep hwTep, TypedReadWriteTransaction<Configuration> tx,
194 Integer monitorInterval, Class<? extends TunnelMonitoringTypeBase> monitorProtocol)
195 throws ExecutionException, InterruptedException {
196 Optional<TransportZone> transportZoneOptional = tx.read(InstanceIdentifier.builder(TransportZones.class)
197 .child(TransportZone.class, new TransportZoneKey(hwTep.getTransportZone())).build()).get();
198 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
199 if (transportZoneOptional.isPresent()) {
200 TransportZone tzone = transportZoneOptional.get();
201 String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
202 int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
203 //do we need to check tunnel type?
204 if (tzone.getDeviceVteps() != null && !tzone.getDeviceVteps().isEmpty()) {
205 for (DeviceVteps hwVtepDS : tzone.getDeviceVteps().values()) {
206 if (Objects.equals(hwVtepDS.getIpAddress(), hwTep.getHwIp())) {
207 continue;//dont mesh with self
209 LOG.trace("wire up {} and {}",hwTep, hwVtepDS);
210 if (!wireUp(hwTep.getTopoId(), hwTep.getNodeId(), hwTep.getHwIp(),
211 hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
213 monitorInterval, monitorProtocol, tx)) {
214 LOG.error("Unable to build tunnel {} -- {}",
215 hwTep.getHwIp(), hwVtepDS.getIpAddress());
218 LOG.trace("wire up {} and {}", hwVtepDS,hwTep);
219 if (!wireUp(hwTep.getTopoId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
220 hwTep.getNodeId(), hwTep.getHwIp(),
221 tunType, false, monitorInterval,
222 monitorProtocol, tx)) {
223 LOG.error("Unable to build tunnel {} -- {}",
224 hwVtepDS.getIpAddress(), hwTep.getHwIp());
228 for (Vteps vtep : tzone.getVteps().values()) {
229 if (Objects.equals(vtep.getIpAddress(), hwTep.getHwIp())) {
233 String cssID = vtep.getDpnId().toString();
234 LOG.trace("wire up {} and {}",hwTep, vtep);
235 if (!wireUp(hwTep.getTopoId(), hwTep.getNodeId(), hwTep.getHwIp(), cssID,
237 tunType,false, monitorInterval, monitorProtocol,
239 LOG.error("Unable to build tunnel {} -- {}",
240 hwTep.getHwIp(), vtep.getIpAddress());
243 LOG.trace("wire up {} and {}", vtep,hwTep);
244 boolean useOfTunnel = ItmUtils.falseIfNull(vtep.isOptionOfTunnel());
245 if (!wireUp(vtep.getDpnId(), portName, vlanId, vtep.getIpAddress(),
246 useOfTunnel, hwTep.getNodeId(),hwTep.getHwIp(),
248 monitorInterval, monitorProtocol, tx)) {
249 LOG.debug("wireUp returned false");
255 //for tunnels from TOR device
256 private boolean wireUp(String topoId, String srcNodeid, IpAddress srcIp, String dstNodeId, IpAddress dstIp,
257 Class<? extends TunnelTypeBase> tunType,
258 Boolean monitorEnabled, Integer monitorInterval,
259 Class<? extends TunnelMonitoringTypeBase> monitorProtocol,
260 TypedWriteTransaction<Configuration> tx) {
261 IpAddress gatewayIpObj = IpAddressBuilder.getDefaultInstance("0.0.0.0");
262 IpAddress gwyIpAddress = gatewayIpObj;
263 String parentIf = ItmUtils.getHwParentIf(topoId, srcNodeid);
264 String tunTypeStr = tunType.getName();
265 String tunnelIfName = ItmUtils.getTrunkInterfaceName(parentIf,
266 srcIp.stringValue(), dstIp.stringValue(), tunTypeStr);
267 LOG.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, "
268 + "source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp,
269 dstIp, gwyIpAddress);
270 Interface hwTunnelIf = ItmUtils.buildHwTunnelInterface(tunnelIfName,
271 trunkInterface(tunType), true, topoId, srcNodeid, tunType, srcIp,
272 dstIp, gwyIpAddress, monitorEnabled, monitorProtocol, monitorInterval);
273 InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class)
274 .child(Interface.class, new InterfaceKey(tunnelIfName)).build();
275 LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf);
276 ItmUtils.ITM_CACHE.addInterface(hwTunnelIf);
277 tx.mergeParentStructureMerge(ifIID, hwTunnelIf);
278 // also update itm-state ds?
279 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(ExternalTunnelList.class)
280 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId),
281 getExternalTunnelKey(srcNodeid), tunType));
282 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(getExternalTunnelKey(srcNodeid),
283 getExternalTunnelKey(dstNodeId), tunType, tunnelIfName);
284 tx.mergeParentStructureMerge(path, tnl);
285 ItmUtils.ITM_CACHE.addExternalTunnel(tnl);
289 //for tunnels from OVS
290 private boolean wireUp(Uint64 dpnId, String portname, Integer vlanId, IpAddress srcIp, Boolean remoteIpFlow,
291 String dstNodeId, IpAddress dstIp,
292 Class<? extends TunnelTypeBase> tunType, Boolean monitorEnabled, Integer monitorInterval,
293 Class<? extends TunnelMonitoringTypeBase> monitorProtocol,
294 TypedWriteTransaction<Configuration> tx) {
296 IpAddress gwyIpAddress = GATEWAY_IP_OBJ;
298 String parentIf = ItmUtils.getInterfaceName(dpnId, portname, vlanId);
299 String tunTypeStr = tunType.getName();
300 String tunnelIfName = ItmUtils.getTrunkInterfaceName(parentIf,
301 srcIp.stringValue(), dstIp.stringValue(), tunTypeStr);
302 LOG.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, "
303 + "source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp,
304 dstIp, gwyIpAddress);
305 Interface extTunnelIf = ItmUtils.buildTunnelInterface(dpnId, tunnelIfName,
306 trunkInterface(tunType), true, tunType, srcIp, dstIp,
307 false, monitorEnabled, monitorProtocol, monitorInterval, remoteIpFlow, null);
308 InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class,
309 new InterfaceKey(tunnelIfName)).build();
310 LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf);
311 tx.mergeParentStructureMerge(ifIID, extTunnelIf);
312 ItmUtils.ITM_CACHE.addInterface(extTunnelIf);
313 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(ExternalTunnelList.class)
314 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId),
315 dpnId.toString(), tunType));
316 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(dpnId.toString(),
317 getExternalTunnelKey(dstNodeId),
318 tunType, tunnelIfName);
319 tx.mergeParentStructureMerge(path, tnl);
320 ItmUtils.ITM_CACHE.addExternalTunnel(tnl);
324 private static String trunkInterface(Class<? extends TunnelTypeBase> tunType) {
325 return trunkInterface(tunType.getName());
328 private static String trunkInterface(String tunType) {
329 return tunType + " Trunk Interface";
332 @SuppressFBWarnings("RV_CHECK_FOR_POSITIVE_INDEXOF")
333 static String getExternalTunnelKey(String nodeid) {
334 final int index = nodeid.indexOf("physicalswitch");
336 nodeid = nodeid.substring(0, index - 1);