a4e9a75220bbef0efc0ed303c2cfddba1d78a446
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / statehelpers / OvsInterfaceStateUpdateHelper.java
1 /*
2  * Copyright (c) 2016 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 com.google.common.util.concurrent.ListenableFuture;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.genius.interfacemanager.IfmUtil;
15 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
16 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import java.util.ArrayList;
30 import java.util.List;
31
32 public class OvsInterfaceStateUpdateHelper {
33     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
34
35     public static List<ListenableFuture<Void>> updateState(InstanceIdentifier<FlowCapableNodeConnector> key,
36                                                            AlivenessMonitorService alivenessMonitorService,
37                                                            DataBroker dataBroker, String interfaceName,
38                                                            FlowCapableNodeConnector flowCapableNodeConnectorNew,
39                                                            FlowCapableNodeConnector flowCapableNodeConnectorOld) {
40         LOG.debug("Update of Interface State for port: {}", interfaceName);
41         List<ListenableFuture<Void>> futures = new ArrayList<>();
42         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
43
44         Interface.OperStatus operStatusNew = getOpState(flowCapableNodeConnectorNew);
45         MacAddress macAddressNew = flowCapableNodeConnectorNew.getHardwareAddress();
46
47         Interface.OperStatus operStatusOld = getOpState(flowCapableNodeConnectorOld);
48         MacAddress macAddressOld = flowCapableNodeConnectorOld.getHardwareAddress();
49
50         boolean opstateModified = false;
51         boolean hardwareAddressModified = false;
52         if (!operStatusNew.equals(operStatusOld)) {
53             opstateModified = true;
54         }
55         if (!macAddressNew.equals(macAddressOld)) {
56             hardwareAddressModified = true;
57         }
58
59         if (!opstateModified && !hardwareAddressModified) {
60             LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
61             return futures;
62         }
63
64         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
65                 InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
66
67         // For tunnels, derive the final opstate based on the bfd tunnel monitoring status
68         if (modifyTunnel(iface, opstateModified)
69                 && InterfaceManagerCommonUtils.checkIfBfdStateIsDown(iface.getName())) {
70             operStatusNew = Interface.OperStatus.Down;
71             opstateModified = operStatusNew.equals(operStatusOld);
72         }
73
74         if (!opstateModified && !hardwareAddressModified) {
75             LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
76             return futures;
77         }
78         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
79         if (hardwareAddressModified) {
80             LOG.debug("Hw-Address Modified for Port: {}", interfaceName);
81             PhysAddress physAddress = new PhysAddress(macAddressNew.getValue());
82             ifaceBuilder.setPhysAddress(physAddress);
83         }
84         // modify the attributes in interface operational DS
85         handleInterfaceStateUpdates(iface, transaction, dataBroker, ifaceBuilder, opstateModified, interfaceName,
86                 flowCapableNodeConnectorNew.getName(), operStatusNew);
87
88         // start/stop monitoring based on opState
89         if (modifyTunnel(iface, opstateModified)) {
90             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface.getAugmentation(IfTunnel.class),
91                     iface.getName(), operStatusNew);
92         }
93
94         futures.add(transaction.submit());
95         return futures;
96     }
97
98     public static void updateInterfaceStateOnNodeRemove(String interfaceName,
99             FlowCapableNodeConnector flowCapableNodeConnector, DataBroker dataBroker,
100             AlivenessMonitorService alivenessMonitorService, WriteTransaction transaction) {
101         LOG.debug("Updating interface oper-status to UNKNOWN for : {}", interfaceName);
102
103         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
104         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
105                 InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
106         handleInterfaceStateUpdates(iface,transaction, dataBroker,
107                         ifaceBuilder, true, interfaceName, flowCapableNodeConnector.getName(),
108                         Interface.OperStatus.Unknown);
109         if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
110             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface.getAugmentation(IfTunnel.class),
111                     interfaceName, Interface.OperStatus.Unknown);
112         }
113     }
114
115     public static Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector) {
116         Interface.OperStatus operStatus = flowCapableNodeConnector.getState().isLive()
117                 && !flowCapableNodeConnector.getConfiguration().isPORTDOWN()
118                  ? Interface.OperStatus.Up : Interface.OperStatus.Down;
119         return operStatus;
120     }
121
122     public static void handleInterfaceStateUpdates(
123             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
124             WriteTransaction transaction, DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
125             String interfaceName, String portName, Interface.OperStatus opState) {
126         // if interface config DS is null, do the update only for the lower-layer-interfaces
127         // which have no corresponding config entries
128         if (iface == null && !interfaceName.equals(portName)) {
129             return;
130         }
131         LOG.debug("updating interface state entry for {}", interfaceName);
132         InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
133         ifaceBuilder.setKey(new InterfaceKey(interfaceName));
134         if (modifyOpState(iface, opStateModified)) {
135             LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
136             ifaceBuilder.setOperStatus(opState);
137         }
138         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), false);
139     }
140
141     public static void handleTunnelMonitoringUpdates(AlivenessMonitorService alivenessMonitorService,
142             DataBroker dataBroker, IfTunnel ifTunnel, String interfaceName, Interface.OperStatus operStatus) {
143         LOG.debug("handling tunnel monitoring updates for {} due to opstate modification", interfaceName);
144         if (operStatus == Interface.OperStatus.Down || operStatus == Interface.OperStatus.Unknown) {
145             AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, ifTunnel, interfaceName);
146         } else {
147             AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, ifTunnel, interfaceName);
148         }
149     }
150
151     public static boolean modifyOpState(
152             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
153             boolean opStateModified) {
154         return opStateModified && (iface == null || iface != null && iface.isEnabled());
155     }
156
157     public static boolean modifyTunnel(
158             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
159             boolean opStateModified) {
160         return modifyOpState(iface, opStateModified) && iface != null && iface.getAugmentation(IfTunnel.class) != null;
161     }
162 }