aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/drivers')
-rw-r--r--framework/src/onos/drivers/features.xml2
-rw-r--r--framework/src/onos/drivers/pom.xml5
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java12
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java2
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java (renamed from framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OFOpticalSwitchImplLINC13.java)2
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java7
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java123
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java348
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java238
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java4
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java18
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java272
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java12
-rw-r--r--framework/src/onos/drivers/src/main/resources/onos-drivers.xml18
14 files changed, 710 insertions, 353 deletions
diff --git a/framework/src/onos/drivers/features.xml b/framework/src/onos/drivers/features.xml
index a7144492..e83f93fa 100644
--- a/framework/src/onos/drivers/features.xml
+++ b/framework/src/onos/drivers/features.xml
@@ -24,5 +24,7 @@
<bundle>mvn:${project.groupId}/onos-ovsdb-api/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-ovsdb-rfc/${project.version}</bundle>
+
+ <bundle>mvn:${project.groupId}/onos-netconf-api/${project.version}</bundle>
</feature>
</features>
diff --git a/framework/src/onos/drivers/pom.xml b/framework/src/onos/drivers/pom.xml
index 56a39a8e..db0a3985 100644
--- a/framework/src/onos/drivers/pom.xml
+++ b/framework/src/onos/drivers/pom.xml
@@ -67,6 +67,11 @@
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-netconf-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.felix</groupId>
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java
index 082c5a6d..b8f1fd91 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java
@@ -38,10 +38,12 @@ public class NiciraExtensionInterpreter extends AbstractHandlerBehaviour
@Override
public boolean supported(ExtensionType extensionType) {
- if (extensionType.equals(ExtensionType.ExtensionTypes.NICIRA_SET_TUNNEL_DST)) {
+ if (extensionType.equals(ExtensionType.ExtensionTypes.NICIRA_SET_TUNNEL_DST.type())) {
+ return true;
+ }
+ if (extensionType.equals(ExtensionType.ExtensionTypes.NICIRA_RESUBMIT.type())) {
return true;
}
-
return false;
}
@@ -53,6 +55,9 @@ public class NiciraExtensionInterpreter extends AbstractHandlerBehaviour
return factory.actions().setField(factory.oxms().tunnelIpv4Dst(
IPv4Address.of(tunnelDst.tunnelDst().toInt())));
}
+ if (type.equals(ExtensionType.ExtensionTypes.NICIRA_RESUBMIT.type())) {
+ // TODO this will be implemented later
+ }
return null;
}
@@ -78,6 +83,9 @@ public class NiciraExtensionInterpreter extends AbstractHandlerBehaviour
if (type.equals(ExtensionType.ExtensionTypes.NICIRA_SET_TUNNEL_DST.type())) {
return new NiciraSetTunnelDst();
}
+ if (type.equals(ExtensionType.ExtensionTypes.NICIRA_RESUBMIT.type())) {
+ return new NiciraResubmit();
+ }
throw new UnsupportedOperationException(
"Driver does not support extension type " + type.toString());
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
index 16aa1b07..a20b2479 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
@@ -49,6 +49,8 @@ public class NiciraSetTunnelDst extends AbstractExtensionInstruction {
/**
* Creates a new set tunnel destination instruction with a particular IPv4
* address.
+ *
+ * @param tunnelDst tunnel destination IPv4 address
*/
NiciraSetTunnelDst(Ip4Address tunnelDst) {
checkNotNull(tunnelDst);
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OFOpticalSwitchImplLINC13.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
index 7faee374..ff65e0c6 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OFOpticalSwitchImplLINC13.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
@@ -53,7 +53,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* while it sends *all* ports (both tap and WDM ports, i.e., OCh and OMS) in the experimenter port desc stats reply.
*
*/
-public class OFOpticalSwitchImplLINC13
+public class OfOpticalSwitchImplLinc13
extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
index 77b48298..6451160a 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
@@ -54,6 +54,13 @@ public class OvsdbBridgeConfig extends AbstractHandlerBehaviour
}
@Override
+ public void addBridge(BridgeName bridgeName, String dpid, String exPortName) {
+ DriverHandler handler = handler();
+ OvsdbClientService clientService = getOvsdbClientService(handler);
+ clientService.createBridge(bridgeName.name(), dpid, exPortName);
+ }
+
+ @Override
public boolean addBridge(BridgeName bridgeName, String dpid, List<ControllerInfo> controllers) {
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
index a830ed49..0cb30d28 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
@@ -17,6 +17,16 @@ package org.onosproject.driver.pipeline;
import static org.slf4j.LoggerFactory.getLogger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -25,6 +35,8 @@ import org.onosproject.net.flow.FlowRuleOperations;
import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.slf4j.Logger;
@@ -37,16 +49,76 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
private final Logger log = getLogger(getClass());
@Override
+ protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
+ VlanIdCriterion vidCriterion,
+ VlanId assignedVlan,
+ ApplicationId applicationId) {
+ List<FlowRule> rules = new ArrayList<FlowRule>();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchVlanId(vidCriterion.vlanId());
+ treatment.transition(TMAC_TABLE);
+
+ VlanId storeVlan = null;
+ if (vidCriterion.vlanId() == VlanId.NONE) {
+ // untagged packets are assigned vlans
+ treatment.pushVlan().setVlanId(assignedVlan);
+ storeVlan = assignedVlan;
+ } else {
+ storeVlan = vidCriterion.vlanId();
+ }
+
+ // ofdpa cannot match on ALL portnumber, so we need to use separate
+ // rules for each port.
+ List<PortNumber> portnums = new ArrayList<PortNumber>();
+ if (portCriterion.port() == PortNumber.ALL) {
+ for (Port port : deviceService.getPorts(deviceId)) {
+ if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
+ portnums.add(port.number());
+ }
+ }
+ } else {
+ portnums.add(portCriterion.port());
+ }
+
+ for (PortNumber pnum : portnums) {
+ // update storage
+ port2Vlan.put(pnum, storeVlan);
+ Set<PortNumber> vlanPorts = vlan2Port.get(storeVlan);
+ if (vlanPorts == null) {
+ vlanPorts = Collections.newSetFromMap(
+ new ConcurrentHashMap<PortNumber, Boolean>());
+ vlanPorts.add(pnum);
+ vlan2Port.put(storeVlan, vlanPorts);
+ } else {
+ vlanPorts.add(pnum);
+ }
+ // create rest of flowrule
+ selector.matchInPort(pnum);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(VLAN_TABLE).build();
+ rules.add(rule);
+ }
+ return rules;
+ }
+
+
+ @Override
protected void initializePipeline() {
processPortTable();
+ // vlan table processing not required, as default is to drop packets
+ // which can be accomplished without a table-miss-entry.
processTmacTable();
processIpTable();
+ processMplsTable();
processBridgingTable();
processAclTable();
- // XXX implement table miss entries and default groups
- //processVlanTable();
- //processMPLSTable();
- //processGroupTable();
}
@Override
@@ -140,6 +212,49 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
}));
}
+ @Override
+ protected void processMplsTable() {
+ //table miss entry
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+ treatment.transition(MPLS_TABLE_1);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(LOWEST_PRIORITY)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(MPLS_TABLE_0).build();
+ ops = ops.add(rule);
+
+ treatment.transition(ACL_TABLE);
+ rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(LOWEST_PRIORITY)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(MPLS_TABLE_1).build();
+ ops = ops.add(rule);
+
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Initialized MPLS tables");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to initialize MPLS tables");
+ }
+ }));
+ }
+
private void processBridgingTable() {
//table miss entry
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
index b1a1256a..cf3c7e89 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
@@ -23,11 +23,13 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.onlab.osgi.ServiceDirectory;
@@ -122,7 +124,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
protected static final long OFPP_MAX = 0xffffff00L;
private static final int HIGHEST_PRIORITY = 0xffff;
- private static final int DEFAULT_PRIORITY = 0x8000;
+ protected static final int DEFAULT_PRIORITY = 0x8000;
protected static final int LOWEST_PRIORITY = 0x0;
/*
@@ -147,6 +149,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
private static final int L3UNICASTMASK = 0x20000000;
//private static final int MPLSINTERFACEMASK = 0x90000000;
private static final int L3ECMPMASK = 0x70000000;
+ private static final int L2FLOODMASK = 0x40000000;
private final Logger log = getLogger(getClass());
private ServiceDirectory serviceDirectory;
@@ -176,6 +179,13 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
private Set<IPCriterion> sentIpFilters = Collections.newSetFromMap(
new ConcurrentHashMap<IPCriterion, Boolean>());
+ // local stores for port-vlan mapping
+ Map<PortNumber, VlanId> port2Vlan = new ConcurrentHashMap<PortNumber, VlanId>();
+ Map<VlanId, Set<PortNumber>> vlan2Port = new ConcurrentHashMap<VlanId,
+ Set<PortNumber>>();
+
+
+
@Override
public void init(DeviceId deviceId, PipelinerContext context) {
this.serviceDirectory = context.directory();
@@ -275,26 +285,23 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
@Override
public void next(NextObjective nextObjective) {
- switch (nextObjective.type()) {
- case SIMPLE:
- Collection<TrafficTreatment> treatments = nextObjective.next();
- if (treatments.size() != 1) {
- log.error("Next Objectives of type Simple should only have a "
- + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id());
- fail(nextObjective, ObjectiveError.BADPARAMS);
- return;
+ log.debug("Processing NextObjective id{} op{}", nextObjective.id(),
+ nextObjective.op());
+ if (nextObjective.op() == Objective.Operation.REMOVE) {
+ if (nextObjective.next().isEmpty()) {
+ removeGroup(nextObjective);
+ } else {
+ removeBucketFromGroup(nextObjective);
}
- processSimpleNextObjective(nextObjective);
- break;
- case HASHED:
- case BROADCAST:
- case FAILOVER:
- fail(nextObjective, ObjectiveError.UNSUPPORTED);
- log.warn("Unsupported next objective type {}", nextObjective.type());
- break;
- default:
- fail(nextObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown next objective type {}", nextObjective.type());
+ } else if (nextObjective.op() == Objective.Operation.ADD) {
+ NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id());
+ if (nextGroup != null) {
+ addBucketToGroup(nextObjective);
+ } else {
+ addGroup(nextObjective);
+ }
+ } else {
+ log.warn("Unsupported operation {}", nextObjective.op());
}
}
@@ -302,6 +309,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
// Flow handling
//////////////////////////////////////
+
/**
* As per OFDPA 2.0 TTP, filtering of VLAN ids, MAC addresses (for routing)
* and IP addresses configured on switch ports happen in different tables.
@@ -455,13 +463,19 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchVlanId(vidCriterion.vlanId());
+ treatment.transition(TMAC_TABLE);
+
+ VlanId storeVlan = null;
if (vidCriterion.vlanId() == VlanId.NONE) {
// untagged packets are assigned vlans
treatment.pushVlan().setVlanId(assignedVlan);
- // XXX ofdpa may require an additional vlan match on the assigned vlan
- // and it may not require the push.
+ // XXX ofdpa will require an additional vlan match on the assigned vlan
+ // and it may not require the push. This is not in compliance with OF
+ // standard. Waiting on what the exact flows are going to look like.
+ storeVlan = assignedVlan;
+ } else {
+ storeVlan = vidCriterion.vlanId();
}
- treatment.transition(TMAC_TABLE);
// ofdpa cannot match on ALL portnumber, so we need to use separate
// rules for each port.
@@ -475,7 +489,20 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
} else {
portnums.add(portCriterion.port());
}
+
for (PortNumber pnum : portnums) {
+ // update storage
+ port2Vlan.put(pnum, storeVlan);
+ Set<PortNumber> vlanPorts = vlan2Port.get(storeVlan);
+ if (vlanPorts == null) {
+ vlanPorts = Collections.newSetFromMap(
+ new ConcurrentHashMap<PortNumber, Boolean>());
+ vlanPorts.add(pnum);
+ vlan2Port.put(storeVlan, vlanPorts);
+ } else {
+ vlanPorts.add(pnum);
+ }
+ // create rest of flowrule
selector.matchInPort(pnum);
FlowRule rule = DefaultFlowRule.builder()
.forDevice(deviceId)
@@ -707,10 +734,39 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
// Group handling
//////////////////////////////////////
+ private void addGroup(NextObjective nextObjective) {
+ switch (nextObjective.type()) {
+ case SIMPLE:
+ Collection<TrafficTreatment> treatments = nextObjective.next();
+ if (treatments.size() != 1) {
+ log.error("Next Objectives of type Simple should only have a "
+ + "single Traffic Treatment. Next Objective Id:{}",
+ nextObjective.id());
+ fail(nextObjective, ObjectiveError.BADPARAMS);
+ return;
+ }
+ processSimpleNextObjective(nextObjective);
+ break;
+ case BROADCAST:
+ processBroadcastNextObjective(nextObjective);
+ break;
+ case HASHED:
+ processHashedNextObjective(nextObjective);
+ break;
+ case FAILOVER:
+ fail(nextObjective, ObjectiveError.UNSUPPORTED);
+ log.warn("Unsupported next objective type {}", nextObjective.type());
+ break;
+ default:
+ fail(nextObjective, ObjectiveError.UNKNOWN);
+ log.warn("Unknown next objective type {}", nextObjective.type());
+ }
+ }
+
/**
* As per the OFDPA 2.0 TTP, packets are sent out of ports by using
* a chain of groups, namely an L3 Unicast Group that points to an L2 Interface
- * Group which in turns points to an output port. The Next Objective passed
+ * Group which in-turn points to an output port. The Next Objective passed
* in by the application has to be broken up into a group chain
* to satisfy this TTP.
*
@@ -769,7 +825,9 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
Integer l3groupId = L3UNICASTMASK | (int) portNum;
l3utt.group(new DefaultGroupId(l2groupId));
GroupChainElem gce = new GroupChainElem(l3groupkey, l3groupId,
- l3utt.build(), nextObj.appId());
+ GroupDescription.Type.INDIRECT,
+ Collections.singletonList(l3utt.build()),
+ nextObj.appId(), 1);
// create object for local and distributed storage
List<GroupKey> gkeys = new ArrayList<GroupKey>();
@@ -796,27 +854,201 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
/**
+ * As per the OFDPA 2.0 TTP, packets are sent out of ports by using
+ * a chain of groups. The Next Objective passed in by the application
+ * has to be broken up into a group chain comprising of an
+ * L2 Flood group whose buckets point to L2 Interface groups.
+ *
+ * @param nextObj the nextObjective of type BROADCAST
+ */
+ private void processBroadcastNextObjective(NextObjective nextObj) {
+ // break up broadcast next objective to multiple groups
+ Collection<TrafficTreatment> buckets = nextObj.next();
+
+ // each treatment is converted to an L2 interface group
+ int indicator = 0;
+ VlanId vlanid = null;
+ List<GroupInfo> groupInfoCollection = new ArrayList<>();
+ for (TrafficTreatment treatment : buckets) {
+ TrafficTreatment.Builder newTreatment = DefaultTrafficTreatment.builder();
+ PortNumber portNum = null;
+ // ensure that the only allowed treatments are pop-vlan and output
+ for (Instruction ins : treatment.allInstructions()) {
+ if (ins.type() == Instruction.Type.L2MODIFICATION) {
+ L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
+ switch (l2ins.subtype()) {
+ case VLAN_POP:
+ newTreatment.add(l2ins);
+ break;
+ default:
+ log.debug("action {} not permitted for broadcast nextObj",
+ l2ins.subtype());
+ break;
+ }
+ } else if (ins.type() == Instruction.Type.OUTPUT) {
+ portNum = ((OutputInstruction) ins).port();
+ newTreatment.add(ins);
+ } else {
+ log.debug("TrafficTreatment of type {} not permitted in "
+ + " broadcast nextObjective", ins.type());
+ }
+ }
+
+ // also ensure that all ports are in the same vlan
+ VlanId thisvlanid = port2Vlan.get(portNum);
+ if (vlanid == null) {
+ vlanid = thisvlanid;
+ } else {
+ if (!vlanid.equals(thisvlanid)) {
+ log.error("Driver requires all ports in a broadcast nextObj "
+ + "to be in the same vlan. Different vlans found "
+ + "{} and {}. Aborting group creation", vlanid, thisvlanid);
+ return;
+ }
+ }
+
+ // assemble info for all l2 interface groups
+ indicator += GROUP1MASK;
+ int l2gk = nextObj.id() | indicator;
+ final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
+ Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) |
+ (int) portNum.toLong();
+ GroupBucket newbucket =
+ DefaultGroupBucket.createIndirectGroupBucket(newTreatment.build());
+
+ // store the info needed to create this group
+ groupInfoCollection.add(new GroupInfo(l2groupId, l2groupkey, newbucket));
+ }
+
+ // assemble info for l2 flood group
+ int l2floodgk = nextObj.id() | GROUP0MASK;
+ final GroupKey l2floodgroupkey = new DefaultGroupKey(appKryo.serialize(l2floodgk));
+ Integer l2floodgroupId = L2FLOODMASK | (vlanid.toShort() << 16) | nextObj.id();
+ // collection of treatment with groupids of l2 interface groups
+ List<TrafficTreatment> floodtt = new ArrayList<>();
+ for (GroupInfo gi : groupInfoCollection) {
+ TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
+ ttb.group(new DefaultGroupId(gi.groupId));
+ floodtt.add(ttb.build());
+ }
+ GroupChainElem gce = new GroupChainElem(l2floodgroupkey, l2floodgroupId,
+ GroupDescription.Type.ALL,
+ floodtt,
+ nextObj.appId(),
+ groupInfoCollection.size());
+
+ // create objects for local and distributed storage
+ List<GroupKey> gkeys = new ArrayList<GroupKey>();
+ gkeys.add(l2floodgroupkey); // group0 in chain
+ OfdpaGroupChain ofdpaGrp = new OfdpaGroupChain(gkeys, nextObj);
+
+ // store l2floodgroupkey with the ofdpaGroupChain for the nextObjective
+ // that depends on it
+ pendingNextObjectives.put(l2floodgroupkey, ofdpaGrp);
+
+ for (GroupInfo gi : groupInfoCollection) {
+ // store all l2groupkeys with the groupChainElem for the l2floodgroup
+ // that depends on it
+ pendingGroups.put(gi.groupKey, gce);
+
+ // create and send groups for all l2 interface groups
+ GroupDescription groupDescription =
+ new DefaultGroupDescription(
+ deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(gi.groupBucket)),
+ gi.groupKey,
+ gi.groupId,
+ nextObj.appId());
+ groupService.addGroup(groupDescription);
+ }
+ }
+
+ private class GroupInfo {
+ private Integer groupId;
+ private GroupKey groupKey;
+ private GroupBucket groupBucket;
+
+ GroupInfo(Integer groupId, GroupKey groupKey, GroupBucket groupBucket) {
+ this.groupBucket = groupBucket;
+ this.groupId = groupId;
+ this.groupKey = groupKey;
+ }
+ }
+
+ private void processHashedNextObjective(NextObjective nextObj) {
+ // TODO Auto-generated method stub
+ }
+
+ private void addBucketToGroup(NextObjective nextObjective) {
+ // TODO Auto-generated method stub
+ }
+
+ private void removeBucketFromGroup(NextObjective nextObjective) {
+ // TODO Auto-generated method stub
+ }
+
+ private void removeGroup(NextObjective nextObjective) {
+ // TODO Auto-generated method stub
+ }
+
+ /**
* Processes next element of a group chain. Assumption is that if this
* group points to another group, the latter has already been created
* and this driver has received notification for it. A second assumption is
* that if there is another group waiting for this group then the appropriate
* stores already have the information to act upon the notification for the
* creating of this group.
+ * <p>
+ * The processing of the GroupChainElement depends on the number of groups
+ * this element is waiting on. For all group types other than SIMPLE, a
+ * GroupChainElement could be waiting on multiple groups.
*
* @param gce the group chain element to be processed next
*/
private void processGroupChain(GroupChainElem gce) {
- GroupBucket bucket = DefaultGroupBucket
- .createIndirectGroupBucket(gce.getBucketActions());
- GroupDescription groupDesc = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(bucket)),
- gce.getGkey(),
- gce.getGivenGroupId(),
- gce.getAppId());
- groupService.addGroup(groupDesc);
- }
+ int waitOnGroups = gce.decrementAndGetGroupsWaitedOn();
+ if (waitOnGroups != 0) {
+ log.debug("GCE: {} waiting on {} groups. Not processing yet",
+ gce, waitOnGroups);
+ return;
+ }
+ List<GroupBucket> buckets = new ArrayList<>();
+ switch (gce.groupType) {
+ case INDIRECT:
+ GroupBucket ibucket = DefaultGroupBucket
+ .createIndirectGroupBucket(gce.bucketActions.iterator().next());
+ buckets.add(ibucket);
+ break;
+ case ALL:
+ for (TrafficTreatment tt : gce.bucketActions) {
+ GroupBucket abucket = DefaultGroupBucket
+ .createAllGroupBucket(tt);
+ buckets.add(abucket);
+ }
+ break;
+ case SELECT:
+ for (TrafficTreatment tt : gce.bucketActions) {
+ GroupBucket sbucket = DefaultGroupBucket
+ .createSelectGroupBucket(tt);
+ buckets.add(sbucket);
+ }
+ break;
+ case FAILOVER:
+ default:
+ log.error("Unknown or unimplemented GroupChainElem {}", gce);
+ }
+ if (buckets.size() > 0) {
+ GroupDescription groupDesc = new DefaultGroupDescription(
+ deviceId, gce.groupType,
+ new GroupBuckets(buckets),
+ gce.gkey,
+ gce.givenGroupId,
+ gce.appId);
+ groupService.addGroup(groupDesc);
+ }
+ }
private class GroupChecker implements Runnable {
@Override
@@ -836,7 +1068,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
log.info("Group service processed group key {}. Processing next "
+ "group in group chain with group key {}",
appKryo.deserialize(key.key()),
- appKryo.deserialize(gce.getGkey().key()));
+ appKryo.deserialize(gce.gkey.key()));
processGroupChain(gce);
} else {
OfdpaGroupChain obj = pendingNextObjectives.getIfPresent(key);
@@ -865,7 +1097,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
log.info("group ADDED with group key {} .. "
+ "Processing next group in group chain with group key {}",
appKryo.deserialize(key.key()),
- appKryo.deserialize(gce.getGkey().key()));
+ appKryo.deserialize(gce.gkey.key()));
processGroupChain(gce);
} else {
OfdpaGroupChain obj = pendingNextObjectives.getIfPresent(key);
@@ -889,6 +1121,11 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
* look like group0 --> group 1 --> outPort. Information about the groups
* themselves can be fetched from the Group Service using the group keys from
* objects instantiating this class.
+ *
+ * XXX Revisit this - since the forwarding objective only ever needs the
+ * groupkey of the top-level group in the group chain, why store a series
+ * of groupkeys. Also the group-chain list only works for 1-to-1 chaining,
+ * not for 1-to-many chaining.
*/
private class OfdpaGroupChain implements NextGroup {
private final NextObjective nextObj;
@@ -924,33 +1161,40 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
* preceding groups in the group chain to be created.
*/
private class GroupChainElem {
- private TrafficTreatment bucketActions;
+ private Collection<TrafficTreatment> bucketActions;
private Integer givenGroupId;
+ private GroupDescription.Type groupType;
private GroupKey gkey;
private ApplicationId appId;
+ private AtomicInteger waitOnGroups;
- public GroupChainElem(GroupKey gkey, Integer givenGroupId,
- TrafficTreatment tr, ApplicationId appId) {
+ GroupChainElem(GroupKey gkey, Integer givenGroupId,
+ GroupDescription.Type groupType,
+ Collection<TrafficTreatment> tr, ApplicationId appId,
+ int waitOnGroups) {
this.bucketActions = tr;
this.givenGroupId = givenGroupId;
+ this.groupType = groupType;
this.gkey = gkey;
this.appId = appId;
+ this.waitOnGroups = new AtomicInteger(waitOnGroups);
}
- public TrafficTreatment getBucketActions() {
- return bucketActions;
- }
-
- public Integer getGivenGroupId() {
- return givenGroupId;
+ /**
+ * This methods atomically decrements the counter for the number of
+ * groups this GroupChainElement is waiting on, for notifications from
+ * the Group Service. When this method returns a value of 0, this
+ * GroupChainElement is ready to be processed.
+ *
+ * @return integer indication of the number of notifications being waited on
+ */
+ int decrementAndGetGroupsWaitedOn() {
+ return waitOnGroups.decrementAndGet();
}
- public GroupKey getGkey() {
- return gkey;
- }
-
- public ApplicationId getAppId() {
- return appId;
+ @Override
+ public String toString() {
+ return Integer.toHexString(givenGroupId);
}
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java
deleted file mode 100644
index c735af3f..00000000
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright 2015 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.driver.pipeline;
-
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.EthType;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.MastershipRole;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.Pipeliner;
-import org.onosproject.net.behaviour.PipelinerContext;
-import org.onosproject.net.device.DefaultDeviceDescription;
-import org.onosproject.net.device.DeviceDescription;
-import org.onosproject.net.device.DeviceProvider;
-import org.onosproject.net.device.DeviceProviderRegistry;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.FlowRuleOperationsContext;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.packet.PacketPriority;
-import org.onosproject.net.provider.AbstractProvider;
-import org.onosproject.net.provider.ProviderId;
-import org.slf4j.Logger;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Pipeliner for OLT device.
- */
-public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
-
- private final Logger log = getLogger(getClass());
-
- static final ProviderId PID = new ProviderId("olt", "org.onosproject.olt", true);
-
- static final String DEVICE = "isAccess";
- static final String OLT = "true";
-
- private ServiceDirectory serviceDirectory;
- private FlowRuleService flowRuleService;
- private DeviceId deviceId;
- private CoreService coreService;
-
- private ApplicationId appId;
-
- private DeviceProvider provider = new AnnotationProvider();
-
-
- @Override
- public void init(DeviceId deviceId, PipelinerContext context) {
- this.serviceDirectory = context.directory();
- this.deviceId = deviceId;
- DeviceProviderRegistry registry =
- serviceDirectory.get(DeviceProviderRegistry.class);
- flowRuleService = serviceDirectory.get(FlowRuleService.class);
- coreService = serviceDirectory.get(CoreService.class);
-
- /*try {
- DeviceProviderService providerService = registry.register(provider);
- providerService.deviceConnected(deviceId,
- description(deviceId, DEVICE, OLT));
- } finally {
- registry.unregister(provider);
- }*/
-
- appId = coreService.registerApplication(
- "org.onosproject.driver.OLTPipeline");
-
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(EthType.EtherType.EAPOL.ethType().toShort())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .punt()
- .build();
-
- FlowRule flowRule = new DefaultFlowRule(deviceId, selector, treatment,
- PacketPriority.CONTROL.priorityValue(),
- appId, 0, true, null);
-
- //flowRuleService.applyFlowRules(flowRule);
- }
-
- @Override
- public void filter(FilteringObjective filter) {
- throw new UnsupportedOperationException("OLT does not filter.");
- }
-
- @Override
- public void forward(ForwardingObjective fwd) {
- FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
-
- if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
- throw new UnsupportedOperationException(
- "Only VERSATILE is supported.");
- }
-
- boolean isPunt = fwd.treatment().immediate().stream().anyMatch(i -> {
- if (i instanceof Instructions.OutputInstruction) {
- Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
- return out.port().equals(PortNumber.CONTROLLER);
- }
- return false;
- });
-
- if (isPunt) {
- return;
- }
-
- TrafficSelector selector = fwd.selector();
- TrafficTreatment treatment = fwd.treatment();
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector)
- .withTreatment(treatment)
- .fromApp(fwd.appId())
- .withPriority(fwd.priority());
-
- if (fwd.permanent()) {
- ruleBuilder.makePermanent();
- } else {
- ruleBuilder.makeTemporary(fwd.timeout());
- }
-
- switch (fwd.op()) {
- case ADD:
- flowBuilder.add(ruleBuilder.build());
- break;
- case REMOVE:
- flowBuilder.remove(ruleBuilder.build());
- break;
- default:
- log.warn("Unknown operation {}", fwd.op());
- }
-
- flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- if (fwd.context().isPresent()) {
- fwd.context().get().onSuccess(fwd);
- }
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- if (fwd.context().isPresent()) {
- fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }
- }));
- }
-
- @Override
- public void next(NextObjective nextObjective) {
- throw new UnsupportedOperationException("OLT does not next hop.");
- }
-
- /**
- * Build a device description.
- *
- * @param deviceId a deviceId
- * @param key the key of the annotation
- * @param value the value for the annotation
- * @return a device description
- */
- private DeviceDescription description(DeviceId deviceId, String key, String value) {
- DeviceService deviceService = serviceDirectory.get(DeviceService.class);
- Device device = deviceService.getDevice(deviceId);
-
- checkNotNull(device, "Device not found in device service.");
-
- DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
- if (value != null) {
- builder.set(key, value);
- } else {
- builder.remove(key);
- }
- return new DefaultDeviceDescription(device.id().uri(), device.type(),
- device.manufacturer(), device.hwVersion(),
- device.swVersion(), device.serialNumber(),
- device.chassisId(), builder.build());
- }
-
- /**
- * Simple ancillary provider used to annotate device.
- */
- private static final class AnnotationProvider
- extends AbstractProvider implements DeviceProvider {
- private AnnotationProvider() {
- super(PID);
- }
-
- @Override
- public void triggerProbe(DeviceId deviceId) {
- }
-
- @Override
- public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
- }
-
- @Override
- public boolean isReachable(DeviceId deviceId) {
- return false;
- }
- }
-
-}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
index 32d6b103..69d20835 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
@@ -462,10 +462,10 @@ public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner
private void initializePipeline() {
//processIpUnicastTable(true);
- processACLTable(true);
+ processAclTable(true);
}
- private void processACLTable(boolean install) {
+ private void processAclTable(boolean install) {
TrafficSelector.Builder selector;
TrafficTreatment.Builder treatment;
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
index 23ef5f2b..bd49e688 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
@@ -15,13 +15,6 @@
*/
package org.onosproject.driver.pipeline;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
@@ -57,8 +50,15 @@ import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
-import org.slf4j.Logger;
import org.onosproject.store.serializers.KryoNamespaces;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Simple 2-Table Pipeline for Software/NPU based routers. This pipeline
@@ -100,7 +100,7 @@ public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipe
flowRuleService = serviceDirectory.get(FlowRuleService.class);
flowObjectiveStore = context.store();
driverId = coreService.registerApplication(
- "org.onosproject.driver.OVSCorsaPipeline");
+ "org.onosproject.driver.SoftRouterPipeline");
filters = Collections.newSetFromMap(new ConcurrentHashMap<Filter, Boolean>());
pendingVersatiles = Collections.newSetFromMap(
new ConcurrentHashMap<ForwardingObjective, Boolean>());
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
index 31297ff4..b5541065 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
@@ -25,6 +25,7 @@ import com.google.common.cache.RemovalNotification;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
@@ -54,6 +55,7 @@ import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
import org.onosproject.net.flowobjective.ForwardingObjective;
@@ -94,7 +96,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
private static final int TABLE_TMAC = 1;
private static final int TABLE_IPV4_UNICAST = 2;
private static final int TABLE_MPLS = 3;
+ private static final int TABLE_DMAC = 4;
private static final int TABLE_ACL = 5;
+ private static final int TABLE_SMAC = 6;
/**
* Set the default values. These variables will get overwritten based on the
@@ -104,7 +108,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
protected int tmacTableId = TABLE_TMAC;
protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST;
protected int mplsTableId = TABLE_MPLS;
+ protected int dstMacTableId = TABLE_DMAC;
protected int aclTableId = TABLE_ACL;
+ protected int srcMacTableId = TABLE_SMAC;
protected final Logger log = getLogger(getClass());
@@ -448,12 +454,14 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) {
OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0);
if (o.port() == PortNumber.CONTROLLER) {
- log.warn("Punts to the controller are handled by misses in"
- + " the TMAC, IP and MPLS tables.");
- return Collections.emptySet();
+ treatmentBuilder.punt();
+ treatment = treatmentBuilder.build();
+ } else {
+ treatment = fwd.treatment();
}
+ } else {
+ treatment = fwd.treatment();
}
- treatment = fwd.treatment();
} else {
log.warn("VERSATILE forwarding objective needs next objective ID "
+ "or treatment.");
@@ -475,19 +483,52 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
return Collections.singletonList(ruleBuilder.build());
}
- protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
- log.debug("Processing specific");
+ private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) {
TrafficSelector selector = fwd.selector();
EthTypeCriterion ethType = (EthTypeCriterion) selector
.getCriterion(Criterion.Type.ETH_TYPE);
if ((ethType == null) ||
- (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
- (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
+ ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
+ (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isSupportedEthDstObjective(ForwardingObjective fwd) {
+ TrafficSelector selector = fwd.selector();
+ EthCriterion ethDst = (EthCriterion) selector
+ .getCriterion(Criterion.Type.ETH_DST);
+ VlanIdCriterion vlanId = (VlanIdCriterion) selector
+ .getCriterion(Criterion.Type.VLAN_VID);
+ if (ethDst == null && vlanId == null) {
+ return false;
+ }
+ return true;
+ }
+
+ protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
+ log.debug("Processing specific");
+ boolean isEthTypeObj = isSupportedEthTypeObjective(fwd);
+ boolean isEthDstObj = isSupportedEthDstObjective(fwd);
+
+ if (isEthTypeObj) {
+ return processEthTypeSpecificObjective(fwd);
+ } else if (isEthDstObj) {
+ return processEthDstSpecificObjective(fwd);
+ } else {
log.warn("processSpecific: Unsupported "
+ "forwarding objective criteraia");
fail(fwd, ObjectiveError.UNSUPPORTED);
return Collections.emptySet();
}
+ }
+
+ protected Collection<FlowRule>
+ processEthTypeSpecificObjective(ForwardingObjective fwd) {
+ TrafficSelector selector = fwd.selector();
+ EthTypeCriterion ethType = (EthTypeCriterion) selector
+ .getCriterion(Criterion.Type.ETH_TYPE);
TrafficSelector.Builder filteredSelectorBuilder =
DefaultTrafficSelector.builder();
@@ -565,59 +606,167 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
}
- protected List<FlowRule> processEthDstFilter(Criterion c,
+ protected Collection<FlowRule>
+ processEthDstSpecificObjective(ForwardingObjective fwd) {
+ List<FlowRule> rules = new ArrayList<>();
+
+ // Build filtered selector
+ TrafficSelector selector = fwd.selector();
+ EthCriterion ethCriterion = (EthCriterion) selector
+ .getCriterion(Criterion.Type.ETH_DST);
+ VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector
+ .getCriterion(Criterion.Type.VLAN_VID);
+ TrafficSelector.Builder filteredSelectorBuilder =
+ DefaultTrafficSelector.builder();
+ // Do not match MacAddress for subnet broadcast entry
+ if (!ethCriterion.mac().equals(MacAddress.NONE)) {
+ filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
+ }
+ filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
+ TrafficSelector filteredSelector = filteredSelectorBuilder.build();
+
+ // Build filtered treatment
+ TrafficTreatment.Builder treatmentBuilder =
+ DefaultTrafficTreatment.builder();
+ if (fwd.treatment() != null) {
+ treatmentBuilder.deferred();
+ fwd.treatment().allInstructions().forEach(treatmentBuilder::add);
+ }
+ if (fwd.nextId() != null) {
+ NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
+ if (next != null) {
+ GroupKey key = appKryo.deserialize(next.data());
+ Group group = groupService.getGroup(deviceId, key);
+ if (group != null) {
+ treatmentBuilder.deferred().group(group.id());
+ } else {
+ log.warn("Group Missing");
+ fail(fwd, ObjectiveError.GROUPMISSING);
+ return Collections.emptySet();
+ }
+ }
+ }
+ treatmentBuilder.immediate().transition(aclTableId);
+ TrafficTreatment filteredTreatment = treatmentBuilder.build();
+
+ // Build bridging table entries
+ FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
+ flowRuleBuilder.fromApp(fwd.appId())
+ .withPriority(fwd.priority())
+ .forDevice(deviceId)
+ .withSelector(filteredSelector)
+ .withTreatment(filteredTreatment)
+ .forTable(dstMacTableId);
+ if (fwd.permanent()) {
+ flowRuleBuilder.makePermanent();
+ } else {
+ flowRuleBuilder.makeTemporary(fwd.timeout());
+ }
+ rules.add(flowRuleBuilder.build());
+
+ /*
+ // TODO Emulate source MAC table behavior
+ // Do not install source MAC table entry for subnet broadcast
+ if (!ethCriterion.mac().equals(MacAddress.NONE)) {
+ // Build filtered selector
+ selector = fwd.selector();
+ ethCriterion = (EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST);
+ filteredSelectorBuilder = DefaultTrafficSelector.builder();
+ filteredSelectorBuilder.matchEthSrc(ethCriterion.mac());
+ filteredSelector = filteredSelectorBuilder.build();
+
+ // Build empty treatment. Apply existing instruction if match.
+ treatmentBuilder = DefaultTrafficTreatment.builder();
+ filteredTreatment = treatmentBuilder.build();
+
+ // Build bridging table entries
+ flowRuleBuilder = DefaultFlowRule.builder();
+ flowRuleBuilder.fromApp(fwd.appId())
+ .withPriority(fwd.priority())
+ .forDevice(deviceId)
+ .withSelector(filteredSelector)
+ .withTreatment(filteredTreatment)
+ .forTable(srcMacTableId)
+ .makePermanent();
+ rules.add(flowRuleBuilder.build());
+ }
+ */
+
+ return rules;
+ }
+
+ protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
+ VlanIdCriterion vlanIdCriterion,
FilteringObjective filt,
+ VlanId assignedVlan,
ApplicationId applicationId) {
+ //handling untagged packets via assigned VLAN
+ if (vlanIdCriterion.vlanId() == VlanId.NONE) {
+ vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
+ }
+
+ /*
+ * Note: CpqD switches do not handle MPLS-related operation properly
+ * for a packet with VLAN tag. We pop VLAN here as a workaround.
+ * Side effect: HostService learns redundant hosts with same MAC but
+ * different VLAN. No known side effect on the network reachability.
+ */
List<FlowRule> rules = new ArrayList<>();
- EthCriterion e = (EthCriterion) c;
TrafficSelector.Builder selectorIp = DefaultTrafficSelector
.builder();
TrafficTreatment.Builder treatmentIp = DefaultTrafficTreatment
.builder();
- selectorIp.matchEthDst(e.mac());
+ selectorIp.matchEthDst(ethCriterion.mac());
selectorIp.matchEthType(Ethernet.TYPE_IPV4);
+ selectorIp.matchVlanId(vlanIdCriterion.vlanId());
+ treatmentIp.popVlan();
treatmentIp.transition(ipv4UnicastTableId);
FlowRule ruleIp = DefaultFlowRule.builder().forDevice(deviceId)
.withSelector(selectorIp.build())
.withTreatment(treatmentIp.build())
.withPriority(filt.priority()).fromApp(applicationId)
.makePermanent().forTable(tmacTableId).build();
- log.debug("adding IP ETH rule for MAC: {}", e.mac());
+ log.debug("adding IP ETH rule for MAC: {}", ethCriterion.mac());
rules.add(ruleIp);
TrafficSelector.Builder selectorMpls = DefaultTrafficSelector
.builder();
TrafficTreatment.Builder treatmentMpls = DefaultTrafficTreatment
.builder();
- selectorMpls.matchEthDst(e.mac());
+ selectorMpls.matchEthDst(ethCriterion.mac());
selectorMpls.matchEthType(Ethernet.MPLS_UNICAST);
+ selectorMpls.matchVlanId(vlanIdCriterion.vlanId());
+ treatmentMpls.popVlan();
treatmentMpls.transition(mplsTableId);
FlowRule ruleMpls = DefaultFlowRule.builder()
.forDevice(deviceId).withSelector(selectorMpls.build())
.withTreatment(treatmentMpls.build())
.withPriority(filt.priority()).fromApp(applicationId)
.makePermanent().forTable(tmacTableId).build();
- log.debug("adding MPLS ETH rule for MAC: {}", e.mac());
+ log.debug("adding MPLS ETH rule for MAC: {}", ethCriterion.mac());
rules.add(ruleMpls);
return rules;
}
- protected List<FlowRule> processVlanIdFilter(Criterion c,
+ protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
FilteringObjective filt,
+ VlanId assignedVlan,
ApplicationId applicationId) {
List<FlowRule> rules = new ArrayList<>();
- VlanIdCriterion v = (VlanIdCriterion) c;
- log.debug("adding rule for VLAN: {}", v.vlanId());
+ log.debug("adding rule for VLAN: {}", vlanIdCriterion.vlanId());
TrafficSelector.Builder selector = DefaultTrafficSelector
.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment
.builder();
PortCriterion p = (PortCriterion) filt.key();
- if (v.vlanId() != VlanId.NONE) {
- selector.matchVlanId(v.vlanId());
+ if (vlanIdCriterion.vlanId() != VlanId.NONE) {
+ selector.matchVlanId(vlanIdCriterion.vlanId());
selector.matchInPort(p.port());
treatment.deferred().popVlan();
+ } else {
+ selector.matchInPort(p.port());
+ treatment.immediate().pushVlan().setVlanId(assignedVlan);
}
treatment.transition(tmacTableId);
FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId)
@@ -641,30 +790,79 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
fail(filt, ObjectiveError.UNKNOWN);
return;
}
+
+ EthCriterion ethCriterion = null;
+ VlanIdCriterion vlanIdCriterion = null;
+
// convert filtering conditions for switch-intfs into flowrules
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- for (Criterion c : filt.conditions()) {
- if (c.type() == Criterion.Type.ETH_DST) {
- for (FlowRule rule : processEthDstFilter(c,
- filt,
- applicationId)) {
- ops = install ? ops.add(rule) : ops.remove(rule);
- }
- } else if (c.type() == Criterion.Type.VLAN_VID) {
- for (FlowRule rule : processVlanIdFilter(c,
- filt,
- applicationId)) {
- ops = install ? ops.add(rule) : ops.remove(rule);
- }
- } else if (c.type() == Criterion.Type.IPV4_DST) {
+
+ for (Criterion criterion : filt.conditions()) {
+ if (criterion.type() == Criterion.Type.ETH_DST) {
+ ethCriterion = (EthCriterion) criterion;
+ } else if (criterion.type() == Criterion.Type.VLAN_VID) {
+ vlanIdCriterion = (VlanIdCriterion) criterion;
+ } else if (criterion.type() == Criterion.Type.IPV4_DST) {
log.debug("driver does not process IP filtering rules as it " +
"sends all misses in the IP table to the controller");
} else {
log.warn("Driver does not currently process filtering condition"
- + " of type: {}", c.type());
+ + " of type: {}", criterion.type());
fail(filt, ObjectiveError.UNSUPPORTED);
}
}
+
+ VlanId assignedVlan = null;
+ if (vlanIdCriterion != null && vlanIdCriterion.vlanId() == VlanId.NONE) {
+ // Assign a VLAN ID to untagged packets
+ if (filt.meta() == null) {
+ log.error("Missing metadata in filtering objective required "
+ + "for vlan assignment in dev {}", deviceId);
+ fail(filt, ObjectiveError.BADPARAMS);
+ return;
+ }
+ for (Instruction i : filt.meta().allInstructions()) {
+ if (i instanceof ModVlanIdInstruction) {
+ assignedVlan = ((ModVlanIdInstruction) i).vlanId();
+ }
+ }
+ if (assignedVlan == null) {
+ log.error("Driver requires an assigned vlan-id to tag incoming "
+ + "untagged packets. Not processing vlan filters on "
+ + "device {}", deviceId);
+ fail(filt, ObjectiveError.BADPARAMS);
+ return;
+ }
+ }
+
+ if (ethCriterion == null) {
+ log.debug("filtering objective missing dstMac, cannot program TMAC table");
+ } else {
+ for (FlowRule tmacRule : processEthDstFilter(ethCriterion,
+ vlanIdCriterion,
+ filt,
+ assignedVlan,
+ applicationId)) {
+ log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}",
+ tmacRule, deviceId);
+ ops = install ? ops.add(tmacRule) : ops.remove(tmacRule);
+ }
+ }
+
+ if (ethCriterion == null || vlanIdCriterion == null) {
+ log.debug("filtering objective missing dstMac or vlan, cannot program"
+ + "Vlan Table");
+ } else {
+ for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion,
+ filt,
+ assignedVlan,
+ applicationId)) {
+ log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}",
+ vlanRule, deviceId);
+ ops = install ? ops.add(vlanRule) : ops.remove(vlanRule);
+ }
+ }
+
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
@@ -686,10 +884,10 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
protected void setTableMissEntries() {
// set all table-miss-entries
populateTableMissEntry(vlanTableId, true, false, false, -1);
- populateTableMissEntry(tmacTableId, true, false, false, -1);
- populateTableMissEntry(ipv4UnicastTableId, false, true, true,
- aclTableId);
+ populateTableMissEntry(tmacTableId, false, false, true, dstMacTableId);
+ populateTableMissEntry(ipv4UnicastTableId, false, true, true, aclTableId);
populateTableMissEntry(mplsTableId, false, true, true, aclTableId);
+ populateTableMissEntry(dstMacTableId, false, false, true, aclTableId);
populateTableMissEntry(aclTableId, false, false, false, -1);
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
index 3267d550..91f2679c 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
@@ -21,6 +21,7 @@ import java.util.List;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flow.DefaultFlowRule;
@@ -34,6 +35,7 @@ import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
@@ -175,12 +177,13 @@ public class SpringOpenTTPDell extends SpringOpenTTP {
//Dell switches need ETH_DST based match condition in all IP table entries.
//So while processing the ETH_DST based filtering objective, store
//the device MAC to be used locally to use it while pushing the IP rules.
- protected List<FlowRule> processEthDstFilter(Criterion c,
+ protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
+ VlanIdCriterion vlanIdCriterion,
FilteringObjective filt,
+ VlanId assignedVlan,
ApplicationId applicationId) {
// Store device termination Mac to be used in IP flow entries
- EthCriterion e = (EthCriterion) c;
- deviceTMac = e.mac();
+ deviceTMac = ethCriterion.mac();
log.debug("For now not adding any TMAC rules "
+ "into Dell switches as it is ignoring");
@@ -189,8 +192,9 @@ public class SpringOpenTTPDell extends SpringOpenTTP {
}
@Override
- protected List<FlowRule> processVlanIdFilter(Criterion c,
+ protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
FilteringObjective filt,
+ VlanId assignedVlan,
ApplicationId applicationId) {
log.debug("For now not adding any VLAN rules "
+ "into Dell switches as it is ignoring");
diff --git a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
index af498832..0349e1c2 100644
--- a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
+++ b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
@@ -37,6 +37,13 @@
<behaviour api="org.onosproject.net.behaviour.ExtensionResolver"
impl="org.onosproject.driver.extensions.NiciraExtensionInterpreter" />
</driver>
+ <driver name="ovs-netconf" extends="default"
+ manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*">
+ <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
+ impl="org.onosproject.driver.handshaker.NiciraSwitchHandshaker"/>
+ <behaviour api="org.onosproject.net.behaviour.ControllerConfig"
+ impl="org.onosproject.driver.netconf.NetconfControllerConfig"/>
+ </driver>
<driver name="ovs-corsa" extends="ovs"
manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
@@ -61,7 +68,7 @@
manufacturer="FlowForwarding.org" hwVersion="Unknown"
swVersion="LINC-OE OpenFlow Software Switch 1.1">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
- impl="org.onosproject.driver.handshaker.OFOpticalSwitchImplLINC13"/>
+ impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/>
</driver>
<driver name="corsa"
manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1">
@@ -78,12 +85,12 @@
<driver name="pmc-olt" extends="default"
manufacturer="Big Switch Networks" hwVersion="ivs 0.5" swVersion="ivs 0.5">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OLTPipeline"/>
+ impl="org.onosproject.driver.pipeline.OltPipeline"/>
</driver>
<driver name="g.fast" extends="default"
manufacturer="TEST1" hwVersion="TEST2" swVersion="TEST3">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OLTPipeline"/>
+ impl="org.onosproject.driver.pipeline.OltPipeline"/>
</driver>
<!-- The SoftRouter driver is meant to be used by any software/NPU based
~ switch that wishes to implement a simple 2-table router. To use this
@@ -124,7 +131,7 @@
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
</driver>
- <driver name="onosfw" extends="default"
+ <driver name="onosfw" extends="ovs"
manufacturer="" hwVersion="" swVersion="">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OpenVSwitchPipeline"/>
@@ -134,5 +141,8 @@
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFOpticalSwitch13"/>
</driver>
+ <driver name="aos" extends="ofdpa"
+ manufacturer="Accton" hwVersion=".*" swVersion="1.*">
+ </driver>
</drivers>