- openflowplugin
committers:
- <<: *odl_openflowplugin_ptl
- - name: 'Shuva Jyoti Kar'
- email: 'shukar@cisco.com'
- company: 'cisco'
- id: 'SHUVA JYOTI KAR'
- timezone: 'Unknown/Unknown'
- - name: 'Jozef Bacigal'
- email: 'jozef.bacigal@pantheon.tech'
- company: 'pantheon'
- id: 'batky'
- timezone: 'Unknown/Unknown'
- - name: 'Michal Rehak'
- email: 'lagosaurus.42@gmail.com'
- company: ''
- id: 'michal.rehak'
- timezone: 'Unknown/Unknown'
- - name: 'Ed Warnicke'
- email: 'hagbard@gmail.com'
- company: ''
- id: 'hagbard'
- timezone: 'Unknown/Unknown'
- - name: 'Prasanna Huddar'
- email: 'prasanna.k.huddar@gmail.com'
- company: ''
- id: 'prasannakh'
- timezone: 'Unknown/Unknown'
- - name: 'Anil Vishnoi'
- email: 'avishnoi@redhat.com'
- company: 'Redhat'
- id: 'Avishnoi'
- timezone: 'Unknown/Unknown'
- - name: 'Jozef Bacigál'
- email: 'jozef.bacigal@me.com'
- company: 'me'
- id: 'jbacigal'
- timezone: 'Unknown/Unknown'
- - name: 'Abhijit Kumbhare'
- email: 'abhijitkoss@gmail.com'
- company: ''
- id: 'abhijit2511'
- timezone: 'Unknown/Unknown'
- - name: 'Shuva Kar'
- email: 'shuva.jyoti.kar.87@gmail.com'
- company: ''
- id: 'shuvajyotikar'
- timezone: 'Unknown/Unknown'
- - name: 'Hema Gopalakrishnan'
- email: 'hema.gopalkrishnan@ericsson.com'
- company: 'Ericsson'
- id: 'Hematg'
- timezone: 'Unknown/Unknown'
- name: 'Gobinath Suganthan'
email: 'gobinath@ericsson.com'
company: 'Ericsson'
= salBundleService.controlBundle(closeBundleInput);
/* Open a new bundle on the switch */
- ListenableFuture<RpcResult<ControlBundleOutput>> openBundle =
- Futures.transformAsync(closeBundle,
- rpcResult -> salBundleService.controlBundle(openBundleInput),
- service);
+ ListenableFuture<RpcResult<ControlBundleOutput>> openBundle
+ = Futures.transformAsync(closeBundle, rpcResult -> {
+ if (rpcResult.isSuccessful()) {
+ LOG.debug("Existing bundle is successfully closed for device {}", dpnId);
+ }
+ return salBundleService.controlBundle(openBundleInput);
+ }, service);
/* Push groups and flows via bundle add messages */
ListenableFuture<RpcResult<AddBundleMessagesOutput>> deleteAllFlowGroupsFuture
= Futures.transformAsync(openBundle, rpcResult -> {
if (rpcResult.isSuccessful()) {
+ LOG.debug("Open bundle is successful for device {}", dpnId);
return salBundleService.addBundleMessages(deleteAllFlowGroupsInput);
}
return Futures.immediateFuture(null);
public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesManagerImpl.class);
- static final int STARTUP_LOOP_TICK = 500;
- static final int STARTUP_LOOP_MAX_RETRIES = 8;
+ static final int STARTUP_LOOP_TICK = 1000;
+ static final int STARTUP_LOOP_MAX_RETRIES = 240;
private static final int FRM_RECONCILIATION_PRIORITY = Integer.getInteger("frm.reconciliation.priority", 1);
private static final String SERVICE_NAME = "FRM";
@Singleton
public class ListenerRegistrationHelper {
private static final Logger LOG = LoggerFactory.getLogger(ListenerRegistrationHelper.class);
- private final long inventoryCheckTimer = 1;
+ private static final long INVENTORY_CHECK_TIMER = 1;
private final String operational = "OPERATIONAL";
private final ListeningExecutorService listeningExecutorService;
private final DataBroker dataBroker;
while (! getInventoryConfigDataStoreStatus().equals(operational)) {
try {
LOG.debug("Retrying for datastore to become operational for listener {}", listener);
- Thread.sleep(inventoryCheckTimer * 1000);
+ Thread.sleep(INVENTORY_CHECK_TIMER * 1000);
} catch (InterruptedException e) {
LOG.info("registerDataTreeChangeListener thread is interrupted");
Thread.currentThread().interrupt();
private static final Logger LOG = LoggerFactory.getLogger(FrmUtil.class);
private static final String SEPARATOR = ":";
private static final long RPC_RESULT_TIMEOUT = 2500;
+ public static final String OPENFLOW_PREFIX = "openflow:";
private static final String JMX_OBJ_NAME_LIST_OF_SHRDS = "org.opendaylight.controller:type="
+ "DistributedConfigDatastore,Category=ShardManager,name=shard-manager-config";
actions = ((WriteActionsCase)instruction.getInstruction())
.getWriteActions().nonnullAction().values();
}
- for (Action action : actions) {
- if (action.getAction().implementedInterface()
- .equals(ActionType.GROUP_ACTION.getActionType())) {
- return ((GroupActionCase) action.getAction()).getGroupAction()
- .getGroupId();
+ if (actions != null) {
+ for (Action action : actions) {
+ if (action.getAction().implementedInterface().equals(ActionType.GROUP_ACTION.getActionType())) {
+ return ((GroupActionCase) action.getAction()).getGroupAction().getGroupId();
+ }
}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. 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.southboundcli.cli;
+
+import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.OPENFLOW_PREFIX;
+
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
+
+@Command(scope = "openflow", name = "getflownodecache", description = "Print all flow/group cache")
+public class GetFlowGroupCacheProvider extends OsgiCommandSupport {
+
+ @Option(name = "-d", description = "Node Id")
+ String dpnId;
+
+ private FlowGroupCacheManager flowGroupCacheManager;
+
+ public GetFlowGroupCacheProvider(final FlowGroupCacheManager flowGroupCacheManager) {
+ this.flowGroupCacheManager = flowGroupCacheManager;
+ }
+
+ @SuppressWarnings("checkstyle:RegexpSinglelineJava")
+ @Override
+ protected Object doExecute() throws Exception {
+ String nodeId = OPENFLOW_PREFIX + dpnId;
+ List<String> result = new ArrayList<>();
+
+ if (dpnId == null) {
+ Map<String, Queue<FlowGroupCache>> flowGroupCacheListForAllNodes = flowGroupCacheManager
+ .getAllNodesFlowGroupCache();
+ if (!flowGroupCacheListForAllNodes.isEmpty()) {
+ StringBuilder stringBuilder = new StringBuilder();
+ Formatter formatter = new Formatter(stringBuilder);
+ result.add(getAllLocalNodesHeaderOutput());
+ result.add(getLineSeparator());
+ for (Map.Entry<String, Queue<FlowGroupCache>> cacheEntry : flowGroupCacheListForAllNodes.entrySet()) {
+ String[] temp = cacheEntry.getKey().split(":");
+ String node = temp[1];
+ Queue<FlowGroupCache> flowGroupCacheList = cacheEntry.getValue();
+ synchronized (flowGroupCacheList) {
+ for (FlowGroupCache cache : flowGroupCacheList) {
+ result.add(formatter.format("%-15s %1s %-10s %1s %-8s %1s %-21s %1s %-60s",
+ node, "", cache.getDescription(), "", cache.getStatus(), "",
+ cache.getTime(), "", cache.getId()).toString());
+ stringBuilder.setLength(0);
+ }
+ }
+ }
+ formatter.close();
+ result.stream().forEach(p -> System.out.println(p));
+ } else {
+ session.getConsole().println("No flow/group is programmed yet");
+ }
+ } else {
+ if (!flowGroupCacheManager.getAllNodesFlowGroupCache().containsKey(nodeId)) {
+ session.getConsole().println("No node available for this NodeID");
+ return null;
+ }
+ Queue<FlowGroupCache> flowGroupCacheList = flowGroupCacheManager.getAllNodesFlowGroupCache()
+ .get(nodeId);
+ if (!flowGroupCacheList.isEmpty()) {
+ StringBuilder stringBuilder = new StringBuilder();
+ Formatter formatter = new Formatter(stringBuilder);
+ result.add(String.format("Number of flows and groups in cache for node %s : %d", nodeId,
+ flowGroupCacheList.size()));
+ result.add(getLocalNodeHeaderOutput());
+ result.add(getLineSeparator());
+ for (FlowGroupCache cache : flowGroupCacheList) {
+ result.add(formatter.format("%-10s %1s %-8s %1s %-23s %1s %-60s",
+ cache.getDescription(), "", cache.getStatus(), "",
+ cache.getTime(), "", cache.getId()).toString());
+ stringBuilder.setLength(0);
+ }
+ formatter.close();
+ result.stream().forEach(p -> System.out.println(p));
+ } else {
+ session.getConsole().println("No flow/group is programmed yet for the the node " + nodeId);
+ }
+ }
+ return null;
+ }
+
+ private String getLocalNodeHeaderOutput() {
+ Formatter formatter = new Formatter();
+ String header = formatter.format("%-10s %1s %-8s %1s %-23s %1s %-60s",
+ "TableId", "", "Status", "", "Time", "", "Flow/Group Id").toString();
+ formatter.close();
+ return header;
+ }
+
+ private String getAllLocalNodesHeaderOutput() {
+ Formatter formatter = new Formatter();
+ String header = formatter.format("%-15s %1s %-10s %1s %-8s %1s %-23s %1s %-60s",
+ "DpnId", "", "TableId", "", "Status", "", "Time", "", "Flow/Group Id").toString();
+ formatter.close();
+ return header;
+ }
+
+ private String getLineSeparator() {
+ return "---------------------------------------------------------------------------------------------"
+ + "-----------------------------------------------";
+ }
+}
<reference id="clusterMemberInfoProvider"
interface="org.opendaylight.infrautils.diagstatus.ClusterMemberInfo"
availability="optional"/>
-
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
<command name="openflow/getallnodes">
<action class="org.opendaylight.openflowplugin.applications.southboundcli.cli.GetAllNodesCommandProvider">
<argument value="${org.osgi.service.http.port}"/>
</action>
</command>
+ <command name="openflow/getflownodecache">
+ <action class="org.opendaylight.openflowplugin.applications.southboundcli.cli.GetFlowGroupCacheProvider">
+ <argument ref="flowCacheManager"/>
+ </action>
+ </command>
</command-bundle>
</blueprint>
\ No newline at end of file
<reference id="dataBroker"
interface="org.opendaylight.mdsal.binding.api.DataBroker"/>
- <reference id="flowGroupCacheManager" interface="org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager"/>
+ <reference id="flowCacheManager" interface="org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager"/>
<odl:rpc-service id="frmReconciliationService"
interface="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.frm.reconciliation.service.rev180227.FrmReconciliationService"/>
-
<bean id="alarmAgent"
class="org.opendaylight.openflowplugin.applications.southboundcli.alarm.AlarmAgent" init-method="start">
</bean>
<argument ref="frmReconciliationService"/>
<argument ref="alarmAgent"/>
<argument ref="nodeListener"/>
- <argument ref="flowGroupCacheManager"/>
+ <argument ref="flowCacheManager"/>
</bean>
<odl:rpc-implementation ref="reconciliationService"/>
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.experimenter.input.experimenter.data.of.choice.BundleControlOnf;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.experimenter.input.experimenter.data.of.choice.BundleControlOnfBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.experimenter.input.experimenter.data.of.choice.bundle.control.onf.OnfControlGroupingDataBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Converter for BundleControl messages (ONF approved extension #230).
ConverterMessageToOFJava<BundleControlSal, BundleControlOnf, ExtensionConvertorData>,
ConvertorMessageFromOFJava<BundleControlOnf, MessagePath> {
+ private static final Logger LOG = LoggerFactory.getLogger(BundleControlConverter.class);
+
@Override
public BundleControlOnf convert(final BundleControlSal experimenterMessageCase, final ExtensionConvertorData data) {
+ LOG.trace("Converting the bundle control message for device {} with xid {} and type {}",
+ data.getDatapathId(), data.getXid(), experimenterMessageCase.getSalControlData().getType());
return new BundleControlOnfBuilder().setOnfControlGroupingData(
new OnfControlGroupingDataBuilder(experimenterMessageCase.getSalControlData()).build()).build();
}
*/
package org.opendaylight.openflowplugin.extension.onf.converter;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
+import org.opendaylight.openflowplugin.extension.api.ExtensionConvertorData;
import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
import org.opendaylight.openflowplugin.extension.onf.BundleTestUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.experimenter.input.experimenter.data.of.choice.BundleControlOnfBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.experimenter.input.experimenter.data.of.choice.bundle.control.onf.OnfControlGroupingDataBuilder;
import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
/**
* Test for {@link org.opendaylight.openflowplugin.extension.onf.converter.BundleControlConverter}.
private void testConvertDown(final boolean withProperty) {
final BundleControlSal original = createOFPMessage(withProperty);
- final BundleControlOnf converted = converter.convert(original, null);
+ final ExtensionConvertorData data = new ExtensionConvertorData((short)1);
+ data.setXid(Uint32.valueOf(0L));
+ data.setDatapathId(Uint64.valueOf(BigInteger.ONE));
+ final BundleControlOnf converted = converter.convert(original, data);
testConvert(original, converted, withProperty);
}
--- /dev/null
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. 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;
+
+import java.time.LocalDateTime;
+
+public class FlowGroupCache {
+ private final String id;
+ private final String description;
+ private final FlowGroupStatus status;
+ private final LocalDateTime time;
+
+ public FlowGroupCache(String id, String description, FlowGroupStatus status,
+ LocalDateTime time) {
+ this.id = id;
+ this.description = description;
+ this.status = status;
+ this.time = time;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public FlowGroupStatus getStatus() {
+ return status;
+ }
+
+ public LocalDateTime getTime() {
+ return time;
+ }
+}
package org.opendaylight.openflowplugin.api.openflow;
import java.util.Map;
+import java.util.Queue;
public interface FlowGroupCacheManager {
Map<String, ReconciliationState> getReconciliationStates();
+
+ Map<String, Queue<FlowGroupCache>> getAllNodesFlowGroupCache();
}
--- /dev/null
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. 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;
+
+public enum FlowGroupStatus {
+ ADDED,
+ MODIFIED,
+ REMOVED
+}
\ No newline at end of file
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.checkerframework.checker.lock.qual.GuardedBy;
import org.opendaylight.mdsal.binding.api.WriteTransaction;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
}
@GuardedBy("txLock")
+ @SuppressWarnings("checkstyle:IllegalCatch")
public boolean submitTransaction(boolean doSync) {
synchronized (txLock) {
if (!submitIsEnabled) {
if (initCommit || doSync) {
try {
- submitFuture.get(5L, TimeUnit.SECONDS);
- } catch (InterruptedException | ExecutionException | TimeoutException ex) {
- LOG.error("Exception during INITIAL({}) || doSync({}) transaction submitting. ",
- initCommit, doSync, ex);
+ SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(500, 6);
+ looper.loopUntilNoException(() -> submitFuture.get(5L, TimeUnit.SECONDS));
+ } catch (Exception ex) {
+ LOG.error("Exception during INITIAL({}) || doSync({}) transaction submitting for device {}",
+ initCommit, doSync, nodeId, ex);
return false;
}
initCommit = false;
import org.opendaylight.openflowjava.protocol.api.connection.OpenflowDiagStatusProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderList;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager;
private ContextChainHolderImpl contextChainHolder;
private final OpenflowDiagStatusProvider openflowDiagStatusProvider;
private final SystemReadyMonitor systemReadyMonitor;
+ private final FlowGroupCacheManager flowGroupCacheManager;
private final SettableFuture<Void> fullyStarted = SettableFuture.create();
private static final String OPENFLOW_SERVICE_NAME = "OPENFLOW";
final @Reference EntityOwnershipService entityOwnershipService,
final MastershipChangeServiceManager mastershipChangeServiceManager,
final @Reference OpenflowDiagStatusProvider openflowDiagStatusProvider,
- final @Reference SystemReadyMonitor systemReadyMonitor) {
+ final @Reference SystemReadyMonitor systemReadyMonitor,
+ final FlowGroupCacheManager flowGroupCacheManager) {
this.switchConnectionProviders = switchConnectionProviders;
this.dataBroker = pingPongDataBroker;
this.rpcProviderRegistry = rpcProviderRegistry;
this.mastershipChangeServiceManager = mastershipChangeServiceManager;
this.openflowDiagStatusProvider = openflowDiagStatusProvider;
this.systemReadyMonitor = systemReadyMonitor;
+ this.flowGroupCacheManager = flowGroupCacheManager;
}
@Override
rpcProviderRegistry,
extensionConverterManager,
convertorManager,
- notificationPublishService);
+ notificationPublishService,
+ flowGroupCacheManager);
statisticsManager = new StatisticsManagerImpl(
config,
deviceManager.setContextChainHolder(contextChainHolder);
deviceManager.initialize();
systemReadyMonitor.registerListener(this);
- LOG.info("registered onSystemBootReady() listener for deferred startSwitchConnections()");
+ LOG.info("registered onSystemBootReady() listener for OpenFlowPluginProvider");
}
@Override
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
import org.opendaylight.mdsal.binding.api.RpcProviderService;
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
private final ConvertorExecutor convertorExecutor;
private final NotificationPublishService notificationPublishService;
private ContextChainMastershipWatcher contextChainMastershipWatcher;
+ private final FlowGroupCacheManager flowGroupCacheManager;
RpcContextImpl(@NonNull final RpcProviderService rpcProviderRegistry,
final int maxRequests,
@NonNull final ExtensionConverterProvider extensionConverterProvider,
@NonNull final ConvertorExecutor convertorExecutor,
@NonNull final NotificationPublishService notificationPublishService,
- final boolean statisticsRpcEnabled) {
+ final boolean statisticsRpcEnabled,
+ @NonNull final FlowGroupCacheManager flowGroupCacheManager) {
this.deviceContext = deviceContext;
this.deviceInfo = deviceContext.getDeviceInfo();
this.nodeInstanceIdentifier = deviceContext.getDeviceInfo().getNodeInstanceIdentifier();
this.extensionConverterProvider = extensionConverterProvider;
this.notificationPublishService = notificationPublishService;
this.convertorExecutor = convertorExecutor;
+ this.flowGroupCacheManager = flowGroupCacheManager;
this.isStatisticsRpcEnabled = statisticsRpcEnabled;
this.tracker = new Semaphore(maxRequests, true);
}
@Override
public void instantiateServiceInstance() {
- MdSalRegistrationUtils.registerServices(this, deviceContext, extensionConverterProvider, convertorExecutor);
+ MdSalRegistrationUtils.registerServices(this, deviceContext, extensionConverterProvider,
+ convertorExecutor, flowGroupCacheManager);
if (isStatisticsRpcEnabled && !deviceContext.canUseSingleLayerSerialization()) {
MdSalRegistrationUtils.registerStatCompatibilityServices(
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
private final ExtensionConverterProvider extensionConverterProvider;
private final ConvertorExecutor convertorExecutor;
private final NotificationPublishService notificationPublishService;
+ private final FlowGroupCacheManager flowGroupCacheManager;
public RpcManagerImpl(final OpenflowProviderConfig config,
final RpcProviderService rpcProviderRegistry,
final ExtensionConverterProvider extensionConverterProvider,
final ConvertorExecutor convertorExecutor,
- final NotificationPublishService notificationPublishService) {
+ final NotificationPublishService notificationPublishService,
+ final FlowGroupCacheManager flowGroupCacheManager) {
this.config = config;
this.rpcProviderRegistry = rpcProviderRegistry;
this.extensionConverterProvider = extensionConverterProvider;
this.convertorExecutor = convertorExecutor;
this.notificationPublishService = notificationPublishService;
+ this.flowGroupCacheManager = flowGroupCacheManager;
}
@Override
extensionConverterProvider,
convertorExecutor,
notificationPublishService,
- config.isIsStatisticsRpcEnabled());
+ config.isIsStatisticsRpcEnabled(),
+ flowGroupCacheManager);
contexts.put(deviceContext.getDeviceInfo(), rpcContext);
return rpcContext;
package org.opendaylight.openflowplugin.impl.services.cache;
import java.util.Map;
+import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton;
import org.apache.aries.blueprint.annotation.service.Service;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.ReconciliationState;
public class FlowGroupCacheManagerImpl implements FlowGroupCacheManager {
private Map<String, ReconciliationState> reconciliationStates = new ConcurrentHashMap<>();
+ private Map<String, Queue<FlowGroupCache>> allNodesFlowGroupCache = new ConcurrentHashMap<>();
+
+ @Override
+ public Map<String, Queue<FlowGroupCache>> getAllNodesFlowGroupCache() {
+ return allNodesFlowGroupCache;
+ }
@Override
public Map<String, ReconciliationState> getReconciliationStates() {
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Simple bundle extension service.
*/
public class SalBundleServiceImpl implements SalBundleService {
-
+ private static final Logger LOG = LoggerFactory.getLogger(SalBundleServiceImpl.class);
private final SalExperimenterMessageService experimenterMessageService;
public SalBundleServiceImpl(final SalExperimenterMessageService experimenterMessageService) {
@Override
public ListenableFuture<RpcResult<ControlBundleOutput>> controlBundle(ControlBundleInput input) {
+ LOG.debug("Control message for device {} and bundle type {}", input.getNode(), input.getType());
final SendExperimenterInputBuilder experimenterInputBuilder = new SendExperimenterInputBuilder();
experimenterInputBuilder.setNode(input.getNode());
experimenterInputBuilder.setExperimenterMessageOfChoice(
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class SalExperimenterMessageServiceImpl extends AbstractSimpleService<SendExperimenterInput,
SendExperimenterOutput> implements SalExperimenterMessageService {
-
+ private static final Logger LOG = LoggerFactory.getLogger(SalExperimenterMessageServiceImpl.class);
private final ExtensionConverterProvider extensionConverterProvider;
public SalExperimenterMessageServiceImpl(final RequestContextStack requestContextStack,
ExtensionConvertorData> messageConverter = extensionConverterProvider.getMessageConverter(key);
if (messageConverter == null) {
+ LOG.warn("Unable to find message converter for experimenter xid {} for device {}", xid,
+ extractDatapathId(input.getNode()));
throw new ServiceException(new ConverterNotFoundException(key.toString()));
}
final ExperimenterInputBuilder experimenterInputBld;
.setVersion(getVersion())
.setXid(xid.getValue());
} catch (ConversionException e) {
+ LOG.warn("Error while building experimenter message with id {} and xid {} for device {}",
+ messageConverter.getExperimenterId(), xid, extractDatapathId(input.getNode()), e);
throw new ServiceException(e);
}
*/
package org.opendaylight.openflowplugin.impl.services.sal;
+import com.google.common.collect.EvictingQueue;
+import com.google.common.collect.Queues;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
+import java.util.Queue;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupStatus;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerFlowService;
import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
import org.opendaylight.openflowplugin.impl.util.FlowCreatorUtil;
+import org.opendaylight.openflowplugin.impl.util.PathUtil;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
private final SingleLayerFlowService<RemoveFlowOutput> flowRemoveMessage;
private final DeviceContext deviceContext;
private static final Uint8 OFPTT_ALL = Uint8.MAX_VALUE;
+ private final FlowGroupCacheManager provider;
+ public static final int FLOWGROUP_CACHE_SIZE = 10000;
+
public SalFlowServiceImpl(final RequestContextStack requestContextStack,
final DeviceContext deviceContext,
- final ConvertorExecutor convertorExecutor) {
+ final ConvertorExecutor convertorExecutor,
+ final FlowGroupCacheManager provider) {
this.deviceContext = deviceContext;
+ this.provider = provider;
flowRemove = new MultiLayerFlowService<>(requestContextStack,
deviceContext,
RemoveFlowOutput.class,
final FlowRegistryKey flowRegistryKey =
FlowRegistryKeyFactory.create(deviceContext.getDeviceInfo().getVersion(), input);
final ListenableFuture<RpcResult<AddFlowOutput>> future;
-
+ NodeId nodeId = PathUtil.extractNodeId(input.getNode());
if (flowAddMessage.canUseSingleLayerSerialization()) {
future = flowAddMessage.handleServiceCall(input);
- Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey), MoreExecutors.directExecutor());
+ Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey, nodeId),
+ MoreExecutors.directExecutor());
} else {
future = flowAdd.processFlowModInputBuilders(flowAdd.toFlowModInputs(input));
- Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey), MoreExecutors.directExecutor());
+ Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey, nodeId),
+ MoreExecutors.directExecutor());
}
return future;
@Override
public ListenableFuture<RpcResult<RemoveFlowOutput>> removeFlow(final RemoveFlowInput input) {
final ListenableFuture<RpcResult<RemoveFlowOutput>> future;
-
+ NodeId nodeId = PathUtil.extractNodeId(input.getNode());
if (flowRemoveMessage.canUseSingleLayerSerialization()) {
future = flowRemoveMessage.handleServiceCall(input);
- Futures.addCallback(future, new RemoveFlowCallback(input), MoreExecutors.directExecutor());
+ Futures.addCallback(future, new RemoveFlowCallback(input, nodeId), MoreExecutors.directExecutor());
} else {
future = flowRemove.processFlowModInputBuilders(flowRemove.toFlowModInputs(input));
- Futures.addCallback(future, new RemoveFlowCallback(input), MoreExecutors.directExecutor());
+ Futures.addCallback(future, new RemoveFlowCallback(input, nodeId), MoreExecutors.directExecutor());
}
return future;
public ListenableFuture<RpcResult<UpdateFlowOutput>> updateFlow(final UpdateFlowInput input) {
final UpdatedFlow updated = input.getUpdatedFlow();
final OriginalFlow original = input.getOriginalFlow();
-
+ String nodeId = PathUtil.extractNodeId(input.getNode()).getValue();
final List<FlowModInputBuilder> allFlowMods = new ArrayList<>();
final List<FlowModInputBuilder> ofFlowModInputs;
future = flowUpdate.processFlowModInputBuilders(allFlowMods);
}
- Futures.addCallback(future, new UpdateFlowCallback(input), MoreExecutors.directExecutor());
+ Futures.addCallback(future, new UpdateFlowCallback(input, nodeId), MoreExecutors.directExecutor());
return future;
}
private final class AddFlowCallback implements FutureCallback<RpcResult<AddFlowOutput>> {
private final AddFlowInput input;
private final FlowRegistryKey flowRegistryKey;
+ private final NodeId nodeId;
private AddFlowCallback(final AddFlowInput input,
- final FlowRegistryKey flowRegistryKey) {
+ final FlowRegistryKey flowRegistryKey,
+ final NodeId nodeId) {
this.input = input;
this.flowRegistryKey = flowRegistryKey;
+ this.nodeId = nodeId;
}
@Override
public void onSuccess(final RpcResult<AddFlowOutput> rpcResult) {
if (rpcResult.isSuccessful()) {
final FlowDescriptor flowDescriptor;
-
+ final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
+ FlowGroupCache cache = new FlowGroupCache(flowId.getValue(), input.getTableId().toString(),
+ FlowGroupStatus.ADDED, LocalDateTime.now());
+ if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+ provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+ } else {
+ Queue<FlowGroupCache> flowGroupCacheList =
+ Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+ flowGroupCacheList.add(cache);
+ provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+ }
if (input.getFlowRef() != null) {
- final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
flowDescriptor = FlowDescriptorFactory.create(input.getTableId(), flowId);
deviceContext.getDeviceFlowRegistry().storeDescriptor(flowRegistryKey, flowDescriptor);
} else {
private final class RemoveFlowCallback implements FutureCallback<RpcResult<RemoveFlowOutput>> {
private final RemoveFlowInput input;
+ private final NodeId nodeId;
- private RemoveFlowCallback(final RemoveFlowInput input) {
+ private RemoveFlowCallback(final RemoveFlowInput input, final NodeId nodeId) {
this.input = input;
+ this.nodeId = nodeId;
}
@Override
FlowRegistryKey flowRegistryKey =
FlowRegistryKeyFactory.create(deviceContext.getDeviceInfo().getVersion(), input);
deviceContext.getDeviceFlowRegistry().addMark(flowRegistryKey);
+ final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
+ FlowGroupCache cache = new FlowGroupCache(flowId.getValue(),
+ input.getTableId().toString(), FlowGroupStatus.REMOVED,
+ LocalDateTime.now());
+ if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+ provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+ } else {
+ Queue<FlowGroupCache> flowGroupCacheList =
+ Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+ flowGroupCacheList.add(cache);
+ provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+ }
} else {
deviceContext.getDeviceFlowRegistry().clearFlowRegistry();
}
private final class UpdateFlowCallback implements FutureCallback<RpcResult<UpdateFlowOutput>> {
private final UpdateFlowInput input;
+ private final String nodeId;
- private UpdateFlowCallback(UpdateFlowInput input) {
+ private UpdateFlowCallback(UpdateFlowInput input, String nodeId) {
this.input = input;
+ this.nodeId = nodeId;
}
@Override
public void onSuccess(final RpcResult<UpdateFlowOutput> updateFlowOutputRpcResult) {
final DeviceFlowRegistry deviceFlowRegistry = deviceContext.getDeviceFlowRegistry();
-
+ final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
final UpdatedFlow updated = input.getUpdatedFlow();
final OriginalFlow original = input.getOriginalFlow();
final FlowRegistryKey origFlowRegistryKey =
final boolean isUpdate = origFlowDescriptor != null;
final FlowDescriptor updatedFlowDescriptor;
+ FlowGroupCache cache = new FlowGroupCache(flowId.getValue(), updated.getTableId().toString(),
+ FlowGroupStatus.MODIFIED,
+ LocalDateTime.now());
+ if (provider.getAllNodesFlowGroupCache().containsKey(nodeId)) {
+ provider.getAllNodesFlowGroupCache().get(nodeId).add(cache);
+ } else {
+ Queue<FlowGroupCache> flowGroupCacheList =
+ Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+ flowGroupCacheList.add(cache);
+ provider.getAllNodesFlowGroupCache().put(nodeId, flowGroupCacheList);
+ }
if (input.getFlowRef() != null) {
updatedFlowDescriptor =
*/
package org.opendaylight.openflowplugin.impl.services.sal;
+import com.google.common.collect.EvictingQueue;
+import com.google.common.collect.Queues;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
+import java.time.LocalDateTime;
+import java.util.Queue;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupStatus;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerGroupService;
import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerGroupService;
import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
+import org.opendaylight.openflowplugin.impl.util.PathUtil;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final SingleLayerGroupService<RemoveGroupOutput> removeGroupMessage;
private final DeviceContext deviceContext;
+ private final FlowGroupCacheManager provider ;
+
+ public static final int FLOWGROUP_CACHE_SIZE = 10000;
public SalGroupServiceImpl(final RequestContextStack requestContextStack,
final DeviceContext deviceContext,
- final ConvertorExecutor convertorExecutor) {
+ final ConvertorExecutor convertorExecutor,
+ final FlowGroupCacheManager provider) {
this.deviceContext = deviceContext;
+ this.provider = provider;
addGroup = new MultiLayerGroupService<>(requestContextStack,
deviceContext,
AddGroupOutput.class,
addGroupMessage.canUseSingleLayerSerialization()
? addGroupMessage.handleServiceCall(input)
: addGroup.handleServiceCall(input);
-
+ String nodeId = PathUtil.extractNodeId(input.getNode()).getValue();
Futures.addCallback(resultFuture, new FutureCallback<RpcResult<AddGroupOutput>>() {
@Override
public void onSuccess(RpcResult<AddGroupOutput> result) {
if (result.isSuccessful()) {
- LOG.debug("adding group successful {}", input.getGroupId().getValue());
+ LOG.debug("adding group successful {}", input.getGroupId());
+ FlowGroupCache cache = new FlowGroupCache(input.getGroupId().toString(),
+ input.getGroupType().getName(), FlowGroupStatus.ADDED,
+ LocalDateTime.now());
+ if (provider.getAllNodesFlowGroupCache().containsKey(nodeId)) {
+ provider.getAllNodesFlowGroupCache().get(nodeId).add(cache);
+ } else {
+ Queue<FlowGroupCache> flowGroupCacheList =
+ Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+ flowGroupCacheList.add(cache);
+ provider.getAllNodesFlowGroupCache().put(nodeId, flowGroupCacheList);
+ }
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Group add with id={} failed, errors={}", input.getGroupId().getValue(),
@Override
public void onSuccess(RpcResult<UpdateGroupOutput> result) {
if (result.isSuccessful()) {
+ NodeId nodeId = PathUtil.extractNodeId(input.getNode());
+ FlowGroupCache cache = new FlowGroupCache(
+ input.getUpdatedGroup().getGroupId().getValue().toString(),
+ input.getUpdatedGroup().getGroupType().getName(), FlowGroupStatus.MODIFIED,
+ LocalDateTime.now());
+ if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+ provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+ } else {
+ Queue<FlowGroupCache> flowGroupCacheList =
+ Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+ flowGroupCacheList.add(cache);
+ provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+ }
if (LOG.isDebugEnabled()) {
LOG.debug("Group update with original id={} finished without error",
input.getOriginalGroup().getGroupId().getValue());
public void onSuccess(RpcResult<RemoveGroupOutput> result) {
if (result.isSuccessful()) {
if (LOG.isDebugEnabled()) {
+ NodeId nodeId = PathUtil.extractNodeId(input.getNode());
LOG.debug("Group remove with id={} finished without error", input.getGroupId().getValue());
+ FlowGroupCache cache = new FlowGroupCache(input.getGroupId().getValue().toString(),
+ input.getGroupType().getName(), FlowGroupStatus.REMOVED,
+ LocalDateTime.now());
+ if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+ provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+ } else {
+ Queue<FlowGroupCache> flowGroupCacheList =
+ Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+ flowGroupCacheList.add(cache);
+ provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+ }
}
} else {
LOG.warn("Group remove with id={} failed, errors={}", input.getGroupId().getValue(),
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.compatibility.Delegator;
public static void registerServices(@NonNull final RpcContext rpcContext,
@NonNull final DeviceContext deviceContext,
final ExtensionConverterProvider extensionConverterProvider,
- final ConvertorExecutor convertorExecutor) {
+ final ConvertorExecutor convertorExecutor,
+ final FlowGroupCacheManager flowGroupCacheManager) {
// TODO: Use multipart writer provider from device context
final MultipartWriterProvider multipartWriterProvider = MultipartWriterProviderFactory
.createDefaultProvider(deviceContext);
// create service instances
- final SalFlowServiceImpl salFlowService = new SalFlowServiceImpl(rpcContext, deviceContext, convertorExecutor);
+ final SalFlowServiceImpl salFlowService = new SalFlowServiceImpl(rpcContext, deviceContext,
+ convertorExecutor, flowGroupCacheManager);
final FlowCapableTransactionServiceImpl flowCapableTransactionService =
new FlowCapableTransactionServiceImpl(rpcContext, deviceContext);
final SalAsyncConfigServiceImpl salAsyncConfigService =
new SalAsyncConfigServiceImpl(rpcContext, deviceContext);
final SalGroupServiceImpl salGroupService =
- new SalGroupServiceImpl(rpcContext, deviceContext, convertorExecutor);
+ new SalGroupServiceImpl(rpcContext, deviceContext, convertorExecutor, flowGroupCacheManager);
final SalMeterServiceImpl salMeterService =
new SalMeterServiceImpl(rpcContext, deviceContext, convertorExecutor);
import org.opendaylight.openflowjava.protocol.api.connection.OpenflowDiagStatusProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderList;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty;
import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager;
@Mock
MastershipChangeServiceManager mastershipChangeServiceManager;
+ @Mock
+ FlowGroupCacheManager flowGroupCacheManager;
+
private static final int RPC_REQUESTS_QUOTA = 500;
private static final long GLOBAL_NOTIFICATION_QUOTA = 131072;
private static final Uint16 THREAD_POOL_MIN_THREADS = Uint16.ONE;
entityOwnershipService,
mastershipChangeServiceManager,
ofPluginDiagstatusProvider,
- systemReadyMonitor);
+ systemReadyMonitor,
+ flowGroupCacheManager);
provider.initialize();
// Calling the onSystemBootReady() callback
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
private static final int MAX_REQUESTS = 5;
private RpcContextImpl rpcContext;
-
+ @Mock
+ private FlowGroupCacheManager flowGroupCacheManager;
@Mock
private RpcProviderService rpcProviderRegistry;
@Mock
deviceContext,
extensionConverterProvider,
convertorExecutor,
- notificationPublishService, true);
+ notificationPublishService, true, flowGroupCacheManager);
when(rpcProviderRegistry.registerRpcImplementation(eq(TestRpcService.class), eq(serviceInstance), anySet()))
.thenReturn(routedRpcReg);
deviceContext,
extensionConverterProvider,
convertorExecutor,
- notificationPublishService, true)) {
+ notificationPublishService, true, flowGroupCacheManager)) {
final RequestContext<?> requestContext = rpcContext.createRequestContext();
assertNotNull(requestContext);
}
deviceContext,
extensionConverterProvider,
convertorExecutor,
- notificationPublishService, true)) {
+ notificationPublishService, true, flowGroupCacheManager)) {
final RequestContext<?> requestContext = rpcContext.createRequestContext();
assertNull(requestContext);
}
deviceContext,
extensionConverterProvider,
convertorExecutor,
- notificationPublishService, true)) {
+ notificationPublishService, true, flowGroupCacheManager)) {
final RequestContext<?> requestContext = rpcContext.createRequestContext();
assertNotNull(requestContext);
requestContext.close();
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
import org.opendaylight.mdsal.binding.api.RpcProviderService;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
private NotificationPublishService notificationPublishService;
@Mock
private KeyedInstanceIdentifier<Node, NodeKey> nodePath;
+ @Mock
+ private FlowGroupCacheManager flowGroupCacheManager;
private final NodeId nodeId = new NodeId("openflow-junit:1");
.setRpcRequestsQuota(new NonZeroUint16Type(QUOTA_VALUE))
.setIsStatisticsRpcEnabled(false)
.build(),
- rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService);
+ rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService,
+ flowGroupCacheManager);
FeaturesReply features = new GetFeaturesOutputBuilder()
.setVersion(OFConstants.OFP_VERSION_1_3)
*/
package org.opendaylight.openflowplugin.impl.services.sal;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.common.util.concurrent.Futures;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import junit.framework.TestCase;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupStatus;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.services.cache.FlowGroupCacheManagerImpl;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
private static final KeyedInstanceIdentifier<Table, TableKey> TABLE_II
= NODE_II.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(DUMMY_TABLE_ID));
+ private NodeRef noderef = new NodeRef(NODE_II);
+ private static final String KEY = "0";
+ private static FlowGroupCache flowcache =
+ new FlowGroupCache("0","mock class", FlowGroupStatus.ADDED, LocalDateTime.MAX);
+
+ private static Queue<FlowGroupCache> caches() {
+ Queue<FlowGroupCache> cache = new LinkedList<>();
+ cache.add(flowcache);
+ return cache;
+ }
+
+ private static final Queue<FlowGroupCache> CACHE = caches();
+
+ private static Map<String, Queue<FlowGroupCache>> createMap() {
+ Map<String,Queue<FlowGroupCache>> myMap = new HashMap<>();
+ myMap.put(KEY, CACHE);
+ return myMap;
+ }
+
+ private static final Map<String, Queue<FlowGroupCache>> MYMAP = createMap();
+
@Mock
private RequestContextStack mockedRequestContextStack;
@Mock
private DeviceFlowRegistry deviceFlowRegistry;
@Mock
private GetFeaturesOutput mockedFeaturesOutput;
+ @Mock
+ private FlowGroupCacheManagerImpl flowGroupCacheManager;
@Before
public void initialization() {
when(mockedDeviceInfo.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
+ when(flowGroupCacheManager.getAllNodesFlowGroupCache()).thenReturn(MYMAP);
}
private SalFlowServiceImpl mockSalFlowService(final short version) {
when(mockedDeviceInfo.getVersion()).thenReturn(version);
final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
- return new SalFlowServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager);
+ return new SalFlowServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager,
+ flowGroupCacheManager);
}
@Test
AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
.setMatch(match)
.setTableId((short)1)
+ .setNode(noderef)
.build();
Mockito.doReturn(Futures.<RequestContext<Object>>immediateFailedFuture(new Exception("ut-failed-response")))
.when(requestContext).getFuture();
- mockingFlowRegistryLookup();
final Future<RpcResult<AddFlowOutput>> rpcResultFuture =
mockSalFlowService(version).addFlow(mockedAddFlowInput);
RemoveFlowInput mockedRemoveFlowInput = new RemoveFlowInputBuilder()
.setTableId((short)1)
.setMatch(match)
+ .setNode(noderef)
.build();
Mockito.doReturn(Futures.<RequestContext<Object>>immediateFailedFuture(new Exception("ut-failed-response")))
AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
.setMatch(match)
.setTableId((short)1)
+ .setNode(noderef)
.build();
SalFlowServiceImpl salFlowService = mockSalFlowService(version);
- mockingFlowRegistryLookup();
verifyOutput(salFlowService.addFlow(mockedAddFlowInput));
}
RemoveFlowInput mockedRemoveFlowInput = new RemoveFlowInputBuilder()
.setMatch(match)
.setTableId((short)1)
+ .setNode(noderef)
.build();
SalFlowServiceImpl salFlowService = mockSalFlowService(version);
when(mockedUpdateFlowInput1.getOriginalFlow()).thenReturn(mockedOriginalFlow1);
SalFlowServiceImpl salFlowService = mockSalFlowService(version);
-
+ when(mockedUpdateFlowInput.getNode()).thenReturn(noderef);
+ when(mockedUpdateFlowInput1.getNode()).thenReturn(noderef);
verifyOutput(salFlowService.updateFlow(mockedUpdateFlowInput));
verifyOutput(salFlowService.updateFlow(mockedUpdateFlowInput1));
}
- private void mockingFlowRegistryLookup() {
- FlowDescriptor mockedFlowDescriptor = mock(FlowDescriptor.class);
- FlowId flowId = new FlowId(DUMMY_FLOW_ID);
- when(mockedFlowDescriptor.getFlowId()).thenReturn(flowId);
-
- when(deviceFlowRegistry
- .retrieveDescriptor(any(FlowRegistryKey.class))).thenReturn(mockedFlowDescriptor);
- }
-
private static <T extends DataObject> void verifyOutput(final Future<RpcResult<T>> rpcResultFuture)
throws ExecutionException, InterruptedException {
assertNotNull(rpcResultFuture);
import org.junit.Test;
import org.mockito.Mock;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
public class SalGroupServiceImplTest extends ServiceMocking {
private static final Long DUMMY_GROUP_ID = 15L;
+ private static final
+ KeyedInstanceIdentifier<Node, NodeKey> NODE_II = InstanceIdentifier.create(Nodes.class).child(Node.class,
+ new NodeKey(new NodeId(DUMMY_NODE_ID)));
+ NodeRef noderef = new NodeRef(NODE_II);
@Mock
DeviceGroupRegistry mockedDeviceGroupRegistry;
+ FlowGroupCacheManager flowGroupCacheManager;
SalGroupServiceImpl salGroupService;
@Override
protected void setup() {
final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
- salGroupService = new SalGroupServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager);
+ salGroupService = new SalGroupServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager,
+ flowGroupCacheManager);
}
@Test
private void addGroup() {
final GroupId dummyGroupId = new GroupId(DUMMY_GROUP_ID);
- AddGroupInput addGroupInput = new AddGroupInputBuilder().setGroupId(dummyGroupId).build();
+ AddGroupInput addGroupInput = new AddGroupInputBuilder().setGroupId(dummyGroupId).setNode(noderef).build();
this.<AddGroupOutput>mockSuccessfulFuture();
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
private NotificationPublishService notificationPublishService;
private ConvertorManager convertorManager;
+ private FlowGroupCacheManager flowGroupCacheManager;
@Before
public void setUp() {
MdSalRegistrationUtils.registerServices(mockedRpcContext,
mockedDeviceContext,
extensionConverterProvider,
- convertorManager);
+ convertorManager,
+ flowGroupCacheManager);
verify(mockedRpcContext, times(NUMBER_OF_RPC_SERVICE_REGISTRATION)).registerRpcServiceImplementation(
any(), any(RpcService.class));
}