2 * Copyright (c) 2015, 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.vpnservice.itm.confighelpers;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
14 import com.google.common.base.Optional;
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.vpnservice.itm.globals.ITMConstants;
19 import org.opendaylight.vpnservice.itm.impl.ItmUtils;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.binding.*;
46 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.apache.commons.net.util.SubnetUtils;
51 import com.google.common.util.concurrent.FutureCallback;
52 import com.google.common.util.concurrent.ListenableFuture;
54 public class ItmExternalTunnelAddWorker {
55 private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class);
57 private static final FutureCallback<Void> DEFAULT_CALLBACK =
58 new FutureCallback<Void>() {
59 public void onSuccess(Void result) {
60 logger.debug("Success in Datastore operation");
63 public void onFailure(Throwable error) {
64 logger.error("Error in Datastore operation", error);
70 public static List<ListenableFuture<Void>> buildTunnelsToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
71 List<DPNTEPsInfo> cfgDpnList, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
72 List<ListenableFuture<Void>> futures = new ArrayList<>();
73 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
74 if (null != cfgDpnList) {
75 for (DPNTEPsInfo teps : cfgDpnList) {
76 // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels
77 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
78 String interfaceName = firstEndPt.getInterfaceName();
79 String tunTypeStr = tunType.getName();
80 String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue(), tunTypeStr);
81 char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue();
82 String subnetMaskStr = String.valueOf(subnetMaskArray);
83 SubnetUtils utils = new SubnetUtils(subnetMaskStr);
84 String dcGwyIpStr = String.valueOf(extIp.getValue());
85 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
86 IpAddress gwyIpAddress = (utils.getInfo().isInRange(dcGwyIpStr)) ? gatewayIpObj : firstEndPt.getGwIpAddress();
87 logger.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, DC Gateway IP - {} gateway IP - {}", trunkInterfaceName, interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress);
88 Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName, String.format("%s %s", ItmUtils.convertTunnelTypetoString(tunType), "Trunk Interface"), true, tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress, firstEndPt.getVLANID(), false,false,null);
89 logger.debug(" Trunk Interface builder - {} ", iface);
90 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
91 logger.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
92 logger.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
93 t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
94 // update external_tunnel_list ds
95 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
96 ExternalTunnelList.class)
97 .child(ExternalTunnel.class, new ExternalTunnelKey(extIp.toString(), teps.getDPNID().toString(), tunType));
98 ExternalTunnel tnl = ItmUtils.buildExternalTunnel( teps.getDPNID().toString(), extIp.toString(),
99 tunType, trunkInterfaceName);
100 t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
102 futures.add(t.submit());
107 public static List<ListenableFuture<Void>> buildTunnelsFromDpnToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
108 List<BigInteger> dpnId, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
109 List<ListenableFuture<Void>> futures = new ArrayList<>();
110 List<DPNTEPsInfo> cfgDpnList = (dpnId == null) ? ItmUtils.getTunnelMeshInfo(dataBroker) : ItmUtils.getDPNTEPListFromDPNId(dataBroker, dpnId);
111 futures = buildTunnelsToExternalEndPoint(dataBroker, idManagerService, cfgDpnList, extIp, tunType);
115 public static List<ListenableFuture<Void>> buildHwVtepsTunnels(DataBroker dataBroker, IdManagerService idManagerService, List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> cfgdHwVteps) {
116 List<ListenableFuture<Void>> futures = new ArrayList<>();
117 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
118 if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
119 logger.trace("calling tunnels from css {}",cfgdDpnList);
120 tunnelsFromCSS(cfgdDpnList, idManagerService , futures, t , dataBroker);
123 if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty() ) {
124 logger.trace("calling tunnels from hwTep {}",cfgdHwVteps);
125 tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, t, dataBroker);
128 if ((cfgdDpnList != null && !cfgdDpnList.isEmpty()) || (cfgdHwVteps != null && !cfgdHwVteps.isEmpty()))
129 futures.add(t.submit());
133 private static void tunnelsFromCSS(List<DPNTEPsInfo> cfgdDpnList, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
134 for (DPNTEPsInfo dpn : cfgdDpnList) {
135 logger.trace("processing dpn {}" , dpn);
136 if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty())
137 for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) {
138 InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((tep.getTransportZone()))).build();
139 Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
140 if (tZoneOptional.isPresent()) {
141 TransportZone tZone = tZoneOptional.get();
142 //do we need to check tunnel type?
143 if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
144 for (Subnets sub : tZone.getSubnets()) {
145 if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
146 for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
147 String cssID = dpn.getDPNID().toString();
148 String nodeId = hwVtepDS.getNodeId();
150 Boolean monitorEnabled = ItmUtils.readMonitoringStateFromDS(dataBroker);
151 Integer monitorInterval = ItmUtils.readMonitorIntervalfromDS(dataBroker);
152 logger.trace("wire up {} and {}",tep, hwVtepDS);
153 if (!wireUp(dpn.getDPNID(), tep.getPortname(), sub.getVlanId(), tep.getIpAddress(), nodeId, hwVtepDS.getIpAddress(), tep.getSubnetMask(),
154 sub.getGatewayIp(), sub.getPrefix(), tZone.getTunnelType(),monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
155 logger.error("Unable to build tunnel {} -- {}", tep.getIpAddress(), hwVtepDS.getIpAddress());
157 logger.trace("wire up {} and {}", hwVtepDS,tep);
158 if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), cssID, tep.getIpAddress(), sub.getPrefix(),
159 sub.getGatewayIp(), tep.getSubnetMask(), tZone.getTunnelType(), monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
160 logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), tep.getIpAddress());
171 private static void tunnelsFromhWVtep(List<HwVtep> cfgdHwVteps, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
172 for (HwVtep hwTep : cfgdHwVteps) {
173 InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((hwTep.getTransportZone()))).build();
174 Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
175 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
176 if (tZoneOptional.isPresent()) {
177 TransportZone tZone = tZoneOptional.get();
178 //do we need to check tunnel type?
179 if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
180 for (Subnets sub : tZone.getSubnets()) {
181 if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
182 for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
183 if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp()))
184 continue;//dont mesh with self
186 Boolean monitorEnabled = ItmUtils.readMonitoringStateFromDS(dataBroker);
187 Integer monitorInterval = ItmUtils.readMonitorIntervalfromDS(dataBroker);
188 logger.trace("wire up {} and {}",hwTep, hwVtepDS);
189 if (!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
190 hwTep.getIpPrefix(), hwTep.getGatewayIP(), sub.getPrefix(), tunType,monitorEnabled,
191 ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
192 logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), hwVtepDS.getIpAddress());
194 logger.trace("wire up {} and {}", hwVtepDS,hwTep);
195 if (!wireUp(hwTep.getTopo_id(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), hwTep.getNode_id(), hwTep.getHwIp(),
196 sub.getPrefix(), sub.getGatewayIp(), hwTep.getIpPrefix(), tunType, monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
197 logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), hwTep.getHwIp());
200 if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
201 for (Vteps vtep : sub.getVteps()) {
203 String cssID = vtep.getDpnId().toString();
204 Boolean monitorEnabled = ItmUtils.readMonitoringStateFromDS(dataBroker);
205 Integer monitorInterval = ItmUtils.readMonitorIntervalfromDS(dataBroker);
206 logger.trace("wire up {} and {}",hwTep, vtep);
207 if(!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), cssID, vtep.getIpAddress(), hwTep.getIpPrefix(),
208 hwTep.getGatewayIP(), sub.getPrefix(), tunType,monitorEnabled, ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t ))
209 logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), vtep.getIpAddress());
211 logger.trace("wire up {} and {}", vtep,hwTep);
212 if(!wireUp(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId(), vtep.getIpAddress(),
213 hwTep.getNode_id(),hwTep.getHwIp(),sub.getPrefix(), sub.getGatewayIp(),hwTep.getIpPrefix(),
214 tunType,monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL,idManagerService, dataBroker, futures, t ));
225 //for tunnels from TOR device
226 private static boolean wireUp(String topo_id, String srcNodeid, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
227 IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType,Boolean monitorEnabled,
228 Integer monitorInterval,IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
229 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
230 IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? gatewayIpObj : gWIp;
231 String parentIf = ItmUtils.getHwParentIf(topo_id, srcNodeid);
232 String tunTypeStr = tunType.getName();
233 String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
234 srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue(), tunTypeStr);
235 logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
236 Interface hwTunnelIf = ItmUtils.buildHwTunnelInterface(tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"),
237 true, topo_id, srcNodeid, tunType, srcIp, dstIp, gwyIpAddress, monitorEnabled, monitorInterval);
238 InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
239 logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf);
240 ItmUtils.itmCache.addInterface(hwTunnelIf);
241 t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, hwTunnelIf, true);
242 // also update itm-state ds?
243 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
244 ExternalTunnelList.class)
245 .child(ExternalTunnel.class, new ExternalTunnelKey( getExternalTunnelKey(dstNodeId), getExternalTunnelKey(srcNodeid), tunType));
246 ExternalTunnel tnl = ItmUtils.buildExternalTunnel( getExternalTunnelKey(srcNodeid),
247 getExternalTunnelKey(dstNodeId),
248 tunType, tunnelIfName);
249 t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
250 ItmUtils.itmCache.addExternalTunnel(tnl);
254 //for tunnels from CSS
255 private static boolean wireUp(BigInteger dpnId,String portname, Integer vlanId, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
256 IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType,Boolean monitorEnabled, Integer monitorInterval,
257 IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
258 IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
259 IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? gatewayIpObj : gWIp;
260 String parentIf = ItmUtils.getInterfaceName(dpnId, portname, vlanId);
261 String tunTypeStr = tunType.getName();
262 String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
263 srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue(), tunTypeStr);
264 logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
265 Interface extTunnelIf = ItmUtils.buildTunnelInterface(dpnId, tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"), true, tunType, srcIp, dstIp, gwyIpAddress, vlanId, false,monitorEnabled, monitorInterval);
266 InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
267 logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf);
268 t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, extTunnelIf, true);
269 ItmUtils.itmCache.addInterface(extTunnelIf);
270 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
271 ExternalTunnelList.class)
272 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId), dpnId.toString(), tunType));
273 ExternalTunnel tnl = ItmUtils.buildExternalTunnel( dpnId.toString(),
274 getExternalTunnelKey(dstNodeId),
275 tunType, tunnelIfName);
276 t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
277 ItmUtils.itmCache.addExternalTunnel(tnl);
281 static String getExternalTunnelKey(String nodeid) {
282 if (nodeid.indexOf("physicalswitch") > 0) {
283 nodeid = nodeid.substring(0, nodeid.indexOf("physicalswitch") - 1);