2 * Copyright (c) 2017 Hewlett Packard Enterprise, Co. 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 static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
11 import static org.opendaylight.mdsal.binding.util.Datastore.OPERATIONAL;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
19 import java.util.Objects;
20 import java.util.Optional;
21 import java.util.concurrent.Callable;
22 import java.util.concurrent.ExecutionException;
23 import javax.inject.Inject;
24 import javax.inject.Singleton;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
27 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
28 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceAdminState;
29 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
30 import org.opendaylight.genius.itm.impl.ItmUtils;
31 import org.opendaylight.genius.mdsalutil.ActionInfo;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
34 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
35 import org.opendaylight.mdsal.binding.api.DataBroker;
36 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
37 import org.opendaylight.mdsal.binding.util.Datastore.Operational;
38 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
39 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
40 import org.opendaylight.mdsal.binding.util.TypedReadTransaction;
41 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
42 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.InterfaceChildInfo;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntryKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.itm.config.TunnelAggregation;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.itm.config.TunnelAggregationKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.opendaylight.yangtools.yang.common.Uint64;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
73 public class ItmTunnelAggregationHelper {
75 public static final int ADD_TUNNEL = 0;
76 public static final int DEL_TUNNEL = 1;
77 public static final int MOD_TUNNEL = 2;
78 public static final int MOD_GROUP_TUNNEL = 3;
79 public static final int DEFAULT_WEIGHT = 1;
80 public static final long INVALID_ID = 0;
82 private static final Logger LOG = LoggerFactory.getLogger(ItmTunnelAggregationHelper.class);
83 private static boolean tunnelAggregationEnabled;
85 private final IInterfaceManager interfaceManager;
86 private final IMdsalApiManager mdsalManager;
87 private final JobCoordinator jobCoordinator;
90 public ItmTunnelAggregationHelper(final IInterfaceManager interfaceMngr,
91 final IMdsalApiManager mdsalMngr,
92 final ItmConfig itmConfig,
93 final JobCoordinator jobCoordinator) {
94 this.interfaceManager = interfaceMngr;
95 this.mdsalManager = mdsalMngr;
96 this.jobCoordinator = jobCoordinator;
97 initTunnelAggregationConfig(itmConfig);
100 public static boolean isTunnelAggregationEnabled() {
101 return tunnelAggregationEnabled;
104 public void createLogicalTunnelSelectGroup(TypedWriteTransaction<Configuration> tx,
105 Uint64 srcDpnId, String interfaceName, int lportTag) {
106 Group group = prepareLogicalTunnelSelectGroup(interfaceName, lportTag);
107 LOG.debug("MULTIPLE_VxLAN_TUNNELS: group id {} installed for {} srcDpnId {}",
108 group.getGroupId().getValue(), interfaceName, srcDpnId);
109 mdsalManager.addGroup(tx, srcDpnId, group);
112 public void updateLogicalTunnelSelectGroup(InterfaceParentEntry entry, DataBroker broker) {
113 String logicTunnelName = entry.getParentInterface();
114 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
115 .interfaces.Interface ifaceConfig = ItmUtils.getInterface(logicTunnelName, interfaceManager);
116 if (ifaceConfig == null || !ifaceConfig.getType().isAssignableFrom(Tunnel.class)) {
119 IfTunnel ifTunnel = ifaceConfig.augmentation(IfTunnel.class);
120 if (!ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
123 LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateLogicalTunnelSelectGroup name {}", logicTunnelName);
124 TunnelAggregationUpdateWorker worker =
125 new TunnelAggregationUpdateWorker(null, null, ifaceConfig, entry, MOD_GROUP_TUNNEL, broker);
126 jobCoordinator.enqueueJob(logicTunnelName, worker);
129 public void updateLogicalTunnelState(Interface ifaceState, int tunnelAction, DataBroker broker) {
130 updateLogicalTunnelState(null, ifaceState, tunnelAction, broker);
133 public void updateLogicalTunnelState(Interface ifStateOrigin, Interface ifStateUpdated,
134 int tunnelAction, DataBroker broker) {
135 if (!tunnelAggregationEnabled || ifStateUpdated == null) {
136 LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateLogicalTunnelState - wrong configuration -"
137 + " tunnelAggregationEnabled {} ifStateUpdated {}", tunnelAggregationEnabled, ifStateUpdated);
140 String ifName = ifStateUpdated.getName();
141 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
142 ItmUtils.getInterface(ifName, interfaceManager);
143 IfTunnel ifTunnel = iface != null ? iface.augmentation(IfTunnel.class) : null;
144 if (iface == null || ifTunnel == null) {
145 LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateLogicalTunnelState - not tunnel interface {}", ifName);
148 String logicTunnelName = null;
149 if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
150 logicTunnelName = ifStateUpdated.getName();
152 ParentRefs parentRefs = iface.augmentation(ParentRefs.class);
153 if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class) && parentRefs != null) {
154 logicTunnelName = parentRefs.getParentInterface();
157 if (logicTunnelName != null) {
158 TunnelAggregationUpdateWorker worker =
159 new TunnelAggregationUpdateWorker(ifStateOrigin, ifStateUpdated, iface, null, tunnelAction, broker);
160 jobCoordinator.enqueueJob(logicTunnelName, worker);
164 private void initTunnelAggregationConfig(ItmConfig itmConfig) {
165 // Load balancing of VxLAN feature is guarded by a global configuration option in the ITM,
166 // only when the feature is enabled, the logical tunnel interfaces should be created.
167 boolean tunnelAggregationConfigEnabled = false;
168 Map<TunnelAggregationKey, TunnelAggregation> tunnelsConfig = itmConfig != null
169 ? itmConfig.getTunnelAggregation() : null;
170 if (tunnelsConfig != null) {
171 for (TunnelAggregation tnlCfg : tunnelsConfig.values()) {
172 Class<? extends TunnelTypeBase> tunType = ItmUtils.getTunnelType(tnlCfg.key().getTunnelType());
173 if (tunType.isAssignableFrom(TunnelTypeVxlan.class)) {
174 tunnelAggregationConfigEnabled = tnlCfg.isEnabled();
175 LOG.info("MULTIPLE_VxLAN_TUNNELS: tunnelAggregationEnabled {}", tunnelAggregationConfigEnabled);
180 tunnelAggregationEnabled = tunnelAggregationConfigEnabled;
183 private Group prepareLogicalTunnelSelectGroup(String interfaceName, int lportTag) {
184 long groupId = interfaceManager.getLogicalTunnelSelectGroupId(lportTag);
185 return MDSALUtil.buildGroup(groupId, interfaceName, GroupTypes.GroupSelect,
186 MDSALUtil.buildBucketLists(Collections.emptyList()));
189 private Bucket createBucket(String interfaceName, IfTunnel ifTunnel, int bucketId, int portNumber) {
190 List<ActionInfo> listActionInfo = interfaceManager.getInterfaceEgressActions(interfaceName);
191 if (listActionInfo == null) {
192 listActionInfo = Collections.emptyList();
194 if (listActionInfo.isEmpty()) {
195 LOG.warn("MULTIPLE_VxLAN_TUNNELS: could not build Egress bucket for {}", interfaceName);
197 Integer portWeight = ifTunnel.getWeight() != null ? ifTunnel.getWeight().toJava() : DEFAULT_WEIGHT;
198 return MDSALUtil.buildBucket(MDSALUtil.buildActions(listActionInfo), portWeight, bucketId,
199 portNumber, MDSALUtil.WATCH_GROUP);
202 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
203 justification = "https://github.com/spotbugs/spotbugs/issues/811")
204 private void updateTunnelAggregationGroup(TypedWriteTransaction<Configuration> tx,
205 InterfaceParentEntry parentEntry) {
206 String logicTunnelName = parentEntry.getParentInterface();
207 InternalTunnel logicInternalTunnel = ItmUtils.ITM_CACHE.getInternalTunnel(logicTunnelName);
208 if (logicInternalTunnel == null) {
209 LOG.debug("MULTIPLE_VxLAN_TUNNELS: {} not found in internal tunnels list", logicTunnelName);
212 InterfaceInfo ifLogicTunnel = interfaceManager.getInterfaceInfoFromOperationalDataStore(logicTunnelName);
213 long groupId = ifLogicTunnel != null
214 ? interfaceManager.getLogicalTunnelSelectGroupId(ifLogicTunnel.getInterfaceTag()) : INVALID_ID;
215 Uint64 srcDpnId = logicInternalTunnel.getSourceDPN();
216 List<Bucket> listBuckets = new ArrayList<>();
217 @Nullable Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
218 parentEntry.getInterfaceChildEntry();
219 if (interfaceChildEntries == null || interfaceChildEntries.isEmpty()) {
220 LOG.debug("MULTIPLE_VxLAN_TUNNELS: empty child list in group {}", parentEntry.getParentInterface());
223 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
224 String curChildName = interfaceChildEntry.getChildInterface();
225 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
226 childIface = ItmUtils.getInterface(curChildName, interfaceManager);
227 IfTunnel ifTunnel = childIface != null ? childIface.augmentation(IfTunnel.class) : null;
228 if (ifTunnel == null || !ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
229 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not tunnel interface {} found in group {}",
230 curChildName, logicTunnelName);
233 ParentRefs parentRefs = childIface.augmentation(ParentRefs.class);
234 if (parentRefs == null) {
235 LOG.debug("MULTIPLE_VxLAN_TUNNELS: parent refs not specified for interface {} in group {}",
236 curChildName, logicTunnelName);
239 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(curChildName);
240 if (ifInfo == null) {
241 LOG.debug("MULTIPLE_VxLAN_TUNNELS: interface state not found for {} in groupId {}",
242 curChildName, groupId);
246 List<InterfaceChildEntry> val = new ArrayList<>(interfaceChildEntries.values());
247 int bucketId = val.indexOf(interfaceChildEntry);
249 LOG.debug("MULTIPLE_VxLAN_TUNNELS: updateTunnelAggregationGroup - add bucketId {} to groupId {}",
251 listBuckets.add(createBucket(curChildName, ifTunnel, bucketId, ifInfo.getPortNo()));
253 if (!listBuckets.isEmpty()) {
254 Group group = MDSALUtil.buildGroup(groupId, logicTunnelName, GroupTypes.GroupSelect,
255 MDSALUtil.buildBucketLists(listBuckets));
256 mdsalManager.addGroup(tx, srcDpnId, group);
260 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
261 justification = "https://github.com/spotbugs/spotbugs/issues/811")
262 private void updateTunnelAggregationGroupBucket(Interface ifaceState, IfTunnel ifTunnel,
263 ParentRefs parentRefs, InterfaceParentEntry groupParentEntry,
264 int action, TypedReadWriteTransaction<Configuration> tx)
265 throws ExecutionException, InterruptedException {
266 String logicTunnelName = parentRefs.getParentInterface();
267 @Nullable Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
268 groupParentEntry.getInterfaceChildEntry();
269 if (interfaceChildEntries == null) {
270 LOG.debug("MULTIPLE_VxLAN_TUNNELS: empty child list in group {}", groupParentEntry.getParentInterface());
273 String ifaceName = ifaceState.getName();
274 InterfaceChildEntry childEntry = new InterfaceChildEntryBuilder().setChildInterface(ifaceName)
275 .withKey(new InterfaceChildEntryKey(ifaceName)).build();
276 List<InterfaceChildEntry> val = new ArrayList<>(interfaceChildEntries.values());
277 int bucketId = val.indexOf(childEntry);
279 if (bucketId == -1) {
280 LOG.debug("MULTIPLE_VxLAN_TUNNELS: wrong child id for {} in group {}", ifaceName,
281 groupParentEntry.getParentInterface());
284 InterfaceInfo ifLogicTunnel = interfaceManager.getInterfaceInfoFromOperationalDataStore(logicTunnelName);
285 long groupId = ifLogicTunnel != null
286 ? interfaceManager.getLogicalTunnelSelectGroupId(ifLogicTunnel.getInterfaceTag()) : INVALID_ID;
287 if (groupId == INVALID_ID) {
288 LOG.warn("MULTIPLE_VxLAN_TUNNELS: unknown group id for logic tunnel {}", logicTunnelName);
291 String lowerLayerIf = ifaceState.getLowerLayerIf().get(0); // openflow:dpnid:portnum
292 String[] split = lowerLayerIf.split(IfmConstants.OF_URI_SEPARATOR);
293 Uint64 srcDpnId = Uint64.valueOf(split[1]);
294 int portNumber = Integer.parseInt(split[2]);
295 if (action == ADD_TUNNEL) {
296 if (!mdsalManager.groupExists(srcDpnId, groupId)) {
297 createLogicalTunnelSelectGroup(tx, srcDpnId, logicTunnelName, ifLogicTunnel.getInterfaceTag());
299 Bucket buckt = createBucket(ifaceName, ifTunnel, bucketId, portNumber);
300 LOG.debug("MULTIPLE_VxLAN_TUNNELS: add bucketId {} to groupId {}", bucketId, groupId);
301 mdsalManager.addBucket(tx, srcDpnId, groupId, buckt);
303 LOG.debug("MULTIPLE_VxLAN_TUNNELS: remove bucketId {} from groupId {}", bucketId, groupId);
304 mdsalManager.removeBucket(tx, srcDpnId, groupId, bucketId);
308 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
309 justification = "https://github.com/spotbugs/spotbugs/issues/811")
310 private void updateLogicalTunnelGroupOperStatus(String logicalTunnelIfaceName, Interface ifaceState,
311 InterfaceParentEntry parentEntry, TypedReadWriteTransaction<Operational> tx)
312 throws ExecutionException, InterruptedException {
313 if (parentEntry == null) {
314 LOG.debug("MULTIPLE_VxLAN_TUNNELS: uninitialized parent entry {}", logicalTunnelIfaceName);
317 OperStatus newOperStatus = getAggregatedOperStatus(ifaceState, parentEntry);
318 if (logicalTunnelIfaceName.equals(ifaceState.getName())) { //the current interface is logical tunnel itself
319 if (ifaceState.getOperStatus() != newOperStatus) {
320 updateInterfaceOperStatus(logicalTunnelIfaceName, ifaceState, newOperStatus, tx);
323 InterfaceInfo ifLogicInfo =
324 interfaceManager.getInterfaceInfoFromOperationalDataStore(logicalTunnelIfaceName);
325 if (isLogicalTunnelStateUpdateNeeded(newOperStatus, ifLogicInfo)) {
326 InstanceIdentifier<Interface> id = ItmUtils.buildStateInterfaceId(logicalTunnelIfaceName);
327 Optional<Interface> ifState = tx.read(id).get();
328 if (ifState.isPresent()) {
329 Interface ifStateLogicTunnel = ifState.get();
330 updateInterfaceOperStatus(logicalTunnelIfaceName, ifStateLogicTunnel, newOperStatus, tx);
336 private boolean isLogicalTunnelStateUpdateNeeded(OperStatus newOperStatus, InterfaceInfo ifLogicInfo) {
337 return ifLogicInfo != null && (ifLogicInfo.getOpState() == InterfaceInfo.InterfaceOpState.UP
338 && newOperStatus == OperStatus.Down
339 || ifLogicInfo.getOpState() == InterfaceInfo.InterfaceOpState.DOWN && newOperStatus == OperStatus.Up);
342 private OperStatus getAggregatedOperStatus(Interface ifaceState, InterfaceParentEntry parentEntry) {
343 String logicalTunnelName = parentEntry.getParentInterface();
344 if (!Objects.equals(logicalTunnelName, ifaceState.getName()) && ifaceState.getOperStatus() == OperStatus.Up) {
345 return OperStatus.Up;
348 @Nullable Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
349 parentEntry.getInterfaceChildEntry();
350 if (interfaceChildEntries == null || interfaceChildEntries.isEmpty()) {
351 LOG.debug("MULTIPLE_VxLAN_TUNNELS: OperStatus is Down, because of the empty child list in group {}",
352 parentEntry.getParentInterface());
353 return OperStatus.Down;
355 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
356 String curChildInterface = interfaceChildEntry.getChildInterface();
357 if (!Objects.equals(curChildInterface, ifaceState.getName())) {
358 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(curChildInterface);
359 if (ifInfo != null && InterfaceInfo.InterfaceOpState.UP.equals(ifInfo.getOpState())) {
360 return OperStatus.Up;
364 return OperStatus.Down;
367 private void updateInterfaceOperStatus(String ifaceName, Interface ifaceState,
368 OperStatus st, TypedWriteTransaction<Operational> tx) {
369 LOG.debug("MULTIPLE_VxLAN_TUNNELS: update OperStatus to be {} for {}", st.toString(), ifaceName);
370 InstanceIdentifier<Interface> idLogicGroup = ItmUtils.buildStateInterfaceId(ifaceName);
371 InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder(ifaceState);
372 ifaceBuilderChild.setOperStatus(st);
373 tx.mergeParentStructureMerge(idLogicGroup, ifaceBuilderChild.build());
376 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
377 justification = "https://github.com/spotbugs/spotbugs/issues/811")
378 private void updateLogicalTunnelAdminStatus(String logicalTunnelName, Interface ifOrigin,
379 Interface ifUpdated, InterfaceParentEntry parentEntry, TypedWriteTransaction<Operational> tx) {
381 if (ifOrigin == null || ifUpdated == null || ifOrigin.getAdminStatus() == ifUpdated.getAdminStatus()) {
384 @Nullable Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
385 parentEntry.getInterfaceChildEntry();
386 if (interfaceChildEntries == null || interfaceChildEntries.isEmpty()) {
387 LOG.debug("MULTIPLE_VxLAN_TUNNELS: empty child list in group {}", logicalTunnelName);
390 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
391 String curChildInterface = interfaceChildEntry.getChildInterface();
392 updateInterfaceAdminStatus(curChildInterface, ifUpdated.getAdminStatus(), tx);
396 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
397 justification = "https://github.com/spotbugs/spotbugs/issues/811")
398 private void updateInterfaceAdminStatus(String logicalTunnelName, Interface ifState,
399 TypedWriteTransaction<Operational> tx) {
400 InterfaceInfo ifLogicTunnelInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(logicalTunnelName);
401 if (ifLogicTunnelInfo == null) {
404 if (ifState.getAdminStatus() == AdminStatus.Up
405 && ifLogicTunnelInfo.getAdminState() != InterfaceAdminState.ENABLED) {
406 updateInterfaceAdminStatus(ifState.getName(), AdminStatus.Down, tx);
410 private void updateInterfaceAdminStatus(String ifaceName, AdminStatus st, TypedWriteTransaction<Operational> tx) {
411 LOG.debug("MULTIPLE_VxLAN_TUNNELS: update AdminStatus to be {} for {}", st.toString(), ifaceName);
412 InstanceIdentifier<Interface> id = ItmUtils.buildStateInterfaceId(ifaceName);
413 InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder();
414 ifaceBuilderChild.withKey(new InterfaceKey(ifaceName));
415 ifaceBuilderChild.setAdminStatus(st);
416 tx.mergeParentStructureMerge(id, ifaceBuilderChild.build());
419 private class TunnelAggregationUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
421 private final Interface ifStateOrigin;
422 private final Interface ifStateUpdated;
423 private final ManagedNewTransactionRunner txRunner;
424 private final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
425 .interfaces.rev140508.interfaces.Interface ifaceConfig;
426 private final int ifaceAction;
427 private final InterfaceParentEntry parentEntry;
429 TunnelAggregationUpdateWorker(Interface ifStateOrig, Interface ifStateUpdated,
430 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
431 .interfaces.Interface iface, InterfaceParentEntry entry, int action, DataBroker broker) {
432 this.ifStateOrigin = ifStateOrig;
433 this.ifStateUpdated = ifStateUpdated;
434 this.ifaceConfig = iface;
435 this.ifaceAction = action;
436 this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
437 this.parentEntry = entry;
441 public List<? extends ListenableFuture<?>> call() {
442 List<ListenableFuture<?>> futures = new ArrayList<>();
443 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
444 if (ifaceAction == MOD_GROUP_TUNNEL) {
445 updateTunnelAggregationGroup(confTx, parentEntry);
448 IfTunnel ifTunnel = ifaceConfig != null ? ifaceConfig.augmentation(IfTunnel.class) : null;
449 if (ifTunnel == null) {
450 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not tunnel interface {}", ifaceConfig.getName());
453 if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
454 String logicTunnelIfaceName = ifStateUpdated.getName();
455 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
456 final InterfaceParentEntry interfaceParentEntry =
457 getInterfaceParentEntry(logicTunnelIfaceName, confTx);
458 updateLogicalTunnelGroupOperStatus(logicTunnelIfaceName, ifStateUpdated,
459 interfaceParentEntry,
461 updateLogicalTunnelAdminStatus(logicTunnelIfaceName, ifStateOrigin, ifStateUpdated,
462 interfaceParentEntry, operTx);
466 if (!ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
467 LOG.debug("MULTIPLE_VxLAN_TUNNELS: wrong tunnel type {}", ifTunnel.getTunnelInterfaceType());
470 ParentRefs parentRefs = ifaceConfig.augmentation(ParentRefs.class);
471 if (parentRefs == null) {
472 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not updated parent ref for {}", ifaceConfig.getName());
475 String logicTunnelIfaceName = parentRefs.getParentInterface();
476 InterfaceParentEntry groupEntry = getInterfaceParentEntry(logicTunnelIfaceName, confTx);
477 if (groupEntry == null) {
478 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not found InterfaceParentEntry for {}",
479 logicTunnelIfaceName);
482 if (ifaceAction == ADD_TUNNEL) {
483 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
484 operTx -> updateInterfaceAdminStatus(logicTunnelIfaceName, ifStateUpdated, operTx)));
485 updateTunnelAggregationGroupBucket(ifStateUpdated, ifTunnel, parentRefs, groupEntry,
488 } else if (ifaceAction == DEL_TUNNEL) {
489 updateTunnelAggregationGroupBucket(ifStateUpdated, ifTunnel, parentRefs, groupEntry,
493 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL,
494 operTx -> updateLogicalTunnelGroupOperStatus(logicTunnelIfaceName, ifStateUpdated, groupEntry,
500 private InterfaceParentEntry getInterfaceParentEntry(String logicalGroupName,
501 TypedReadTransaction<Configuration> tx) throws ExecutionException, InterruptedException {
502 InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(logicalGroupName);
503 InstanceIdentifier.InstanceIdentifierBuilder<InterfaceParentEntry> intfIdBuilder =
504 InstanceIdentifier.builder(InterfaceChildInfo.class)
505 .child(InterfaceParentEntry.class, interfaceParentEntryKey);
506 InstanceIdentifier<InterfaceParentEntry> intfId = intfIdBuilder.build();
507 return tx.read(intfId).get().orElse(null);