Table features support for existing openflowplugin 85/34185/1
authorAnil Vishnoi <vishnoianil@gmail.com>
Fri, 22 Jan 2016 04:45:04 +0000 (20:45 -0800)
committerAnil Vishnoi <vishnoianil@gmail.com>
Fri, 5 Feb 2016 18:57:09 +0000 (18:57 +0000)
Patch 2 : Fixes javadoc error

Change-Id: Ibabecb59848c5df470aace8f93b355d1e700d261
Signed-off-by: Anil Vishnoi <vishnoianil@gmail.com>
(cherry picked from commit fa7311ff2ba8a07a578861fbbb2481400213cd29)

applications/inventory-manager/src/main/java/org/opendaylight/openflowplugin/applications/inventory/manager/FlowCapableInventoryProvider.java
applications/inventory-manager/src/main/java/org/opendaylight/openflowplugin/applications/inventory/manager/NodeTablesFeatureCommitter.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/md/ModelDrivenSwitch.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/role/OfEntityManager.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/ModelDrivenSwitchImpl.java

index 807af2e2a601b6e7ba59786a52450ddbf779f191..c6114972a6da1517cef1a83342b7201826878685 100644 (file)
@@ -35,6 +35,7 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable, Transacti
     private final DataBroker dataBroker;
     private BindingTransactionChain txChain;
     private ListenerRegistration<?> listenerRegistration;
+    private ListenerRegistration<?> tableFeatureListenerRegistration;
     private Thread thread;
 
     FlowCapableInventoryProvider(final DataBroker dataBroker, final NotificationProviderService notificationService) {
@@ -46,6 +47,11 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable, Transacti
         final NodeChangeCommiter changeCommiter = new NodeChangeCommiter(FlowCapableInventoryProvider.this);
         this.listenerRegistration = this.notificationService.registerNotificationListener(changeCommiter);
 
+        final NodeTablesFeatureCommitter nodeTablesFeatureCommitter =
+                new NodeTablesFeatureCommitter(FlowCapableInventoryProvider.this);
+        this.tableFeatureListenerRegistration = this.notificationService.registerNotificationListener(nodeTablesFeatureCommitter);
+
+
         this.txChain = (dataBroker.createTransactionChain(this));
         thread = new Thread(this);
         thread.setDaemon(true);
@@ -203,6 +209,15 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable, Transacti
             listenerRegistration = null;
         }
 
+        if (this.tableFeatureListenerRegistration != null) {
+            try {
+                this.tableFeatureListenerRegistration.close();
+            } catch (final Exception e) {
+                LOG.error("Failed to stop inventory provider", e);
+            }
+            tableFeatureListenerRegistration = null;
+        }
+
         if (thread != null) {
             thread.interrupt();
             thread.join();
diff --git a/applications/inventory-manager/src/main/java/org/opendaylight/openflowplugin/applications/inventory/manager/NodeTablesFeatureCommitter.java b/applications/inventory-manager/src/main/java/org/opendaylight/openflowplugin/applications/inventory/manager/NodeTablesFeatureCommitter.java
new file mode 100644 (file)
index 0000000..685938f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.applications.inventory.manager;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.TableUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Class receives and processes table feature updates. It augment table feature on table node
+ * in the inventory tree (node/table/{table-id}).
+ * Created by vishnoianil on 1/21/16.
+ */
+public class NodeTablesFeatureCommitter implements SalTableListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
+
+    private final FlowCapableInventoryProvider manager;
+
+    public NodeTablesFeatureCommitter(final FlowCapableInventoryProvider manager) {
+        this.manager = Preconditions.checkNotNull(manager);
+    }
+
+    @Override
+    public void onTableUpdated(final TableUpdated notification) {
+        final NodeId nodeId = notification.getNode().getValue().firstKeyOf(Node.class).getId();
+        LOG.info("Table feature notification received from {}", nodeId.getValue());
+        manager.enqueue(new InventoryOperation() {
+            @Override
+            public void applyOperation(final ReadWriteTransaction tx) {
+                List<TableFeatures> swTablesFeatures = notification.getTableFeatures();
+                final InstanceIdentifier<FlowCapableNode> flowCapableNodeII = InstanceIdentifier.create(Nodes.class)
+                        .child(Node.class, new NodeKey(nodeId)).augmentation(FlowCapableNode.class);
+
+                LOG.debug("Table feature update message contains feature data for {} tables from node {}",
+                        swTablesFeatures != null?swTablesFeatures.size():0, nodeId.getValue());
+
+                for (final TableFeatures tableFeatureData : swTablesFeatures) {
+                    final Short tableId = tableFeatureData.getTableId();
+                    final KeyedInstanceIdentifier<TableFeatures, TableFeaturesKey> tableFeaturesII = flowCapableNodeII
+                            .child(Table.class, new TableKey(tableId))
+                            .child(TableFeatures.class,new TableFeaturesKey(tableId));
+
+                    LOG.trace("Updating table feature for table {} of node {}", tableId, nodeId.getValue());
+                    tx.put(LogicalDatastoreType.OPERATIONAL, tableFeaturesII, tableFeatureData, true);
+                }
+            }
+        });
+    }
+}
index d47a08440e214ebcb59374ffd88c6fe6e74f5682..d923209c3d95630879d7c9979cf67cd9881da4ba 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.openflowplugin.api.openflow.md;
 
