|
32 | 32 | import org.onosproject.net.flow.criteria.PiCriterion; |
33 | 33 | import org.onosproject.net.flow.criteria.PortCriterion; |
34 | 34 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
| 35 | +import org.onosproject.net.flow.instructions.Instructions; |
| 36 | +import org.onosproject.net.flow.instructions.L2ModificationInstruction; |
35 | 37 | import org.onosproject.net.flowobjective.FilteringObjective; |
| 38 | +import org.onosproject.net.flowobjective.Objective; |
36 | 39 | import org.onosproject.net.flowobjective.ObjectiveError; |
37 | 40 | import org.onosproject.net.pi.runtime.PiAction; |
38 | 41 | import org.onosproject.net.pi.runtime.PiActionParam; |
39 | 42 | import org.onosproject.pipelines.fabric.impl.behaviour.FabricCapabilities; |
40 | 43 | import org.onosproject.pipelines.fabric.impl.behaviour.FabricConstants; |
| 44 | +import org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils; |
41 | 45 |
|
42 | 46 | import java.util.Collection; |
43 | 47 | import java.util.List; |
44 | 48 |
|
45 | 49 | import static java.lang.String.format; |
| 50 | +import static org.onosproject.net.flow.criteria.Criterion.Type.INNER_VLAN_VID; |
| 51 | +import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID; |
46 | 52 | import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.criterion; |
47 | 53 |
|
48 | 54 | /** |
@@ -95,11 +101,53 @@ public ObjectiveTranslation doTranslate(FilteringObjective obj) |
95 | 101 | obj.conditions(), Criterion.Type.ETH_DST_MASKED); |
96 | 102 |
|
97 | 103 | ingressPortVlanRule(obj, inPort, outerVlan, innerVlan, resultBuilder); |
98 | | - fwdClassifierRules(obj, inPort, ethDst, ethDstMasked, resultBuilder); |
99 | | - |
| 104 | + if (shouldAddFwdClassifierRule(obj)) { |
| 105 | + fwdClassifierRules(obj, inPort, ethDst, ethDstMasked, resultBuilder); |
| 106 | + } else { |
| 107 | + log.debug("Skipping fwd classifier rules for device {}.", deviceId); |
| 108 | + } |
100 | 109 | return resultBuilder.build(); |
101 | 110 | } |
102 | 111 |
|
| 112 | + private boolean shouldAddFwdClassifierRule(FilteringObjective obj) { |
| 113 | + // NOTE: in fabric pipeline the forwarding classifier acts similarly |
| 114 | + // to the TMAC table of OFDPA that matches on input port. |
| 115 | + |
| 116 | + // Forwarding classifier rules should be added to translation when: |
| 117 | + // - the operation is ADD OR |
| 118 | + // - it doesn't refer to double tagged traffic OR |
| 119 | + // - it refers to double tagged traffic |
| 120 | + // and SR is triggering the removal of forwarding classifier rules. |
| 121 | + return obj.op() == Objective.Operation.ADD || |
| 122 | + !isDoubleTagged(obj) || |
| 123 | + (isDoubleTagged(obj) && isLastDoubleTaggedForPort(obj)); |
| 124 | + } |
| 125 | + |
| 126 | + /** |
| 127 | + * Check if the given filtering objective is the last filtering objective |
| 128 | + * for a double-tagged host for a specific port. |
| 129 | + * <p> |
| 130 | + * {@see org.onosproject.segmentrouting.RoutingRulePopulator#buildDoubleTaggedFilteringObj()} |
| 131 | + * {@see org.onosproject.segmentrouting.RoutingRulePopulator#processDoubleTaggedFilter()} |
| 132 | + * |
| 133 | + * @param obj Filtering objective to check. |
| 134 | + * @return True if SR is signaling to remove the forwarding classifier rule, |
| 135 | + * false otherwise. |
| 136 | + */ |
| 137 | + private boolean isLastDoubleTaggedForPort(FilteringObjective obj) { |
| 138 | + Instructions.MetadataInstruction meta = obj.meta().writeMetadata(); |
| 139 | + // SR is setting this metadata when a double tagged filtering objective |
| 140 | + // is removed and no other hosts is sharing the same input port. |
| 141 | + return (meta != null && (meta.metadata() & meta.metadataMask()) == 1); |
| 142 | + } |
| 143 | + |
| 144 | + private boolean isDoubleTagged(FilteringObjective obj) { |
| 145 | + return obj.meta() != null && |
| 146 | + FabricUtils.l2Instruction(obj.meta(), L2ModificationInstruction.L2SubType.VLAN_POP) != null && |
| 147 | + FabricUtils.criterion(obj.conditions(), VLAN_VID) != null && |
| 148 | + FabricUtils.criterion(obj.conditions(), INNER_VLAN_VID) != null; |
| 149 | + } |
| 150 | + |
103 | 151 | private void ingressPortVlanRule( |
104 | 152 | FilteringObjective obj, |
105 | 153 | Criterion inPortCriterion, |
|
0 commit comments