5564a1f2f0a29ca41becad38fc14549c32b71c09
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / statehelpers / OvsInterfaceStateUpdateHelper.java
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers;
9
10 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
11
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Objects;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18
19 import org.apache.aries.blueprint.annotation.service.Reference;
20 import org.opendaylight.genius.infra.Datastore.Operational;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
22 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
23 import org.opendaylight.genius.infra.TypedWriteTransaction;
24 import org.opendaylight.genius.interfacemanager.IfmUtil;
25 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
26 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
27 import org.opendaylight.mdsal.binding.api.DataBroker;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 @Singleton
40 public class OvsInterfaceStateUpdateHelper {
41     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
42
43     private final ManagedNewTransactionRunner txRunner;
44     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
45     private final AlivenessMonitorUtils alivenessMonitorUtils;
46
47     @Inject
48     public OvsInterfaceStateUpdateHelper(@Reference DataBroker dataBroker,
49                                          AlivenessMonitorUtils alivenessMonitorUtils,
50                                          InterfaceManagerCommonUtils interfaceManagerCommonUtils) {
51         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
52         this.interfaceManagerCommonUtils =  interfaceManagerCommonUtils;
53         this.alivenessMonitorUtils = alivenessMonitorUtils;
54     }
55
56     public List<ListenableFuture<Void>> updateState(String interfaceName,
57             FlowCapableNodeConnector flowCapableNodeConnectorNew,
58             FlowCapableNodeConnector flowCapableNodeConnectorOld) {
59         LOG.debug("Updating interface state information for interface: {}", interfaceName);
60
61         Interface.OperStatus operStatusNew = InterfaceManagerCommonUtils.getOpState(flowCapableNodeConnectorNew);
62         MacAddress macAddressNew = flowCapableNodeConnectorNew.getHardwareAddress();
63
64         Interface.OperStatus operStatusOld = InterfaceManagerCommonUtils.getOpState(flowCapableNodeConnectorOld);
65         MacAddress macAddressOld = flowCapableNodeConnectorOld.getHardwareAddress();
66
67         boolean opstateModified = !operStatusNew.equals(operStatusOld);
68         boolean hardwareAddressModified = !Objects.equals(macAddressNew, macAddressOld);
69
70         if (!opstateModified && !hardwareAddressModified) {
71             LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
72             return Collections.emptyList();
73         }
74
75         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
76             .interfaces.rev140508.interfaces.Interface iface = interfaceManagerCommonUtils
77                 .getInterfaceFromConfigDS(interfaceName);
78
79         // For monitoring enabled tunnels, skip opstate update
80         if (isTunnelInterface(iface) && !modifyTunnelOpState(iface, opstateModified)) {
81             LOG.debug("skip interface-state updation for monitoring enabled tunnel interface {}", interfaceName);
82             opstateModified = false;
83         }
84
85         if (!opstateModified && !hardwareAddressModified) {
86             LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
87             return Collections.emptyList();
88         }
89         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
90         if (hardwareAddressModified) {
91             LOG.debug("Hw-Address Modified for Port: {}", interfaceName);
92             PhysAddress physAddress = new PhysAddress(macAddressNew.getValue());
93             ifaceBuilder.setPhysAddress(physAddress);
94         }
95
96         if (opstateModified) {
97             return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
98                 // modify the attributes in interface operational DS
99                 handleInterfaceStateUpdates(iface, tx, ifaceBuilder, true, interfaceName,
100                         flowCapableNodeConnectorNew.getName(), operStatusNew);
101
102                 // start/stop monitoring based on opState
103                 if (isTunnelInterface(iface)) {
104                     handleTunnelMonitoringUpdates(iface.augmentation(IfTunnel.class), iface.getName(),
105                             operStatusNew);
106                 }
107             }));
108         } else {
109             return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
110                 // modify the attributes in interface operational DS
111                 handleInterfaceStateUpdates(iface, tx, ifaceBuilder, false, interfaceName,
112                         flowCapableNodeConnectorNew.getName(), operStatusNew);
113             }));
114         }
115     }
116
117     public void updateInterfaceStateOnNodeRemove(String interfaceName,
118             FlowCapableNodeConnector flowCapableNodeConnector, TypedWriteTransaction<Operational> tx) {
119         LOG.debug("Updating interface oper-status to UNKNOWN for : {}", interfaceName);
120
121         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
122         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
123             .ietf.interfaces.rev140508.interfaces.Interface iface = interfaceManagerCommonUtils
124                 .getInterfaceFromConfigDS(interfaceName);
125         handleInterfaceStateUpdates(iface, tx, ifaceBuilder, true, interfaceName,
126                 flowCapableNodeConnector.getName(), Interface.OperStatus.Unknown);
127         if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
128             handleTunnelMonitoringUpdates(iface.augmentation(IfTunnel.class), interfaceName,
129                     Interface.OperStatus.Unknown);
130         }
131     }
132
133     private void handleInterfaceStateUpdates(
134             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
135                 .ietf.interfaces.rev140508.interfaces.Interface iface,
136             TypedWriteTransaction<Operational> tx, InterfaceBuilder ifaceBuilder, boolean opStateModified,
137             String interfaceName, String portName, Interface.OperStatus opState) {
138         // if interface config DS is null, do the update only for the
139         // lower-layer-interfaces
140         // which have no corresponding config entries
141         if (iface == null && !interfaceName.equals(portName)) {
142             return;
143         }
144
145         final Interface interfaceState = interfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName);
146         if (interfaceState == null || (interfaceState.getOperStatus() == opState)) {
147             LOG.warn("Ignoring: updating interface state for interface {}",
148                     interfaceName);
149             return;
150         }
151
152         LOG.debug("updating interface state entry for {}", interfaceName);
153         InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
154         ifaceBuilder.withKey(new InterfaceKey(interfaceName));
155         if (modifyOpState(iface, opStateModified)) {
156             LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
157             ifaceBuilder.setOperStatus(opState);
158         }
159         tx.merge(ifStateId, ifaceBuilder.build());
160     }
161
162     public void handleTunnelMonitoringUpdates(IfTunnel ifTunnel,
163             String interfaceName, Interface.OperStatus operStatus) {
164         LOG.debug("handling tunnel monitoring updates for {} due to opstate modification", interfaceName);
165         if (operStatus == Interface.OperStatus.Down || operStatus == Interface.OperStatus.Unknown) {
166             alivenessMonitorUtils.stopLLDPMonitoring(ifTunnel, interfaceName);
167         } else {
168             alivenessMonitorUtils.startLLDPMonitoring(ifTunnel, interfaceName);
169         }
170     }
171
172     public static boolean modifyOpState(
173             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
174                 .interfaces.rev140508.interfaces.Interface iface,
175             boolean opStateModified) {
176         return opStateModified && (iface == null || iface.isEnabled());
177     }
178
179     public static boolean isTunnelInterface(
180             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
181                 .ietf.interfaces.rev140508.interfaces.Interface iface) {
182         return iface != null && iface.augmentation(IfTunnel.class) != null;
183     }
184
185     public static boolean modifyTunnelOpState(
186             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
187                 .ietf.interfaces.rev140508.interfaces.Interface iface,
188             boolean opStateModified) {
189         if (!iface.augmentation(IfTunnel.class).isMonitorEnabled()) {
190             return modifyOpState(iface, opStateModified);
191         }
192         return false;
193     }
194 }