+import com.google.common.base.Optional;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
@@ -28,6 +29,8 @@ import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
+import java.math.BigInteger;
+
 /**
  * interface concatenating all md-sal services provided by OF-switch
  */
@@ -70,4 +73,10 @@ public interface ModelDrivenSwitch
      */
     void setEntityOwnership(boolean isOwner);
 
+    /**
+     * Send table feature to the switch to get tables features for all the tables.
+     * @return Transaction id
+     */
+    Optional<BigInteger> sendEmptyTableFeatureRequest();
+
 }
index bcd12998b81e061bab6309cf429fa60aadfbe7ac..36154b300ea2cc2de1ad529a61da844177982ce3 100644 (file)
@@ -271,7 +271,7 @@ public class OfEntityManager implements TransactionChainListener{
 
         }
         if (sessionContext != null) {
-            //Register the RPC, give then *this* controller instance is going to be master owner.
+            //Register the RPC, given *this* controller instance is going to be master owner.
             //If role registration fails for this node, it will deregister as a candidate for
             //ownership and that will make this controller non-owner and it will deregister the
             // router rpc.
@@ -289,6 +289,7 @@ public class OfEntityManager implements TransactionChainListener{
                     LOG.info("onDeviceOwnershipChanged: Controller is successfully set as a " +
                             "MASTER controller for {}", targetSwitchDPId);
                     entsession.get(entity).getOfSwitch().setEntityOwnership(newRole==OfpRole.BECOMEMASTER);
+                    entsession.get(entity).getOfSwitch().sendEmptyTableFeatureRequest();
                     sendNodeAddedNotification(entsession.get(entity));
 
                 }
@@ -403,6 +404,7 @@ public class OfEntityManager implements TransactionChainListener{
         entityMetadata.getContext().getNotificationEnqueuer().enqueueNotification(
                 entityMetadata.getWrappedNotification());
     }
+
     private class MDSwitchMetaData {
 
         final private ModelDrivenSwitch ofSwitch;
index 8478fc814078b1434765f7f34d2aed6df17d2fe2..df42e34ccdb838169cbc8222f71dc58917ccfa71 100644 (file)
@@ -7,10 +7,14 @@
  */
 package org.opendaylight.openflowplugin.openflow.md.core.sal;
 
+import com.google.common.base.Optional;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+
+import java.math.BigInteger;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
@@ -70,7 +74,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfigInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfigOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.MultipartRequestTableFeaturesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.ConnectionCookie;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortInput;
@@ -483,4 +492,30 @@ public class ModelDrivenSwitchImpl extends AbstractModelDrivenSwitch {
         OFRpcTask<SetConfigInput, RpcResult<SetConfigOutput>> task = OFRpcTaskFactory.createSetNodeConfigTask(rpcTaskContext, input, null);
         return task.submit();
     }
+
+    @Override
+    public Optional<BigInteger> sendEmptyTableFeatureRequest() {
+        LOG.debug("Send table feature request to {}",nodeId);
+
+        final Long xid = rpcTaskContext.getSession().getNextXid();
+
+        MultipartRequestTableFeaturesCaseBuilder caseBuilder = new MultipartRequestTableFeaturesCaseBuilder();
+        MultipartRequestTableFeaturesBuilder requestBuilder = new MultipartRequestTableFeaturesBuilder();
+        caseBuilder.setMultipartRequestTableFeatures(requestBuilder.build());
+
+        MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
+        mprInput.setType(MultipartType.OFPMPTABLEFEATURES);
+        mprInput.setVersion(rpcTaskContext.getSession().getPrimaryConductor().getVersion());
+        mprInput.setXid(xid);
+        mprInput.setFlags(new MultipartRequestFlags(false));
+
+        mprInput.setMultipartRequestBody(caseBuilder.build());
+
+        Future<RpcResult<Void>> resultFromOFLib = rpcTaskContext.getMessageService()
+                .multipartRequest(mprInput.build(), null);
+
+        return Optional.of(BigInteger.valueOf(xid));
+
+    }
+
 }