e16300cb5d538f8d7bf8cf54d853c2009dd9812b
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / confighelpers / ItmExternalTunnelAddWorker.java
1 /*
2  * Copyright (c) 2016, 2017 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.genius.itm.confighelpers;
9
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;
47
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");
51
52     private final ItmConfig itmConfig;
53     private final DPNTEPsInfoCache dpnTEPsInfoCache;
54
55     public ItmExternalTunnelAddWorker(ItmConfig itmConfig, DPNTEPsInfoCache dpnTEPsInfoCache) {
56         this.itmConfig = itmConfig;
57         this.dpnTEPsInfoCache = dpnTEPsInfoCache;
58     }
59
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);
82
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.merge(trunkIdentifier, iface, true);
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.merge(path, tnl, true);
95                 ItmUtils.ITM_CACHE.addExternalTunnel(tnl);
96
97             }
98         }
99     }
100
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);
107     }
108
109     public void buildHwVtepsTunnels(List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> cfgdHwVteps,
110                                     TypedReadWriteTransaction<Configuration> tx) {
111
112         Integer monitorInterval = ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL;
113         Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
114
115         if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
116             LOG.trace("calling tunnels from OVS {}",cfgdDpnList);
117             tunnelsFromOVS(cfgdDpnList, tx, monitorInterval, monitorProtocol);
118         }
119         if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty()) {
120             LOG.trace("calling tunnels from hwTep {}",cfgdHwVteps);
121             cfgdHwVteps.forEach(hwVtep -> {
122                 try {
123                     tunnelsFromhWVtep(hwVtep, tx, monitorInterval, monitorProtocol);
124                 } catch (ExecutionException | InterruptedException e) {
125                     LOG.error("Tunnel Creation failed for {} due to ", hwVtep.getTransportZone(), e);
126                 }
127             });
128         }
129     }
130
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()) {
138                         try {
139                             createTunnelsFromOVSinTransportZone(zone.getZoneName(), dpn, tep, tx, monitorInterval,
140                                     monitorProtocol);
141                         } catch (ExecutionException | InterruptedException e) {
142                             LOG.error("Tunnel Creation failed for {} due to ", zone.getZoneName(), e);
143                         }
144                     }
145                 }
146             }
147         }
148     }
149
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()) {
164                     //dont mesh if hwVteps and OVS-tep have same ip-address
165                     if (Objects.equals(hwVtepDS.getIpAddress(), tep.getIpAddress())) {
166                         continue;
167                     }
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());
177                     }
178                     //TOR-OVS
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());
186                     }
187
188                 }
189             }
190         }
191     }
192
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()) {
206                     if (Objects.equals(hwVtepDS.getIpAddress(), hwTep.getHwIp())) {
207                         continue;//dont mesh with self
208                     }
209                     LOG.trace("wire up {} and {}",hwTep, hwVtepDS);
210                     if (!wireUp(hwTep.getTopoId(), hwTep.getNodeId(), hwTep.getHwIp(),
211                             hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
212                             tunType, false,
213                             monitorInterval, monitorProtocol, tx)) {
214                         LOG.error("Unable to build tunnel {} -- {}",
215                                 hwTep.getHwIp(), hwVtepDS.getIpAddress());
216                     }
217                     //TOR2-TOR1
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());
225                     }
226                 }
227             }
228             for (Vteps vtep : tzone.getVteps()) {
229                 if (Objects.equals(vtep.getIpAddress(), hwTep.getHwIp())) {
230                     continue;
231                 }
232                 //TOR-OVS
233                 String cssID = vtep.getDpnId().toString();
234                 LOG.trace("wire up {} and {}",hwTep, vtep);
235                 if (!wireUp(hwTep.getTopoId(), hwTep.getNodeId(), hwTep.getHwIp(), cssID,
236                         vtep.getIpAddress(),
237                         tunType,false, monitorInterval, monitorProtocol,
238                         tx)) {
239                     LOG.error("Unable to build tunnel {} -- {}",
240                             hwTep.getHwIp(), vtep.getIpAddress());
241                 }
242                 //OVS-TOR
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(),
247                         tunType, false,
248                         monitorInterval, monitorProtocol, tx)) {
249                     LOG.debug("wireUp returned false");
250                 }
251             }
252         }
253     }
254
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.merge(ifIID, hwTunnelIf, true);
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.merge(path, tnl, true);
285         ItmUtils.ITM_CACHE.addExternalTunnel(tnl);
286         return true;
287     }
288
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) {
295
296         IpAddress gwyIpAddress = GATEWAY_IP_OBJ;
297
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.merge(ifIID, extTunnelIf, true);
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.merge(path, tnl, true);
320         ItmUtils.ITM_CACHE.addExternalTunnel(tnl);
321         return true;
322     }
323
324     private static String trunkInterface(Class<? extends TunnelTypeBase> tunType) {
325         return trunkInterface(tunType.getName());
326     }
327
328     private static String trunkInterface(String tunType) {
329         return tunType + " Trunk Interface";
330     }
331
332     @SuppressFBWarnings("RV_CHECK_FOR_POSITIVE_INDEXOF")
333     static String getExternalTunnelKey(String nodeid) {
334         final int index = nodeid.indexOf("physicalswitch");
335         if (index > 0) {
336             nodeid = nodeid.substring(0, index - 1);
337         }
338         return nodeid;
339     }
340
341 }