MDSAL-API Migration
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / statehelpers / OvsInterfaceStateAddHelper.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.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.MoreExecutors;
17 import java.util.ArrayList;
18 import java.util.List;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.apache.aries.blueprint.annotation.service.Reference;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
24 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
25 import org.opendaylight.genius.interfacemanager.IfmConstants;
26 import org.opendaylight.genius.interfacemanager.IfmUtil;
27 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
28 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
29 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
30 import org.opendaylight.mdsal.binding.api.DataBroker;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
38 import org.opendaylight.yangtools.yang.common.Uint64;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * This worker is responsible for adding the openflow-interfaces/of-port-info
44  * container in odl-interface-openflow yang. Where applicable: Create the
45  * entries in Interface-State OperDS. Create the entries in Inventory OperDS.
46  */
47
48 @Singleton
49 public final class OvsInterfaceStateAddHelper {
50     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateAddHelper.class);
51     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
52
53     private final ManagedNewTransactionRunner txRunner;
54     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
55     private final AlivenessMonitorUtils alivenessMonitorUtils;
56
57     @Inject
58     public OvsInterfaceStateAddHelper(@Reference DataBroker dataBroker, AlivenessMonitorUtils alivenessMonitorUtils,
59                                       InterfaceManagerCommonUtils interfaceManagerCommonUtils) {
60         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
61         this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
62         this.alivenessMonitorUtils = alivenessMonitorUtils;
63     }
64
65     public List<ListenableFuture<Void>> addState(String interfaceName, Interface parentInterface) {
66         if (parentInterface.getLowerLayerIf() == null || parentInterface.getLowerLayerIf().isEmpty()) {
67             LOG.trace("Cannot obtain lower layer if, not proceeding with Interface State addition for interface: {}",
68                     interfaceName);
69         }
70         NodeConnectorId nodeConnectorId = new NodeConnectorId(parentInterface.getLowerLayerIf().get(0));
71         PhysAddress physAddress = parentInterface.getPhysAddress();
72         long portNo = IfmUtil.getPortNumberFromNodeConnectorId(nodeConnectorId);
73         return addState(nodeConnectorId, interfaceName, portNo, physAddress);
74     }
75
76
77
78     public List<ListenableFuture<Void>> addState(NodeConnectorId nodeConnectorId, String interfaceName,
79             FlowCapableNodeConnector fcNodeConnectorNew) {
80         long portNo = IfmUtil.getPortNumberFromNodeConnectorId(nodeConnectorId);
81         PhysAddress physAddress = IfmUtil.getPhyAddress(portNo, fcNodeConnectorNew);
82         return addState(nodeConnectorId, interfaceName, portNo, physAddress);
83     }
84
85     private List<ListenableFuture<Void>> addState(NodeConnectorId nodeConnectorId, String interfaceName,
86             long portNo, PhysAddress physAddress) {
87         LOG.info("Adding Interface State to Oper DS for interface: {}", interfaceName);
88
89         if (portNo == IfmConstants.INVALID_PORT_NO) {
90             LOG.trace("Cannot derive port number, not proceeding with Interface State " + "addition for interface: {}",
91                     interfaceName);
92             return null;
93         }
94
95         List<ListenableFuture<Void>> futures = new ArrayList<>();
96
97         Interface.OperStatus operStatus = Interface.OperStatus.Up;
98         Interface.AdminStatus adminStatus = Interface.AdminStatus.Up;
99
100         // Fetch the interface from config DS if exists
101         InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
102         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
103             .interfaces.rev140508.interfaces.Interface iface = interfaceManagerCommonUtils
104                 .getInterfaceFromConfigDS(interfaceKey);
105
106         if (InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
107                 && !validateTunnelPortAttributes(nodeConnectorId, iface)) {
108             return futures;
109         }
110
111         futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
112             Interface ifState = interfaceManagerCommonUtils.addStateEntry(iface, interfaceName,
113                     tx, physAddress, operStatus, adminStatus, nodeConnectorId);
114
115             // If this interface is a tunnel interface, create the tunnel ingress
116             // flow,and start tunnel monitoring
117             if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
118                 handleTunnelMonitoringAddition(futures, nodeConnectorId, ifState.getIfIndex(), iface, interfaceName,
119                         portNo);
120                 return;
121             }
122
123             // install ingress flow if this is an l2vlan interface
124             if (InterfaceManagerCommonUtils.isVlanInterface(iface) && iface.isEnabled() && ifState
125                     .getOperStatus() == org.opendaylight.yang.gen.v1.urn
126                     .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up) {
127                 Uint64 dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
128                 FlowBasedServicesUtils.installLportIngressFlow(dpId, portNo, iface, futures, txRunner,
129                         ifState.getIfIndex());
130                 futures.add(FlowBasedServicesUtils.bindDefaultEgressDispatcherService(txRunner, iface,
131                         Long.toString(portNo), interfaceName, ifState.getIfIndex()));
132                 EVENT_LOGGER.debug("IFM-OvsInterfaceState, ADD, IngressFlow {}", interfaceName);
133             }
134         }));
135         EVENT_LOGGER.debug("IFM-OvsInterfaceState,ADD {}", interfaceName);
136         return futures;
137     }
138
139     public void handleTunnelMonitoringAddition(List<ListenableFuture<Void>> futures, NodeConnectorId nodeConnectorId,
140             Integer ifIndex,
141             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
142                     .ietf.interfaces.rev140508.interfaces.Interface interfaceInfo, String interfaceName, long portNo) {
143         EVENT_LOGGER.debug("IFM-OvsInterfaceState,ADD,TunnelIngressFlow {}", interfaceName);
144         Uint64 dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
145         ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
146             interfaceManagerCommonUtils.addTunnelIngressFlow(
147                 tx, interfaceInfo.augmentation(IfTunnel.class), dpId, portNo, interfaceName, ifIndex);
148             FlowBasedServicesUtils.bindDefaultEgressDispatcherService(tx, interfaceInfo,
149                 Long.toString(portNo), interfaceName, ifIndex);
150         });
151         futures.add(future);
152         Futures.addCallback(future, new FutureCallback<Void>() {
153             @Override
154             public void onSuccess(@Nullable Void result) {
155                 alivenessMonitorUtils.startLLDPMonitoring(interfaceInfo.augmentation(IfTunnel.class), interfaceName);
156             }
157
158             @Override
159             public void onFailure(Throwable throwable) {
160                 LOG.error("Unable to add tunnel monitoring", throwable);
161             }
162         }, MoreExecutors.directExecutor());
163     }
164
165     public static boolean validateTunnelPortAttributes(NodeConnectorId nodeConnectorId,
166             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
167                 .ietf.interfaces.rev140508.interfaces.Interface iface) {
168         Uint64 currentDpnId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
169         if (iface != null) {
170             ParentRefs parentRefs = iface.augmentation(ParentRefs.class);
171             if (!currentDpnId.equals(parentRefs.getDatapathNodeIdentifier())) {
172                 LOG.warn(
173                         "Received tunnel state add notification for tunnel {} from dpn {} where as "
174                                 + "the northbound configured dpn is {}",
175                         iface.getName(), currentDpnId, parentRefs.getDatapathNodeIdentifier());
176                 return false;
177             }
178         }
179         return true;
180     }
181 }