Support for Table Features 34/18334/9
authorJozef Gloncak <jgloncak@cisco.com>
Tue, 28 Apr 2015 12:41:06 +0000 (14:41 +0200)
committerJozef Gloncak <jgloncak@cisco.com>
Wed, 29 Apr 2015 11:07:39 +0000 (13:07 +0200)
FlowListenerTest.java - removed equals which checks concrete transaction ID.
If changes are done on flow also TableForwarder is notified because listener is
listening on subtree changes. Therefore can happend that sometimes changes in
table are processed before changes in flow and therefore is generated transaction
ID DOM-2 instead DOM-1.

Change-Id: I3570c03fda0b532833c85bae01ed4a10cc14a2d2
Signed-off-by: HemaTG <hema.gopalkrishnan@ericsson.com>
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesManager.java
applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/FlowNodeReconciliationImpl.java
applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/ForwardingRulesManagerImpl.java
applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/TableForwarder.java [new file with mode: 0644]
applications/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java
applications/forwardingrules-manager/src/test/java/test/mock/util/RpcProviderRegistryMock.java
applications/forwardingrules-manager/src/test/java/test/mock/util/SalTableServiceMock.java [new file with mode: 0644]
model/model-flow-service/src/main/yang/sal-table.yang

index 4c695f2837143adee9217c451faaaa99b940706a..1de3a1b37d8b9a17a804f1550bd1f47d0ecce723 100644 (file)
@@ -11,11 +11,13 @@ package org.opendaylight.openflowplugin.applications.frm;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+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.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
@@ -98,6 +100,13 @@ public interface ForwardingRulesManager extends AutoCloseable {
      */
     public SalMeterService getSalMeterService();
 
+    /**
+     * Table RPC service
+     *
+     * @return
+     */
+    public SalTableService getSalTableService();
+
     /**
      * Content definition method and prevent code duplicity in Reconcil
      * @return ForwardingRulesCommiter&lt;Flow&gt;
@@ -116,6 +125,12 @@ public interface ForwardingRulesManager extends AutoCloseable {
      */
     public ForwardingRulesCommiter<Meter> getMeterCommiter();
 
+    /**
+     * Content definition method and prevent code duplicity
+     * @return ForwardingRulesCommiter&lt;Table&gt;
+     */
+    public ForwardingRulesCommiter<Table> getTableCommiter();
+
     /**
      * Content definition method
      * @return FlowNodeReconciliation
index 0564131b4850838d959fd5df4438ef0c395c85a5..b47af791c6078c69572269aa24699d1a38401136 100644 (file)
@@ -148,6 +148,16 @@ public class FlowNodeReconciliationImpl implements FlowNodeReconciliation {
         }
 
         if (flowNode.isPresent()) {
+               /* Tables - have to be pushed before groups */
+               // CHECK if while pusing the update, updateTableInput can be null to emulate a table add
+               List<Table> tableList = flowNode.get().getTable() != null 
+                               ? flowNode.get().getTable() : Collections.<Table> emptyList() ;
+               for (Table table : tableList) {
+                       final KeyedInstanceIdentifier<Table, TableKey> tableIdent = 
+                                       nodeIdent.child(Table.class, table.getKey());
+                       this.provider.getTableCommiter().update(tableIdent, table, null ,nodeIdent) ;
+               }
+               
             /* Groups - have to be first */
             List<Group> groups = flowNode.get().getGroup() != null
                     ? flowNode.get().getGroup() : Collections.<Group> emptyList();
index 2e78b5e4ec04a693a964d299556037ead8711c7a..fa4c24009aeb43e42b05c22a4b22fdae139c0e06 100644 (file)
@@ -26,6 +26,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalF
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,10 +57,12 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
     private final SalFlowService salFlowService;
     private final SalGroupService salGroupService;
     private final SalMeterService salMeterService;
+    private final SalTableService salTableService;
 
     private ForwardingRulesCommiter<Flow> flowListener;
     private ForwardingRulesCommiter<Group> groupListener;
     private ForwardingRulesCommiter<Meter> meterListener;
+    private ForwardingRulesCommiter<Table> tableListener;
     private FlowNodeReconciliation nodeListener;
 
     public ForwardingRulesManagerImpl(final DataBroker dataBroker,
@@ -73,15 +77,22 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
                 "RPC SalGroupService not found.");
         this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
                 "RPC SalMeterService not found.");
