2 * Copyright (c) 2020 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
9 package org.opendaylight.genius.interfacemanager;
11 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
13 import com.google.common.base.Preconditions;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.util.concurrent.ExecutionException;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.mdsal.binding.api.DataBroker;
20 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
21 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
22 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
23 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
24 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
25 import org.opendaylight.openflowplugin.applications.reconciliation.NotificationRegistration;
26 import org.opendaylight.openflowplugin.applications.reconciliation.ReconciliationManager;
27 import org.opendaylight.openflowplugin.applications.reconciliation.ReconciliationNotificationListener;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.rf.state.rev170713.ResultState;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.opendaylight.yangtools.yang.common.Uint64;
40 import org.opendaylight.yangtools.yang.common.Uint8;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 * Pre-creates the nodes and tables in the FRM config/inventory datastore
46 * whenever a switch is connected. This class implements the callback provided
47 * by openflowplugin to do the node and tables pre-creation.
50 public class FrmNodeAndTablesBuilder implements ReconciliationNotificationListener {
52 private static final Logger LOGGER = LoggerFactory.getLogger(FrmNodeAndTablesBuilder.class);
54 private static final String SERVICE_NAME = "FrmNodeAndTablesBuilder";
55 private static final short CANARY_TABLE_ID = 255;
56 private static final int SLEEP_BETWEEN_RETRIES = 1000;
57 private static final int MAX_RETRIES = 3;
58 private static final int TASK_PRIORITY = 2;
60 private final DataBroker dataBroker;
61 private NotificationRegistration registration;
62 private final ManagedNewTransactionRunner txRunner;
65 public FrmNodeAndTablesBuilder(DataBroker dataBroker,
66 ReconciliationManager reconciliationManager) {
67 this.dataBroker = dataBroker;
68 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
69 reconciliationManager = Preconditions.checkNotNull(reconciliationManager,
70 "ReconciliationManager cannot be null!");
71 reconciliationManager.registerService(this);
72 LOGGER.info("FrmNodeAndTablesBuilder has started successfully.");
76 public void close() throws Exception {
77 if (registration != null) {
84 public ListenableFuture<Boolean> startReconciliation(DeviceInfo connectedNode) {
85 return Futures.immediateFuture(preCreateInventoryNodeAndTables(connectedNode, MAX_RETRIES,
86 SLEEP_BETWEEN_RETRIES));
90 public ListenableFuture<Boolean> endReconciliation(DeviceInfo node) {
91 return Futures.immediateFuture(true);
95 public String getName() {
100 public ResultState getResultState() {
101 return ResultState.DONOTHING;
105 public int getPriority() {
106 return TASK_PRIORITY;
109 private boolean preCreateInventoryNodeAndTables(DeviceInfo connectedNode, int maxRetries,
110 int sleepBetweenRetries) {
111 Uint64 dpnId = getDpnIdFromNodeIdent(connectedNode);
112 Node nodeDpn = buildDpnNode(dpnId);
113 LOGGER.info("Pre-creating FRM node and tables for {}", dpnId);
115 ListenableFuture<?> future = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
116 if (!isTableAlreadyPrecreated(tx, nodeDpn)) {
117 LOGGER.info("{} getting connected for first time,"
118 + "proceed with FRM node and table pre-create", dpnId);
119 for (short tableId = 0; tableId <= 255; tableId++) {
120 InstanceIdentifier<Table> tableIId = InstanceIdentifier.builder(Nodes.class)
121 .child(Node.class, nodeDpn.key()).augmentation(FlowCapableNode.class)
122 .child(Table.class, new TableKey(Uint8.valueOf(tableId))).build();
123 tx.mergeParentStructureMerge(tableIId,
124 new TableBuilder().withKey(new TableKey(Uint8.valueOf(tableId))).build());
126 LOGGER.info("Pre-creating FRM node and tables for {} is finished", dpnId);
128 LOGGER.info("FRM node and tables already present for {}", dpnId);
134 } catch (InterruptedException | ExecutionException ex) {
135 LOGGER.error("Pre-creating FRM node and tables for {} failed, retrying.. {}", dpnId, maxRetries);
137 if (maxRetries > 0) {
139 Thread.sleep(sleepBetweenRetries);
140 } catch (InterruptedException e) {
150 private boolean isTableAlreadyPrecreated(TypedReadWriteTransaction<Configuration> tx, Node nodeDpn)
151 throws ExecutionException, InterruptedException {
152 InstanceIdentifier<Table> tableIId = InstanceIdentifier.builder(Nodes.class)
153 .child(Node.class, nodeDpn.key()).augmentation(FlowCapableNode.class)
154 .child(Table.class, new TableKey(CANARY_TABLE_ID)).build();
155 return tx.exists(tableIId).get();
158 private Uint64 getDpnIdFromNodeIdent(final DeviceInfo nodeIdentity) {
159 Uint64 nodeName = nodeIdentity.getDatapathId();
163 protected Node buildDpnNode(Uint64 dpnId) {
164 NodeId nodeId = new NodeId("openflow:" + dpnId);
165 Node nodeDpn = new NodeBuilder().setId(nodeId).withKey(new NodeKey(nodeId)).build();