2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
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;
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.
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");
53 private final ManagedNewTransactionRunner txRunner;
54 private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
55 private final AlivenessMonitorUtils alivenessMonitorUtils;
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;
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: {}",
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);
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);
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);
89 if (portNo == IfmConstants.INVALID_PORT_NO) {
90 LOG.trace("Cannot derive port number, not proceeding with Interface State " + "addition for interface: {}",
95 List<ListenableFuture<Void>> futures = new ArrayList<>();
97 Interface.OperStatus operStatus = Interface.OperStatus.Up;
98 Interface.AdminStatus adminStatus = Interface.AdminStatus.Up;
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);
106 if (InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
107 && !validateTunnelPortAttributes(nodeConnectorId, iface)) {
111 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
112 Interface ifState = interfaceManagerCommonUtils.addStateEntry(iface, interfaceName,
113 tx, physAddress, operStatus, adminStatus, nodeConnectorId);
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,
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);
135 EVENT_LOGGER.debug("IFM-OvsInterfaceState,ADD {}", interfaceName);
139 public void handleTunnelMonitoringAddition(List<ListenableFuture<Void>> futures, NodeConnectorId nodeConnectorId,
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);
152 Futures.addCallback(future, new FutureCallback<Void>() {
154 public void onSuccess(@Nullable Void result) {
155 alivenessMonitorUtils.startLLDPMonitoring(interfaceInfo.augmentation(IfTunnel.class), interfaceName);
159 public void onFailure(Throwable throwable) {
160 LOG.error("Unable to add tunnel monitoring", throwable);
162 }, MoreExecutors.directExecutor());
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);
170 ParentRefs parentRefs = iface.augmentation(ParentRefs.class);
171 if (!currentDpnId.equals(parentRefs.getDatapathNodeIdentifier())) {
173 "Received tunnel state add notification for tunnel {} from dpn {} where as "
174 + "the northbound configured dpn is {}",
175 iface.getName(), currentDpnId, parentRefs.getDatapathNodeIdentifier());