public static final int DEFUALT_STATUS = FlowCounter.OperationStatus.INIT.status();
public static final int DEFAULT_FLOW_COUNT = 0;
+ public static final int DEFAULT_TABLE_COUNT = 0;
public static final long DEFAULT_COMPLETION_TIME = 0;
public static final String DEFAULT_UNITS = "ns";
public static final String DEVICE_TYPE_PREFIX = "openflow:";
return BulkOMaticUtils.DEFAULT_UNITS;
}
}
+
+ @Override
+ public long getTableCount() {
+ if (writer != null) {
+ return writer.getTableCount();
+ }
+ return BulkOMaticUtils.DEFAULT_TABLE_COUNT;
+ }
}
public interface FlowCounterMBean {
- public long getFlowCount();
+ default public long getFlowCount() {
+ return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
+ }
- public int getReadOpStatus();
+ default public int getReadOpStatus() {
+ return BulkOMaticUtils.DEFUALT_STATUS;
+ }
- public int getWriteOpStatus();
+ default public int getWriteOpStatus() {
+ return BulkOMaticUtils.DEFUALT_STATUS;
+ }
- public long getTaskCompletionTime();
+ default public long getTaskCompletionTime() {
+ return BulkOMaticUtils.DEFAULT_COMPLETION_TIME;
+ }
- public String getUnits();
+ default public String getUnits() {
+ return BulkOMaticUtils.DEFAULT_UNITS;
+ }
+
+ default public long getTableCount() {
+ return BulkOMaticUtils.DEFAULT_TABLE_COUNT;
+ }
}
package org.opendaylight.openflowplugin.applications.bulk.o.matic;
import com.google.common.base.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
public class FlowReader implements Runnable, FlowCounterMBean {
private static final Logger LOG = LoggerFactory.getLogger(FlowReader.class);
private final DataBroker dataBroker;
private final short startTableId;
private final short endTableId;
private final boolean isConfigDs;
- private AtomicLong flowCount = new AtomicLong(0);
+ private AtomicLong flowCount = new AtomicLong();
private AtomicInteger readOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
- private static final String UNITS = "ns";
private FlowReader(final DataBroker dataBroker,
final Integer dpnCount,
public int getReadOpStatus() {
return readOpStatus.get();
}
-
- @Override
- public int getWriteOpStatus() {
- return BulkOMaticUtils.DEFUALT_STATUS;
- }
-
- @Override
- public long getTaskCompletionTime() {
- return BulkOMaticUtils.DEFAULT_COMPLETION_TIME;
- }
-
- @Override
- public String getUnits() {
- return UNITS;
- }
}
\ No newline at end of file
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
public class FlowWriterConcurrent implements FlowCounterMBean {
private static final Logger LOG = LoggerFactory.getLogger(FlowWriterConcurrent.class);
public static final String USING_CONCURRENT_IMPLEMENTATION_OF_FLOW_WRITER = "Using Concurrent implementation of Flow Writer.";
private final ExecutorService flowPusher;
private long startTime;
private AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
- private AtomicInteger countDpnWriteCompletion = new AtomicInteger(0);
- private AtomicLong taskCompletionTime = new AtomicLong(0);
- private static final String UNITS = "ns";
+ private AtomicInteger countDpnWriteCompletion = new AtomicInteger();
+ private AtomicLong taskCompletionTime = new AtomicLong();
public FlowWriterConcurrent(final DataBroker dataBroker, ExecutorService flowPusher) {
this.dataBroker = dataBroker;
}
public void addFlows(Integer dpnCount, Integer flowsPerDPN, int batchSize,
- int sleepMillis, int sleepAfter, short startTableId, short endTableId) {
+ int sleepMillis, int sleepAfter, short startTableId, short endTableId,
+ boolean isCreateParents) {
LOG.info(USING_CONCURRENT_IMPLEMENTATION_OF_FLOW_WRITER);
countDpnWriteCompletion.set(dpnCount);
startTime = System.nanoTime();
for (int i = 1; i <= dpnCount; i++) {
FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i),
- flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId);
+ flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId, isCreateParents);
flowPusher.execute(task);
}
}
countDpnWriteCompletion.set(dpnCount);
for (int i = 1; i <= dpnCount; i++) {
FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, false, batchSize,
- 0, 1, startTableId, endTableId);
+ 0, 1, startTableId, endTableId, false);
flowPusher.execute(task);
}
}
- @Override
- public long getFlowCount() {
- return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
- }
-
- @Override
- public int getReadOpStatus() {
- return BulkOMaticUtils.DEFUALT_STATUS;
- }
-
@Override
public int getWriteOpStatus() {
return writeOpStatus.get();
return taskCompletionTime.get();
}
- @Override
- public String getUnits() {
- return UNITS;
- }
-
private class FlowHandlerTask implements Runnable {
private final String dpId;
private final boolean add;
private final short startTableId;
private final short endTableId;
private AtomicInteger remainingTxReturn = new AtomicInteger(0);
+ private final boolean isCreateParents;
public FlowHandlerTask(final String dpId,
final int flowsPerDpn,
final int sleepMillis,
final int sleepAfter,
final short startTableId,
- final short endTableId){
+ final short endTableId,
+ final boolean isCreateParents){
this.dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + dpId;
this.add = add;
this.flowsPerDpn = flowsPerDpn;
this.sleepAfter = sleepAfter;
this.startTableId = startTableId;
this.endTableId = endTableId;
+ this.isCreateParents = isCreateParents;
remainingTxReturn.set(flowsPerDpn/batchSize);
}
private void addFlowToTx(WriteTransaction writeTransaction, String flowId, InstanceIdentifier<Flow> flowIid, Flow flow, Integer sourceIp, Short tableId){
if (add) {
LOG.trace("Adding flow for flowId: {}, flowIid: {}", flowId, flowIid);
- writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, true);
+ writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, isCreateParents);
} else {
LOG.trace("Deleting flow for flowId: {}, flowIid: {}", flowId, flowIid);
writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowIid);
package org.opendaylight.openflowplugin.applications.bulk.o.matic;
import com.google.common.base.Optional;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-
public class FlowWriterDirectOFRpc {
private static final Logger LOG = LoggerFactory.getLogger(FlowWriterDirectOFRpc.class);
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
public class FlowWriterSequential implements FlowCounterMBean {
private static final Logger LOG = LoggerFactory.getLogger(FlowWriterSequential.class);
private final DataBroker dataBroker;
protected int dpnCount;
private long startTime;
private AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
- private AtomicInteger countDpnWriteCompletion = new AtomicInteger(0);
- private AtomicLong taskCompletionTime = new AtomicLong(0);
- private static final String UNITS = "ns";
+ private AtomicInteger countDpnWriteCompletion = new AtomicInteger();
+ private AtomicLong taskCompletionTime = new AtomicLong();
public FlowWriterSequential(final DataBroker dataBroker, ExecutorService flowPusher) {
this.dataBroker = dataBroker;
}
public void addFlows(Integer dpnCount, Integer flowsPerDPN, int batchSize, int sleepMillis,
- short startTableId, short endTableId) {
+ short startTableId, short endTableId, boolean isCreateParents) {
LOG.info("Using Sequential implementation of Flow Writer.");
this.dpnCount = dpnCount;
countDpnWriteCompletion.set(dpnCount);
startTime = System.nanoTime();
for (int i = 1; i <= dpnCount; i++) {
FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, true, batchSize,
- sleepMillis, startTableId, endTableId);
+ sleepMillis, startTableId, endTableId, isCreateParents);
flowPusher.execute(task);
}
}
countDpnWriteCompletion.set(dpnCount);
for (int i = 1; i <= dpnCount; i++) {
FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, false, batchSize, 0,
- startTableId, endTableId);
+ startTableId, endTableId, false);
flowPusher.execute(task);
}
}
- @Override
- public long getFlowCount() {
- return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
- }
-
- @Override
- public int getReadOpStatus() {
- return BulkOMaticUtils.DEFUALT_STATUS;
- }
-
@Override
public int getWriteOpStatus() {
return writeOpStatus.get();
return taskCompletionTime.get();
}
- @Override
- public String getUnits() {
- return UNITS;
- }
-
private class FlowHandlerTask implements Runnable {
private final String dpId;
private final int flowsPerDpn;
private final int sleepMillis;
private final short startTableId;
private final short endTableId;
+ private final boolean isCreateParents;
public FlowHandlerTask(final String dpId,
final int flowsPerDpn,
final int batchSize,
int sleepMillis,
final short startTableId,
- final short endTableId){
+ final short endTableId,
+ final boolean isCreateParents){
this.dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + dpId;
this.add = add;
this.flowsPerDpn = flowsPerDpn;
this.sleepMillis = sleepMillis;
this.startTableId = startTableId;
this.endTableId = endTableId;
+ this.isCreateParents = isCreateParents;
}
@Override
Flow flow) {
if (add) {
LOG.trace("Adding flow for flowId: {}, flowIid: {}", flowId, flowIid);
- writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, true);
+ writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, isCreateParents);
} else {
LOG.trace("Deleting flow for flowId: {}, flowIid: {}", flowId, flowIid);
writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowIid);
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
public class FlowWriterTxChain implements FlowCounterMBean {
private static final Logger LOG = LoggerFactory.getLogger(FlowWriterTxChain.class);
private final DataBroker dataBroker;
private final ExecutorService flowPusher;
private long startTime;
private AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
- private AtomicInteger countDpnWriteCompletion = new AtomicInteger(0);
- private AtomicLong taskCompletionTime = new AtomicLong(0);
- private final String UNITS = "ns";
+ private AtomicInteger countDpnWriteCompletion = new AtomicInteger();
+ private AtomicLong taskCompletionTime = new AtomicLong();
public FlowWriterTxChain(final DataBroker dataBroker, ExecutorService flowPusher){
this.dataBroker = dataBroker;
}
public void addFlows(Integer dpnCount, Integer flowsPerDPN, int batchSize,
- int sleepMillis, int sleepAfter, short startTableId, short endTableId) {
+ int sleepMillis, int sleepAfter, short startTableId, short endTableId,
+ boolean isCreateParents) {
LOG.info("Using Transaction Chain Flow Writer Impl");
countDpnWriteCompletion.set(dpnCount);
startTime = System.nanoTime();
for (int i = 1; i <= dpnCount; i++) {
FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i),
- flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId);
+ flowsPerDPN, true, batchSize, sleepMillis, sleepAfter, startTableId, endTableId, isCreateParents);
flowPusher.execute(task);
}
}
countDpnWriteCompletion.set(dpnCount);
for (int i = 1; i <= dpnCount; i++) {
FlowHandlerTask task = new FlowHandlerTask(Integer.toString(i), flowsPerDPN, false, batchSize,
- 0, 1, startTableId, endTableId);
+ 0, 1, startTableId, endTableId, false);
flowPusher.execute(task);
}
}
- @Override
- public long getFlowCount() {
- return BulkOMaticUtils.DEFAULT_FLOW_COUNT;
- }
-
- @Override
- public int getReadOpStatus() {
- return BulkOMaticUtils.DEFUALT_STATUS;
- }
-
@Override
public int getWriteOpStatus() {
return writeOpStatus.get();
return taskCompletionTime.get();
}
- @Override
- public String getUnits() {
- return UNITS;
- }
-
private class FlowHandlerTask implements Runnable, TransactionChainListener {
private final String dpId;
private final boolean add;
private final int sleepMillis;
private final short startTableId;
private final short endTableId;
+ private final boolean isCreateParents;
private AtomicInteger remainingTxReturn = new AtomicInteger(0);
BindingTransactionChain txChain;
final int sleepMillis,
final int sleepAfter,
final short startTableId,
- final short endTableId){
+ final short endTableId,
+ final boolean isCreateParents){
this.dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + dpId;
this.add = add;
this.flowsPerDpn = flowsPerDpn;
this.sleepAfter = sleepAfter;
this.startTableId = startTableId;
this.endTableId = endTableId;
+ this.isCreateParents = isCreateParents;
remainingTxReturn.set(flowsPerDpn/batchSize);
}
private void writeTxToDs(WriteTransaction writeTransaction, String flowId, InstanceIdentifier<Flow> flowIid, Flow flow, Integer sourceIp, Short tableId){
if (add) {
LOG.trace("Adding flow for flowId: {}, flowIid: {}", flowId, flowIid);
- writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, true);
+ writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowIid, flow, isCreateParents);
} else {
LOG.trace("Deleting flow for flowId: {}, flowIid: {}", flowId, flowIid);
writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowIid);
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsDsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsRpcInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.SalBulkFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput.Operation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.ds.list.grouping.BulkFlowDsItem;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
flowTester.addFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
input.getBatchSize().intValue(), input.getSleepFor().intValue(),
input.getSleepAfter().intValue(), input.getStartTableId().shortValue(),
- input.getEndTableId().shortValue());
+ input.getEndTableId().shortValue(), input.isCreateParents());
} else {
flowTester.deleteFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
input.getBatchSize().intValue(), input.getStartTableId().shortValue(),
if (input.isIsAdd()){
flowTester.addFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
input.getBatchSize().intValue(), input.getSleepFor().intValue(),
- input.getStartTableId().shortValue(), input.getEndTableId().shortValue());
+ input.getStartTableId().shortValue(), input.getEndTableId().shortValue(),
+ input.isCreateParents());
} else {
flowTester.deleteFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
input.getBatchSize().intValue(), input.getStartTableId().shortValue(),
flowTester.addFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
input.getBatchSize().intValue(), input.getSleepFor().intValue(),
input.getSleepAfter().intValue(), input.getStartTableId().shortValue(),
- input.getEndTableId().shortValue());
+ input.getEndTableId().shortValue(), input.isCreateParents());
} else {
flowTester.deleteFlows(input.getDpnCount().intValue(), input.getFlowsPerDpn().intValue(),
input.getBatchSize().intValue(), input.getStartTableId().shortValue(),
return Futures.immediateFuture(rpcResultBuilder.build());
}
+ @Override
+ public Future<RpcResult<Void>> tableTest(final TableTestInput input) {
+ final TableWriter writer = new TableWriter(dataBroker, fjService);
+ flowCounterBeanImpl.setWriter(writer);
+ switch (input.getOperation()) {
+ case Add:
+ writer.addTables(input.getDpnCount().intValue(),
+ input.getStartTableId().shortValue(), input.getEndTableId().shortValue());
+ break;
+ case Delete:
+ writer.deleteTables(input.getDpnCount().intValue(),
+ input.getStartTableId().shortValue(), input.getEndTableId().shortValue());
+ break;
+ default:
+ RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.failed();
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+ RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.success();
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
@Override
public Future<RpcResult<Void>> flowRpcAddMultiple(FlowRpcAddMultipleInput input) {
FlowWriterDirectOFRpc flowTesterRPC = new FlowWriterDirectOFRpc(dataBroker, flowService, fjService);
--- /dev/null
+/*
+ * Copyright (c) 2017 Ericsson 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.bulk.o.matic;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+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.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TableWriter implements FlowCounterMBean {
+ private final Logger LOG = LoggerFactory.getLogger(TableWriter.class);
+
+ private final AtomicInteger writeOpStatus = new AtomicInteger(FlowCounter.OperationStatus.INIT.status());
+ private final AtomicLong taskCompletionTime = new AtomicLong(BulkOMaticUtils.DEFAULT_COMPLETION_TIME);
+ private final AtomicInteger successfulWrites = new AtomicInteger();
+ private final AtomicInteger failedWrites = new AtomicInteger();
+ private final DataBroker dataBroker;
+ private final ExecutorService tablePusher;
+
+ public TableWriter(final DataBroker dataBroker, final ExecutorService tablePusher) {
+ this.dataBroker = dataBroker;
+ this.tablePusher = tablePusher;
+ }
+
+ public void addTables(final int dpnCount, final short startTableId, final short endTableId) {
+ LOG.info("Starting to add tables: {} to {} on each of {}", startTableId, endTableId, dpnCount);
+ TableHandlerTask task = new TableHandlerTask(dpnCount, startTableId, endTableId, true);
+ tablePusher.execute(task);
+ }
+
+ public void deleteTables(int dpnCount, short startTableId, short endTableId) {
+ LOG.info("Starting to delete tables: {} to {} on each of {}", startTableId, endTableId, dpnCount);
+ TableHandlerTask task = new TableHandlerTask(dpnCount, startTableId, endTableId, false);
+ tablePusher.execute(task);
+ }
+
+ @Override
+ public int getWriteOpStatus() {
+ return writeOpStatus.get();
+ }
+
+ @Override
+ public long getTaskCompletionTime() {
+ return taskCompletionTime.get();
+ }
+
+ @Override
+ public long getTableCount() {
+ return successfulWrites.get();
+ }
+
+ private class TableHandlerTask implements Runnable {
+
+ private short startTableId;
+ private short endTableId;
+ private int dpnCount;
+ private boolean isAdd;
+
+ public TableHandlerTask(int dpnCount, short startTableId, short endTableId, boolean isAdd) {
+ this.dpnCount = dpnCount;
+ this.startTableId = startTableId;
+ this.endTableId = endTableId;
+ this.isAdd = isAdd;
+ }
+
+ @Override
+ public void run() {
+ writeOpStatus.set(FlowCounter.OperationStatus.IN_PROGRESS.status());
+ int totalTables = dpnCount * (endTableId - startTableId + 1);
+
+ for (int dpn = 1; dpn <= dpnCount; dpn++) {
+ String dpId = BulkOMaticUtils.DEVICE_TYPE_PREFIX + String.valueOf(dpn);
+ for (short tableId = startTableId; tableId <= endTableId; tableId++) {
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ Table table = new TableBuilder().setKey(new TableKey(tableId))
+ .setId(tableId)
+ .build();
+ InstanceIdentifier<Table> tableIId = BulkOMaticUtils.getTableId(tableId, dpId);
+
+ if (isAdd) {
+ wtx.put(LogicalDatastoreType.CONFIGURATION, tableIId, table, true);
+ } else {
+ wtx.delete(LogicalDatastoreType.CONFIGURATION, tableIId);
+ }
+
+ CheckedFuture<Void, TransactionCommitFailedException> future = wtx.submit();
+
+ Futures.addCallback(future, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(@Nullable Void v) {
+ if (successfulWrites.incrementAndGet() == totalTables) {
+ if (failedWrites.get() > 0) {
+ writeOpStatus.set(FlowCounter.OperationStatus.FAILURE.status());
+ } else {
+ writeOpStatus.set(FlowCounter.OperationStatus.SUCCESS.status());
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.error("Table addition Failed. Error: {}", throwable);
+ if (failedWrites.incrementAndGet() == totalTables) {
+ writeOpStatus.set(FlowCounter.OperationStatus.FAILURE.status());
+ }
+ }
+ });
+ }
+ }
+ }
+ }
+}
}
rpc flow-test {
- input {
- leaf is-add {
- type boolean;
- mandatory true;
- status current;
- description "Add or delete";
- }
- leaf dpn-count {
- type uint32;
- mandatory true;
- status current;
- description "No of DPNs";
- }
- leaf flows-per-dpn {
- type uint32;
- mandatory true;
- status current;
- description "Flows to be pushed per DPN";
- }
- leaf start-table-id {
- type uint32;
- mandatory true;
- status current;
- description "Start adding flows from this table id";
- }
- leaf end-table-id {
- type uint32;
- mandatory true;
- status current;
- description "The last table to add flows to and then wrap around";
- }
- leaf batch-size {
- type uint32;
- mandatory true;
- status current;
- description "batch size";
- }
- leaf seq {
- type boolean;
- mandatory true;
- status current;
- description "Whether to use sequential or concurrent writer";
- }
- leaf tx-chain {
- type boolean;
- mandatory true;
- status current;
- description "Whether to use PingPong Broker or not. seq is ignored.";
- }
- leaf sleep-for {
- type uint32;
- mandatory true;
- status current;
- description "sleep for the given milliseconds";
- }
- leaf sleep-after {
- type uint32;
- mandatory true;
- status current;
- description "Sleep after the given number of iterations. Will be used in the concurrent case only";
- }
- }
+ input {
+ leaf create-parents {
+ type boolean;
+ mandatory true;
+ status current;
+ description "Create parents if doesn't exist";
+ }
+ leaf is-add {
+ type boolean;
+ mandatory true;
+ status current;
+ description "Add or delete";
+ }
+ leaf dpn-count {
+ type uint32;
+ mandatory true;
+ status current;
+ description "No of DPNs";
+ }
+ leaf flows-per-dpn {
+ type uint32;
+ mandatory true;
+ status current;
+ description "Flows to be pushed per DPN";
+ }
+ leaf start-table-id {
+ type uint32;
+ mandatory true;
+ status current;
+ description "Start adding flows from this table id";
+ }
+ leaf end-table-id {
+ type uint32;
+ mandatory true;
+ status current;
+ description "The last table to add flows to and then wrap around";
+ }
+ leaf batch-size {
+ type uint32;
+ mandatory true;
+ status current;
+ description "batch size";
+ }
+ leaf seq {
+ type boolean;
+ mandatory true;
+ status current;
+ description "Whether to use sequential or concurrent writer";
+ }
+ leaf tx-chain {
+ type boolean;
+ mandatory true;
+ status current;
+ description "Whether to use PingPong Broker or not. seq is ignored.";
+ }
+ leaf sleep-for {
+ type uint32;
+ mandatory true;
+ status current;
+ description "sleep for the given milliseconds";
+ }
+ leaf sleep-after {
+ type uint32;
+ mandatory true;
+ status current;
+ description "Sleep after the given number of iterations. Will be used in the concurrent case only";
+ }
+ }
}
rpc read-flow-test {
}
}
}
+
+ rpc table-test {
+ input {
+ leaf operation {
+ type enumeration {
+ enum add;
+ enum delete;
+ }
+ status current;
+ description "Type of operation, add or delete";
+ }
+
+ leaf dpn-count {
+ type uint32;
+ mandatory true;
+ status current;
+ description "Total number of dpns to add these tables";
+ }
+
+ leaf start-table-id {
+ type uint32;
+ mandatory true;
+ status current;
+ description "Starting table id";
+ }
+
+ leaf end-table-id {
+ type uint32;
+ mandatory true;
+ status current;
+ description "Last table id";
+ }
+ }
+ }
}
}
@Test
public void testAddFlows() throws Exception {
- flowWriterConcurrent.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1);
+ flowWriterConcurrent.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1, true);
Mockito.verify(wTx, Mockito.times(FLOWS_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
}
}
@Test
public void testAddFlows() throws Exception {
- flowWriterSequential.addFlows(1, FLOWS_PER_DPN, 10, 10, (short)0, (short)1);
+ flowWriterSequential.addFlows(1, FLOWS_PER_DPN, 10, 10, (short)0, (short)1, true);
Mockito.verify(wTx, Mockito.times(FLOWS_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
}
}
@Test
public void testAddFlows() throws Exception {
- flowWriterTxChain.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1);
+ flowWriterTxChain.addFlows(1, FLOWS_PER_DPN, 10, 10, 10, (short)0, (short)1, true);
Mockito.verify(wTx, Mockito.times(FLOWS_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsDsInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsRpcInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsRpcInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInput.Operation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.TableTestInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.ds.list.grouping.BulkFlowDsItem;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.ds.list.grouping.BulkFlowDsItemBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.list.grouping.BulkFlowItem;
.setSleepAfter(20L)
.setSleepFor(1L)
.setStartTableId(1L)
- .setTxChain(true);
+ .setTxChain(true)
+ .setCreateParents(true);
FlowTestInput flowTestInput = flowTestInputBuilder.build();
Assert.assertTrue(salBulkFlowService.flowRpcAddMultiple(flowRpcAddMultipleInput).get().isSuccessful());
}
+
+ @Test
+ public void testTableTest() throws Exception {
+ final TableTestInputBuilder tableTestInputBuilder = new TableTestInputBuilder()
+ .setStartTableId(0L)
+ .setEndTableId(99L)
+ .setDpnCount(1L)
+ .setOperation(Operation.Add);
+
+ TableTestInput tableTestInput = tableTestInputBuilder.build();
+
+ Assert.assertTrue(salBulkFlowService.tableTest(tableTestInput).get().isSuccessful());
+
+ tableTestInputBuilder.setOperation(Operation.Delete);
+ tableTestInput = tableTestInputBuilder.build();
+
+ Assert.assertTrue(salBulkFlowService.tableTest(tableTestInput).get().isSuccessful());
+ }
}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2017 Cisco 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.bulk.o.matic;
+
+import static org.mockito.Mockito.doReturn;
+
+import com.google.common.util.concurrent.Futures;
+import java.util.concurrent.ExecutorService;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test for {@link FlowWriterSequential}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TableWriterTest {
+ private static final Logger LOG = LoggerFactory.getLogger(TableWriterTest.class);
+
+ private static final int TABLES_PER_DPN = 100;
+ private static final int DPN_COUNT = 1;
+ private static final short START_TABLE_ID = 0;
+ private static final short END_TABLE_ID = 99;
+
+ @Mock
+ private DataBroker mockDataBroker;
+ @Mock
+ private ExecutorService mockTablePusher;
+ @Mock
+ private WriteTransaction wTx;
+
+ private TableWriter tableWriter;
+
+ @Before
+ public void setUp() throws Exception {
+
+ doReturn(wTx).when(mockDataBroker).newWriteOnlyTransaction();
+ Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
+
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ ((Runnable)invocation.getArguments()[0]).run();
+ return null;
+ }
+ }).when(mockTablePusher).execute(Matchers.<Runnable>any());
+
+ tableWriter = new TableWriter(mockDataBroker, mockTablePusher);
+ }
+ @Test
+ public void testAddTables() throws Exception {
+ tableWriter.addTables(DPN_COUNT, START_TABLE_ID, END_TABLE_ID);
+ Mockito.verify(wTx, Mockito.times(TABLES_PER_DPN)).put(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any(), Matchers.<DataObject>any(), Matchers.anyBoolean());
+ }
+
+ @Test
+ public void testDeleteTables() throws Exception {
+ tableWriter.deleteTables(DPN_COUNT, START_TABLE_ID, END_TABLE_ID);
+ Mockito.verify(wTx, Mockito.times(TABLES_PER_DPN)).delete(Matchers.<LogicalDatastoreType>any(), Matchers.<InstanceIdentifier<DataObject>>any());
+ }
+}
\ No newline at end of file
builder.setPortNumber(updated.getPortNumber());
builder.setState(updated.getState());
builder.setSupported(updated.getSupported());
+ builder.setReason(updated.getReason());
return builder.build();
}
<artifactId>openflowplugin-karaf</artifactId>
<version>0.5.0-SNAPSHOT</version>
<packaging>pom</packaging>
- <prerequisites>
- <maven>3.0</maven>
- </prerequisites>
<properties>
<openflowplugin.version>0.5.0-SNAPSHOT</openflowplugin.version>
import org.opendaylight.openflowjava.nx.codec.match.ArpTpaCodec;
import org.opendaylight.openflowjava.nx.codec.match.CtStateCodec;
import org.opendaylight.openflowjava.nx.codec.match.CtZoneCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EncapEthDstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EncapEthSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EncapEthTypeCodec;
import org.opendaylight.openflowjava.nx.codec.match.EthDstCodec;
import org.opendaylight.openflowjava.nx.codec.match.EthSrcCodec;
import org.opendaylight.openflowjava.nx.codec.match.EthTypeCodec;
import org.opendaylight.openflowjava.nx.codec.match.IcmpTypeCodec;
-import org.opendaylight.openflowjava.nx.codec.match.IpSrcCodec;
-import org.opendaylight.openflowjava.nx.codec.match.IpDstCodec;
import org.opendaylight.openflowjava.nx.codec.match.InPortCodec;
+import org.opendaylight.openflowjava.nx.codec.match.IpDstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.IpSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.Ipv6DstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.Ipv6SrcCodec;
import org.opendaylight.openflowjava.nx.codec.match.MplsLabelCodec;
+import org.opendaylight.openflowjava.nx.codec.match.NshMdtypeCodec;
+import org.opendaylight.openflowjava.nx.codec.match.NshNpCodec;
import org.opendaylight.openflowjava.nx.codec.match.Nshc1Codec;
import org.opendaylight.openflowjava.nx.codec.match.Nshc2Codec;
import org.opendaylight.openflowjava.nx.codec.match.Nshc3Codec;
import org.opendaylight.openflowjava.nx.codec.match.Reg7Codec;
import org.opendaylight.openflowjava.nx.codec.match.TcpDstCodec;
import org.opendaylight.openflowjava.nx.codec.match.TcpSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.TunGpeNpCodec;
import org.opendaylight.openflowjava.nx.codec.match.TunIdCodec;
import org.opendaylight.openflowjava.nx.codec.match.TunIpv4DstCodec;
import org.opendaylight.openflowjava.nx.codec.match.TunIpv4SrcCodec;
-import org.opendaylight.openflowjava.nx.codec.match.EncapEthTypeCodec;
-import org.opendaylight.openflowjava.nx.codec.match.EncapEthSrcCodec;
-import org.opendaylight.openflowjava.nx.codec.match.EncapEthDstCodec;
-import org.opendaylight.openflowjava.nx.codec.match.NshMdtypeCodec;
-import org.opendaylight.openflowjava.nx.codec.match.NshNpCodec;
-import org.opendaylight.openflowjava.nx.codec.match.TunGpeNpCodec;
import org.opendaylight.openflowjava.nx.codec.match.UdpDstCodec;
import org.opendaylight.openflowjava.nx.codec.match.UdpSrcCodec;
public static final CtZoneCodec CT_ZONE_CODEC = new CtZoneCodec();
public static final IpSrcCodec IP_SRC_CODEC = new IpSrcCodec();
public static final IpDstCodec IP_DST_CODEC = new IpDstCodec();
+ public static final Ipv6SrcCodec IPV6_SRC_CODEC = new Ipv6SrcCodec();
+ public static final Ipv6DstCodec IPV6_DST_CODEC = new Ipv6DstCodec();
public static final IcmpTypeCodec ICMP_TYPE_CODEC = new IcmpTypeCodec();
}
outBuffer.writeShort(action.getNxActionConntrack().getConntrackZone().shortValue());
outBuffer.writeByte(action.getNxActionConntrack().getRecircTable().byteValue());
outBuffer.writeZero(5);
- serializeCtAction(outBuffer,action, length);
+ serializeCtAction(outBuffer,action);
}
private int getActionLength(final ActionConntrack action) {
}
for (CtActions ctActions : ctActionsList) {
if (ctActions.getOfpactActions() instanceof NxActionNatCase) {
- length += NX_NAT_LENGTH;
NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
NxActionNat natAction = nxActionNatCase.getNxActionNat();
- short rangePresent = natAction.getRangePresent().shortValue();
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
- length += INT_LENGTH;
+ int natLength = getNatActionLength(natAction);
+ int pad = 8 - (natLength % 8);
+ length += natLength + pad;
}
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
- length += INT_LENGTH;
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
- length += SHORT_LENGTH;
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
- length += SHORT_LENGTH;
- }
- }
}
LOG.trace("ActionLength :conntrack: length {}",length);
return length;
}
- private void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action, final int length) {
+ private int getNatActionLength(final NxActionNat natAction) {
+ int natLength = NX_NAT_LENGTH;
+ short rangePresent = natAction.getRangePresent().shortValue();
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
+ natLength += INT_LENGTH;
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
+ natLength += INT_LENGTH;
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
+ natLength += SHORT_LENGTH;
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
+ natLength += SHORT_LENGTH;
+ }
+ return natLength;
+
+ }
+
+ private void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action) {
List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
if (ctActionsList != null) {
for (CtActions ctActions : ctActionsList) {
if (ctActions.getOfpactActions() instanceof NxActionNatCase){
NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
NxActionNat natAction = nxActionNatCase.getNxActionNat();
- int pad = length % 8;
- serializeHeader(length + pad, NXAST_NAT_SUBTYPE, outBuffer);
+ int natLength = getNatActionLength(natAction);
+ int pad = 8 - (natLength % 8);
+ serializeHeader(natLength + pad, NXAST_NAT_SUBTYPE, outBuffer);
outBuffer.writeZero(2);
outBuffer.writeShort(natAction.getFlags().shortValue());
short rangePresent = natAction.getRangePresent().shortValue();
nxActionConntrackBuilder.setRecircTable(message.readUnsignedByte());
message.skipBytes(5);
if (length > CT_LENGTH) {
- dserializeCtAction(message,nxActionConntrackBuilder);
+ dserializeCtAction(message,nxActionConntrackBuilder, length - CT_LENGTH);
}
ActionBuilder actionBuilder = new ActionBuilder();
actionBuilder.setExperimenterId(getExperimenterId());
return actionBuilder.build();
}
- private void dserializeCtAction(final ByteBuf message, final NxActionConntrackBuilder nxActionConntrackBuilder) {
- deserializeCtHeader(message);
-
- NxActionNatBuilder nxActionNatBuilder = new NxActionNatBuilder();
- message.skipBytes(2);
- nxActionNatBuilder.setFlags(message.readUnsignedShort());
-
- int rangePresent = message.readUnsignedShort();
- nxActionNatBuilder.setRangePresent(rangePresent);
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
- InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
- nxActionNatBuilder.setIpAddressMin(new IpAddress(address.getHostAddress().toCharArray()));
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
- InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
- nxActionNatBuilder.setIpAddressMax(new IpAddress(address.getHostAddress().toCharArray()));
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
- nxActionNatBuilder.setPortMin(message.readUnsignedShort());
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
- nxActionNatBuilder.setPortMax(message.readUnsignedShort());
- }
- NxActionNatCaseBuilder caseBuilder = new NxActionNatCaseBuilder();
- caseBuilder.setNxActionNat(nxActionNatBuilder.build());
- CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
- ctActionsBuilder.setOfpactActions(caseBuilder.build());
+ private void dserializeCtAction(final ByteBuf message, final NxActionConntrackBuilder nxActionConntrackBuilder,
+ int ctActionsLength) {
List<CtActions> ctActionsList = new ArrayList<>();
- ctActionsList.add(ctActionsBuilder.build());
+ while (ctActionsLength > 0){
+ int startIndex = message.readerIndex();
+ int length = deserializeCtHeader(message);
+ ctActionsLength = ctActionsLength - length;
+ NxActionNatBuilder nxActionNatBuilder = new NxActionNatBuilder();
+ message.skipBytes(2);
+ nxActionNatBuilder.setFlags(message.readUnsignedShort());
+
+ int rangePresent = message.readUnsignedShort();
+ nxActionNatBuilder.setRangePresent(rangePresent);
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
+ InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
+ nxActionNatBuilder.setIpAddressMin(new IpAddress(address.getHostAddress().toCharArray()));
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
+ InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
+ nxActionNatBuilder.setIpAddressMax(new IpAddress(address.getHostAddress().toCharArray()));
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
+ nxActionNatBuilder.setPortMin(message.readUnsignedShort());
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
+ nxActionNatBuilder.setPortMax(message.readUnsignedShort());
+ }
+ NxActionNatCaseBuilder caseBuilder = new NxActionNatCaseBuilder();
+ caseBuilder.setNxActionNat(nxActionNatBuilder.build());
+ CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
+ ctActionsBuilder.setOfpactActions(caseBuilder.build());
+ ctActionsList.add(ctActionsBuilder.build());
+ int pad = length - (message.readerIndex() - startIndex);
+ message.skipBytes(pad);
+ }
nxActionConntrackBuilder.setCtActions(ctActionsList);
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Red Hat, 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.openflowjava.nx.codec.match;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.dst.grouping.IpDstValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValueBuilder;
+
+/**
+ * @author Sridhar Gaddam (sgaddam@redhat.com)
+ */
+public class Ipv6DstCodec extends AbstractMatchCodec {
+
+ private static final int VALUE_LENGTH = 16;
+ private static final int NXM_FIELD_CODE = 20;
+ public static final MatchEntrySerializerKey<Nxm1Class, NxmOfIpDst> SERIALIZER_KEY = new MatchEntrySerializerKey<>(
+ EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmOfIpDst.class);
+ public static final MatchEntryDeserializerKey DESERIALIZER_KEY = new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, NXM_FIELD_CODE);
+
+
+ @Override
+ public MatchEntry deserialize(ByteBuf message) {
+ MatchEntryBuilder matchEntriesBuilder = deserializeHeader(message);
+ IpDstCaseValueBuilder caseBuilder = new IpDstCaseValueBuilder();
+ caseBuilder.setIpDstValues(new IpDstValuesBuilder().setValue(message.readUnsignedInt()).build());
+ matchEntriesBuilder.setMatchEntryValue(caseBuilder.build());
+ return matchEntriesBuilder.build();
+ }
+
+ @Override
+ public void serialize(MatchEntry input, ByteBuf outBuffer) {
+ serializeHeader(input, outBuffer);
+ IpDstCaseValue ipDstCase = ((IpDstCaseValue) input.getMatchEntryValue());
+ outBuffer.writeInt(ipDstCase.getIpDstValues().getValue().intValue());
+ }
+
+ @Override
+ public int getNxmFieldCode() {
+ return NXM_FIELD_CODE;
+ }
+
+ @Override
+ public int getOxmClassCode() {
+ return OxmMatchConstants.NXM_1_CLASS;
+ }
+
+ @Override
+ public int getValueLength() {
+ return VALUE_LENGTH;
+ }
+
+ @Override
+ public Class<? extends MatchField> getNxmField() {
+ return NxmOfIpDst.class;
+ }
+
+ @Override
+ public Class<? extends OxmClassBase> getOxmClass() {
+ return Nxm1Class.class;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Red Hat, 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.openflowjava.nx.codec.match;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.src.grouping.IpSrcValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValueBuilder;
+
+/**
+ * @author Sridhar Gaddam (sgaddam@redhat.com)
+ */
+public class Ipv6SrcCodec extends AbstractMatchCodec {
+
+ private static final int VALUE_LENGTH = 16;
+ private static final int NXM_FIELD_CODE = 19;
+ public static final MatchEntrySerializerKey<Nxm1Class, NxmOfIpSrc> SERIALIZER_KEY = new MatchEntrySerializerKey<>(
+ EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmOfIpSrc.class);
+ public static final MatchEntryDeserializerKey DESERIALIZER_KEY = new MatchEntryDeserializerKey(
+ EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, NXM_FIELD_CODE);
+
+
+ @Override
+ public MatchEntry deserialize(ByteBuf message) {
+ MatchEntryBuilder matchEntriesBuilder = deserializeHeader(message);
+ IpSrcCaseValueBuilder caseBuilder = new IpSrcCaseValueBuilder();
+ caseBuilder.setIpSrcValues(new IpSrcValuesBuilder().setValue(message.readUnsignedInt()).build());
+ matchEntriesBuilder.setMatchEntryValue(caseBuilder.build());
+ return matchEntriesBuilder.build();
+ }
+
+ @Override
+ public void serialize(MatchEntry input, ByteBuf outBuffer) {
+ serializeHeader(input, outBuffer);
+ IpSrcCaseValue ipSrcCase = ((IpSrcCaseValue) input.getMatchEntryValue());
+ outBuffer.writeInt(ipSrcCase.getIpSrcValues().getValue().intValue());
+ }
+
+ @Override
+ public int getNxmFieldCode() {
+ return NXM_FIELD_CODE;
+ }
+
+ @Override
+ public int getOxmClassCode() {
+ return OxmMatchConstants.NXM_1_CLASS;
+ }
+
+ @Override
+ public int getValueLength() {
+ return VALUE_LENGTH;
+ }
+
+ @Override
+ public Class<? extends MatchField> getNxmField() {
+ return NxmOfIpSrc.class;
+ }
+
+ @Override
+ public Class<? extends OxmClassBase> getOxmClass() {
+ return Nxm1Class.class;
+ }
+
+}
private final int length = 24;
private final byte nxastConntrackSubtype = 35;
- private final int nxNatLength = 32;
+ private final int nxNatLengthAction1 = 32;
+ private final int nxNatLengthAction2 = 24;
private final byte nxastNatSubtype = 36;
@Before
action = createAction();
conntrackCodec.serialize(action, buffer);
- Assert.assertEquals(56, buffer.readableBytes());
+ Assert.assertEquals(length + nxNatLengthAction1 + nxNatLengthAction2, buffer.readableBytes());
Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort());
- Assert.assertEquals(length + nxNatLength, buffer.readUnsignedShort());
+ Assert.assertEquals(length + nxNatLengthAction1 + nxNatLengthAction2, buffer.readUnsignedShort());
Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt());
Assert.assertEquals(nxastConntrackSubtype, buffer.readUnsignedShort());
Assert.assertEquals(1, buffer.readUnsignedShort());
Assert.assertEquals(4, buffer.readByte());
buffer.skipBytes(5);
Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort());
- Assert.assertEquals(nxNatLength, buffer.readUnsignedShort());
+ Assert.assertEquals(nxNatLengthAction1, buffer.readUnsignedShort());
Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt());
Assert.assertEquals(nxastNatSubtype, buffer.readUnsignedShort());
buffer.skipBytes(2);
Assert.assertEquals(3000, buffer.readUnsignedShort());
Assert.assertEquals(4000, buffer.readUnsignedShort());
buffer.skipBytes(4);
+ Assert.assertEquals(EncodeConstants.EXPERIMENTER_VALUE, buffer.readUnsignedShort());
+ Assert.assertEquals(nxNatLengthAction2, buffer.readUnsignedShort());
+ Assert.assertEquals(NiciraConstants.NX_VENDOR_ID.intValue(), buffer.readUnsignedInt());
+ Assert.assertEquals(nxastNatSubtype, buffer.readUnsignedShort());
+ buffer.skipBytes(2);
+ Assert.assertEquals(5, buffer.readUnsignedShort());
+ Assert.assertEquals(0x21, buffer.readUnsignedShort());
+ Assert.assertEquals(3232235520L, buffer.readUnsignedInt());
+ Assert.assertEquals(4000, buffer.readUnsignedShort());
+ buffer.skipBytes(2);
}
@Test
Assert.assertEquals("192.168.10.0", natAction.getIpAddressMax().getIpv4Address().getValue());
Assert.assertEquals(3000, natAction.getPortMin().shortValue());
Assert.assertEquals(4000, natAction.getPortMax().shortValue());
-
+ nxActionNatCase = (NxActionNatCase) ctActions.get(1).getOfpactActions();
+ natAction = nxActionNatCase.getNxActionNat();
+ Assert.assertEquals(5, natAction.getFlags().shortValue());
+ Assert.assertEquals(0x21, natAction.getRangePresent().intValue());
+ Assert.assertEquals("192.168.0.0", natAction.getIpAddressMin().getIpv4Address().getValue());
+ Assert.assertEquals(4000, natAction.getPortMax().shortValue());
}
@Test
ctActionsBuilder.setOfpactActions(nxActionNatCaseBuilder.build());
List<CtActions> ctActionsList = new ArrayList<>();
ctActionsList.add(ctActionsBuilder.build());
+ nxActionNatBuilder = new NxActionNatBuilder();
+ nxActionNatBuilder.setFlags(5);
+ nxActionNatBuilder.setRangePresent(0x21);
+ nxActionNatBuilder.setIpAddressMin(new IpAddress("192.168.0.0".toCharArray()));
+ nxActionNatBuilder.setPortMax(4000);
+ nxActionNatCaseBuilder = new NxActionNatCaseBuilder();
+ nxActionNatCaseBuilder.setNxActionNat(nxActionNatBuilder.build());
+ ctActionsBuilder = new CtActionsBuilder();
+ ctActionsBuilder.setOfpactActions(nxActionNatCaseBuilder.build());
+ ctActionsList.add(ctActionsBuilder.build());
nxActionConntrackBuilder.setCtActions(ctActionsList);
ExperimenterId experimenterId = new ExperimenterId(NiciraConstants.NX_VENDOR_ID);
private void createBufer(ByteBuf message) {
message.writeShort(EncodeConstants.EXPERIMENTER_VALUE);
- message.writeShort(length + nxastNatSubtype);
+ message.writeShort(length + nxNatLengthAction1 + nxNatLengthAction2);
message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue());
message.writeShort(nxastConntrackSubtype);
//FLAG = 1
//ADDS 5 empty bytes
message.writeZero(5);
message.writeShort(EncodeConstants.EXPERIMENTER_VALUE);
- message.writeShort(nxNatLength);
+ message.writeShort(nxNatLengthAction1);
message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue());
message.writeShort(nxastNatSubtype);
message.writeZero(2);
message.writeShort(3000);
//PORT MAX
message.writeShort(4000);
+ message.writeZero(4);
+
+ message.writeShort(EncodeConstants.EXPERIMENTER_VALUE);
+ message.writeShort(nxNatLengthAction2);
+ message.writeInt(NiciraConstants.NX_VENDOR_ID.intValue());
+ message.writeShort(nxastNatSubtype);
+ message.writeZero(2);
+ //NAT FLAG
+ message.writeShort(5);
+ //RANGE PRESENT
+ message.writeShort(0x21);
+ //IP ADDRESS MIN
+ message.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(new Ipv4Address("192.168.0.0")));
+ //PORT MAX
+ message.writeShort(4000);
+ message.writeZero(2);
}
private void createBuferWIthoutCtAction(ByteBuf message) {
--- /dev/null
+/**
+ * Copyright (c) 2017 Red Hat, 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.openflowjava.nx.codec.match;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.dst.grouping.IpDstValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpDstCaseValueBuilder;
+
+public class Ipv6DstCodecTest {
+
+ Ipv6DstCodec ipv6DstCodec;
+ ByteBuf buffer;
+ MatchEntry input;
+
+ private static final int VALUE_LENGTH = 16;
+ private static final int NXM_FIELD_CODE = 20;
+
+ @Before
+ public void setUp() {
+ ipv6DstCodec = new Ipv6DstCodec();
+ buffer = ByteBufAllocator.DEFAULT.buffer();
+ }
+
+ @Test
+ public void serializeTest() {
+ input = createMatchEntry();
+ ipv6DstCodec.serialize(input, buffer);
+
+ assertEquals(OxmMatchConstants.NXM_1_CLASS, buffer.readUnsignedShort());
+ short fieldMask = buffer.readUnsignedByte();
+ assertEquals(NXM_FIELD_CODE, fieldMask >> 1);
+ assertEquals(0, fieldMask & 1);
+ assertEquals(VALUE_LENGTH, buffer.readUnsignedByte());
+ assertEquals(1, buffer.readUnsignedInt());
+ }
+
+ @Test
+ public void deserializeTest() {
+ createBuffer(buffer);
+
+ input = ipv6DstCodec.deserialize(buffer);
+
+ IpDstCaseValue result = ((IpDstCaseValue) input.getMatchEntryValue());
+
+ assertEquals(Nxm1Class.class, input.getOxmClass());
+ assertEquals(NxmOfIpDst.class, input.getOxmMatchField());
+ assertEquals(false, input.isHasMask());
+ assertEquals(2, result.getIpDstValues().getValue().intValue());
+ }
+
+
+ private MatchEntry createMatchEntry() {
+ MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+ IpDstCaseValueBuilder caseBuilder = new IpDstCaseValueBuilder();
+ IpDstValuesBuilder valuesBuilder = new IpDstValuesBuilder();
+
+ matchEntryBuilder.setOxmClass(Nxm1Class.class);
+ matchEntryBuilder.setOxmMatchField(NxmOfIpDst.class);
+ matchEntryBuilder.setHasMask(false);
+
+ valuesBuilder.setValue((long)1);
+
+ caseBuilder.setIpDstValues(valuesBuilder.build());
+ matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
+ return matchEntryBuilder.build();
+ }
+
+ private void createBuffer(ByteBuf message) {
+ message.writeShort(OxmMatchConstants.NXM_1_CLASS);
+
+ int fieldMask = (NXM_FIELD_CODE << 1);
+ message.writeByte(fieldMask);
+ message.writeByte(VALUE_LENGTH);
+ message.writeInt(2);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2017 Red Hat, 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.openflowjava.nx.codec.match;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfIpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.ofj.nxm.of.match.ip.src.grouping.IpSrcValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.IpSrcCaseValueBuilder;
+
+public class Ipv6SrcCodecTest {
+
+ Ipv6SrcCodec ipv6SrcCodec;
+ ByteBuf buffer;
+ MatchEntry input;
+
+ private static final int VALUE_LENGTH = 16;
+ private static final int NXM_FIELD_CODE = 19;
+
+ @Before
+ public void setUp() {
+ ipv6SrcCodec = new Ipv6SrcCodec();
+ buffer = ByteBufAllocator.DEFAULT.buffer();
+ }
+
+ @Test
+ public void serializeTest() {
+ input = createMatchEntry();
+ ipv6SrcCodec.serialize(input, buffer);
+
+ assertEquals(OxmMatchConstants.NXM_1_CLASS, buffer.readUnsignedShort());
+ short fieldMask = buffer.readUnsignedByte();
+ assertEquals(NXM_FIELD_CODE, fieldMask >> 1);
+ assertEquals(0, fieldMask & 1);
+ assertEquals(VALUE_LENGTH, buffer.readUnsignedByte());
+ assertEquals(1, buffer.readUnsignedInt());
+ }
+
+ @Test
+ public void deserializeTest() {
+ createBuffer(buffer);
+
+ input = ipv6SrcCodec.deserialize(buffer);
+
+ IpSrcCaseValue result = ((IpSrcCaseValue) input.getMatchEntryValue());
+
+ assertEquals(Nxm1Class.class, input.getOxmClass());
+ assertEquals(NxmOfIpSrc.class, input.getOxmMatchField());
+ assertEquals(false, input.isHasMask());
+ assertEquals(2, result.getIpSrcValues().getValue().intValue());
+ }
+
+ private MatchEntry createMatchEntry() {
+ MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+ IpSrcCaseValueBuilder caseBuilder = new IpSrcCaseValueBuilder();
+ IpSrcValuesBuilder valuesBuilder = new IpSrcValuesBuilder();
+
+ matchEntryBuilder.setOxmClass(Nxm1Class.class);
+ matchEntryBuilder.setOxmMatchField(NxmOfIpSrc.class);
+ matchEntryBuilder.setHasMask(false);
+
+ valuesBuilder.setValue((long)1);
+
+ caseBuilder.setIpSrcValues(valuesBuilder.build());
+ matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
+ return matchEntryBuilder.build();
+ }
+
+ private void createBuffer(ByteBuf message) {
+ message.writeShort(OxmMatchConstants.NXM_1_CLASS);
+
+ int fieldMask = (NXM_FIELD_CODE << 1);
+ message.writeByte(fieldMask);
+ message.writeByte(VALUE_LENGTH);
+ message.writeInt(2);
+ }
+
+}
*/
package org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.action;
+import com.google.common.base.Preconditions;
import org.opendaylight.openflowjava.nx.NiciraMatchCodecs;
import org.opendaylight.openflowjava.nx.codec.match.NxmHeader;
import org.opendaylight.openflowplugin.extension.api.ConvertorActionFromOFJava;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpShaCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6DstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6SrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxIpv6SrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc1Case;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc1CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc2Case;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNsiCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNspCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNspCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthSrcCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxEncapEthDstCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshMdtypeCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshNpCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxOfInPortCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunGpeNpCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpShaCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpThaCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpThaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6DstCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6SrcCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxIpv6SrcCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1Case;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc2Case;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNsiCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNspCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNspCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthSrcCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxEncapEthDstCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshMdtypeCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshNpCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfMplsLabelCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunGpeNpCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIpv4DstCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpDstCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpSrcCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfIpSrcCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxOfInPortCaseBuilder;
-
-import com.google.common.base.Preconditions;
/**
* @author msunal
if (dstValue == NiciraMatchCodecs.IP_DST_CODEC.getHeaderWithoutHasMask().toLong()) {
return new DstOfIpDstCaseBuilder().setOfIpDst(true).build();
}
+ if (dstValue == NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong()) {
+ return new DstNxIpv6SrcCaseBuilder().setNxIpv6Src(true).build();
+ }
+ if (dstValue == NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong()) {
+ return new DstNxIpv6DstCaseBuilder().setNxIpv6Dst(true).build();
+ }
if (dstValue == NiciraMatchCodecs.ICMP_TYPE_CODEC.getHeaderWithoutHasMask().toLong()) {
return new DstOfIcmpTypeCaseBuilder().setOfIcmpType(true).build();
}
if (srcValue == NiciraMatchCodecs.IP_SRC_CODEC.getHeaderWithoutHasMask().toLong()) {
return new SrcOfIpSrcCaseBuilder().setOfIpSrc(true).build();
}
+ if (srcValue == NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong()) {
+ return new SrcNxIpv6SrcCaseBuilder().setNxIpv6Src(true).build();
+ }
+ if (srcValue == NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong()) {
+ return new SrcNxIpv6DstCaseBuilder().setNxIpv6Dst(true).build();
+ }
throw new CodecPreconditionException("Missing codec for " + new NxmHeader(srcValue));
}
if (dstChoice instanceof DstOfIpDstCase) {
return NiciraMatchCodecs.IP_DST_CODEC.getHeaderWithoutHasMask().toLong();
}
+ if (dstChoice instanceof DstNxIpv6SrcCase) {
+ return NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong();
+ }
+ if (dstChoice instanceof DstNxIpv6DstCase) {
+ return NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong();
+ }
if (dstChoice instanceof DstOfIcmpTypeCase) {
return NiciraMatchCodecs.ICMP_TYPE_CODEC.getHeaderWithoutHasMask().toLong();
}
if (srcChoice instanceof SrcOfIpDstCase) {
return NiciraMatchCodecs.IP_DST_CODEC.getHeaderWithoutHasMask().toLong();
}
+ if (srcChoice instanceof SrcNxIpv6SrcCase) {
+ return NiciraMatchCodecs.IPV6_SRC_CODEC.getHeaderWithoutHasMask().toLong();
+ }
+ if (srcChoice instanceof SrcNxIpv6DstCase) {
+ return NiciraMatchCodecs.IPV6_DST_CODEC.getHeaderWithoutHasMask().toLong();
+ }
if (srcChoice instanceof SrcNxEncapEthSrcCase) {
return NiciraMatchCodecs.ENCAP_ETH_SRC_CODEC.getHeaderWithoutHasMask().toLong();
}
type empty;
}
}
+ grouping nxm-nx-ipv6-src-grouping {
+ leaf nx-ipv6-src {
+ type empty;
+ }
+ }
+ grouping nxm-nx-ipv6-dst-grouping {
+ leaf nx-ipv6-dst {
+ type empty;
+ }
+ }
grouping nxm-of-icmp-type-grouping {
leaf of-icmp-type {
type empty;
case dst-of-ip-dst-case {
uses nxm-of-ip-dst-grouping;
}
+ case dst-nx-ipv6-src-case {
+ uses nxm-nx-ipv6-src-grouping;
+ }
+ case dst-nx-ipv6-dst-case {
+ uses nxm-nx-ipv6-dst-grouping;
+ }
case dst-of-icmp-type-case {
uses nxm-of-icmp-type-grouping;
}
case src-of-ip-dst-case {
uses nxm-of-ip-dst-grouping;
}
+ case src-nx-ipv6-src-case {
+ uses nxm-nx-ipv6-src-grouping;
+ }
+ case src-nx-ipv6-dst-case {
+ uses nxm-nx-ipv6-dst-grouping;
+ }
case src-nx-encap-eth-src-case {
uses nxm-nx-encap-eth-src-grouping;
}
grouping flow-node-connector {
description "Wrapper of openflow port. TODO::simplify/rename";
+ leaf reason {
+ type port:port-reason;
+ }
uses port:flow-capable-port;
}
String MESSAGE = "Cannot stop abstract services, check implementation of cluster services";
- /**
- * Replace actual connection.
- * @param connectionContext new connection
- */
- default void replaceConnection(final ConnectionContext connectionContext) {
- //Nothing to do
- }
-
/**
* Context state.
*/
/**
* About to stop services in cluster not master anymore or going down.
* @return Future most of services need time to be closed.
- * @param connectionInterrupted true if clustering services stopping by device disconnect.
*/
- default ListenableFuture<Void> stopClusterServices(boolean connectionInterrupted) {
- return Futures.immediateFailedFuture(
- new RejectedExecutionException(MESSAGE));
- }
-
- /**
- * About to stop services in cluster not master anymore or going down.
- * @return Future most of services need time to be closed.
- */
- default ListenableFuture<Void> stopClusterServices() {
- return stopClusterServices(false);
- }
+ ListenableFuture<Void> stopClusterServices();
/**
* Get cluster singleton service identifier.
package org.opendaylight.openflowplugin.api.openflow.connection;
+import java.util.List;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
/**
* <p>
* Should be called after nodeId and features are set in connection context.
*/
void handshakeSuccessful();
+
+ /**
+ * Handle received port status message
+ * @param portStatusMessage port status message
+ */
+ void handlePortStatusMessage(PortStatusMessage portStatusMessage);
+
+ List<PortStatusMessage> retrieveAndClearPortStatusMessages();
+
}
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceReplyProcessor;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainStateListener;
import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
DeviceReplyProcessor,
TxFacade,
DeviceRegistry,
- RequestContextStack {
+ RequestContextStack,
+ ContextChainStateListener {
/**
* Method close all auxiliary connections and primary connection.
void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory);
- void putLifecycleServiceIntoTxChainManager(LifecycleService lifecycleService);
-
boolean isSkipTableFeatures();
/**
/**
* Stop the working contexts, but not release them.
- * @param connectionDropped true if stop the chain due to connection drop
* @return Future
*/
- ListenableFuture<Void> stopChain(boolean connectionDropped);
+ ListenableFuture<Void> stopChain();
@Override
void close();
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.api.openflow.lifecycle;
+
+/**
+ * Listens to changes about context chain state
+ */
+public interface ContextChainStateListener {
+
+ /**
+ * Event triggered on context chain state change
+ * @param state context chain state
+ */
+ void onStateAcquired(ContextChainState state);
+
+}
* Event occurs if there was a try to acquire MASTER role.
* But it was not possible to start this MASTER role on device.
* @param deviceInfo for this device
- * @param reason
+ * @param reason reason
+ * @param mandatory if it is mandatory connection will be dropped
*/
- void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason);
+ void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason, final boolean mandatory);
+
+ /**
+ * Event occurs if there was a try to acquire MASTER role.
+ * But it was not possible to start this MASTER role on device.
+ * @param deviceInfo for this device
+ * @param reason reason
+ */
+ default void onNotAbleToStartMastershipMandatory(final DeviceInfo deviceInfo, @Nonnull final String reason) {
+ onNotAbleToStartMastership(deviceInfo, reason, true);
+ }
/**
* Changed to MASTER role on device.
import com.google.common.base.Preconditions;
import java.math.BigInteger;
import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
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.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration;
private HandshakeContext handshakeContext;
private DeviceInfo deviceInfo;
+ private List<PortStatusMessage> portStatusMessages = new ArrayList<>();
/**
* @param connectionAdapter
}
connectionState = ConnectionContext.CONNECTION_STATE.RIP;
+ portStatusMessages.clear();
unregisterOutboundQueue();
closeHandshakeContext();
@Override
public void onConnectionClosed() {
-
connectionState = ConnectionContext.CONNECTION_STATE.RIP;
if (null == nodeId){
auxiliaryId,
getConnectionState());
+ portStatusMessages.clear();
unregisterOutboundQueue();
closeHandshakeContext();
propagateDeviceDisconnectedEvent();
connectionState = CONNECTION_STATE.WORKING;
}
+ @Override
+ public void handlePortStatusMessage(final PortStatusMessage portStatusMessage) {
+ if (Objects.isNull(deviceInfo)) {
+ LOG.debug("NOOP: Port-status message during handshake phase not supported: {}", portStatusMessage);
+ return;
+ }
+
+ LOG.debug("Handling alien port status message {} for node {}", portStatusMessage, nodeId);
+ portStatusMessages.add(portStatusMessage);
+ }
+
+ @Override
+ public List<PortStatusMessage> retrieveAndClearPortStatusMessages() {
+ final List<PortStatusMessage> immutablePortStatusMessages = Collections.unmodifiableList(portStatusMessages);
+ portStatusMessages.clear();
+ return immutablePortStatusMessages;
+ }
+
@Override
public DeviceInfo getDeviceInfo() {
return this.deviceInfo;
@Override
public void onSuccess(@Nullable final RpcResult<BarrierOutput> result) {
if (LOG.isDebugEnabled()) {
- LOG.debug("succeeded by getting sweep barrier after post-handshake for device {}", connectionContext.getNodeId().getValue());
+ LOG.debug("succeeded by getting sweep barrier after post-handshake for device {}", connectionContext.getDeviceInfo().getLOGValue());
}
try {
ConnectionStatus connectionStatusResult = deviceConnectedHandler.deviceConnected(connectionContext);
if (!ConnectionStatus.MAY_CONTINUE.equals(connectionStatusResult)) {
connectionContext.closeConnection(true);
}
- SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
+ SessionStatistics.countEvent(connectionContext.getDeviceInfo().getLOGValue(),
SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
} catch (final Exception e) {
- LOG.error("ConnectionContext initial processing failed: ", e);
- SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
+ LOG.error("ConnectionContext initial processing failed for device {}", connectionContext.getDeviceInfo().getLOGValue(), e);
+ SessionStatistics.countEvent(connectionContext.getDeviceInfo().getLOGValue(),
SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
connectionContext.closeConnection(true);
}
@Override
public void onFailure(final Throwable t) {
- LOG.error("failed to get sweep barrier after post-handshake for device {}", connectionContext.getNodeId());
+ LOG.error("failed to get sweep barrier after post-handshake for device {}", connectionContext.getDeviceInfo().getLOGValue(), t);
connectionContext.closeConnection(false);
}
};
@Override
public void onPortStatusMessage(final PortStatusMessage notification) {
- LOG.debug("NOOP: Port-status message during handshake phase not supported: {}", notification);
+ connectionContext.handlePortStatusMessage(notification);
}
/**
package org.opendaylight.openflowplugin.impl.datastore.multipart;
+import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
.child(FlowCapableNodeConnectorStatistics.class),
new FlowCapableNodeConnectorStatisticsBuilder(stat)
.build(),
- withParents);
+ OFConstants.OFP_VERSION_1_0 == features.getVersion() || withParents);
});
}
package org.opendaylight.openflowplugin.impl.device;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Verify;
import com.google.common.util.concurrent.FutureCallback;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
-import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
import org.opendaylight.openflowplugin.api.ConnectionException;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainMastershipState;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainState;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.MastershipChangeListener;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.impl.device.initialization.AbstractDeviceInitializer;
import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
import org.opendaylight.openflowplugin.impl.device.listener.MultiMsgCollectorImpl;
-import org.opendaylight.openflowplugin.impl.device.listener.OpenflowProtocolListenerFullImpl;
import org.opendaylight.openflowplugin.impl.registry.flow.DeviceFlowRegistryImpl;
import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.openflowplugin.impl.registry.group.DeviceGroupRegistryImpl;
// Timeout in seconds after what we will give up on propagating role
private static final int SET_ROLE_TIMEOUT = 10;
+ // Timeout in milliseconds after what we will give up on initializing device
+ private static final int DEVICE_INIT_TIMEOUT = 9000;
+
private static final int LOW_WATERMARK = 1000;
private static final int HIGH_WATERMARK = 2000;
private final MultipartWriterProvider writerProvider;
private final DeviceManager myManager;
private final DeviceInitializerProvider deviceInitializerProvider;
private final boolean useSingleLayerSerialization;
- private OutboundQueueProvider outboundQueueProvider;
- private boolean isInitialTransactionSubmitted;
+ private boolean hasState;
DeviceContextImpl(
@Nonnull final ConnectionContext primaryConnectionContext,
final DeviceInitializerProvider deviceInitializerProvider) {
this.primaryConnectionContext = primaryConnectionContext;
- this.outboundQueueProvider = (OutboundQueueProvider) primaryConnectionContext.getOutboundQueueProvider();
this.deviceInfo = primaryConnectionContext.getDeviceInfo();
this.hashedWheelTimer = hashedWheelTimer;
this.deviceInitializerProvider = deviceInitializerProvider;
@Override
public boolean initialSubmitTransaction() {
- if (initialized) {
- isInitialTransactionSubmitted = true;
- return transactionChainManager.initialSubmitWriteTransaction();
- }
-
- return false;
+ return (initialized && transactionChainManager.initialSubmitWriteTransaction());
}
@Override
public void processPortStatusMessage(final PortStatusMessage portStatus) {
messageSpy.spyMessage(portStatus.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS);
- if (isInitialTransactionSubmitted) {
+ if (initialized) {
try {
writePortStatusMessage(portStatus);
submitTransaction();
LOG.warn("Error processing port status message for port {} on device {}",
portStatus.getPortNo(), getDeviceInfo().getLOGValue(), e);
}
+ } else if (!hasState) {
+ primaryConnectionContext.handlePortStatusMessage(portStatus);
}
}
this.switchFeaturesMandatory = switchFeaturesMandatory;
}
- @Override
- public synchronized void replaceConnection(final ConnectionContext connectionContext) {
-
- primaryConnectionContext = null;
- deviceInfo = null;
- packetInLimiter = null;
-
- primaryConnectionContext = connectionContext;
- deviceInfo = primaryConnectionContext.getDeviceInfo();
-
- packetInLimiter = new PacketInRateLimiter(primaryConnectionContext.getConnectionAdapter(),
- /*initial*/ LOW_WATERMARK, /*initial*/HIGH_WATERMARK, messageSpy, REJECTED_DRAIN_FACTOR);
-
- primaryConnectionContext.setOutboundQueueProvider(outboundQueueProvider);
-
- final OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration =
- primaryConnectionContext.getConnectionAdapter().registerOutboundQueueHandler(
- outboundQueueProvider,
- myManager.getBarrierCountLimit(),
- myManager.getBarrierIntervalNanos());
-
- primaryConnectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
-
- final OpenflowProtocolListenerFullImpl messageListener = new OpenflowProtocolListenerFullImpl(
- primaryConnectionContext.getConnectionAdapter(), this);
-
- primaryConnectionContext.getConnectionAdapter().setMessageListener(messageListener);
-
- LOG.info("ConnectionEvent: Connection on device:{}, NodeId:{} switched.",
- primaryConnectionContext.getConnectionAdapter().getRemoteAddress(),
- primaryConnectionContext.getDeviceInfo().getNodeId());
-
- }
-
@Override
public CONTEXT_STATE getState() {
return this.state;
}
@Override
- public ListenableFuture<Void> stopClusterServices(boolean connectionInterrupted) {
- final ListenableFuture<Void> deactivateTxManagerFuture = initialized
+ public ListenableFuture<Void> stopClusterServices() {
+ return initialized
? transactionChainManager.deactivateTransactionManager()
: Futures.immediateFuture(null);
-
- if (!connectionInterrupted) {
- final ListenableFuture<Void> makeSlaveFuture
- = Futures.transform(makeDeviceSlave(), new Function<RpcResult<SetRoleOutput>, Void>() {
- @Nullable
- @Override
- public Void apply(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
- return null;
- }
- });
-
- Futures.addCallback(makeSlaveFuture, new FutureCallback<Void>() {
- @Override
- public void onSuccess(@Nullable Void aVoid) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Role SLAVE was successfully propagated on device, node {}", deviceInfo.getLOGValue());
- }
- }
-
- @Override
- public void onFailure(final Throwable throwable) {
- LOG.warn("Was not able to set role SLAVE to device on node {} ", deviceInfo.getLOGValue());
- LOG.trace("Error occurred on device role setting, probably connection loss: ", throwable);
- }
- });
- }
- return deactivateTxManagerFuture;
}
@Override
//NOOP
}
- @Override
- public void putLifecycleServiceIntoTxChainManager(final LifecycleService lifecycleService){
- if (initialized) {
- this.transactionChainManager.setLifecycleService(lifecycleService);
- }
- }
-
@Override
public boolean canUseSingleLayerSerialization() {
return useSingleLayerSerialization && getDeviceInfo().getVersion() >= OFConstants.OFP_VERSION_1_3;
LOG.info("Starting device context cluster services for node {}", deviceInfo.getLOGValue());
lazyTransactionManagerInitialization();
- this.transactionChainManager.activateTransactionManager();
+
+ try {
+ final List<PortStatusMessage> portStatusMessages = primaryConnectionContext
+ .retrieveAndClearPortStatusMessages();
+
+ portStatusMessages.forEach(this::writePortStatusMessage);
+ submitTransaction();
+ } catch (final Exception ex) {
+ LOG.warn("Error processing port status messages from device {}", getDeviceInfo().getLOGValue(), ex);
+ return false;
+ }
try {
final java.util.Optional<AbstractDeviceInitializer> initializer = deviceInitializerProvider
.lookup(deviceInfo.getVersion());
if (initializer.isPresent()) {
- initializer.get().initialize(this, switchFeaturesMandatory, writerProvider, convertorExecutor);
+ initializer
+ .get()
+ .initialize(this, switchFeaturesMandatory, writerProvider, convertorExecutor)
+ .get(DEVICE_INIT_TIMEOUT, TimeUnit.MILLISECONDS);
} else {
throw new ExecutionException(new ConnectionException("Unsupported version " + deviceInfo.getVersion()));
}
- } catch (ExecutionException | InterruptedException e) {
- LOG.warn("Device {} cannot be initialized: ", deviceInfo.getLOGValue(), e);
+ } catch (ExecutionException | InterruptedException | TimeoutException ex) {
+ LOG.warn("Device {} cannot be initialized: ", deviceInfo.getLOGValue(), ex);
return false;
}
this.deviceFlowRegistry = new DeviceFlowRegistryImpl(deviceInfo.getVersion(), dataBroker, deviceInfo.getNodeInstanceIdentifier());
this.deviceGroupRegistry = new DeviceGroupRegistryImpl();
this.deviceMeterRegistry = new DeviceMeterRegistryImpl();
+ this.transactionChainManager.activateTransactionManager();
this.initialized = true;
}
}
return sendRoleChangeToDevice(OfpRole.BECOMESLAVE);
}
+ @Override
+ public void onStateAcquired(final ContextChainState state) {
+ hasState = true;
+ }
+
private class RpcResultFutureCallback implements FutureCallback<RpcResult<SetRoleOutput>> {
private final MastershipChangeListener mastershipChangeListener;
@Override
public void onFailure(final Throwable throwable) {
- mastershipChangeListener.onNotAbleToStartMastership(
+ mastershipChangeListener.onNotAbleToStartMastershipMandatory(
deviceInfo,
"Was not able to set MASTER role on device");
}
}
mastershipChangeListener.onNotAbleToStartMastership(
deviceInfo,
- "Was not able to fill flow registry on device");
+ "Was not able to fill flow registry on device",
+ false);
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Device context removed for node {}", deviceInfo.getLOGValue());
}
- this.updatePacketInRateLimiters();
+ if (deviceContexts.size() > 0) {
+ this.updatePacketInRateLimiters();
+ }
}
@Override
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
private final Object txLock = new Object();
private final DataBroker dataBroker;
private final String nodeId;
- private LifecycleService lifecycleService;
@GuardedBy("txLock")
private WriteTransaction wTx;
TransactionChainManager(@Nonnull final DataBroker dataBroker,
@Nonnull final DeviceInfo deviceInfo) {
this.dataBroker = dataBroker;
- this.nodeId = deviceInfo.getNodeInstanceIdentifier().getKey().getId().getValue();
+ this.nodeId = deviceInfo.getLOGValue();
this.lastSubmittedFuture = Futures.immediateFuture(null);
}
Optional.ofNullable(txChainFactoryTemp).ifPresent(TransactionChain::close);
}
- public void setLifecycleService(final LifecycleService lifecycleService) {
- this.lifecycleService = lifecycleService;
- }
-
boolean initialSubmitWriteTransaction() {
enableSubmit();
return submitWriteTransaction();
*/
void activateTransactionManager() {
if (LOG.isDebugEnabled()) {
- LOG.debug("activateTransactionManager for node {} transaction submit is set to {}", this.nodeId, submitIsEnabled);
+ LOG.debug("activateTransactionManager for node {} transaction submit is set to {}",
+ this.nodeId, submitIsEnabled);
}
synchronized (txLock) {
if (TransactionChainManagerStatus.SLEEPING == transactionChainManagerStatus) {
- Preconditions.checkState(txChainFactory == null, "TxChainFactory survive last close.");
- Preconditions.checkState(wTx == null, "We have some unexpected WriteTransaction.");
+ Preconditions.checkState(txChainFactory == null,
+ "TxChainFactory survive last close.");
+ Preconditions.checkState(wTx == null,
+ "We have some unexpected WriteTransaction.");
this.transactionChainManagerStatus = TransactionChainManagerStatus.WORKING;
this.submitIsEnabled = false;
this.initCommit = true;
if (TransactionChainManagerStatus.WORKING == transactionChainManagerStatus) {
transactionChainManagerStatus = TransactionChainManagerStatus.SLEEPING;
future = txChainShuttingDown();
- Preconditions.checkState(wTx == null, "We have some unexpected WriteTransaction.");
+ Preconditions.checkState(wTx == null,
+ "We have some unexpected WriteTransaction.");
Futures.addCallback(future, new FutureCallback<Void>() {
@Override
public void onSuccess(final Void result) {
}
});
} else {
- // TODO : ignoring redundant deactivate invocation
+ // ignoring redundant deactivate invocation
future = Futures.immediateCheckedFuture(null);
}
}
return true;
}
Preconditions.checkState(TransactionChainManagerStatus.WORKING == transactionChainManagerStatus,
- "we have here Uncompleted Transaction for node {} and we are not MASTER", this.nodeId);
+ "we have here Uncompleted Transaction for node {} and we are not MASTER",
+ this.nodeId);
final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
lastSubmittedFuture = submitFuture;
wTx = null;
}
@GuardedBy("txLock")
- @Nullable
private void ensureTransaction() {
if (wTx == null && TransactionChainManagerStatus.WORKING == transactionChainManagerStatus
&& txChainFactory != null) {
* @param deviceContext device context
* @param multipartWriterProvider multipart writer provider
*/
- public void initialize(@Nonnull final DeviceContext deviceContext,
- final boolean switchFeaturesMandatory,
- @Nullable final MultipartWriterProvider multipartWriterProvider,
- @Nullable final ConvertorExecutor convertorExecutor) throws ExecutionException,InterruptedException {
+ public Future<Void> initialize(@Nonnull final DeviceContext deviceContext,
+ final boolean switchFeaturesMandatory,
+ @Nullable final MultipartWriterProvider multipartWriterProvider,
+ @Nullable final ConvertorExecutor convertorExecutor) throws ExecutionException,InterruptedException {
Preconditions.checkNotNull(deviceContext);
// Write node to datastore
throw new ExecutionException(new ConnectionException("Failed to write node " + deviceContext.getDeviceInfo().getNodeId() + " to DS ", e));
}
- // Synchronously get information about device
- initializeNodeInformation(deviceContext, switchFeaturesMandatory, multipartWriterProvider, convertorExecutor)
- .get();
+ // Get information about device
+ return initializeNodeInformation(deviceContext, switchFeaturesMandatory, multipartWriterProvider, convertorExecutor);
}
protected abstract Future<Void> initializeNodeInformation(@Nonnull final DeviceContext deviceContext,
@Override
public <T extends OFPManager> void addManager(final T manager) {
if (Objects.isNull(deviceManager) && manager instanceof DeviceManager) {
- LOG.debug("Device manager was set.");
+ LOG.trace("Context chain holder: Device manager OK.");
deviceManager = (DeviceManager) manager;
} else if (Objects.isNull(rpcManager) && manager instanceof RpcManager) {
- LOG.debug("RPC manager was set.");
+ LOG.trace("Context chain holder: RPC manager OK.");
rpcManager = (RpcManager) manager;
} else if (Objects.isNull(statisticsManager) && manager instanceof StatisticsManager) {
- LOG.debug("Statistics manager was set.");
+ LOG.trace("Context chain holder: Statistics manager OK.");
statisticsManager = (StatisticsManager) manager;
}
}
}
@Override
- public void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason) {
+ public void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason, final boolean mandatory) {
this.withoutRoleChains.remove(deviceInfo);
LOG.warn("Not able to set MASTER role on device {}, reason: {}", deviceInfo.getLOGValue(), reason);
- if (contextChainMap.containsKey(deviceInfo)) {
- destroyContextChain(deviceInfo);
+ if (mandatory && contextChainMap.containsKey(deviceInfo)) {
+ LOG.warn("This mastering is mandatory, destroying context chain and closing connection.");
+ Futures.transform(contextChainMap.get(deviceInfo).stopChain(), new Function<Void, Object>() {
+ @Nullable
+ @Override
+ public Object apply(@Nullable Void aVoid) {
+ destroyContextChain(deviceInfo);
+ return null;
+ }
+ });
}
}
this.withoutRoleChains.forEach((deviceInfo, contextChain) -> contextChain.makeDeviceSlave());
timer.newTimeout(new RoleTimerTask(), this.checkRoleMaster, TimeUnit.MILLISECONDS);
} else {
- final Set<DeviceInfo> setOfClosedChains = new ConcurrentSet<>();
- if (!this.contextChainMap.isEmpty()) {
- this.contextChainMap.forEach((deviceInfo, contextChain) -> {
- if (!contextChain.hasState()) {
- LOG.warn("Context chain {} is long time without state. Closing.", deviceInfo);
- setOfClosedChains.add(deviceInfo);
- contextChain.close();
- }
- });
- setOfClosedChains.forEach(this.contextChainMap::remove);
- }
- if (this.contextChainMap.isEmpty()) {
- this.stopTimerRole();
- } else {
- timer.newTimeout(new RoleTimerTask(), this.checkRoleMaster, TimeUnit.MILLISECONDS);
- }
+ this.stopTimerRole();
}
}
public void close() throws Exception {
this.contextChainMap.forEach((deviceInfo, contextChain) -> {
if (contextChain.isMastered(ContextChainMastershipState.CHECK)) {
- contextChain.stopChain(true);
+ contextChain.stopChain();
}
contextChain.close();
});
@Override
public void ownershipChanged(EntityOwnershipChange entityOwnershipChange) {
- if (!entityOwnershipChange.hasOwner() && !entityOwnershipChange.isOwner() && entityOwnershipChange.wasOwner()) {
+ if (!entityOwnershipChange.hasOwner()) {
final YangInstanceIdentifier yii = entityOwnershipChange.getEntity().getId();
final YangInstanceIdentifier.NodeIdentifierWithPredicates niiwp =
(YangInstanceIdentifier.NodeIdentifierWithPredicates) yii.getLastPathArgument();
String entityName = niiwp.getKeyValues().values().iterator().next().toString();
if (LOG.isDebugEnabled()) {
- LOG.debug("Last master for entity : {}", entityName);
+ LOG.debug("Entity {} has no owner", entityName);
}
if (entityName != null ){
if (entry.getKey().getNodeId().equals(nodeId)) {
inMap = entry.getKey();
break;
- }
+ }
}
if (Objects.nonNull(inMap)) {
markToBeRemoved.add(inMap);
.removeDeviceFromOperationalDS(DeviceStateUtil.createNodeInstanceIdentifier(nodeId))
.checkedGet(5L, TimeUnit.SECONDS);
} catch (TimeoutException | TransactionCommitFailedException e) {
- LOG.warn("Not able to remove device {} from DS", nodeId);
+ LOG.info("Not able to remove device {} from DS. Probably removed by another cluster node.",
+ nodeId);
}
}
- }
- }
+ }
+ }
}
private void sendNotificationNodeAdded(final DeviceInfo deviceInfo) {
import com.google.common.util.concurrent.ListenableFuture;
import io.netty.util.internal.ConcurrentSet;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChain;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainMastershipState;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainStateListener;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
private volatile ContextChainState contextChainState;
- private boolean masterStateOnDevice;
- private boolean initialGathering;
- private boolean initialSubmitting;
- private boolean registryFilling;
+ private AtomicBoolean masterStateOnDevice;
+ private AtomicBoolean initialGathering;
+ private AtomicBoolean initialSubmitting;
+ private AtomicBoolean registryFilling;
ContextChainImpl(final ConnectionContext connectionContext) {
this.primaryConnection = connectionContext;
this.contextChainState = ContextChainState.UNDEFINED;
- this.masterStateOnDevice = false;
- this.initialGathering = false;
- this.initialSubmitting = false;
- this.registryFilling = false;
+ this.masterStateOnDevice = new AtomicBoolean(false);
+ this.initialGathering = new AtomicBoolean(false);
+ this.initialSubmitting = new AtomicBoolean(false);
+ this.registryFilling = new AtomicBoolean(false);
this.deviceInfo = connectionContext.getDeviceInfo();
}
}
}
}
+
contexts.add(context);
}
}
@Override
- public ListenableFuture<Void> stopChain(boolean connectionDropped) {
+ public ListenableFuture<Void> stopChain() {
//TODO: stopClusterServices change parameter
final List<ListenableFuture<Void>> futureList = new ArrayList<>();
futureList.add(statisticsContext.stopClusterServices());
futureList.add(rpcContext.stopClusterServices());
- futureList.add(deviceContext.stopClusterServices(connectionDropped));
-
+ futureList.add(deviceContext.stopClusterServices());
+ this.unMasterMe();
return Futures.transform(Futures.successfulAsList(futureList), new Function<List<Void>, Void>() {
@Nullable
@Override
});
}
+ private void unMasterMe() {
+ this.registryFilling.set(false);
+ this.initialSubmitting.set(false);
+ this.initialGathering.set(false);
+ this.masterStateOnDevice.set(false);
+ }
+
@Override
public void close() {
this.auxiliaryConnections.forEach(connectionContext -> connectionContext.closeConnection(false));
@Override
public void makeContextChainStateSlave() {
- this.contextChainState = ContextChainState.WORKING_SLAVE;
+ this.unMasterMe();
+ changeState(ContextChainState.WORKING_SLAVE);
}
@Override
public ListenableFuture<Void> connectionDropped() {
if (this.contextChainState == ContextChainState.WORKING_MASTER) {
- return this.stopChain(true);
+ return this.stopChain();
}
+ this.unMasterMe();
return Futures.immediateFuture(null);
}
@Override
public void makeDeviceSlave() {
+ this.unMasterMe();
this.lifecycleService.makeDeviceSlave(this.deviceContext);
}
switch (mastershipState) {
case INITIAL_SUBMIT:
LOG.debug("Device {}, initial submit OK.", deviceInfo.getLOGValue());
- this.initialSubmitting = true;
+ this.initialSubmitting.set(true);
break;
case MASTER_ON_DEVICE:
LOG.debug("Device {}, master state OK.", deviceInfo.getLOGValue());
- this.masterStateOnDevice = true;
+ this.masterStateOnDevice.set(true);
break;
case INITIAL_GATHERING:
LOG.debug("Device {}, initial gathering OK.", deviceInfo.getLOGValue());
- this.initialGathering = true;
+ this.initialGathering.set(true);
break;
+ //Flow registry fill is not mandatory to work as a master
case INITIAL_FLOW_REGISTRY_FILL:
LOG.debug("Device {}, initial registry filling OK.", deviceInfo.getLOGValue());
- this.registryFilling = true;
+ this.registryFilling.set(true);
case CHECK:
default:
}
final boolean result =
- this.initialGathering &&
- this.masterStateOnDevice &&
- this.initialSubmitting &&
- this.registryFilling;
+ this.initialGathering.get() &&
+ this.masterStateOnDevice.get() &&
+ this.initialSubmitting.get();
if (result && mastershipState != ContextChainMastershipState.CHECK) {
- LOG.info("Device {} is able to work as master.", deviceInfo.getLOGValue());
- contextChainState = ContextChainState.WORKING_MASTER;
+ LOG.info("Device {} is able to work as master{}",
+ deviceInfo.getLOGValue(),
+ this.registryFilling.get() ? " WITHOUT flow registry !!!" : ".");
+ changeState(ContextChainState.WORKING_MASTER);
}
return result;
}
this.auxiliaryConnections.remove(connectionContext);
return true;
}
+
+ private void changeState(final ContextChainState contextChainState) {
+ boolean propagate = this.contextChainState == ContextChainState.UNDEFINED;
+ this.contextChainState = contextChainState;
+
+ if (propagate) {
+ contexts.stream()
+ .filter(ContextChainStateListener.class::isInstance)
+ .map(ContextChainStateListener.class::cast)
+ .forEach(listener -> listener.onStateAcquired(contextChainState));
+ }
+ }
}
LOG.info("Starting clustering MASTER services for node {}", deviceInfo.getLOGValue());
if (!clusterInitializationPhaseHandler.onContextInstantiateService(mastershipChangeListener)) {
- mastershipChangeListener.onNotAbleToStartMastership(deviceInfo, "Cannot initialize device.");
+ mastershipChangeListener.onNotAbleToStartMastershipMandatory(deviceInfo, "Cannot initialize device.");
}
}
import io.netty.buffer.ByteBuf;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderSerializer;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.ExperimenterIdCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
});
// Serialize match extensions
- ExtensionResolvers.getMatchExtensionResolver().getExtension(match).map(extensions -> {
- extensions.getExtensionList().forEach(extension -> {
- // TODO: Remove also extension converters
- final MatchEntry entry = OFSessionUtil
- .getExtensionConvertorProvider()
- .<MatchEntry>getConverter(new ConverterExtensionKey<>(
- extension.getExtensionKey(),
- OFConstants.OFP_VERSION_1_3))
- .convert(extension.getExtension());
-
- final MatchEntrySerializerKey<?, ?> key = new MatchEntrySerializerKey<>(
- EncodeConstants.OF13_VERSION_ID, entry.getOxmClass(), entry.getOxmMatchField());
-
- // If entry is experimenter, set experimenter ID to key
- if (entry.getOxmClass().equals(ExperimenterClass.class)) {
- key.setExperimenterId(ExperimenterIdCase.class.cast(entry.getMatchEntryValue())
- .getExperimenter().getExperimenter().getValue());
- }
-
- final OFSerializer<MatchEntry> entrySerializer = registry.getSerializer(key);
- entrySerializer.serialize(entry, outBuffer);
- });
-
- return extensions;
+ ExtensionResolvers
+ .getMatchExtensionResolver()
+ .getExtension(match)
+ .flatMap(extensions -> Optional.ofNullable(extensions.getExtensionList()))
+ .ifPresent(extensionList -> serializeExtensionList(extensionList, outBuffer));
+ }
+
+ private void serializeExtensionList(final List<ExtensionList> extensionList, final ByteBuf outBuffer) {
+ // TODO: Remove also extension converters
+ extensionList.forEach(extension -> {
+ final ConverterExtensionKey<? extends ExtensionKey> converterExtensionKey =
+ new ConverterExtensionKey<>(extension.getExtensionKey(), OFConstants.OFP_VERSION_1_3);
+
+ Optional.ofNullable(OFSessionUtil.getExtensionConvertorProvider())
+ .flatMap(provider -> Optional.ofNullable(provider.<MatchEntry>getConverter(converterExtensionKey)))
+ .map(matchEntryConvertorToOFJava -> {
+ final MatchEntry entry = matchEntryConvertorToOFJava.convert(extension.getExtension());
+
+ final MatchEntrySerializerKey<?, ?> key = new MatchEntrySerializerKey<>(
+ EncodeConstants.OF13_VERSION_ID, entry.getOxmClass(), entry.getOxmMatchField());
+
+ // If entry is experimenter, set experimenter ID to key
+ if (entry.getOxmClass().equals(ExperimenterClass.class)) {
+ key.setExperimenterId(ExperimenterIdCase.class.cast(entry.getMatchEntryValue())
+ .getExperimenter().getExperimenter().getValue());
+ }
+
+ final OFSerializer<MatchEntry> entrySerializer = registry.getSerializer(key);
+ entrySerializer.serialize(entry, outBuffer);
+ return entry;
+ })
+ .orElseGet(() -> {
+ LOG.warn("Serializer for match entry {} for version {} not found.",
+ extension.getExtension().getImplementedInterface(),
+ OFConstants.OFP_VERSION_1_3);
+ return null;
+ });
});
}
}
if (!iterator.hasNext()) {
- if (initial) {
- Futures.addCallback(StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService,
- getDeviceInfo(),
- MultipartType.OFPMPPORTDESC,
- deviceContext,
- deviceContext,
- false,
- convertorExecutor,
- statisticsWriterProvider), new FutureCallback<Boolean>() {
- @Override
- public void onSuccess(final Boolean result) {
- statChainFuture(iterator, resultFuture, false);
- }
- @Override
- public void onFailure(@Nonnull final Throwable t) {
- resultFuture.setException(t);
- }
- });
-
- return;
- }
-
resultFuture.set(Boolean.TRUE);
LOG.debug("Stats collection successfully finished for node {}", getDeviceInfo().getLOGValue());
return;
myManager.startScheduling(deviceInfo);
}
} else {
- mastershipChangeListener.onNotAbleToStartMastership(
+ mastershipChangeListener.onNotAbleToStartMastershipMandatory(
deviceInfo,
"Initial transaction cannot be submitted."
);
@Override
public void onFailure(@Nonnull Throwable throwable) {
- mastershipChangeListener.onNotAbleToStartMastership(
+ mastershipChangeListener.onNotAbleToStartMastershipMandatory(
deviceInfo,
"Initial gathering statistics unsuccessful."
);
import org.opendaylight.openflowplugin.openflow.md.util.PortTranslatorUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* @author tkubas
*/
public class PortUpdateTranslator implements MessageTranslator<PortGrouping, FlowCapableNodeConnector> {
+ private static final Logger logger = LoggerFactory.getLogger(PortUpdateTranslator.class);
@Override
public FlowCapableNodeConnector translate(final PortGrouping input,
builder.setSupported(PortTranslatorUtil.translatePortFeatures(input.getSupportedFeatures()));
builder.setQueue(Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue>emptyList());
}
+ if (input instanceof PortStatusMessage) {
+ if (((PortStatusMessage) input).getReason() != null) {
+ builder.setReason(PortReason.forValue(((PortStatusMessage) input).getReason().getIntValue()));
+ }else {
+ logger.debug("PortStatus Message has reason as null");
+ }
+ }
builder.setCurrentSpeed(input.getCurrSpeed());
builder.setHardwareAddress(input.getHwAddr());
builder.setMaximumSpeed(input.getMaxSpeed());
connectionContextSpy = Mockito.spy(new ConnectionContextImpl(connectionAdapter));
Mockito.when(connectionContextSpy.getConnectionAdapter()).thenReturn(connectionAdapter);
Mockito.when(features.getDatapathId()).thenReturn(BigInteger.TEN);
- Mockito.doNothing().when(connectionContextSpy).handshakeSuccessful();
handshakeListener = new HandshakeListenerImpl(connectionContextSpy, deviceConnectedHandler);
handshakeListener.setHandshakeContext(handshakeContext);
}
public void setUp() throws Exception {
Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
- Mockito.when(deviceContext.stopClusterServices(Mockito.anyBoolean()))
+ Mockito.when(deviceContext.stopClusterServices())
.thenReturn(Futures.immediateFuture(null));
Mockito.when(rpcContext.stopClusterServices()).thenReturn(Futures.immediateFuture(null));
Mockito.when(statisticsContext.stopClusterServices()).thenReturn(Futures.immediateFuture(null));
@Test
public void stopChain() throws Exception {
- contextChain.stopChain(true);
- Mockito.verify(deviceContext).stopClusterServices(Mockito.anyBoolean());
+ contextChain.stopChain();
+ Mockito.verify(deviceContext).stopClusterServices();
Mockito.verify(rpcContext).stopClusterServices();
Mockito.verify(statisticsContext).stopClusterServices();
}
contextChain.isMastered(ContextChainMastershipState.MASTER_ON_DEVICE);
contextChain.isMastered(ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
contextChain.connectionDropped();
- Mockito.verify(deviceContext).stopClusterServices(Mockito.anyBoolean());
+ Mockito.verify(deviceContext).stopClusterServices();
Mockito.verify(rpcContext).stopClusterServices();
Mockito.verify(statisticsContext).stopClusterServices();
}
Mockito.when(deviceContext.onContextInstantiateService(Mockito.any()))
.thenReturn(false);
lifecycleService.instantiateServiceInstance();
- Mockito.verify(mastershipChangeListener).onNotAbleToStartMastership(Mockito.any(DeviceInfo.class), Mockito.anyString());
+ Mockito.verify(mastershipChangeListener).onNotAbleToStartMastershipMandatory(Mockito.any(DeviceInfo.class), Mockito.anyString());
}
@Test
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfigV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortStateV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
return new PortStatusMessageBuilder()
.setPortNo(portNoValue)
+ .setReason(PortReason.OFPPRADD)
.setAdvertisedFeatures(portFeatures13)
.setAdvertisedFeaturesV10(portFeatures10)
.setConfig(portConfig13)
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.tycho</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>equinoxSDK381</groupId>
<artifactId>org.eclipse.equinox.console</artifactId>
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortStateV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public abstract class PortTranslatorUtil {
+ private static final Logger logger = LoggerFactory.getLogger(PortTranslatorUtil.class);
public static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures translatePortFeatures(final PortFeatures apf) {
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures napf = null;
if (apf != null) {
fcncub.setState(PortTranslatorUtil.translatePortState(port.getStateV10()));
fcncub.setSupported(PortTranslatorUtil.translatePortFeatures(port.getSupportedFeaturesV10()));
}
+ if (port instanceof PortStatusMessage) {
+ if (((PortStatusMessage) port).getReason() != null) {
+ fcncub.setReason(PortReason.forValue(((PortStatusMessage) port).getReason().getIntValue()));
+ }else {
+ logger.debug("PortStatus Message has reason as null");
+ }
+ }
fcncub.setCurrentSpeed(port.getCurrSpeed());
fcncub.setHardwareAddress(port.getHwAddr());
fcncub.setMaximumSpeed(port.getMaxSpeed());
<openflowjava.version>0.10.0-SNAPSHOT</openflowjava.version>
<openflowplugin.version>0.5.0-SNAPSHOT</openflowplugin.version>
<sal.api.version>0.13.0-SNAPSHOT</sal.api.version>
- <jmxGeneratorPath>target/generated-sources/config</jmxGeneratorPath>
- <salGeneratorPath>target/generated-sources/sal</salGeneratorPath>
+ <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
+ <salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
<exi.nagasena.version>0000.0002.0053.0</exi.nagasena.version>
<controller.distribution.version>0.6.0-SNAPSHOT</controller.distribution.version>