[ONOS-5487] Implementation skeleton for VirtualFlowProvider.
Changes
1. The default code is added as DefaultVirtualFlowProvider
2. EmbeddingAlgorithm interface is added
3. Simple test code is added
Change-Id: I4f86898b6c78e23909b172f75d4bafc8367cc8b7
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/InternalRoutingAlgorithm.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/InternalRoutingAlgorithm.java
new file mode 100644
index 0000000..84c10a5
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/InternalRoutingAlgorithm.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.provider;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Path;
+
+/**
+ * Abstraction of an embedding algorithm used for embedding virtual objects
+ * into the underlying physical network.
+ */
+public interface InternalRoutingAlgorithm {
+ /**
+ * Find a route between two connect points (i.e. ports)
+ * according to the own logic.
+ *
+ * @param src A start point
+ * @param dst A sink point
+ * @return The path between src and dst calculated from the algorithm
+ */
+ Path findPath(ConnectPoint src, ConnectPoint dst);
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderRegistryService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderRegistryService.java
index 05625e9..701680d 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderRegistryService.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualProviderRegistryService.java
@@ -110,12 +110,13 @@
VirtualProvider getProvider(String scheme);
/**
- * Returns the virtual provider service corresponding to the virtual network and provider.
+ * Returns a virtual provider service corresponding to
+ * the virtual network and provider class type.
*
* @param networkId a virtual network identifier
- * @param virtualProvider a virtual provider
+ * @param providerClass a type of virtual provider
* @return a virtual provider service
*/
VirtualProviderService getProviderService(NetworkId networkId,
- VirtualProvider virtualProvider);
+ Class<? extends VirtualProvider> providerClass);
}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProvider.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProvider.java
new file mode 100644
index 0000000..320d167
--- /dev/null
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProvider.java
@@ -0,0 +1,665 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.impl.provider;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+import javafx.util.Pair;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.incubator.net.virtual.VirtualPort;
+import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
+import org.onosproject.incubator.net.virtual.provider.InternalRoutingAlgorithm;
+import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProvider;
+import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProviderService;
+import org.onosproject.incubator.net.virtual.provider.VirtualProviderRegistryService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.FlowRuleEvent;
+import org.onosproject.net.flow.FlowRuleListener;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.topology.TopologyService;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provider that translate virtual flow rules into physical rules.
+ * Current implementation is based on FlowRules.
+ * This virtualize and de-virtualize virtual flow rules into physical flow rules.
+ * {@link org.onosproject.net.flow.FlowRule}
+ */
+@Component(immediate = true)
+@Service
+public class DefaultVirtualFlowRuleProvider extends AbstractVirtualProvider
+ implements VirtualFlowRuleProvider {
+
+ private static final int FLOW_RULE_PRIORITY = 10;
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TopologyService topologyService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VirtualNetworkAdminService virtualNetworkAdminService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowRuleService flowRuleService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VirtualProviderRegistryService providerRegistryService;
+
+ InternalRoutingAlgorithm internalRoutingAlgorithm;
+ InternalVirtualFlowRuleManager frm;
+ ApplicationId appId;
+ FlowRuleListener flowRuleListener;
+
+ /**
+ * Creates a provider with the supplied identifier.
+ */
+ public DefaultVirtualFlowRuleProvider() {
+ super(new ProviderId("vnet-flow", "org.onosproject.virtual.vnet-flow"));
+ }
+
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication(
+ "org.onosproject.virtual.vnet-flow");
+
+ providerRegistryService.registerProvider(this);
+
+ flowRuleListener = new InternalFlowRuleListener();
+ flowRuleService.addListener(flowRuleListener);
+
+ internalRoutingAlgorithm = new DefaultInternalRoutingAlgorithm();
+ frm = new InternalVirtualFlowRuleManager();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ flowRuleService.removeListener(flowRuleListener);
+ providerRegistryService.unregisterProvider(this);
+ }
+
+ @Modified
+ protected void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+ }
+
+ @Override
+ public void applyFlowRule(NetworkId networkId, FlowRule... flowRules) {
+ for (FlowRule flowRule : flowRules) {
+ devirtualize(networkId, flowRule).forEach(
+ r -> {
+ flowRuleService.applyFlowRules(r);
+ }
+ );
+ }
+ }
+
+ @Override
+ public void removeFlowRule(NetworkId networkId, FlowRule... flowRules) {
+ for (FlowRule flowRule : flowRules) {
+ devirtualize(networkId, flowRule).forEach(
+ r -> {
+ flowRuleService.removeFlowRules(r);
+ }
+ );
+ }
+ }
+
+ @Override
+ public void executeBatch(NetworkId networkId, FlowRuleBatchOperation batch) {
+ checkNotNull(batch);
+
+ //TODO: execute batch mechanism
+ }
+
+ public void setEmbeddingAlgorithm(InternalRoutingAlgorithm
+ internalRoutingAlgorithm) {
+ this.internalRoutingAlgorithm = internalRoutingAlgorithm;
+ }
+
+ /**
+ * Translate the requested physical flow rules into virtual flow rules.
+ *
+ * @param flowRule A virtual flow rule to be translated
+ * @return A flow rule for a specific virtual network
+ */
+ private FlowRule virtualize(FlowRule flowRule) {
+ return frm.getVirtualRule(flowRule);
+ }
+
+ private FlowEntry virtualize(FlowEntry flowEntry) {
+ FlowRule vRule = virtualize(flowEntry);
+ FlowEntry vEntry = new DefaultFlowEntry(vRule, flowEntry.state(),
+ flowEntry.life(),
+ flowEntry.packets(),
+ flowEntry.bytes());
+
+ return vEntry;
+ }
+
+ /**
+ * Translate the requested virtual flow rules into physical flow rules.
+ * The translation could be one to many.
+ *
+ * @param flowRule A flow rule from underlying data plane to be translated
+ * @return A set of flow rules for physical network
+ */
+ private Set<FlowRule> devirtualize(NetworkId networkId, FlowRule flowRule) {
+
+ Set<FlowRule> outRules = new HashSet<>();
+
+ Set<VirtualPort> vPorts = virtualNetworkAdminService
+ .getVirtualPorts(networkId, flowRule.deviceId());
+
+ PortCriterion portCriterion = ((PortCriterion) flowRule.selector()
+ .getCriterion(Criterion.Type.IN_PORT));
+
+ Set<ConnectPoint> ingressPoints = new HashSet<>();
+ if (portCriterion != null) {
+ PortNumber vInPortNum = portCriterion.port();
+
+ Optional<ConnectPoint> optionalCp = vPorts.stream()
+ .filter(v -> v.number().equals(vInPortNum))
+ .map(v -> v.realizedBy()).findFirst();
+ if (!optionalCp.isPresent()) {
+ log.info("Port {} is not realized yet, in Network {}, Device {}",
+ vInPortNum, networkId, flowRule.deviceId());
+ return outRules;
+ }
+ ingressPoints.add(optionalCp.get());
+ } else {
+ for (VirtualPort vPort : vPorts) {
+ if (vPort.realizedBy() != null) {
+ ingressPoints.add(vPort.realizedBy());
+ } else {
+ log.info("Port {} is not realized yet, in Network {}, " +
+ "Device {}",
+ vPort, networkId, flowRule.deviceId());
+ return outRules;
+ }
+ }
+ }
+
+ PortNumber vOutPortNum = flowRule.treatment().allInstructions().stream()
+ .filter(i -> i.type() == Instruction.Type.OUTPUT)
+ .map(i -> ((Instructions.OutputInstruction) i).port())
+ .findFirst().get();
+
+ Optional<ConnectPoint> optionalCpOut = vPorts.stream()
+ .filter(v -> v.number().equals(vOutPortNum))
+ .map(v -> v.realizedBy())
+ .findFirst();
+ if (!optionalCpOut.isPresent()) {
+ log.info("Port {} is not realized yet, in Network {}, Device {}",
+ vOutPortNum, networkId, flowRule.deviceId());
+ return outRules;
+ }
+ ConnectPoint egressPoint = optionalCpOut.get();
+
+ TrafficSelector.Builder commonSelectorBuilder
+ = DefaultTrafficSelector.builder();
+ flowRule.selector().criteria().stream()
+ .filter(c -> c.type() != Criterion.Type.IN_PORT)
+ .forEach(c -> commonSelectorBuilder.add(c));
+ TrafficSelector commonSelector = commonSelectorBuilder.build();
+
+ TrafficTreatment.Builder commonTreatmentBuilder
+ = DefaultTrafficTreatment.builder();
+ flowRule.treatment().allInstructions().stream()
+ .filter(i -> i.type() != Instruction.Type.OUTPUT)
+ .forEach(i -> commonTreatmentBuilder.add(i));
+ TrafficTreatment commonTreatment = commonTreatmentBuilder.build();
+
+ for (ConnectPoint ingressPoint : ingressPoints) {
+ outRules.addAll(generateRules(networkId, ingressPoint, egressPoint,
+ commonSelector, commonTreatment, flowRule));
+ }
+
+ return outRules;
+ }
+
+ private Set<FlowRule> generateRules(NetworkId networkId,
+ ConnectPoint ingressPoint,
+ ConnectPoint egressPoint,
+ TrafficSelector commonSelector,
+ TrafficTreatment commonTreatment,
+ FlowRule flowRule) {
+
+ Set<FlowRule> outRules = new HashSet<>();
+
+ if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
+ //Traffic is handled inside a single physical switch
+ //No tunnel is needed.
+
+ TrafficSelector.Builder selectorBuilder =
+ DefaultTrafficSelector.builder(commonSelector);
+ selectorBuilder.matchInPort(ingressPoint.port());
+
+ TrafficTreatment.Builder treatmentBuilder =
+ DefaultTrafficTreatment.builder(commonTreatment);
+ treatmentBuilder.setOutput(egressPoint.port());
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder();
+ ruleBuilder.fromApp(appId);
+ ruleBuilder.forDevice(ingressPoint.deviceId());
+ ruleBuilder.withSelector(selectorBuilder.build());
+ ruleBuilder.withTreatment(treatmentBuilder.build());
+ ruleBuilder.withPriority(FLOW_RULE_PRIORITY);
+ if (flowRule.isPermanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(flowRule.timeout());
+ }
+
+ FlowRule rule = ruleBuilder.build();
+ frm.addIngressRule(flowRule, rule, networkId);
+ outRules.add(ruleBuilder.build());
+ } else {
+ //Traffic is handled by multiple physical switches
+ //A tunnel is needed.
+
+ Path internalPath = internalRoutingAlgorithm
+ .findPath(ingressPoint, egressPoint);
+ checkNotNull(internalPath, "No path between " +
+ ingressPoint.toString() + " " + egressPoint.toString());
+ ConnectPoint inCp = ingressPoint;
+ ConnectPoint outCp = internalPath.links().get(0).src();
+
+ //ingress point of tunnel
+ TrafficSelector.Builder selectorBuilder =
+ DefaultTrafficSelector.builder(commonSelector);
+ selectorBuilder.matchInPort(ingressPoint.port());
+
+ TrafficTreatment.Builder treatmentBuilder =
+ DefaultTrafficTreatment.builder(commonTreatment);
+ treatmentBuilder.pushVlan()
+ .setVlanId(VlanId.vlanId(networkId.id().shortValue()));
+ treatmentBuilder.setOutput(outCp.port());
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder();
+ ruleBuilder.fromApp(appId);
+ ruleBuilder.forDevice(ingressPoint.deviceId());
+ ruleBuilder.withSelector(selectorBuilder.build());
+ ruleBuilder.withTreatment(treatmentBuilder.build());
+ ruleBuilder.withPriority(FLOW_RULE_PRIORITY);
+ if (flowRule.isPermanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(flowRule.timeout());
+ }
+
+ FlowRule rule = ruleBuilder.build();
+ frm.addIngressRule(flowRule, rule, networkId);
+ outRules.add(ruleBuilder.build());
+
+ //routing inside tunnel
+ inCp = internalPath.links().get(0).dst();
+
+ if (internalPath.links().size() > 1) {
+ for (Link l : internalPath.links()
+ .subList(1, internalPath.links().size() - 1)) {
+
+ outCp = l.src();
+
+ selectorBuilder = DefaultTrafficSelector
+ .builder(commonSelector);
+ selectorBuilder.matchVlanId(
+ VlanId.vlanId(networkId.id().shortValue()));
+ selectorBuilder.matchInPort(inCp.port());
+
+ treatmentBuilder = DefaultTrafficTreatment
+ .builder(commonTreatment);
+ treatmentBuilder.setOutput(outCp.port());
+
+ ruleBuilder = DefaultFlowRule.builder();
+ ruleBuilder.fromApp(appId);
+ ruleBuilder.forDevice(inCp.deviceId());
+ ruleBuilder.withSelector(selectorBuilder.build());
+ ruleBuilder.withTreatment(treatmentBuilder.build());
+ if (flowRule.isPermanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(flowRule.timeout());
+ }
+
+ outRules.add(ruleBuilder.build());
+ inCp = l.dst();
+ }
+ }
+
+ //egress point of tunnel
+ selectorBuilder = DefaultTrafficSelector.builder(commonSelector);
+ selectorBuilder.matchVlanId(
+ VlanId.vlanId(networkId.id().shortValue()));
+ selectorBuilder.matchInPort(ingressPoint.port());
+
+ treatmentBuilder = DefaultTrafficTreatment.builder(commonTreatment);
+ treatmentBuilder.popVlan();
+ treatmentBuilder.setOutput(egressPoint.port());
+
+ ruleBuilder = DefaultFlowRule.builder();
+ ruleBuilder.fromApp(appId);
+ ruleBuilder.forDevice(egressPoint.deviceId());
+ ruleBuilder.withSelector(selectorBuilder.build());
+ ruleBuilder.withTreatment(treatmentBuilder.build());
+ ruleBuilder.withPriority(FLOW_RULE_PRIORITY);
+ if (flowRule.isPermanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(flowRule.timeout());
+ }
+
+ outRules.add(ruleBuilder.build());
+ }
+
+ return outRules;
+ }
+
+ private class InternalFlowRuleListener implements FlowRuleListener {
+ @Override
+ public void event(FlowRuleEvent event) {
+
+ if ((event.type() == FlowRuleEvent.Type.RULE_ADDED) ||
+ (event.type() == FlowRuleEvent.Type.RULE_UPDATED)) {
+ if (frm.isVirtualIngressRule(event.subject())) {
+ NetworkId networkId = frm.getVirtualNetworkId(event.subject());
+ FlowEntry vEntry = getVirtualFlowEntry(event.subject());
+ ImmutableList.Builder<FlowEntry> builder = ImmutableList.builder();
+ builder.add(vEntry);
+
+ VirtualFlowRuleProviderService providerService =
+ (VirtualFlowRuleProviderService) providerRegistryService
+ .getProviderService(networkId,
+ VirtualFlowRuleProvider.class);
+
+ providerService.pushFlowMetrics(vEntry.deviceId(), builder.build());
+ }
+ } else if (event.type() == FlowRuleEvent.Type.RULE_REMOVED) {
+ if (frm.isVirtualIngressRule(event.subject())) {
+ //FIXME confirm all physical rules are removed
+ NetworkId networkId = frm.getVirtualNetworkId(event.subject());
+ FlowEntry vEntry = getVirtualFlowEntry(event.subject());
+
+ VirtualFlowRuleProviderService providerService =
+ (VirtualFlowRuleProviderService) providerRegistryService
+ .getProviderService(networkId,
+ VirtualFlowRuleProvider.class);
+ providerService.flowRemoved(vEntry);
+
+ }
+ }
+ }
+
+ private FlowEntry getVirtualFlowEntry(FlowRule rule) {
+ FlowEntry entry = null;
+ for (FlowEntry fe :
+ flowRuleService.getFlowEntries(rule.deviceId())) {
+ if (rule.exactMatch(fe)) {
+ entry = fe;
+ }
+ }
+
+ FlowRule vRule = virtualize(entry);
+ FlowEntry vEntry = new DefaultFlowEntry(vRule, entry.state(),
+ entry.life(), entry.packets(),
+ entry.bytes());
+
+ return vEntry;
+ }
+ }
+
+ private class InternalVirtualFlowRuleManager {
+ /** <Virtual Network ID, Virtual Device ID, Virtual Flow Rules>.*/
+ final Table<NetworkId, DeviceId, Set<FlowRule>> flowRuleTable
+ = HashBasedTable.create();
+
+ /** <Virtual Network ID, Virtual Device ID, Virtual Flow Rules>.*/
+ final Table<NetworkId, DeviceId, Set<FlowRule>> missingFlowRuleTable
+ = HashBasedTable.create();
+
+ /** <Virtual Network ID, Virtual Device ID, Virtual Flow Entries>.*/
+ final Table<NetworkId, DeviceId, Set<FlowEntry>> flowEntryTable
+ = HashBasedTable.create();
+
+ /** <Physical Flow Rule, Virtual Network ID>.*/
+ final Map<FlowRule, NetworkId> ingressRuleMap = Maps.newConcurrentMap();
+
+ /** <Physical Flow Rule, Virtual Virtual Flow Rule>.*/
+ final Map<FlowRule, FlowRule> virtualizationMap = Maps.newConcurrentMap();
+
+ private int getFlowRuleCount(NetworkId networkId, DeviceId deviceId) {
+ return flowRuleTable.get(networkId, deviceId).size();
+ }
+
+ private int getMissingFlowCount(NetworkId networkId, DeviceId deviceId) {
+ return missingFlowRuleTable.get(networkId, deviceId).size();
+ }
+
+ private int getFlowEntryCount(NetworkId networkId, DeviceId deviceId) {
+ return flowEntryTable.get(networkId, deviceId).size();
+ }
+
+ private Iterable<FlowRule> getFlowRules(NetworkId networkId,
+ DeviceId deviceId) {
+ return flowRuleTable.get(networkId, deviceId);
+ }
+
+ private Iterable<FlowEntry> getFlowEntries(NetworkId networkId,
+ DeviceId deviceId) {
+ return flowEntryTable.get(networkId, deviceId);
+ }
+
+ private void addFlowRule(NetworkId networkId, DeviceId deviceId,
+ FlowRule flowRule) {
+ Set<FlowRule> set = flowRuleTable.get(networkId, deviceId);
+ if (set == null) {
+ set = Sets.newHashSet();
+ flowRuleTable.put(networkId, deviceId, set);
+ }
+ set.add(flowRule);
+ }
+
+ private void removeFlowRule(NetworkId networkId, DeviceId deviceId,
+ FlowRule flowRule) {
+ Set<FlowRule> set = flowRuleTable.get(networkId, deviceId);
+ if (set == null) {
+ return;
+ }
+ set.remove(flowRule);
+ }
+
+ private Set<FlowRule> getMissingRules(NetworkId networkId,
+ DeviceId deviceId) {
+ return missingFlowRuleTable.get(networkId, deviceId);
+ }
+
+ private void addMissingFlowRule(NetworkId networkId, DeviceId deviceId,
+ FlowRule flowRule) {
+ Set<FlowRule> set = missingFlowRuleTable.get(networkId, deviceId);
+ if (set == null) {
+ set = Sets.newHashSet();
+ missingFlowRuleTable.put(networkId, deviceId, set);
+ }
+ set.add(flowRule);
+ }
+
+ private void removeMissingFlowRule(NetworkId networkId, DeviceId deviceId,
+ FlowRule flowRule) {
+ Set<FlowRule> set = missingFlowRuleTable.get(networkId, deviceId);
+ if (set == null) {
+ return;
+ }
+ set.remove(flowRule);
+ }
+
+ private void addFlowEntry(NetworkId networkId, DeviceId deviceId,
+ FlowEntry flowEntry) {
+ Set<FlowEntry> set = flowEntryTable.get(networkId, deviceId);
+ if (set == null) {
+ set = Sets.newHashSet();
+ flowEntryTable.put(networkId, deviceId, set);
+ }
+
+ //Replace old entry with new one
+ set.stream().filter(fe -> fe.exactMatch(flowEntry))
+ .forEach(set::remove);
+ set.add(flowEntry);
+
+ //Remove old entry from missing flow
+ getMissingRules(networkId, deviceId).stream()
+ .filter(fr -> fr.exactMatch(flowEntry))
+ .forEach(fr -> removeMissingFlowRule(networkId, deviceId, fr));
+ }
+
+ private void removeFlowEntry(NetworkId networkId, DeviceId deviceId,
+ FlowEntry flowEntry) {
+ Set<FlowEntry> set = flowEntryTable.get(networkId, deviceId);
+ if (set == null) {
+ return;
+ }
+ set.remove(flowEntry);
+ }
+
+ private void addIngressRule(FlowRule virtualRule, FlowRule physicalRule,
+ NetworkId networkId) {
+ ingressRuleMap.put(physicalRule, networkId);
+ virtualizationMap.put(physicalRule, virtualRule);
+ }
+
+ private FlowRule getVirtualRule(FlowRule physicalRule) {
+ return virtualizationMap.get(physicalRule);
+ }
+
+ private Set<FlowRule> getAllPhysicalRule() {
+ return ImmutableSet.copyOf(virtualizationMap.keySet());
+ }
+
+ private NetworkId getVirtualNetworkId(FlowRule physicalRule) {
+ return ingressRuleMap.get(physicalRule);
+ }
+
+ /**
+ * Test the rule is the ingress rule for virtual rules.
+ *
+ * @param flowRule A flow rule from underlying data plane to be translated
+ * @return True when the rule is for ingress point for a virtual switch
+ */
+ private boolean isVirtualIngressRule(FlowRule flowRule) {
+ return ingressRuleMap.containsKey(flowRule);
+ }
+
+ private Set<Pair<NetworkId, DeviceId>> getCompletedDevice(boolean
+ withMissing) {
+
+ Set<Pair<NetworkId, DeviceId>> completed = new HashSet<>();
+
+ for (Table.Cell<NetworkId, DeviceId, Set<FlowRule>> cell
+ : flowRuleTable.cellSet()) {
+
+ int ruleCount = getFlowRuleCount(cell.getRowKey(),
+ cell.getColumnKey());
+ int missingFlowCount = getMissingFlowCount(cell.getRowKey(),
+ cell.getColumnKey());
+ int entryCount = getFlowEntryCount(cell.getRowKey(),
+ cell.getColumnKey());
+
+ if (withMissing && (ruleCount == missingFlowCount + entryCount)) {
+ if (ruleCount < entryCount) {
+ completed.add(new Pair<>(cell.getRowKey(),
+ cell.getColumnKey()));
+ }
+ } else if (ruleCount == entryCount) {
+ completed.add(new Pair<>(cell.getRowKey(),
+ cell.getColumnKey()));
+ }
+ }
+ return completed;
+ }
+ }
+
+ private class DefaultInternalRoutingAlgorithm
+ implements InternalRoutingAlgorithm {
+
+ @Override
+ public Path findPath(ConnectPoint src, ConnectPoint dst) {
+ Set<Path> paths =
+ topologyService.getPaths(topologyService.currentTopology(),
+ src.deviceId(),
+ dst.deviceId());
+
+ if (paths.isEmpty()) {
+ return null;
+ }
+
+ //TODO the logic find the best path
+ return (Path) paths.toArray()[0];
+ }
+ }
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManager.java
index 40a791f..c822066 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManager.java
@@ -137,7 +137,7 @@
@Override
public synchronized VirtualProviderService
- getProviderService(NetworkId networkId, VirtualProvider virtualProvider) {
+ getProviderService(NetworkId networkId, Class<? extends VirtualProvider> providerClass) {
Set<VirtualProviderService> services = servicesByNetwork.get(networkId);
if (services == null) {
@@ -145,7 +145,7 @@
}
return services.stream()
- .filter(s -> getProviderClass(s).isInstance(virtualProvider))
+ .filter(s -> getProviderClass(s).equals(providerClass))
.findFirst().get();
}
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
index 40658bd..0afc6ea 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
@@ -164,9 +164,9 @@
vnetFlowRuleService2.deviceInstallers = MoreExecutors.newDirectExecutorService();
providerService1 = (VirtualFlowRuleProviderService)
- providerRegistryService.getProviderService(vnet1.id(), provider);
+ providerRegistryService.getProviderService(vnet1.id(), VirtualFlowRuleProvider.class);
providerService2 = (VirtualFlowRuleProviderService)
- providerRegistryService.getProviderService(vnet2.id(), provider);
+ providerRegistryService.getProviderService(vnet2.id(), VirtualFlowRuleProvider.class);
}
@After
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProviderTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProviderTest.java
new file mode 100644
index 0000000..f135464
--- /dev/null
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProviderTest.java
@@ -0,0 +1,663 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.impl.provider;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.core.Version;
+import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
+import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
+import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualHost;
+import org.onosproject.incubator.net.virtual.VirtualLink;
+import org.onosproject.incubator.net.virtual.VirtualNetwork;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.incubator.net.virtual.VirtualPort;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.DefaultPort;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.DisjointPath;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceServiceAdapter;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleListener;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TableStatisticsEntry;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.topology.ClusterId;
+import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.net.topology.TopologyCluster;
+import org.onosproject.net.topology.TopologyGraph;
+import org.onosproject.net.topology.TopologyListener;
+import org.onosproject.net.topology.TopologyService;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+
+public class DefaultVirtualFlowRuleProviderTest {
+ private static final ProviderId PID = new ProviderId("of", "foo");
+
+ private static final DeviceId DID1 = DeviceId.deviceId("of:001");
+ private static final DeviceId DID2 = DeviceId.deviceId("of:002");
+ private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
+ private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);
+
+ private static final DefaultAnnotations ANNOTATIONS =
+ DefaultAnnotations.builder().set("foo", "bar").build();
+
+ private static final Device DEV1 =
+ new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
+ private static final Device DEV2 =
+ new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
+ private static final Port PORT11 =
+ new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
+ private static final Port PORT12 =
+ new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
+ private static final Port PORT21 =
+ new DefaultPort(DEV2, PORT_NUM1, true, ANNOTATIONS);
+ private static final Port PORT22 =
+ new DefaultPort(DEV2, PORT_NUM2, true, ANNOTATIONS);
+
+ private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
+ private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
+ private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM1);
+ private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM2);
+ private static final Link LINK1 = DefaultLink.builder()
+ .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();
+
+ private static final NetworkId VNET_ID = NetworkId.networkId(1);
+ private static final DeviceId VDID = DeviceId.deviceId("of:100");
+
+ private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
+ VNET_ID, TenantId.tenantId("t1"));
+ private static final VirtualDevice VDEV =
+ new DefaultVirtualDevice(VNET_ID, VDID);
+ private static final VirtualPort VPORT1 =
+ new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM1, CP11);
+ private static final VirtualPort VPORT2 =
+ new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM2, CP22);
+
+ private static final int TIMEOUT = 10;
+
+
+ protected DefaultVirtualFlowRuleProvider virtualProvider;
+
+ private ApplicationId vAppId;
+
+ @Before
+ public void setUp() {
+ virtualProvider = new DefaultVirtualFlowRuleProvider();
+
+ virtualProvider.deviceService = new TestDeviceService();
+ virtualProvider.coreService = new TestCoreService();
+ virtualProvider.virtualNetworkAdminService =
+ new TestVirtualNetworkAdminService();
+ virtualProvider.topologyService = new TestTopologyService();
+ virtualProvider.flowRuleService = new TestFlowRuleService();
+ virtualProvider.providerRegistryService = new VirtualProviderManager();
+
+ virtualProvider.activate();
+ vAppId = new TestApplicationId(0, "Virtual App");
+ }
+
+ @After
+ public void tearDown() {
+ virtualProvider.deactivate();
+ virtualProvider.deviceService = null;
+ virtualProvider.coreService = null;
+ }
+
+ @Test
+ public void virtualizeFlowRuleWithInPort() {
+ TrafficSelector ts = DefaultTrafficSelector.builder()
+ .matchInPort(PORT_NUM1).build();
+ TrafficTreatment tr = DefaultTrafficTreatment.builder()
+ .setOutput(PORT_NUM2).build();
+
+ FlowRule r1 = DefaultFlowRule.builder()
+ .forDevice(VDID)
+ .withSelector(ts)
+ .withTreatment(tr)
+ .withPriority(10)
+ .fromApp(vAppId)
+ .makeTemporary(TIMEOUT)
+ .build();
+
+ virtualProvider.applyFlowRule(VNET_ID, r1);
+
+ assertEquals("2 rules should exist", 2,
+ virtualProvider.flowRuleService.getFlowRuleCount());
+
+ Set<FlowEntry> phyRules = new HashSet<>();
+ for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
+ phyRules.add(i);
+ }
+ for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
+ phyRules.add(i);
+ }
+
+ FlowRule in = null;
+ FlowRule out = null;
+
+ for (FlowRule rule : phyRules) {
+
+ L2ModificationInstruction i = (L2ModificationInstruction)
+ rule.treatment().allInstructions().get(0);
+
+ if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
+ in = rule;
+ } else {
+ out = rule;
+ }
+
+ }
+
+ assertEquals(DID1, in.deviceId());
+ assertEquals(DID2, out.deviceId());
+ }
+
+ @Test
+ public void virtualizeFlowRuleWithoutInPort() {
+ TrafficSelector ts = DefaultTrafficSelector.builder().build();
+ TrafficTreatment tr = DefaultTrafficTreatment.builder()
+ .setOutput(PORT_NUM2).build();
+
+ FlowRule r1 = DefaultFlowRule.builder()
+ .forDevice(VDID)
+ .withSelector(ts)
+ .withTreatment(tr)
+ .withPriority(10)
+ .fromApp(vAppId)
+ .makeTemporary(TIMEOUT)
+ .build();
+
+ virtualProvider.applyFlowRule(VNET_ID, r1);
+
+ assertEquals("3 rules should exist", 3,
+ virtualProvider.flowRuleService.getFlowRuleCount());
+
+ FlowRule inFromDID1 = null;
+ FlowRule inFromDID2 = null;
+ FlowRule out = null;
+
+ Set<FlowEntry> phyRules = new HashSet<>();
+ for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
+ phyRules.add(i);
+ }
+ for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
+ phyRules.add(i);
+ }
+
+ for (FlowRule rule : phyRules) {
+ for (Instruction inst : rule.treatment().allInstructions()) {
+ if (inst.type() == Instruction.Type.L2MODIFICATION) {
+ L2ModificationInstruction i = (L2ModificationInstruction) inst;
+ if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
+ inFromDID1 = rule;
+ break;
+ } else {
+ out = rule;
+ break;
+ }
+ } else {
+ inFromDID2 = rule;
+ break;
+ }
+ }
+ }
+
+ assertEquals(DID1, inFromDID1.deviceId());
+ assertEquals(DID2, inFromDID2.deviceId());
+ assertEquals(DID2, out.deviceId());
+ }
+
+ @Test
+ public void removeVirtualizeFlowRule() {
+ TrafficSelector ts = DefaultTrafficSelector.builder().build();
+ TrafficTreatment tr = DefaultTrafficTreatment.builder()
+ .setOutput(PORT_NUM2).build();
+
+ FlowRule r1 = DefaultFlowRule.builder()
+ .forDevice(VDID)
+ .withSelector(ts)
+ .withTreatment(tr)
+ .withPriority(10)
+ .fromApp(vAppId)
+ .makeTemporary(TIMEOUT)
+ .build();
+
+ virtualProvider.removeFlowRule(VNET_ID, r1);
+
+ assertEquals("0 rules should exist", 0,
+ virtualProvider.flowRuleService.getFlowRuleCount());
+ }
+
+
+ private static class TestDeviceService extends DeviceServiceAdapter {
+ @Override
+ public int getDeviceCount() {
+ return 2;
+ }
+
+ @Override
+ public Iterable<Device> getDevices() {
+ return ImmutableList.of(DEV1, DEV2);
+ }
+
+ @Override
+ public Iterable<Device> getAvailableDevices() {
+ return getDevices();
+ }
+
+ @Override
+ public Device getDevice(DeviceId deviceId) {
+ return deviceId.equals(DID2) ? DEV2 : DEV1;
+ }
+ }
+
+ private static class TestCoreService implements CoreService {
+
+ @Override
+ public Version version() {
+ return null;
+ }
+
+ @Override
+ public Set<ApplicationId> getAppIds() {
+ return null;
+ }
+
+ @Override
+ public ApplicationId getAppId(Short id) {
+ return null;
+ }
+
+ @Override
+ public ApplicationId getAppId(String name) {
+ return null;
+ }
+
+ @Override
+ public ApplicationId registerApplication(String name) {
+ return new TestApplicationId(1, name);
+ }
+
+ @Override
+ public ApplicationId registerApplication(String name,
+ Runnable preDeactivate) {
+ return null;
+ }
+
+ @Override
+ public IdGenerator getIdGenerator(String topic) {
+ return null;
+ }
+ }
+
+ private static class TestApplicationId extends DefaultApplicationId {
+ public TestApplicationId(int id, String name) {
+ super(id, name);
+ }
+ }
+
+ private static class TestVirtualNetworkAdminService
+ implements VirtualNetworkAdminService {
+
+ @Override
+ public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
+ return null;
+ }
+
+ @Override
+ public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
+ return ImmutableSet.of(VDEV);
+ }
+
+ @Override
+ public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
+ return null;
+ }
+
+ @Override
+ public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
+ return null;
+ }
+
+ @Override
+ public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
+ DeviceId deviceId) {
+ return ImmutableSet.of(VPORT1, VPORT2);
+ }
+
+ @Override
+ public <T> T get(NetworkId networkId, Class<T> serviceClass) {
+ return null;
+ }
+
+ @Override
+ public ServiceDirectory getServiceDirectory() {
+ return null;
+ }
+
+ @Override
+ public void registerTenantId(TenantId tenantId) {
+
+ }
+
+ @Override
+ public void unregisterTenantId(TenantId tenantId) {
+
+ }
+
+ @Override
+ public Set<TenantId> getTenantIds() {
+ return null;
+ }
+
+ @Override
+ public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
+ return null;
+ }
+
+ @Override
+ public void removeVirtualNetwork(NetworkId networkId) {
+
+ }
+
+ @Override
+ public VirtualDevice createVirtualDevice(NetworkId networkId,
+ DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
+
+ }
+
+ @Override
+ public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
+ MacAddress mac, VlanId vlan,
+ HostLocation location,
+ Set<IpAddress> ips) {
+ return null;
+ }
+
+ @Override
+ public void removeVirtualHost(NetworkId networkId, HostId hostId) {
+
+ }
+
+ @Override
+ public VirtualLink createVirtualLink(NetworkId networkId,
+ ConnectPoint src, ConnectPoint dst) {
+ return null;
+ }
+
+ @Override
+ public void removeVirtualLink(NetworkId networkId,
+ ConnectPoint src, ConnectPoint dst) {
+
+ }
+
+ @Override
+ public VirtualPort createVirtualPort(NetworkId networkId,
+ DeviceId deviceId,
+ PortNumber portNumber,
+ ConnectPoint realizedBy) {
+ return null;
+ }
+
+ @Override
+ public void bindVirtualPort(NetworkId networkId,
+ DeviceId deviceId,
+ PortNumber portNumber,
+ ConnectPoint realizedBy) {
+
+ }
+
+ @Override
+ public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
+ PortNumber portNumber) {
+
+ }
+ }
+
+ private static class TestTopologyService implements TopologyService {
+
+ @Override
+ public void addListener(TopologyListener listener) {
+
+ }
+
+ @Override
+ public void removeListener(TopologyListener listener) {
+
+ }
+
+ @Override
+ public Topology currentTopology() {
+ return null;
+ }
+
+ @Override
+ public boolean isLatest(Topology topology) {
+ return false;
+ }
+
+ @Override
+ public TopologyGraph getGraph(Topology topology) {
+ return null;
+ }
+
+ @Override
+ public Set<TopologyCluster> getClusters(Topology topology) {
+ return null;
+ }
+
+ @Override
+ public TopologyCluster getCluster(Topology topology, ClusterId clusterId) {
+ return null;
+ }
+
+ @Override
+ public Set<DeviceId> getClusterDevices(Topology topology,
+ TopologyCluster cluster) {
+ return null;
+ }
+
+ @Override
+ public Set<Link> getClusterLinks(Topology topology,
+ TopologyCluster cluster) {
+ return null;
+ }
+
+ @Override
+ public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
+ DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
+ 100, ANNOTATIONS);
+ return ImmutableSet.of(path);
+ }
+
+ @Override
+ public Set<Path> getPaths(Topology topology, DeviceId src,
+ DeviceId dst, LinkWeight weight) {
+ DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
+ 100, ANNOTATIONS);
+ return ImmutableSet.of(path);
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(Topology topology,
+ DeviceId src, DeviceId dst) {
+ return null;
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+ DeviceId dst, LinkWeight weight) {
+ return null;
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+ DeviceId dst,
+ Map<Link, Object> riskProfile) {
+ return null;
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+ DeviceId dst, LinkWeight weight,
+ Map<Link, Object> riskProfile) {
+ return null;
+ }
+
+ @Override
+ public boolean isInfrastructure(Topology topology,
+ ConnectPoint connectPoint) {
+ return false;
+ }
+
+ @Override
+ public boolean isBroadcastPoint(Topology topology,
+ ConnectPoint connectPoint) {
+ return false;
+ }
+ }
+
+ private static class TestFlowRuleService implements FlowRuleService {
+ static Set<FlowRule> ruleCollection = new HashSet<>();
+
+ @Override
+ public void addListener(FlowRuleListener listener) {
+
+ }
+
+ @Override
+ public void removeListener(FlowRuleListener listener) {
+
+ }
+
+ @Override
+ public int getFlowRuleCount() {
+ return ruleCollection.size();
+ }
+
+ @Override
+ public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
+ return ruleCollection.stream()
+ .filter(r -> r.deviceId().equals(deviceId))
+ .map(r -> new DefaultFlowEntry(r))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public void applyFlowRules(FlowRule... flowRules) {
+ for (FlowRule rule : flowRules) {
+ ruleCollection.add(rule);
+ }
+ }
+
+ @Override
+ public void purgeFlowRules(DeviceId deviceId) {
+
+ }
+
+ @Override
+ public void removeFlowRules(FlowRule... flowRules) {
+ Set<FlowRule> candidates = new HashSet<>();
+ for (FlowRule rule : flowRules) {
+ ruleCollection.stream()
+ .filter(r -> r.exactMatch(rule))
+ .forEach(candidates::add);
+ }
+ ruleCollection.removeAll(candidates);
+ }
+
+ @Override
+ public void removeFlowRulesById(ApplicationId appId) {
+
+ }
+
+ @Override
+ public Iterable<FlowRule> getFlowRulesById(ApplicationId id) {
+ return null;
+ }
+
+ @Override
+ public Iterable<FlowEntry> getFlowEntriesById(ApplicationId id) {
+ return null;
+ }
+
+ @Override
+ public Iterable<FlowRule> getFlowRulesByGroupId(ApplicationId appId,
+ short groupId) {
+ return null;
+ }
+
+ @Override
+ public void apply(FlowRuleOperations ops) {
+
+ }
+
+ @Override
+ public Iterable<TableStatisticsEntry>
+ getFlowTableStatistics(DeviceId deviceId) {
+ return null;
+ }
+ }
+}
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManagerTest.java
index f952633..6fb7a8d 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualProviderManagerTest.java
@@ -81,7 +81,7 @@
virtualProviderManager.registerProviderService(NETWORK_ID1, providerService1);
assertEquals(providerService1,
- virtualProviderManager.getProviderService(NETWORK_ID1, provider1));
+ virtualProviderManager.getProviderService(NETWORK_ID1, TestProvider1.class));
}
private class TestProvider1 extends AbstractVirtualProvider {