*/
package org.opendaylight.openflowplugin.openflow.md.core.sal;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import com.google.common.base.Optional;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowHashIdMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowHashIdMapping;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.nodes.node.table.FlowHashIdMapKey;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
-
import org.opendaylight.openflowjava.protocol.api.util.BinContent;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
/**
* Recursive helper method for {@link OFRpcTaskFactory#createAddFlowTask(OFRpcTaskContext, AddFlowInput, SwitchConnectionDistinguisher)}
- * and {@link OFRpcTaskFactory#createUpdateFlowTask(OFRpcTaskContext, UpdateFlowInput, SwitchConnectionDistinguisher)} to chain results
+ * and {@link OFRpcTaskFactory#createUpdateFlowTask(OFRpcTaskContext, UpdateFlowInput, SwitchConnectionDistinguisher, ReadWriteTransaction)} to chain results
* of multiple flowmods.
* The next flowmod gets executed if the earlier one is successful.
* All the flowmods should have the same xid, in-order to cross-reference
*/
public static OFRpcTask<UpdateFlowInput, RpcResult<UpdateFlowOutput>> createUpdateFlowTask(
final OFRpcTaskContext taskContext, UpdateFlowInput input,
- SwitchConnectionDistinguisher cookie) {
+ SwitchConnectionDistinguisher cookie, final ReadWriteTransaction rwTx) {
class OFRpcTaskImpl extends OFRpcTask<UpdateFlowInput, RpcResult<UpdateFlowOutput>> {
-
+ final ReadWriteTransaction rwTx;
+ InstanceIdentifier<Table> iiToTable = null;
+ String flowId = null;
public OFRpcTaskImpl(OFRpcTaskContext taskContext, SwitchConnectionDistinguisher cookie,
- UpdateFlowInput input) {
- super(taskContext, cookie, input);
+ final UpdateFlowInput in, final ReadWriteTransaction rwTx) {
+ super(taskContext, cookie, in);
+ InstanceIdentifier<Flow> iiToFlow = (InstanceIdentifier<Flow>)(in.getFlowRef().getValue());
+ iiToTable = in.getFlowRef().getValue().firstIdentifierOf(Table.class);
+ FlowKey flowKey = iiToFlow.firstKeyOf(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow.class, FlowKey.class);
+ if (flowKey != null) {
+ flowId = flowKey.getId().getValue();
+ }
+ this.rwTx = rwTx;
}
@Override
version, getSession().getFeatures().getDatapathId());
}
+ CheckedFuture<Optional<FlowHashIdMapping>, ReadFailedException> hashDeletionFuture = readFlowHashIdMappingFromOperationalDS(rwTx);
+ Futures.addCallback(hashDeletionFuture, new FutureCallback<Optional<FlowHashIdMapping>>() {
+
+ @Override
+ public void onSuccess(Optional<FlowHashIdMapping> optFlowHashIdMapping) {
+ FlowHashIdMapKey flowHashIdMapKeyToDelete = null;
+ if (optFlowHashIdMapping.isPresent()) {
+ FlowHashIdMapping flowHashIdMapping = optFlowHashIdMapping.get();
+ for (FlowHashIdMap flowHashId : flowHashIdMapping.getFlowHashIdMap()) {
+ if (flowHashId.getFlowId().getValue().equals(flowId)) {
+ flowHashIdMapKeyToDelete = flowHashId.getKey();
+ break;
+ }
+ }
+ }
+ if (flowHashIdMapKeyToDelete != null) {
+ final KeyedInstanceIdentifier<FlowHashIdMap, FlowHashIdMapKey> iiToFlowHashIdToDelete = iiToTable
+ .augmentation(FlowHashIdMapping.class).child(FlowHashIdMap.class, flowHashIdMapKeyToDelete);
+ rwTx.delete(LogicalDatastoreType.OPERATIONAL, iiToFlowHashIdToDelete);
+ rwTx.submit();
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LOG.debug("Reading flow-hash-id map from operational DS wasn't successfull");
+ }
+ });
+
+
+
allFlowMods.addAll(ofFlowModInputs);
LOG.debug("Number of flows to push to switch: {}", allFlowMods.size());
result = chainFlowMods(allFlowMods, 0, getTaskContext(), getCookie());
OFRpcTaskUtil.hookFutureNotification(this, result,
getRpcNotificationProviderService(),
createFlowUpdatedNotification(in));
+
return result;
}
+
+ CheckedFuture<Optional<FlowHashIdMapping>, ReadFailedException> readFlowHashIdMappingFromOperationalDS(final ReadWriteTransaction rwTx) {
+ InstanceIdentifier<FlowHashIdMapping> iiToFlowHashIdMapping = iiToTable
+ .augmentation(FlowHashIdMapping.class);
+ return rwTx.read(LogicalDatastoreType.OPERATIONAL, iiToFlowHashIdMapping);
+ }
+
@Override
public Boolean isBarrier() {
return getInput().getUpdatedFlow().isBarrier();
}
}
- return new OFRpcTaskImpl(taskContext, cookie, input);
+ return new OFRpcTaskImpl(taskContext, cookie, input, rwTx);
}