Support IPv4 multicast in P4 fabric pipeline
- Multicast can use the same table as unicast. Merge into one.
- Allow masked destination MAC in classifier table
Note:
- Pipeliner now translates all exact MAC match to masked match with FF:FF:FF:FF:FF:FF mask.
- Interpreter now only uses masked src/dst MAC
Change-Id: Ibd27ebfb2d72ba929031f07a29927eb6f1844f11
(cherry picked from commit 0865779b66a59a623856b1353615e462af5575c5)
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricFilteringPipeliner.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricFilteringPipeliner.java
index a8515e5..7d6ad40 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricFilteringPipeliner.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricFilteringPipeliner.java
@@ -51,12 +51,10 @@
public class FabricFilteringPipeliner {
private static final Logger log = getLogger(FabricFilteringPipeliner.class);
// Forwarding types
- private static final byte FWD_BRIDGING = 0;
- private static final byte FWD_MPLS = 1;
- private static final byte FWD_IPV4_UNICAST = 2;
- private static final byte FWD_IPV4_MULTICAST = 3;
- private static final byte FWD_IPV6_UNICAST = 4;
- private static final byte FWD_IPV6_MULTICAST = 5;
+ static final byte FWD_BRIDGING = 0;
+ static final byte FWD_MPLS = 1;
+ static final byte FWD_IPV4_ROUTING = 2;
+ static final byte FWD_IPV6_ROUTING = 3;
private static final PiCriterion VLAN_VALID = PiCriterion.builder()
.matchExact(FabricConstants.HDR_VLAN_TAG_IS_VALID, new byte[]{1})
.build();
@@ -104,11 +102,16 @@
.map(criterion -> (EthCriterion) criterion)
.findFirst()
.orElse(null);
+ EthCriterion ethDstMaskedCriterion = filterObjective.conditions().stream()
+ .filter(criterion -> criterion.type() == Criterion.Type.ETH_DST_MASKED)
+ .map(criterion -> (EthCriterion) criterion)
+ .findFirst()
+ .orElse(null);
FlowRule inPortVlanTableRule = createInPortVlanTable(inPortCriterion, vlanCriterion,
filterObjective);
Collection<FlowRule> fwdClassifierRules = createFwdClassifierRules(inPortCriterion, ethDstCriterion,
- filterObjective);
+ ethDstMaskedCriterion, filterObjective);
resultBuilder.addFlowRule(inPortVlanTableRule);
fwdClassifierRules.forEach(resultBuilder::addFlowRule);
@@ -155,38 +158,46 @@
private Collection<FlowRule> createFwdClassifierRules(PortCriterion inPortCriterion,
EthCriterion ethDstCriterion,
+ EthCriterion ethDstMaskedCriterion,
FilteringObjective filterObjective) {
+ PortNumber port = inPortCriterion.port();
+
Collection<FlowRule> flowRules = Lists.newArrayList();
if (ethDstCriterion == null) {
- // Bridging table, do nothing
+ if (ethDstMaskedCriterion == null) {
+ // Bridging table, do nothing
+ return flowRules;
+ }
+ // Masked fwd classifier rule
+ MacAddress dstMac = ethDstMaskedCriterion.mac();
+ MacAddress dstMacMask = ethDstMaskedCriterion.mask();
+ FlowRule flow = createMaskedFwdClassifierRule(port, dstMac, dstMacMask, filterObjective);
+ if (flow != null) {
+ flowRules.add(flow);
+ }
return flowRules;
}
- PortNumber port = inPortCriterion.port();
MacAddress dstMac = ethDstCriterion.mac();
- if (dstMac.isMulticast()) {
- flowRules.add(createMulticastFwdClassifierRule(port, dstMac, filterObjective));
- return flowRules;
- }
-
flowRules.addAll(createIpFwdClassifierRules(port, dstMac, filterObjective));
flowRules.add(createMplsFwdClassifierRule(port, dstMac, filterObjective));
return flowRules;
}
- private FlowRule createMulticastFwdClassifierRule(PortNumber inPort, MacAddress dstMac,
- FilteringObjective filterObjective) {
+ private FlowRule createMaskedFwdClassifierRule(PortNumber inPort, MacAddress dstMac, MacAddress dstMacMask,
+ FilteringObjective filterObjective) {
TrafficTreatment treatment;
short ethType;
- if (dstMac.equals(MacAddress.IPV4_MULTICAST)) {
- // Ipv4 multicast
- treatment = createFwdClassifierTreatment(FWD_IPV4_MULTICAST);
+ if (dstMac.equals(MacAddress.IPV4_MULTICAST) && dstMacMask.equals(MacAddress.IPV4_MULTICAST_MASK)) {
+ treatment = createFwdClassifierTreatment(FWD_IPV4_ROUTING);
ethType = Ethernet.TYPE_IPV4;
- } else {
- // IPv6 multicast
- treatment = createFwdClassifierTreatment(FWD_IPV6_MULTICAST);
+ } else if (dstMac.equals(MacAddress.IPV6_MULTICAST) && dstMacMask.equals(MacAddress.IPV6_MULTICAST_MASK)) {
+ treatment = createFwdClassifierTreatment(FWD_IPV6_ROUTING);
ethType = Ethernet.TYPE_IPV6;
+ } else {
+ log.warn("Unsupported masked fwd classifier rule. mac={}. mask={}", dstMac, dstMacMask);
+ return null;
}
- return createFwdClassifierRule(inPort, ethType, dstMac, treatment, filterObjective);
+ return createFwdClassifierRule(inPort, ethType, dstMac, dstMacMask, treatment, filterObjective);
}
private Collection<FlowRule> createIpFwdClassifierRules(PortNumber inPort,
@@ -194,10 +205,10 @@
FilteringObjective filterObjective) {
Collection<FlowRule> flowRules = Lists.newArrayList();
TrafficTreatment treatment;
- treatment = createFwdClassifierTreatment(FWD_IPV4_UNICAST);
- flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV4, dstMac, treatment, filterObjective));
- treatment = createFwdClassifierTreatment(FWD_IPV6_UNICAST);
- flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV6, dstMac, treatment, filterObjective));
+ treatment = createFwdClassifierTreatment(FWD_IPV4_ROUTING);
+ flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV4, dstMac, null, treatment, filterObjective));
+ treatment = createFwdClassifierTreatment(FWD_IPV6_ROUTING);
+ flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV6, dstMac, null, treatment, filterObjective));
return flowRules;
}
@@ -205,18 +216,23 @@
MacAddress dstMac,
FilteringObjective filterObjective) {
TrafficTreatment treatment = createFwdClassifierTreatment(FWD_MPLS);
- return createFwdClassifierRule(inPort, Ethernet.MPLS_UNICAST, dstMac, treatment, filterObjective);
+ return createFwdClassifierRule(inPort, Ethernet.MPLS_UNICAST, dstMac, null, treatment, filterObjective);
}
private FlowRule createFwdClassifierRule(PortNumber inPort,
short ethType,
MacAddress dstMac,
+ MacAddress dstMacMask,
TrafficTreatment treatment,
FilteringObjective filterObjective) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
.matchInPort(inPort)
- .matchEthDst(dstMac)
.matchEthType(ethType);
+ if (dstMacMask != null) {
+ selector.matchEthDstMasked(dstMac, dstMacMask);
+ } else {
+ selector.matchEthDstMasked(dstMac, MacAddress.EXACT_MASK);
+ }
return DefaultFlowRule.builder()
.withSelector(selector.build())