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 java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.genius.itm.globals.ITMConstants;
17 import org.opendaylight.genius.itm.impl.ItmUtils;
18 import org.opendaylight.genius.mdsalutil.MDSALUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TepsNotHostedInTransportZone;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TepsNotHostedInTransportZoneBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TepsNotHostedInTransportZoneKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.tepsnothostedintransportzone.UnknownVteps;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.tepsnothostedintransportzone.UnknownVtepsBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.tepsnothostedintransportzone.UnknownVtepsKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsKey;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 public final class OvsdbTepAddConfigHelper {
43 private static final Logger LOG = LoggerFactory.getLogger(OvsdbTepAddConfigHelper.class);
45 private OvsdbTepAddConfigHelper() { }
48 * Adds the TEP into ITM configuration Datastore in one of the following cases.
49 * 1) default transport zone
50 * 2) Configured transport zone
51 * 3) Unhosted transport zone
53 * @param tepIp TEP-IP address in string
54 * @param strDpnId bridge datapath ID in string
55 * @param tzName transport zone name in string
56 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
57 * @param dataBroker data broker handle to perform operations on config datastore
58 * @param wrTx WriteTransaction object
61 public static void addTepReceivedFromOvsdb(String tepIp, String strDpnId, String tzName,
62 boolean ofTunnel, DataBroker dataBroker, WriteTransaction wrTx) {
63 BigInteger dpnId = BigInteger.valueOf(0);
65 if (strDpnId != null && !strDpnId.isEmpty()) {
66 dpnId = MDSALUtil.getDpnId(strDpnId);
70 IpAddress tepIpAddress = new IpAddress(tepIp.toCharArray());
71 TransportZone tzone = null;
73 // Case: TZ name is not given with OVS TEP.
75 tzName = ITMConstants.DEFAULT_TRANSPORT_ZONE;
76 // add TEP into default-TZ
77 tzone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
79 LOG.error("Error: default-transport-zone is not yet created.");
82 LOG.trace("Add TEP into default-transport-zone.");
84 // Case: Add TEP into corresponding TZ created from Northbound.
85 tzone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
87 // Case: TZ is not configured from Northbound, then add TEP into "teps-not-hosted-in-transport-zone"
88 LOG.trace("Adding TEP with unknown TZ into teps-not-hosted-in-transport-zone.");
89 addUnknownTzTepIntoTepsNotHosted(tzName, tepIpAddress, dpnId, ofTunnel,
93 LOG.trace("Add TEP into transport-zone already configured by Northbound.");
97 // Get subnet list of corresponding TZ created from Northbound.
98 List<Subnets> subnetList = tzone.getSubnets();
99 String portName = ITMConstants.DUMMY_PORT;
101 IpPrefix subnetMaskObj = ItmUtils.getDummySubnet();
103 if (subnetList == null || subnetList.isEmpty()) {
104 if (subnetList == null) {
105 subnetList = new ArrayList<>();
107 List<Vteps> vtepList = new ArrayList<>();
108 LOG.trace("Add TEP in transport-zone when no subnet-list.");
109 addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName, dpnId,
110 portName, ofTunnel, wrTx);
112 List<Vteps> vtepList = null;
114 // subnet list already exists case; check for dummy-subnet
115 for (Subnets subnet : subnetList) {
116 if (subnet.getKey().getPrefix().equals(subnetMaskObj)) {
117 LOG.trace("Subnet exists in the subnet list of transport-zone {}.", tzName);
118 // get vtep list of existing subnet
119 vtepList = subnet.getVteps();
124 if (vtepList == null || vtepList.isEmpty()) {
125 // case: vtep list does not exist or it has no elements
126 if (vtepList == null) {
127 vtepList = new ArrayList<>();
129 LOG.trace("Add TEP in transport-zone when no vtep-list for specific subnet.");
130 addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName,
131 dpnId, portName, ofTunnel, wrTx);
133 // case: vtep list has elements
134 boolean vtepFound = false;
135 Vteps oldVtep = null;
137 for (Vteps vtep : vtepList) {
138 if (vtep.getDpnId().equals(dpnId)) {
141 // get portName of existing vtep
142 portName = vtep.getPortname();
147 addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName,
148 dpnId, portName, ofTunnel, wrTx);
150 // vtep is found, update it with tep-ip
151 vtepList.remove(oldVtep);
152 addVtepInITMConfigDS(subnetList, subnetMaskObj, vtepList, tepIpAddress, tzName,
153 dpnId, portName, ofTunnel, wrTx);
160 * Adds the TEP into Vtep list in the subnet list in the transport zone list
161 * from ITM configuration Datastore by merge operation with write transaction.
163 * @param subnetList subnets list object
164 * @param subnetMaskObj subnet mask in IpPrefix object
165 * @param updatedVtepList updated Vteps list object which will have new TEP for addition
166 * @param tepIpAddress TEP IP address in IpAddress object
167 * @param tzName transport zone name in string
168 * @param dpid bridge datapath ID in BigInteger
169 * @param portName port name as a part of VtepsKey
170 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
171 * @param wrTx WriteTransaction object
173 public static void addVtepInITMConfigDS(List<Subnets> subnetList, IpPrefix subnetMaskObj,
174 List<Vteps> updatedVtepList, IpAddress tepIpAddress, String tzName, BigInteger dpid,
175 String portName, boolean ofTunnel, WriteTransaction wrTx) {
176 //Create TZ node path
177 InstanceIdentifier<TransportZone> tranzportZonePath =
178 InstanceIdentifier.builder(TransportZones.class)
179 .child(TransportZone.class, new TransportZoneKey(tzName)).build();
181 // this check is needed to reuse same function from TransportZoneListener
182 // when VTEP is moved from TepsNotHosted list to TZ configured from Northbound.
183 if (dpid.compareTo(BigInteger.ZERO) > 0) {
185 VtepsKey vtepkey = new VtepsKey(dpid, portName);
187 new VtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).setKey(vtepkey).setPortname(portName)
188 .setOptionOfTunnel(ofTunnel).build();
190 // Add vtep obtained from bridge into list
191 updatedVtepList.add(vtepObj);
193 LOG.trace("Adding TEP (TZ: {} Subnet: {} TEP IP: {} DPID: {}, of-tunnel: {}) in ITM Config DS.", tzName,
194 subnetMaskObj, tepIpAddress, dpid, ofTunnel);
196 // this is case when this function is called while TEPs movement from tepsNotHosted list when
197 // corresponding TZ is configured from northbound.
198 for (Vteps vtep: updatedVtepList) {
199 LOG.trace("Moving TEP (TEP IP: {} DPID: {}, of-tunnel: {})"
200 + "from tepNotHosted list into transport-zone {} in ITM Config DS.",
201 vtep.getIpAddress(), vtep.getDpnId(), ofTunnel, tzName);
205 // Create subnet object
206 SubnetsKey subKey = new SubnetsKey(subnetMaskObj);
207 IpAddress gatewayIP = new IpAddress(ITMConstants.DUMMY_GATEWAY_IP.toCharArray());
208 int vlanID = ITMConstants.DUMMY_VLANID;
211 new SubnetsBuilder().setGatewayIp(gatewayIP)
212 .setKey(subKey).setPrefix(subnetMaskObj)
213 .setVlanId(vlanID).setVteps(updatedVtepList).build();
215 // add subnet into subnet list
216 subnetList.add(subnet);
218 // create TZ node with updated subnet having new vtep
219 TransportZone updatedTzone =
220 new TransportZoneBuilder().setKey(new TransportZoneKey(tzName)).setSubnets(subnetList)
221 .setZoneName(tzName).build();
223 // Update TZ in Config DS to add vtep in TZ
224 wrTx.merge(LogicalDatastoreType.CONFIGURATION, tranzportZonePath, updatedTzone, true);
228 * Adds the TEP into Vtep list in the subnet list in the transport zone list
229 * from ITM configuration Datastore by merge operation with write transaction.
231 * @param tzName transport zone name in string
232 * @param tepIpAddress TEP IP address in IpAddress object
233 * @param dpid bridge datapath ID in BigInteger
234 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
235 * @param dataBroker data broker handle to perform operations on config datastore
236 * @param wrTx WriteTransaction object
238 protected static void addUnknownTzTepIntoTepsNotHosted(String tzName, IpAddress tepIpAddress,
239 BigInteger dpid, boolean ofTunnel, DataBroker dataBroker, WriteTransaction wrTx) {
240 List<UnknownVteps> vtepList = null;
242 TepsNotHostedInTransportZone unknownTz =
243 ItmUtils.getUnknownTransportZoneFromITMConfigDS(tzName, dataBroker);
244 if (unknownTz == null) {
245 LOG.trace("Unhosted TransportZone does not exist.");
246 vtepList = new ArrayList<>();
247 addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid, ofTunnel, wrTx);
249 vtepList = unknownTz.getUnknownVteps();
250 if (vtepList == null || vtepList.isEmpty()) {
251 // case: vtep list does not exist or it has no elements
252 if (vtepList == null) {
253 vtepList = new ArrayList<>();
255 LOG.trace("Add TEP in unhosted TZ ({}) when no vtep-list in the TZ.", tzName);
256 addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid, ofTunnel, wrTx);
258 // case: vtep list has elements
259 boolean vtepFound = false;
260 UnknownVteps oldVtep = null;
262 for (UnknownVteps vtep : vtepList) {
263 if (vtep.getDpnId().equals(dpid)) {
270 addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid,
273 // vtep is found, update it with tep-ip
274 vtepList.remove(oldVtep);
275 addVtepIntoTepsNotHosted(vtepList, tepIpAddress, tzName, dpid,
283 * Adds the TEP into Unknown Vtep list under the transport zone in the TepsNotHosted list
284 * from ITM configuration Datastore by merge operation with write transaction.
286 * @param updatedVtepList updated UnknownVteps list object which will have new TEP for addition
288 * @param tepIpAddress TEP IP address in IpAddress object
289 * @param tzName transport zone name in string
290 * @param dpid bridge datapath ID in BigInteger
291 * @param ofTunnel boolean flag for TEP to enable/disable of-tunnel feature on it
292 * @param wrTx WriteTransaction object
294 protected static void addVtepIntoTepsNotHosted(List<UnknownVteps> updatedVtepList,
295 IpAddress tepIpAddress, String tzName, BigInteger dpid, boolean ofTunnel,
296 WriteTransaction wrTx) {
297 //Create TZ node path
298 InstanceIdentifier<TepsNotHostedInTransportZone> transportZonePath =
299 InstanceIdentifier.builder(TransportZones.class)
300 .child(TepsNotHostedInTransportZone.class,
301 new TepsNotHostedInTransportZoneKey(tzName)).build();
304 UnknownVtepsKey vtepkey = new UnknownVtepsKey(dpid);
305 UnknownVteps vtepObj =
306 new UnknownVtepsBuilder().setDpnId(dpid).setIpAddress(tepIpAddress).setKey(vtepkey)
307 .setOfTunnel(ofTunnel).build();
309 // Add vtep obtained into unknown TZ tep list
310 updatedVtepList.add(vtepObj);
312 // create unknown TZ node with updated vtep list
313 TepsNotHostedInTransportZone updatedTzone = new TepsNotHostedInTransportZoneBuilder()
314 .setKey(new TepsNotHostedInTransportZoneKey(tzName)).setZoneName(tzName)
315 .setUnknownVteps(updatedVtepList).build();
317 LOG.trace("Adding TEP into unhosted (TZ: {}, DPID: {}, TEP IP: {}, of-tunnel: {})"
318 + "in ITM Config DS.", tzName, dpid, tepIpAddress, ofTunnel);
320 // Update TZ in Config DS.
321 wrTx.merge(LogicalDatastoreType.CONFIGURATION, transportZonePath, updatedTzone, true);