+        this.salTableService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalTableService.class),
+                "RPC SalTableService not found.");
     }
 
     @Override
     public void start() {
+
         this.flowListener = new FlowForwarder(this, dataService);
+        
         this.groupListener = new GroupForwarder(this, dataService);
         this.meterListener = new MeterForwarder(this, dataService);
+        
+        this.tableListener = new TableForwarder(this, dataService);
         this.nodeListener = new FlowNodeReconciliationImpl(this, dataService);
         LOG.info("ForwardingRulesManager has started successfully.");
+
     }
 
     @Override
@@ -98,6 +109,10 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
             this.meterListener.close();
             this.meterListener = null;
         }
+        if (this.tableListener != null) {
+            this.tableListener.close();
+            this.tableListener = null;
+        }
         if (this.nodeListener != null) {
             this.nodeListener.close();
             this.nodeListener = null;
@@ -162,6 +177,11 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
         return salMeterService;
     }
 
+    @Override
+    public SalTableService getSalTableService() {
+        return salTableService;
+    }
+
     @Override
     public ForwardingRulesCommiter<Flow> getFlowCommiter() {
         return flowListener;
@@ -177,6 +197,11 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
         return meterListener;
     }
 
+    @Override
+    public ForwardingRulesCommiter<Table> getTableCommiter() {
+        return tableListener;
+    }
+
     @Override
     public FlowNodeReconciliation getFlowNodeReconciliation() {
         return nodeListener;
diff --git a/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/TableForwarder.java b/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/TableForwarder.java
new file mode 100644 (file)
index 0000000..6981b37
--- /dev/null
@@ -0,0 +1,116 @@
+package org.opendaylight.openflowplugin.applications.frm.impl;
+
+import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
+
+import java.util.concurrent.Callable;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+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.inventory.rev130819.NodeRef;
+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.table.service.rev131026.UpdateTableInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.OriginalTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.UpdatedTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableRef;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Preconditions;
+
+public class TableForwarder extends AbstractListeningCommiter<Table> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TableForwarder.class);
+
+    private ListenerRegistration<TableForwarder> listenerRegistration;
+
+    public TableForwarder (final ForwardingRulesManager manager, final DataBroker db) {
+        super(manager, Table.class);
+        Preconditions.checkNotNull(db, "DataBroker can not be null!");
+        final DataTreeIdentifier<Table> treeId = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardPath());
+
+        try {
+            SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(ForwardingRulesManagerImpl.STARTUP_LOOP_TICK,
+                    ForwardingRulesManagerImpl.STARTUP_LOOP_MAX_RETRIES);
+            listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<TableForwarder>>() {
+                @Override
+                public ListenerRegistration<TableForwarder> call() throws Exception {
+                    return db.registerDataTreeChangeListener(treeId, TableForwarder.this);
+                }
+            });
+        } catch (final Exception e) {
+            LOG.warn("FRM Table DataChange listener registration fail!");
+            LOG.debug("FRM Table DataChange listener registration fail ..", e);
+            throw new IllegalStateException("TableForwarder startup fail! System needs restart.", e);
+        }
+    }
+
+    @Override
+    public void close() {
+        if (listenerRegistration != null) {
+            try {
+                listenerRegistration.close();
+            } catch (Exception e) {
+                LOG.error("Error by stop FRM TableChangeListener.", e);
+            }
+            listenerRegistration = null;
+        }
+    }
+
+    @Override
+    protected InstanceIdentifier<Table> getWildCardPath() {
+        return InstanceIdentifier.create(Nodes.class).child(Node.class)
+                .augmentation(FlowCapableNode.class).child(Table.class);
+    }
+
+    @Override
+    public void remove(final InstanceIdentifier<Table> identifier, final Table removeDataObj,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+      // DO Nothing
+    }
+
+    @Override
+    public void update(final InstanceIdentifier<Table> identifier,
+                       final Table original, final Table update,
+                       final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+        LOG.debug( "Received the Table Update request [Tbl id, node Id, original, upd" +
+                       " " + identifier + " " + nodeIdent + " " + original + " " + update );
+
+        final Table originalTable = (original);
+        Table updatedTable ;
+        if( null == update)
+          updatedTable = (original);
+        else
+          updatedTable = (update);
+
+        final UpdateTableInputBuilder builder = new UpdateTableInputBuilder();
+
+        builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+        builder.setTableRef(new TableRef(identifier));
+
+        builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
+
+        builder.setUpdatedTable((new UpdatedTableBuilder(updatedTable)).build());
+
+        builder.setOriginalTable((new OriginalTableBuilder(originalTable)).build());
+        LOG.debug( "Invoking SalTableService " ) ;
+
+        if( this.provider.getSalTableService() != null )
+               System.out.println( " Handle to SalTableServices" + this.provider.getSalTableService()) ;
+        this.provider.getSalTableService().updateTable(builder.build());
+
+    }
+
+    @Override
+    public void add(final InstanceIdentifier<Table> identifier, final Table addDataObj,
+                    final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+       //DO NOthing
+    }
+
+
+}
index c2454418b62bfa4d77b40c5a11583d7e04a8f3a9..e9de0fb1d984e4aa76847ccdcd59bd3567a054fb 100644 (file)
@@ -82,7 +82,6 @@ public class FlowListenerTest extends FRMTest {
         salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
         addFlowCalls = salFlowService.getAddFlowCalls();
         assertEquals(2, addFlowCalls.size());
-        assertEquals("DOM-1", addFlowCalls.get(1).getTransactionUri().getValue());
         assertEquals(2, addFlowCalls.get(1).getTableId().intValue());
         assertEquals(flowII, addFlowCalls.get(1).getFlowRef().getValue());
 
@@ -123,7 +122,6 @@ public class FlowListenerTest extends FRMTest {
         salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
         List<UpdateFlowInput> updateFlowCalls = salFlowService.getUpdateFlowCalls();
         assertEquals(1, updateFlowCalls.size());
-        assertEquals("DOM-1", updateFlowCalls.get(0).getTransactionUri().getValue());
         assertEquals(flowII, updateFlowCalls.get(0).getFlowRef().getValue());
         assertEquals(Boolean.TRUE, updateFlowCalls.get(0).getOriginalFlow().isStrict());
         assertEquals(Boolean.TRUE, updateFlowCalls.get(0).getUpdatedFlow().isStrict());
@@ -169,7 +167,6 @@ public class FlowListenerTest extends FRMTest {
         salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
         List<UpdateFlowInput> updateFlowCalls = salFlowService.getUpdateFlowCalls();
         assertEquals(1, updateFlowCalls.size());
-        assertEquals("DOM-1", updateFlowCalls.get(0).getTransactionUri().getValue());
         assertEquals(flowII, updateFlowCalls.get(0).getFlowRef().getValue());
         assertEquals(ipMatch, updateFlowCalls.get(0).getUpdatedFlow().getMatch().getIpMatch());
         forwardingRulesManager.close();
@@ -205,7 +202,6 @@ public class FlowListenerTest extends FRMTest {
         salFlowService = (SalFlowServiceMock) forwardingRulesManager.getSalFlowService();
         List<RemoveFlowInput> removeFlowCalls = salFlowService.getRemoveFlowCalls();
         assertEquals(1, removeFlowCalls.size());
-        assertEquals("DOM-1", removeFlowCalls.get(0).getTransactionUri().getValue());
         assertEquals(flowII, removeFlowCalls.get(0).getFlowRef().getValue());
         assertEquals(Boolean.TRUE, removeFlowCalls.get(0).isStrict());
 
index ff17a0c366f7edc08482fa145db17563964c6b91..b6a01b4e29142047f325ac77c9b058fe361d1875 100644 (file)
@@ -1,5 +1,7 @@
 package test.mock.util;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
@@ -35,6 +37,8 @@ public class RpcProviderRegistryMock implements RpcProviderRegistry {
             return (T) new SalGroupServiceMock();
         } else if (serviceInterface.equals(SalMeterService.class)) {
             return (T) new SalMeterServiceMock();
+        } else if (serviceInterface.equals(SalTableService.class)) {
+            return (T) new SalTableServiceMock();
         } else {
             return null;
         }
diff --git a/applications/forwardingrules-manager/src/test/java/test/mock/util/SalTableServiceMock.java b/applications/forwardingrules-manager/src/test/java/test/mock/util/SalTableServiceMock.java
new file mode 100644 (file)
index 0000000..52b94d7
--- /dev/null
@@ -0,0 +1,25 @@
+package test.mock.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class SalTableServiceMock implements SalTableService {
+    private List<UpdateTableInput> updateTableInput = new ArrayList<>();
+
+
+    public List<UpdateTableInput> getUpdateTableInput() {
+        return updateTableInput;
+    }
+
+    @Override
+    public Future<RpcResult<UpdateTableOutput>> updateTable(UpdateTableInput input) {
+        updateTableInput.add(input);
+        return null;
+    }
+}
index a40529bef4eff5515f273cd5e133d5f28d7ecb7b..e8b45ace1ad29616286eda0c319b9ee82f21ed59 100644 (file)
@@ -28,6 +28,10 @@ module sal-table {
         description "Configuring openflow table.";
         
         input {
+            uses tr:transaction-metadata;
+            leaf table-ref {
+                    type table-type:table-ref;
+            }
             uses table-update;
             uses tr:transaction-aware;
         }