Merge "Syncing the bug fixes that went in vpnservice after the initial porting of...
[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.genius.interfacemanager.commons.InterfaceMetaUtils;
18 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
19 import org.opendaylight.genius.mdsalutil.MatchInfo;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntryKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import java.math.BigInteger;
38 import java.util.ArrayList;
39 import java.util.List;
40
41 public class OvsInterfaceStateUpdateHelper {
42     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
43
44     public static List<ListenableFuture<Void>> updateState(InstanceIdentifier<FlowCapableNodeConnector> key,
45                                                            AlivenessMonitorService alivenessMonitorService,
46                                                            DataBroker dataBroker, String portName,
47                                                            FlowCapableNodeConnector flowCapableNodeConnectorNew,
48                                                            FlowCapableNodeConnector flowCapableNodeConnectorOld) {
49         LOG.debug("Update of Interface State for port: {}", portName);
50         List<ListenableFuture<Void>> futures = new ArrayList<>();
51         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
52
53         Interface.OperStatus operStatusNew = getOpState(flowCapableNodeConnectorNew);
54         MacAddress macAddressNew = flowCapableNodeConnectorNew.getHardwareAddress();
55
56         Interface.OperStatus operStatusOld = getOpState(flowCapableNodeConnectorOld);
57         MacAddress macAddressOld = flowCapableNodeConnectorOld.getHardwareAddress();
58
59         boolean opstateModified = false;
60         boolean hardwareAddressModified = false;
61         if (!operStatusNew.equals(operStatusOld)) {
62             opstateModified = true;
63         }
64         if (!macAddressNew.equals(macAddressOld)) {
65             hardwareAddressModified = true;
66         }
67
68         if (!opstateModified && !hardwareAddressModified) {
69             LOG.debug("If State entry for port: {} Not Modified.", portName);
70             return futures;
71         }
72
73         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
74         if (hardwareAddressModified) {
75             LOG.debug("Hw-Address Modified for Port: {}", portName);
76             PhysAddress physAddress = new PhysAddress(macAddressNew.getValue());
77             ifaceBuilder.setPhysAddress(physAddress);
78         }
79
80         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
81         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
82                 handleInterfaceStateUpdates(portName, nodeConnectorId,
83                         transaction, dataBroker, ifaceBuilder, opstateModified, operStatusNew);
84
85         InterfaceParentEntry interfaceParentEntry =
86                 InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(portName, dataBroker);
87         if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
88             for (InterfaceChildEntry higherlayerChild : interfaceParentEntry.getInterfaceChildEntry()) {
89                 handleInterfaceStateUpdates(higherlayerChild.getChildInterface(),
90                         nodeConnectorId, transaction, dataBroker, ifaceBuilder, opstateModified, operStatusNew);
91                 InterfaceParentEntry higherLayerParent =
92                         InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(higherlayerChild.getChildInterface(), dataBroker);
93                 if (higherLayerParent != null && higherLayerParent.getInterfaceChildEntry() != null) {
94                     for (InterfaceChildEntry interfaceChildEntry : higherLayerParent.getInterfaceChildEntry()) {
95                         //FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
96                         handleInterfaceStateUpdates(interfaceChildEntry.getChildInterface(), nodeConnectorId,
97                                 transaction, dataBroker, ifaceBuilder, opstateModified, operStatusNew);
98                     }
99                 }
100             }
101         }else {
102             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface, operStatusNew, opstateModified);
103         }
104         futures.add(transaction.submit());
105         return futures;
106     }
107
108     public static Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector){
109         Interface.OperStatus operStatus =
110                 (flowCapableNodeConnector.getState().isLive() &&
111                         !flowCapableNodeConnector.getConfiguration().isPORTDOWN())
112                         ? Interface.OperStatus.Up: Interface.OperStatus.Down;
113         return operStatus;
114     }
115
116     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
117     handleInterfaceStateUpdates(String interfaceName, NodeConnectorId nodeConnectorId,WriteTransaction transaction,
118                                 DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
119                                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState){
120         LOG.debug("updating interface state entry for {}", interfaceName);
121         InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
122         ifaceBuilder.setKey(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
123         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
124                 InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
125         if (modifyOpState(iface, opStateModified)) {
126             LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
127             ifaceBuilder.setOperStatus(opState);
128         }
129         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
130
131         return iface;
132     }
133
134     public static void handleTunnelMonitoringUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
135                                                      org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
136                                                      Interface.OperStatus operStatus, boolean opStateModified){
137         // start/stop monitoring based on opState
138         if(!modifyTunnel(iface, opStateModified)){
139             return;
140         }
141
142         LOG.debug("handling tunnel monitoring updates for {} due to opstate modification", iface.getName());
143         if (operStatus == Interface.OperStatus.Down)
144             AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
145         else
146             AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
147     }
148
149     public static boolean modifyOpState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
150                                         boolean opStateModified){
151         return (opStateModified && (iface == null || iface != null && iface.isEnabled()));
152     }
153
154     public static boolean modifyTunnel(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
155                                        boolean opStateModified){
156         return modifyOpState(iface, opStateModified) && iface != null && iface.getAugmentation(IfTunnel.class) != null;
157     }
158 }