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;
17 import java.util.Objects;
18 import java.util.concurrent.Callable;
19 import javax.inject.Inject;
20 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.bridge.ref.info.BridgeRefEntry;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 public class OvsInterfaceConfigUpdateHelper {
49 private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigUpdateHelper.class);
50 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
52 private final ManagedNewTransactionRunner txRunner;
53 private final JobCoordinator coordinator;
54 private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
55 private final AlivenessMonitorUtils alivenessMonitorUtils;
56 private final OvsInterfaceConfigRemoveHelper ovsInterfaceConfigRemoveHelper;
57 private final OvsInterfaceConfigAddHelper ovsInterfaceConfigAddHelper;
58 private final InterfaceMetaUtils interfaceMetaUtils;
61 public OvsInterfaceConfigUpdateHelper(@Reference DataBroker dataBroker,
62 @Reference JobCoordinator coordinator,
63 InterfaceManagerCommonUtils interfaceManagerCommonUtils,
64 AlivenessMonitorUtils alivenessMonitorUtils,
65 OvsInterfaceConfigRemoveHelper ovsInterfaceConfigRemoveHelper,
66 OvsInterfaceConfigAddHelper ovsInterfaceConfigAddHelper,
67 InterfaceMetaUtils interfaceMetaUtils) {
68 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
69 this.coordinator = coordinator;
70 this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
71 this.alivenessMonitorUtils = alivenessMonitorUtils;
72 this.ovsInterfaceConfigRemoveHelper = ovsInterfaceConfigRemoveHelper;
73 this.ovsInterfaceConfigAddHelper = ovsInterfaceConfigAddHelper;
74 this.interfaceMetaUtils = interfaceMetaUtils;
77 public List<ListenableFuture<Void>> updateConfiguration(Interface interfaceNew, Interface interfaceOld) {
78 List<ListenableFuture<Void>> futures = new ArrayList<>();
79 // If any of the port attributes are modified, treat it as a delete and
81 if (portAttributesModified(interfaceOld, interfaceNew)) {
82 LOG.info("port attributes modified, requires a delete and recreate of {} configuration", interfaceNew
84 futures.addAll(ovsInterfaceConfigRemoveHelper.removeConfiguration(interfaceOld,
85 interfaceOld.augmentation(ParentRefs.class)));
86 futures.addAll(ovsInterfaceConfigAddHelper.addConfiguration(interfaceNew.augmentation(ParentRefs.class),
91 // If there is no operational state entry for the interface, treat it as
93 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
94 .ietf.interfaces.rev140508.interfaces.state.Interface ifState = interfaceManagerCommonUtils
95 .getInterfaceState(interfaceNew.getName());
96 if (ifState == null) {
97 futures.addAll(ovsInterfaceConfigAddHelper.addConfiguration(interfaceNew.augmentation(ParentRefs.class),
102 if (tunnelMonitoringAttributesModified(interfaceOld, interfaceNew)) {
103 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
104 tx -> handleTunnelMonitorUpdates(tx, interfaceNew, interfaceOld)));
105 } else if (!Objects.equals(interfaceNew.isEnabled(), interfaceOld.isEnabled())) {
106 EVENT_LOGGER.debug("IFM-OvsInterfaceConfig,UPDATE {}", interfaceNew.getName());
107 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
108 tx -> handleInterfaceAdminStateUpdates(tx, interfaceNew, ifState)));
114 private static boolean portAttributesModified(Interface interfaceOld, Interface interfaceNew) {
115 ParentRefs parentRefsOld = interfaceOld.augmentation(ParentRefs.class);
116 ParentRefs parentRefsNew = interfaceNew.augmentation(ParentRefs.class);
117 if (checkAugmentations(parentRefsOld, parentRefsNew)) {
121 IfL2vlan ifL2vlanOld = interfaceOld.augmentation(IfL2vlan.class);
122 IfL2vlan ifL2vlanNew = interfaceNew.augmentation(IfL2vlan.class);
123 if (checkAugmentations(ifL2vlanOld, ifL2vlanNew)) {
127 IfTunnel ifTunnelOld = interfaceOld.augmentation(IfTunnel.class);
128 IfTunnel ifTunnelNew = interfaceNew.augmentation(IfTunnel.class);
129 if (checkAugmentations(ifTunnelOld, ifTunnelNew)) {
130 if (!Objects.equals(ifTunnelNew.getTunnelDestination(), ifTunnelOld.getTunnelDestination())
131 || !Objects.equals(ifTunnelNew.getTunnelSource(), ifTunnelOld.getTunnelSource())
132 || ifTunnelNew.getTunnelGateway() != null && ifTunnelOld.getTunnelGateway() != null
133 && !ifTunnelNew.getTunnelGateway().equals(ifTunnelOld.getTunnelGateway())) {
141 private static boolean tunnelMonitoringAttributesModified(Interface interfaceOld, Interface interfaceNew) {
142 IfTunnel ifTunnelOld = interfaceOld.augmentation(IfTunnel.class);
143 IfTunnel ifTunnelNew = interfaceNew.augmentation(IfTunnel.class);
144 return checkAugmentations(ifTunnelOld, ifTunnelNew);
148 * if the tunnel monitoring attributes have changed, handle it based on the
149 * tunnel type. As of now internal vxlan tunnels use LLDP monitoring and
150 * external tunnels use BFD monitoring.
152 private void handleTunnelMonitorUpdates(TypedWriteTransaction<Configuration> transaction,
153 Interface interfaceNew, Interface interfaceOld) {
154 LOG.debug("tunnel monitoring attributes modified for interface {}", interfaceNew.getName());
155 // update termination point on switch, if switch is connected
156 BridgeRefEntry bridgeRefEntry = interfaceMetaUtils.getBridgeReferenceForInterface(interfaceNew);
157 IfTunnel ifTunnel = interfaceNew.augmentation(IfTunnel.class);
158 if (SouthboundUtils.isMonitorProtocolBfd(ifTunnel)
159 && interfaceMetaUtils.bridgeExists(bridgeRefEntry)) {
160 SouthboundUtils.updateBfdParamtersForTerminationPoint(bridgeRefEntry.getBridgeReference().getValue(),
161 interfaceNew.augmentation(IfTunnel.class), interfaceNew.getName(), transaction);
163 // update lldp tunnel monitoring attributes for an internal vxlan
165 alivenessMonitorUtils.handleTunnelMonitorUpdates(interfaceOld, interfaceNew);
169 private void handleInterfaceAdminStateUpdates(TypedWriteTransaction<Operational> transaction,
170 Interface interfaceNew,
171 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
172 .ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
173 IfL2vlan ifL2vlan = interfaceNew.augmentation(IfL2vlan.class);
174 if (ifL2vlan == null || IfL2vlan.L2vlanMode.Trunk != ifL2vlan.getL2vlanMode()
175 && IfL2vlan.L2vlanMode.Transparent != ifL2vlan.getL2vlanMode()) {
178 LOG.info("admin-state modified for interface {}", interfaceNew.getName());
179 OperStatus operStatus = interfaceManagerCommonUtils.updateStateEntry(interfaceNew, transaction , ifState);
180 InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(interfaceNew.getName());
181 InterfaceParentEntry interfaceParentEntry = interfaceMetaUtils
182 .getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey);
183 if (interfaceParentEntry == null || interfaceParentEntry.getInterfaceChildEntry() == null) {
187 VlanMemberStateUpdateWorker vlanMemberStateUpdateWorker = new VlanMemberStateUpdateWorker(txRunner,
188 operStatus, interfaceParentEntry.getInterfaceChildEntry());
189 coordinator.enqueueJob(interfaceNew.getName(), vlanMemberStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
192 private static <T> boolean checkAugmentations(T oldAug, T newAug) {
193 if (oldAug != null && newAug == null || oldAug == null && newAug != null) {
197 return newAug != null && !newAug.equals(oldAug);
200 private static class VlanMemberStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
202 private final ManagedNewTransactionRunner txRunner;
203 private final OperStatus operStatus;
204 private final List<InterfaceChildEntry> interfaceChildEntries;
206 VlanMemberStateUpdateWorker(ManagedNewTransactionRunner txRunner, OperStatus operStatus,
207 List<InterfaceChildEntry> interfaceChildEntries) {
208 this.txRunner = txRunner;
209 this.operStatus = operStatus;
210 this.interfaceChildEntries = interfaceChildEntries;
214 public List<ListenableFuture<Void>> call() {
215 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
216 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
217 InterfaceManagerCommonUtils.updateOperStatus(interfaceChildEntry.getChildInterface(), operStatus,
224 public String toString() {
225 return "VlanMemberStateUpdateWorker [operStatus=" + operStatus + ", interfaceChildEntries="
226 + interfaceChildEntries + "]";