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