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>
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;
/**
*/
public SalMeterService getSalMeterService();
+ /**
+ * Table RPC service
+ *
+ * @return
+ */
+ public SalTableService getSalTableService();
+
/**
* Content definition method and prevent code duplicity in Reconcil
* @return ForwardingRulesCommiter<Flow>
*/
public ForwardingRulesCommiter<Meter> getMeterCommiter();
+ /**
+ * Content definition method and prevent code duplicity
+ * @return ForwardingRulesCommiter<Table>
+ */
+ public ForwardingRulesCommiter<Table> getTableCommiter();
+
/**
* Content definition method
* @return 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();
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;
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,
"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
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;
return salMeterService;
}
+ @Override
+ public SalTableService getSalTableService() {
+ return salTableService;
+ }
+
@Override
public ForwardingRulesCommiter<Flow> getFlowCommiter() {
return flowListener;
return meterListener;
}
+ @Override
+ public ForwardingRulesCommiter<Table> getTableCommiter() {
+ return tableListener;
+ }
+
@Override
public FlowNodeReconciliation getFlowNodeReconciliation() {
return nodeListener;
--- /dev/null
+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
+ }
+
+
+}
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());
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());
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();
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());
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;
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;
}
--- /dev/null
+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;
+ }
+}
description "Configuring openflow table.";
input {
+ uses tr:transaction-metadata;
+ leaf table-ref {
+ type table-type:table-ref;
+ }
uses table-update;
uses tr:transaction-aware;
}