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.interfacemanager.renderer.ovs.confighelpers;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
18 import java.util.Objects;
19 import java.util.concurrent.Callable;
20 import javax.inject.Inject;
21 import javax.inject.Singleton;
22 import org.apache.aries.blueprint.annotation.service.Reference;
23 import org.opendaylight.genius.infra.Datastore.Configuration;
24 import org.opendaylight.genius.infra.Datastore.Operational;
25 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
26 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
27 import org.opendaylight.genius.infra.TypedWriteTransaction;
28 import org.opendaylight.genius.interfacemanager.IfmConstants;
29 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
30 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
31 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
32 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
33 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
34 import org.opendaylight.mdsal.binding.api.DataBroker;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntryKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 public class OvsInterfaceConfigUpdateHelper {
50 private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigUpdateHelper.class);
51 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
53 private final ManagedNewTransactionRunner txRunner;
54 private final JobCoordinator coordinator;
55 private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
56 private final AlivenessMonitorUtils alivenessMonitorUtils;
57 private final OvsInterfaceConfigRemoveHelper ovsInterfaceConfigRemoveHelper;
58 private final OvsInterfaceConfigAddHelper ovsInterfaceConfigAddHelper;
59 private final InterfaceMetaUtils interfaceMetaUtils;
62 public OvsInterfaceConfigUpdateHelper(@Reference DataBroker dataBroker,
63 @Reference JobCoordinator coordinator,
64 InterfaceManagerCommonUtils interfaceManagerCommonUtils,
65 AlivenessMonitorUtils alivenessMonitorUtils,
66 OvsInterfaceConfigRemoveHelper ovsInterfaceConfigRemoveHelper,
67 OvsInterfaceConfigAddHelper ovsInterfaceConfigAddHelper,
68 InterfaceMetaUtils interfaceMetaUtils) {
69 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
70 this.coordinator = coordinator;
71 this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
72 this.alivenessMonitorUtils = alivenessMonitorUtils;
73 this.ovsInterfaceConfigRemoveHelper = ovsInterfaceConfigRemoveHelper;
74 this.ovsInterfaceConfigAddHelper = ovsInterfaceConfigAddHelper;
75 this.interfaceMetaUtils = interfaceMetaUtils;
78 public List<ListenableFuture<Void>> updateConfiguration(Interface interfaceNew, Interface interfaceOld) {
79 List<ListenableFuture<Void>> futures = new ArrayList<>();
80 // If any of the port attributes are modified, treat it as a delete and
82 if (portAttributesModified(interfaceOld, interfaceNew)) {
83 LOG.info("port attributes modified, requires a delete and recreate of {} configuration", interfaceNew
85 futures.addAll(ovsInterfaceConfigRemoveHelper.removeConfiguration(interfaceOld,
86 interfaceOld.augmentation(ParentRefs.class)));
87 futures.addAll(ovsInterfaceConfigAddHelper.addConfiguration(interfaceNew.augmentation(ParentRefs.class),
92 // If there is no operational state entry for the interface, treat it as
94 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
95 .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
96 .getInterfaceState(interfaceNew.getName());
97 if (ifState == null) {
98 futures.addAll(ovsInterfaceConfigAddHelper.addConfiguration(interfaceNew.augmentation(ParentRefs.class),
103 if (tunnelMonitoringAttributesModified(interfaceOld, interfaceNew)) {
104 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
105 tx -> handleTunnelMonitorUpdates(tx, interfaceNew, interfaceOld)));
106 } else if (!Objects.equals(interfaceNew.isEnabled(), interfaceOld.isEnabled())) {
107 EVENT_LOGGER.debug("IFM-OvsInterfaceConfig,UPDATE {}", interfaceNew.getName());
108 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
109 tx -> handleInterfaceAdminStateUpdates(tx, interfaceNew, ifState)));
115 private static boolean portAttributesModified(Interface interfaceOld, Interface interfaceNew) {
116 ParentRefs parentRefsOld = interfaceOld.augmentation(ParentRefs.class);
117 ParentRefs parentRefsNew = interfaceNew.augmentation(ParentRefs.class);
118 if (checkAugmentations(parentRefsOld, parentRefsNew)) {
122 IfL2vlan ifL2vlanOld = interfaceOld.augmentation(IfL2vlan.class);
123 IfL2vlan ifL2vlanNew = interfaceNew.augmentation(IfL2vlan.class);
124 if (checkAugmentations(ifL2vlanOld, ifL2vlanNew)) {
128 IfTunnel ifTunnelOld = interfaceOld.augmentation(IfTunnel.class);
129 IfTunnel ifTunnelNew = interfaceNew.augmentation(IfTunnel.class);
130 if (checkAugmentations(ifTunnelOld, ifTunnelNew)) {
131 if (!Objects.equals(ifTunnelNew.getTunnelDestination(), ifTunnelOld.getTunnelDestination())
132 || !Objects.equals(ifTunnelNew.getTunnelSource(), ifTunnelOld.getTunnelSource())
133 || ifTunnelNew.getTunnelGateway() != null && ifTunnelOld.getTunnelGateway() != null
134 && !ifTunnelNew.getTunnelGateway().equals(ifTunnelOld.getTunnelGateway())) {
142 private static boolean tunnelMonitoringAttributesModified(Interface interfaceOld, Interface interfaceNew) {
143 IfTunnel ifTunnelOld = interfaceOld.augmentation(IfTunnel.class);
144 IfTunnel ifTunnelNew = interfaceNew.augmentation(IfTunnel.class);
145 return checkAugmentations(ifTunnelOld, ifTunnelNew);
149 * if the tunnel monitoring attributes have changed, handle it based on the
150 * tunnel type. As of now internal vxlan tunnels use LLDP monitoring and
151 * external tunnels use BFD monitoring.
153 private void handleTunnelMonitorUpdates(TypedWriteTransaction<Configuration> transaction,
154 Interface interfaceNew, Interface interfaceOld) {
155 LOG.debug("tunnel monitoring attributes modified for interface {}", interfaceNew.getName());
156 // update termination point on switch, if switch is connected
157 BridgeRefEntry bridgeRefEntry = interfaceMetaUtils.getBridgeReferenceForInterface(interfaceNew);
158 IfTunnel ifTunnel = interfaceNew.augmentation(IfTunnel.class);
159 if (SouthboundUtils.isMonitorProtocolBfd(ifTunnel)
160 && interfaceMetaUtils.bridgeExists(bridgeRefEntry)) {
161 SouthboundUtils.updateBfdParamtersForTerminationPoint(bridgeRefEntry.getBridgeReference().getValue(),
162 interfaceNew.augmentation(IfTunnel.class), interfaceNew.getName(), transaction);
164 // update lldp tunnel monitoring attributes for an internal vxlan
166 alivenessMonitorUtils.handleTunnelMonitorUpdates(interfaceOld, interfaceNew);
170 private void handleInterfaceAdminStateUpdates(TypedWriteTransaction<Operational> transaction,
171 Interface interfaceNew,
172 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
173 .ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
174 IfL2vlan ifL2vlan = interfaceNew.augmentation(IfL2vlan.class);
175 if (ifL2vlan == null || IfL2vlan.L2vlanMode.Trunk != ifL2vlan.getL2vlanMode()
176 && IfL2vlan.L2vlanMode.Transparent != ifL2vlan.getL2vlanMode()) {
179 LOG.info("admin-state modified for interface {}", interfaceNew.getName());
180 OperStatus operStatus = interfaceManagerCommonUtils.updateStateEntry(interfaceNew, transaction , ifState);
181 InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(interfaceNew.getName());
182 InterfaceParentEntry interfaceParentEntry = interfaceMetaUtils
183 .getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey);
184 if (interfaceParentEntry == null || interfaceParentEntry.getInterfaceChildEntry() == null) {
188 VlanMemberStateUpdateWorker vlanMemberStateUpdateWorker = new VlanMemberStateUpdateWorker(txRunner,
189 operStatus, interfaceParentEntry.getInterfaceChildEntry());
190 coordinator.enqueueJob(interfaceNew.getName(), vlanMemberStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
193 private static <T> boolean checkAugmentations(T oldAug, T newAug) {
194 if (oldAug != null && newAug == null || oldAug == null && newAug != null) {
198 return newAug != null && !newAug.equals(oldAug);
201 private static class VlanMemberStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
203 private final ManagedNewTransactionRunner txRunner;
204 private final OperStatus operStatus;
205 private final Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries;
207 VlanMemberStateUpdateWorker(ManagedNewTransactionRunner txRunner, OperStatus operStatus,
208 Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries) {
209 this.txRunner = txRunner;
210 this.operStatus = operStatus;
211 this.interfaceChildEntries = interfaceChildEntries;
215 public List<ListenableFuture<Void>> call() {
216 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
217 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
218 InterfaceManagerCommonUtils.updateOperStatus(interfaceChildEntry.getChildInterface(), operStatus,
225 public String toString() {
226 return "VlanMemberStateUpdateWorker [operStatus=" + operStatus + ", interfaceChildEntries="
227 + interfaceChildEntries + "]";