private final DataBroker dataBroker;
private BindingTransactionChain txChain;
private ListenerRegistration<?> listenerRegistration;
+ private ListenerRegistration<?> tableFeatureListenerRegistration;
private Thread thread;
FlowCapableInventoryProvider(final DataBroker dataBroker, final NotificationProviderService notificationService) {
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);
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();
--- /dev/null
+/*
+ * 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);
+ }
+ }
+ });
+ }
+}
*/
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;
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
*/
*/
void setEntityOwnership(boolean isOwner);
+ /**
+ * Send table feature to the switch to get tables features for all the tables.
+ * @return Transaction id
+ */
+ Optional<BigInteger> sendEmptyTableFeatureRequest();
+
}
}
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.
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));
}
entityMetadata.getContext().getNotificationEnqueuer().enqueueNotification(
entityMetadata.getWrappedNotification());
}
+
private class MDSwitchMetaData {
final private ModelDrivenSwitch ofSwitch;
*/
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;
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;
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));
+
+ }
+
}