IPv6 support for vRouter
Changes:
- Adds support to CPRM;
- Updates DHM;
- Fixes SingleSwitchFibInstaller;
- Updates the driver;
- IPv6 unit tests;
Change-Id: I0d9a143fbf5ee8d77ffe3ed3e180fede200d3cdd
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
index 66d0b53..ac9c38a 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
@@ -43,6 +43,8 @@
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.IPProtocolCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
@@ -62,6 +64,10 @@
import java.util.List;
import java.util.Objects;
+import static org.onlab.packet.Ethernet.TYPE_IPV4;
+import static org.onlab.packet.ICMP6.ECHO_REPLY;
+import static org.onlab.packet.ICMP6.ECHO_REQUEST;
+import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
import static org.onlab.util.Tools.delay;
import static org.slf4j.LoggerFactory.getLogger;
@@ -158,25 +164,25 @@
@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;
- }
- 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());
+ 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 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());
}
}
@@ -243,7 +249,7 @@
p = (PortCriterion) filt.key();
} else {
log.warn("No key defined in filtering objective from app: {}. Not"
- + "processing filtering objective", applicationId);
+ + "processing filtering objective", applicationId);
fail(filt, ObjectiveError.UNKNOWN);
return;
}
@@ -261,6 +267,7 @@
fail(filt, ObjectiveError.UNSUPPORTED);
return;
}
+
}
log.debug("Modifying Port/VLAN/MAC filtering rules in filter table: {}/{}/{}",
@@ -276,7 +283,7 @@
selector.matchEthDst(e.mac());
}
selector.matchVlanId(v.vlanId());
- selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchEthType(TYPE_IPV4);
if (!v.vlanId().equals(VlanId.NONE)) {
treatment.popVlan();
}
@@ -291,6 +298,29 @@
.forTable(FILTER_TABLE).build();
ops = install ? ops.add(rule) : ops.remove(rule);
+ // FIXME IPv6 in the multicast use case.
+ // Filtering rules for IPv6.
+ if (e.mask() == null) {
+ selector = DefaultTrafficSelector.builder();
+ selector.matchInPort(p.port());
+ selector.matchEthDst(e.mac());
+ selector.matchVlanId(v.vlanId());
+ selector.matchEthType(Ethernet.TYPE_IPV6);
+ if (!v.vlanId().equals(VlanId.NONE)) {
+ treatment.popVlan();
+ }
+ treatment.transition(FIB_TABLE);
+ rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(FILTER_TABLE).build();
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+ }
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
@@ -309,13 +339,13 @@
private Collection<FlowRule> processForward(ForwardingObjective fwd) {
switch (fwd.flag()) {
- case SPECIFIC:
- return processSpecific(fwd);
- case VERSATILE:
- return processVersatile(fwd);
- default:
- fail(fwd, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", fwd.flag());
+ case SPECIFIC:
+ return processSpecific(fwd);
+ case VERSATILE:
+ return processVersatile(fwd);
+ default:
+ fail(fwd, ObjectiveError.UNKNOWN);
+ log.warn("Unknown forwarding flag {}", fwd.flag());
}
return Collections.emptySet();
}
@@ -335,7 +365,7 @@
Collection<FlowRule> flowrules = new ArrayList<>();
if (fwd.nextId() == null && fwd.treatment() == null) {
log.error("Forwarding objective {} from {} must contain "
- + "nextId or Treatment", fwd.selector(), fwd.appId());
+ + "nextId or Treatment", fwd.selector(), fwd.appId());
return Collections.emptySet();
}
@@ -344,7 +374,8 @@
// A punt rule for IP traffic should be directed to the FIB table
// so that it only takes effect if the packet misses the FIB rules
if (fwd.treatment() != null && containsPunt(fwd.treatment()) &&
- fwd.selector() != null && matchesIp(fwd.selector())) {
+ fwd.selector() != null && matchesIp(fwd.selector()) &&
+ !matchesControlTraffic(fwd.selector())) {
tableId = FIB_TABLE;
}
@@ -395,7 +426,24 @@
private boolean matchesIp(TrafficSelector selector) {
EthTypeCriterion c = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
- return c != null && c.ethType().equals(EthType.EtherType.IPV4.ethType());
+ return c != null && (c.ethType().equals(EthType.EtherType.IPV4.ethType()) ||
+ c.ethType().equals(EthType.EtherType.IPV6.ethType()));
+ }
+
+ private boolean matchesControlTraffic(TrafficSelector selector) {
+ EthTypeCriterion c = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
+ if (c != null && c.ethType().equals(EthType.EtherType.ARP.ethType())) {
+ return true;
+ } else if (c != null && c.ethType().equals(EthType.EtherType.IPV6.ethType())) {
+ IPProtocolCriterion i = (IPProtocolCriterion) selector.getCriterion(Criterion.Type.IP_PROTO);
+ if (i != null && i.protocol() == PROTOCOL_ICMP6) {
+ Icmpv6TypeCriterion ic = (Icmpv6TypeCriterion) selector.getCriterion(Criterion.Type.ICMPV6_TYPE);
+ if (ic.icmpv6Type() != ECHO_REQUEST && ic.icmpv6Type() != ECHO_REPLY) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
@@ -415,19 +463,34 @@
EthTypeCriterion ethType =
(EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
// XXX currently supporting only the L3 unicast table
- if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) {
+ if (ethType == null || (ethType.ethType().toShort() != TYPE_IPV4
+ && ethType.ethType().toShort() != Ethernet.TYPE_IPV6)) {
fail(fwd, ObjectiveError.UNSUPPORTED);
return Collections.emptySet();
}
+ //We build the selector according the eth type.
+ IpPrefix ipPrefix;
+ TrafficSelector.Builder filteredSelector;
+ if (ethType.ethType().toShort() == TYPE_IPV4) {
+ ipPrefix = ((IPCriterion)
+ selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
- IpPrefix ipPrefix = ((IPCriterion)
- selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
+ filteredSelector = DefaultTrafficSelector.builder()
+ .matchEthType(TYPE_IPV4);
+ } else {
+ ipPrefix = ((IPCriterion)
+ selector.getCriterion(Criterion.Type.IPV6_DST)).ip();
- TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4);
-
+ filteredSelector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV6);
+ }
+ // If the prefix is different from the default via.
if (ipPrefix.prefixLength() != 0) {
- filteredSelector.matchIPDst(ipPrefix);
+ if (ethType.ethType().toShort() == TYPE_IPV4) {
+ filteredSelector.matchIPDst(ipPrefix);
+ } else {
+ filteredSelector.matchIPv6Dst(ipPrefix);
+ }
}
TrafficTreatment tt = null;