blob: 73039b5382138634894ee6bd0987a67419c3c52f [file] [log] [blame]
Yi Tseng0b809722017-11-03 10:23:26 -07001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Carmelo Cascone356ab8b2019-09-25 01:02:53 -070017package org.onosproject.pipelines.fabric.impl.behaviour.pipeliner;
Yi Tseng0b809722017-11-03 10:23:26 -070018
Daniele Moro5a2de712019-09-24 14:34:07 -070019import com.google.common.collect.Lists;
Carmelo Casconeb5324e72018-11-25 02:26:32 -080020import org.junit.Before;
Yi Tseng0b809722017-11-03 10:23:26 -070021import org.junit.Test;
22import org.onlab.packet.Ethernet;
23import org.onlab.packet.MacAddress;
24import org.onlab.packet.VlanId;
25import org.onlab.util.ImmutableByteSequence;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.flow.DefaultFlowRule;
28import org.onosproject.net.flow.DefaultTrafficSelector;
29import org.onosproject.net.flow.DefaultTrafficTreatment;
30import org.onosproject.net.flow.FlowRule;
31import org.onosproject.net.flow.TableId;
32import org.onosproject.net.flow.TrafficSelector;
33import org.onosproject.net.flow.TrafficTreatment;
34import org.onosproject.net.flow.criteria.Criteria;
Daniele Moro7c3a0022019-07-12 13:38:34 -070035import org.onosproject.net.flow.criteria.PiCriterion;
Yi Tseng0b809722017-11-03 10:23:26 -070036import org.onosproject.net.flowobjective.DefaultFilteringObjective;
37import org.onosproject.net.flowobjective.FilteringObjective;
38import org.onosproject.net.flowobjective.ObjectiveError;
Yi Tseng0b809722017-11-03 10:23:26 -070039import org.onosproject.net.pi.runtime.PiAction;
40import org.onosproject.net.pi.runtime.PiActionParam;
Carmelo Cascone2102bfb2020-12-04 16:54:24 -080041import org.onosproject.pipelines.fabric.FabricConstants;
Yi Tseng0b809722017-11-03 10:23:26 -070042
Daniele Moro5a2de712019-09-24 14:34:07 -070043import java.util.Collection;
44import java.util.List;
45
Yi Tseng0b809722017-11-03 10:23:26 -070046import static org.junit.Assert.assertEquals;
Wailok Shumfb7e7872021-06-18 17:30:08 +080047import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_PW_TRANSPORT_VLAN;
48import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_VLAN;
49import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ETH_TYPE_EXACT_MASK;
50import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV4_ROUTING;
51import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV6_ROUTING;
52import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_MPLS;
53import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ONE;
54import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_EDGE;
55import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_INFRA;
56import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ZERO;
Yi Tseng0b809722017-11-03 10:23:26 -070057
58/**
59 * Test cases for fabric.p4 pipeline filtering control block.
60 */
Carmelo Cascone2388cc12021-05-26 19:30:30 +020061public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTest {
Yi Tseng0b809722017-11-03 10:23:26 -070062
Carmelo Casconeb5324e72018-11-25 02:26:32 -080063 private FilteringObjectiveTranslator translator;
64
65 @Before
66 public void setup() {
67 super.doSetup();
68 translator = new FilteringObjectiveTranslator(DEVICE_ID, capabilitiesHashed);
69 }
70
Yi Tseng0b809722017-11-03 10:23:26 -070071 /**
72 * Creates one rule for ingress_port_vlan table and 3 rules for
Carmelo Cascone356ab8b2019-09-25 01:02:53 -070073 * fwd_classifier table (IPv4, IPv6 and MPLS unicast) when the condition is
74 * VLAN + MAC.
Yi Tseng0b809722017-11-03 10:23:26 -070075 */
76 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -080077 public void testRouterMacAndVlanFilter() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -070078 FilteringObjective filteringObjective = buildFilteringObjective(ROUTER_MAC);
Carmelo Casconeb5324e72018-11-25 02:26:32 -080079 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -070080 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -070081 // in port vlan flow rule
Daniele Moro5a2de712019-09-24 14:34:07 -070082 expectedFlowRules.add(buildExpectedVlanInPortRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -070083 PORT_1,
84 VlanId.NONE,
85 VlanId.NONE,
86 VLAN_100,
Wailok Shumfb7e7872021-06-18 17:30:08 +080087 PORT_TYPE_EDGE,
Daniele Moro5a2de712019-09-24 14:34:07 -070088 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Yi Tseng0b809722017-11-03 10:23:26 -070089
90 // forwarding classifier ipv4
Daniele Moro5a2de712019-09-24 14:34:07 -070091 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -070092 PORT_1,
93 ROUTER_MAC,
94 null,
95 Ethernet.TYPE_IPV4,
Wailok Shumfb7e7872021-06-18 17:30:08 +080096 FWD_IPV4_ROUTING));
Yi Tseng0b809722017-11-03 10:23:26 -070097
98 // forwarding classifier ipv6
Daniele Moro5a2de712019-09-24 14:34:07 -070099 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700100 PORT_1,
101 ROUTER_MAC,
102 null,
103 Ethernet.TYPE_IPV6,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800104 FWD_IPV6_ROUTING));
Yi Tseng0b809722017-11-03 10:23:26 -0700105
106 // forwarding classifier mpls
Daniele Moro5a2de712019-09-24 14:34:07 -0700107 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700108 PORT_1,
109 ROUTER_MAC,
110 null,
111 Ethernet.MPLS_UNICAST,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800112 FWD_MPLS));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800113
Daniele Moro5a2de712019-09-24 14:34:07 -0700114// ObjectiveTranslation.Builder expectedTranslationBuilder = ObjectiveTranslation.builder()
115// .addFlowRule(inportFlowRuleExpected);
116// for (FlowRule flowRule : classifierV4FlowRuleExpected) {
117// expectedTranslationBuilder.addFlowRule(flowRule);
118// }
119// for (FlowRule flowRule : classifierV6FlowRuleExpected) {
120// expectedTranslationBuilder.addFlowRule(flowRule);
121// }
122// for (FlowRule flowRule : classifierMplsFlowRuleExpected) {
123// expectedTranslationBuilder.addFlowRule(flowRule);
124// }
125 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800126
127 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700128 }
129
130 /**
131 * Creates one rule for ingress_port_vlan table and one rule for
132 * fwd_classifier table (IPv4 multicast) when the condition is ipv4
133 * multicast mac address.
134 */
135 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800136 public void testIpv4MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700137 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
138 .pushVlan()
139 .setVlanId(VLAN_100)
140 .build();
141 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
142 .permit()
143 .withPriority(PRIORITY)
144 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700145 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST, MacAddress.IPV4_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700146 .addCondition(Criteria.matchVlanId(VlanId.NONE))
147 .withMeta(treatment)
148 .fromApp(APP_ID)
149 .makePermanent()
150 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800151 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -0700152 List<FlowRule> expectedFlowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -0700153 // in port vlan flow rule
Daniele Moro5a2de712019-09-24 14:34:07 -0700154 expectedFlowRules.add(buildExpectedVlanInPortRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700155 PORT_1,
156 VlanId.NONE,
157 VlanId.NONE,
158 VLAN_100,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800159 PORT_TYPE_EDGE,
Daniele Moro5a2de712019-09-24 14:34:07 -0700160 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Yi Tseng0b809722017-11-03 10:23:26 -0700161
162 // forwarding classifier
Daniele Moro5a2de712019-09-24 14:34:07 -0700163 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700164 PORT_1,
165 MacAddress.IPV4_MULTICAST,
166 MacAddress.IPV4_MULTICAST_MASK,
167 Ethernet.TYPE_IPV4,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800168 FWD_IPV4_ROUTING));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800169
Daniele Moro5a2de712019-09-24 14:34:07 -0700170 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800171
172 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700173 }
174
175 /**
176 * Creates one rule for ingress_port_vlan table and one rule for
177 * fwd_classifier table (IPv6 multicast) when the condition is ipv6
178 * multicast mac address.
179 */
180 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800181 public void testIpv6MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700182 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
183 .pushVlan()
184 .setVlanId(VLAN_100)
185 .build();
186 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
187 .permit()
188 .withPriority(PRIORITY)
189 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700190 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST, MacAddress.IPV6_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700191 .addCondition(Criteria.matchVlanId(VlanId.NONE))
192 .withMeta(treatment)
193 .fromApp(APP_ID)
194 .makePermanent()
195 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800196 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -0700197 Collection<FlowRule> flowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -0700198 // in port vlan flow rule
Daniele Moro5a2de712019-09-24 14:34:07 -0700199 flowRules.add(buildExpectedVlanInPortRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700200 PORT_1,
201 VlanId.NONE,
202 VlanId.NONE,
203 VLAN_100,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800204 PORT_TYPE_EDGE,
Daniele Moro5a2de712019-09-24 14:34:07 -0700205 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Yi Tseng0b809722017-11-03 10:23:26 -0700206
Daniele Moro5a2de712019-09-24 14:34:07 -0700207 flowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700208 PORT_1,
209 MacAddress.IPV6_MULTICAST,
210 MacAddress.IPV6_MULTICAST_MASK,
211 Ethernet.TYPE_IPV6,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800212 FWD_IPV6_ROUTING));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800213
Daniele Moro5a2de712019-09-24 14:34:07 -0700214 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(flowRules);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800215
216 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700217 }
218
219 /**
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700220 * Creates only one rule for ingress_port_vlan table if there is no
221 * condition of destination mac address. The packet will be handled by
222 * bridging table by default.
Yi Tseng0b809722017-11-03 10:23:26 -0700223 */
224 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800225 public void testFwdBridging() throws Exception {
Yi Tseng0b809722017-11-03 10:23:26 -0700226 FilteringObjective filteringObjective = buildFilteringObjective(null);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800227 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700228
229 // in port vlan flow rule
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700230 FlowRule flowRuleExpected = buildExpectedVlanInPortRule(
231 PORT_1,
232 VlanId.NONE,
233 VlanId.NONE,
234 VLAN_100,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800235 PORT_TYPE_EDGE,
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700236 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700237
238 // No rules in forwarding classifier, will do default action: set fwd type to bridging
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800239
240 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
241 .addFlowRule(flowRuleExpected)
242 .build();
243
244 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700245 }
246
247 /**
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800248 * Test DENY objective.
Yi Tseng0b809722017-11-03 10:23:26 -0700249 */
250 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800251 public void testDenyObjective() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700252 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
253 .deny()
254 .withKey(Criteria.matchInPort(PORT_1))
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800255 .addCondition(Criteria.matchVlanId(VlanId.NONE))
Yi Tseng0b809722017-11-03 10:23:26 -0700256 .fromApp(APP_ID)
257 .makePermanent()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800258 .withPriority(PRIORITY)
Yi Tseng0b809722017-11-03 10:23:26 -0700259 .add();
260
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800261 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700262
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800263 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
264 .matchInPort(PORT_1)
Daniele Moro7c3a0022019-07-12 13:38:34 -0700265 .matchPi(buildPiCriterionVlan(null, null));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800266 PiAction piAction = PiAction.builder()
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700267 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_DENY)
268 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800269 FlowRule expectedFlowRule = DefaultFlowRule.builder()
270 .withPriority(PRIORITY)
271 .withSelector(selector.build())
272 .withTreatment(DefaultTrafficTreatment.builder()
273 .piTableAction(piAction).build())
274 .fromApp(APP_ID)
275 .forDevice(DEVICE_ID)
276 .makePermanent()
277 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)
278 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700279
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800280 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
281 .addFlowRule(expectedFlowRule)
282 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700283
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800284 assertEquals(expectedTranslation, actualTranslation);
285
Yi Tseng0b809722017-11-03 10:23:26 -0700286 }
287
288 /**
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700289 * Test double VLAN pop filtering objective Creates one rule for
290 * ingress_port_vlan table and 3 rules for fwd_classifier table (IPv4, IPv6
291 * and MPLS unicast) when the condition is MAC + VLAN + INNER_VLAN.
Daniele Morof51d0c12019-07-30 10:43:10 -0700292 */
293 @Test
294 public void testPopVlan() throws FabricPipelinerException {
295 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
296 .withKey(Criteria.matchInPort(PORT_1))
297 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
298 .addCondition(Criteria.matchVlanId(VLAN_100))
299 .addCondition(Criteria.matchInnerVlanId(VLAN_200))
300 .withPriority(PRIORITY)
301 .fromApp(APP_ID)
302 .withMeta(DefaultTrafficTreatment.builder()
303 .popVlan()
304 .build())
305 .permit()
306 .add();
307 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -0700308 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
Daniele Morof51d0c12019-07-30 10:43:10 -0700309 // Ingress port vlan rule
Daniele Moro5a2de712019-09-24 14:34:07 -0700310 expectedFlowRules.add(buildExpectedVlanInPortRule(
Wailok Shumfb7e7872021-06-18 17:30:08 +0800311 PORT_1, VLAN_100, VLAN_200, VlanId.NONE, PORT_TYPE_EDGE,
Daniele Moro5a2de712019-09-24 14:34:07 -0700312 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Daniele Morof51d0c12019-07-30 10:43:10 -0700313 // Forwarding classifier rules (ipv6, ipv4, mpls)
Daniele Moro5a2de712019-09-24 14:34:07 -0700314 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700315 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV4,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800316 FWD_IPV4_ROUTING));
Daniele Moro5a2de712019-09-24 14:34:07 -0700317 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700318 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV6,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800319 FWD_IPV6_ROUTING));
Daniele Moro5a2de712019-09-24 14:34:07 -0700320 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700321 PORT_1, ROUTER_MAC, null, Ethernet.MPLS_UNICAST,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800322 FWD_MPLS));
Daniele Moro5a2de712019-09-24 14:34:07 -0700323 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
Daniele Morof51d0c12019-07-30 10:43:10 -0700324
325 assertEquals(expectedTranslation, actualTranslation);
326 }
327
328 /**
Yi Tseng0b809722017-11-03 10:23:26 -0700329 * Incorrect filtering key or filtering conditions test.
330 */
331 @Test
332 public void badParamTest() {
333 // Filtering objective should contains filtering key
334 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
335 .permit()
336 .addCondition(Criteria.matchVlanId(VLAN_100))
337 .fromApp(APP_ID)
338 .makePermanent()
339 .add();
340
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800341 ObjectiveTranslation result1 = translator.translate(filteringObjective);
342 assertError(ObjectiveError.BADPARAMS, result1);
Yi Tseng0b809722017-11-03 10:23:26 -0700343
344 // Filtering objective should use in_port as key
345 filteringObjective = DefaultFilteringObjective.builder()
346 .permit()
347 .withKey(Criteria.matchEthDst(ROUTER_MAC))
348 .addCondition(Criteria.matchVlanId(VLAN_100))
349 .withMeta(DefaultTrafficTreatment.emptyTreatment())
350 .fromApp(APP_ID)
351 .makePermanent()
352 .add();
353
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800354 ObjectiveTranslation result2 = translator.translate(filteringObjective);
355 assertError(ObjectiveError.BADPARAMS, result2);
Yi Tseng0b809722017-11-03 10:23:26 -0700356 }
357
pierventre167d4482021-01-08 17:35:47 +0100358 /**
359 * Test port update scenarios for filtering objective. Creates only one rule for
360 * ingress_port_vlan table.
361 */
362 @Test
Wailok Shumfb7e7872021-06-18 17:30:08 +0800363 public void testIsPortUpdate() throws FabricPipelinerException {
pierventre167d4482021-01-08 17:35:47 +0100364 // Tagged port scenario
365 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
366 .withKey(Criteria.matchInPort(PORT_1))
367 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
368 .addCondition(Criteria.matchVlanId(VLAN_100))
369 .withPriority(PRIORITY)
370 .fromApp(APP_ID)
371 .withMeta(DefaultTrafficTreatment.builder()
372 .writeMetadata(2, 0xffffffffffffffffL)
373 .build())
374 .permit()
375 .add();
376 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
377 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
378 // Ingress port vlan rule
379 expectedFlowRules.add(buildExpectedVlanInPortRule(
Wailok Shumfb7e7872021-06-18 17:30:08 +0800380 PORT_1, VLAN_100, null, VlanId.NONE, PORT_TYPE_EDGE,
pierventre167d4482021-01-08 17:35:47 +0100381 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
382 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
383 assertEquals(expectedTranslation, actualTranslation);
384
385 // Untagged port scenario
386 filteringObjective = DefaultFilteringObjective.builder()
387 .withKey(Criteria.matchInPort(PORT_1))
388 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
389 .addCondition(Criteria.matchVlanId(VlanId.NONE))
390 .withPriority(PRIORITY)
391 .fromApp(APP_ID)
392 .withMeta(DefaultTrafficTreatment.builder()
393 .pushVlan()
394 .setVlanId(VLAN_200)
395 .writeMetadata(2, 0xffffffffffffffffL)
396 .build())
397 .permit()
398 .add();
399 actualTranslation = translator.translate(filteringObjective);
400 expectedFlowRules = Lists.newArrayList();
401 // Ingress port vlan rule
402 expectedFlowRules.add(buildExpectedVlanInPortRule(
Wailok Shumfb7e7872021-06-18 17:30:08 +0800403 PORT_1, VlanId.NONE, null, VLAN_200, PORT_TYPE_EDGE,
pierventre167d4482021-01-08 17:35:47 +0100404 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
405 expectedTranslation = buildExpectedTranslation(expectedFlowRules);
406 assertEquals(expectedTranslation, actualTranslation);
407 }
408
Wailok Shum4f51bde2021-06-11 22:48:41 +0800409 /**
410 * Test no more ports scenario for filtering objective.
411 */
412 @Test
413 public void testNoMorePorts() throws FabricPipelinerException {
414 // Tagged port scenario
415 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
416 .withKey(Criteria.matchInPort(PORT_1))
417 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
418 .addCondition(Criteria.matchVlanId(VLAN_100))
419 .withPriority(PRIORITY)
420 .fromApp(APP_ID)
421 .withMeta(DefaultTrafficTreatment.builder().wipeDeferred().build())
422 .permit()
423 .add();
424 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
425 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
426 // Ingress port vlan rule
427 expectedFlowRules.add(buildExpectedVlanInPortRule(
Wailok Shumfb7e7872021-06-18 17:30:08 +0800428 PORT_1, VLAN_100, null, VlanId.NONE, PORT_TYPE_EDGE,
Wailok Shum4f51bde2021-06-11 22:48:41 +0800429 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
430 // forwarding classifier ipv4
431 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
432 PORT_1,
433 ROUTER_MAC,
434 null,
435 Ethernet.TYPE_IPV4,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800436 FWD_IPV4_ROUTING));
Wailok Shum4f51bde2021-06-11 22:48:41 +0800437 // forwarding classifier ipv6
438 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
439 PORT_1,
440 ROUTER_MAC,
441 null,
442 Ethernet.TYPE_IPV6,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800443 FWD_IPV6_ROUTING));
Wailok Shum4f51bde2021-06-11 22:48:41 +0800444 // forwarding classifier mpls
445 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
446 PORT_1,
447 ROUTER_MAC,
448 null,
449 Ethernet.MPLS_UNICAST,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800450 FWD_MPLS));
Wailok Shum4f51bde2021-06-11 22:48:41 +0800451
452 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
453 assertEquals(expectedTranslation, actualTranslation);
454 }
455
Wailok Shumfb7e7872021-06-18 17:30:08 +0800456 /**
457 * Test is infra port scenarios for filtering objective.
458 */
459 @Test
460 public void testIsInfraPort() throws FabricPipelinerException {
461 // PW transport vlan
462 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
463 .withKey(Criteria.matchInPort(PORT_1))
464 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
465 .addCondition(Criteria.matchVlanId(VlanId.vlanId((short) DEFAULT_PW_TRANSPORT_VLAN)))
466 .withPriority(PRIORITY)
467 .fromApp(APP_ID)
468 .permit()
469 .add();
470 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
471
472 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
473 expectedFlowRules.add(buildExpectedVlanInPortRule(
474 PORT_1, VlanId.vlanId((short) DEFAULT_PW_TRANSPORT_VLAN), null, VlanId.NONE,
475 PORT_TYPE_INFRA, FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
476 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
477 PORT_1,
478 ROUTER_MAC,
479 null,
480 Ethernet.TYPE_IPV4,
481 FWD_IPV4_ROUTING));
482 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
483 PORT_1,
484 ROUTER_MAC,
485 null,
486 Ethernet.TYPE_IPV6,
487 FWD_IPV6_ROUTING));
488 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
489 PORT_1,
490 ROUTER_MAC,
491 null,
492 Ethernet.MPLS_UNICAST,
493 FWD_MPLS));
494
495 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
496 assertEquals(expectedTranslation, actualTranslation);
497
498 // Untagged port scenario
499 filteringObjective = DefaultFilteringObjective.builder()
500 .withKey(Criteria.matchInPort(PORT_1))
501 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
502 .addCondition(Criteria.matchVlanId(VlanId.NONE))
503 .withPriority(PRIORITY)
504 .fromApp(APP_ID)
505 .withMeta(DefaultTrafficTreatment.builder()
506 .pushVlan()
507 .setVlanId(VlanId.vlanId((short) DEFAULT_VLAN))
508 .build())
509 .permit()
510 .add();
511 actualTranslation = translator.translate(filteringObjective);
512 expectedFlowRules = Lists.newArrayList();
513 expectedFlowRules.add(buildExpectedVlanInPortRule(
514 PORT_1, null, null, VlanId.vlanId((short) DEFAULT_VLAN),
515 PORT_TYPE_INFRA, FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
516 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
517 PORT_1,
518 ROUTER_MAC,
519 null,
520 Ethernet.TYPE_IPV4,
521 FWD_IPV4_ROUTING));
522 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
523 PORT_1,
524 ROUTER_MAC,
525 null,
526 Ethernet.TYPE_IPV6,
527 FWD_IPV6_ROUTING));
528 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
529 PORT_1,
530 ROUTER_MAC,
531 null,
532 Ethernet.MPLS_UNICAST,
533 FWD_MPLS));
534
535 expectedTranslation = buildExpectedTranslation(expectedFlowRules);
536 assertEquals(expectedTranslation, actualTranslation);
537 }
538
Yi Tseng0b809722017-11-03 10:23:26 -0700539 /* Utilities */
540
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800541 private void assertError(ObjectiveError error, ObjectiveTranslation actualTranslation) {
542 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.ofError(error);
543 assertEquals(expectedTranslation, actualTranslation);
544 }
545
Yi Tseng0b809722017-11-03 10:23:26 -0700546 private FilteringObjective buildFilteringObjective(MacAddress dstMac) {
547 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
548 .pushVlan()
549 .setVlanId(VLAN_100)
550 .build();
551 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder()
552 .permit()
553 .withPriority(PRIORITY)
554 .withKey(Criteria.matchInPort(PORT_1));
555 if (dstMac != null) {
556 builder.addCondition(Criteria.matchEthDst(dstMac));
557 }
558
559 builder.addCondition(Criteria.matchVlanId(VlanId.NONE))
560 .withMeta(treatment)
561 .fromApp(APP_ID)
562 .makePermanent();
563 return builder.add();
564 }
565
Daniele Moro7c3a0022019-07-12 13:38:34 -0700566 private FlowRule buildExpectedVlanInPortRule(PortNumber inPort,
567 VlanId vlanId,
568 VlanId innerVlanId,
Yi Tseng0b809722017-11-03 10:23:26 -0700569 VlanId internalVlan,
Wailok Shumfb7e7872021-06-18 17:30:08 +0800570 byte portType,
Yi Tseng0b809722017-11-03 10:23:26 -0700571 TableId tableId) {
572
573 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
574 .matchInPort(inPort);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800575 PiAction piAction;
Daniele Moro7c3a0022019-07-12 13:38:34 -0700576 selector.matchPi(buildPiCriterionVlan(vlanId, innerVlanId));
577 if (!vlanValid(vlanId)) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800578 piAction = PiAction.builder()
579 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
Wailok Shumfb7e7872021-06-18 17:30:08 +0800580 .withParameter(new PiActionParam(FabricConstants.VLAN_ID, internalVlan.toShort()))
581 .withParameter(new PiActionParam(FabricConstants.PORT_TYPE, portType))
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800582 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700583 } else {
Yi Tseng0b809722017-11-03 10:23:26 -0700584 selector.matchVlanId(vlanId);
Daniele Morof51d0c12019-07-30 10:43:10 -0700585 if (vlanValid(innerVlanId)) {
586 selector.matchInnerVlanId(innerVlanId);
587 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800588 piAction = PiAction.builder()
589 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
Wailok Shumfb7e7872021-06-18 17:30:08 +0800590 .withParameter(new PiActionParam(FabricConstants.PORT_TYPE, portType))
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800591 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700592 }
593
594 return DefaultFlowRule.builder()
595 .withPriority(PRIORITY)
596 .withSelector(selector.build())
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800597 .withTreatment(DefaultTrafficTreatment.builder()
598 .piTableAction(piAction).build())
Yi Tseng0b809722017-11-03 10:23:26 -0700599 .fromApp(APP_ID)
600 .forDevice(DEVICE_ID)
601 .makePermanent()
602 .forTable(tableId)
603 .build();
604 }
605
Daniele Moro7c3a0022019-07-12 13:38:34 -0700606 private boolean vlanValid(VlanId vlanId) {
607 return (vlanId != null && !vlanId.equals(VlanId.NONE));
608 }
609
610 private PiCriterion buildPiCriterionVlan(VlanId vlanId,
611 VlanId innerVlanId) {
612 PiCriterion.Builder piCriterionBuilder = PiCriterion.builder()
613 .matchExact(FabricConstants.HDR_VLAN_IS_VALID,
614 vlanValid(vlanId) ? ONE : ZERO);
615 return piCriterionBuilder.build();
616 }
617
Daniele Moro5a2de712019-09-24 14:34:07 -0700618 private Collection<FlowRule> buildExpectedFwdClassifierRule(PortNumber inPort,
619 MacAddress dstMac,
620 MacAddress dstMacMask,
621 short ethType,
622 byte fwdClass) {
Yi Tseng43ee7e82018-04-12 16:37:34 +0800623 PiActionParam classParam = new PiActionParam(FabricConstants.FWD_TYPE,
Yi Tseng0b809722017-11-03 10:23:26 -0700624 ImmutableByteSequence.copyFrom(fwdClass));
625 PiAction fwdClassifierAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800626 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE)
Yi Tseng0b809722017-11-03 10:23:26 -0700627 .withParameter(classParam)
628 .build();
629 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
630 .piTableAction(fwdClassifierAction)
631 .build();
632
Daniele Moro5a2de712019-09-24 14:34:07 -0700633 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder()
634 .matchInPort(inPort);
635 if (dstMacMask != null) {
636 sbuilder.matchEthDstMasked(dstMac, dstMacMask);
637 } else {
638 sbuilder.matchEthDstMasked(dstMac, MacAddress.EXACT_MASK);
639 }
640 // Special case for MPLS UNICAST forwarding, need to build 2 rules for MPLS+IPv4 and MPLS+IPv6
641 if (ethType == Ethernet.MPLS_UNICAST) {
642 return buildExpectedFwdClassifierRulesMpls(fwdClassifierAction, treatment, sbuilder);
643 }
644 sbuilder.matchPi(PiCriterion.builder()
645 .matchExact(FabricConstants.HDR_IP_ETH_TYPE, ethType)
646 .build());
647 TrafficSelector selector = sbuilder.build();
648 return List.of(DefaultFlowRule.builder()
649 .withPriority(PRIORITY)
650 .withSelector(selector)
651 .withTreatment(treatment)
652 .fromApp(APP_ID)
653 .forDevice(DEVICE_ID)
654 .makePermanent()
655 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
656 .build());
657 }
658
659 private Collection<FlowRule> buildExpectedFwdClassifierRulesMpls(PiAction fwdClassifierAction,
660 TrafficTreatment treatment,
661 TrafficSelector.Builder selectorBuilder) {
662
663 Collection<FlowRule> flowRules = Lists.newArrayList();
664 TrafficSelector selectorIpv4 = selectorBuilder
665 .add(PiCriterion.builder()
Wailok Shumfb7e7872021-06-18 17:30:08 +0800666 .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, ETH_TYPE_EXACT_MASK)
Daniele Moro5a2de712019-09-24 14:34:07 -0700667 .matchExact(FabricConstants.HDR_IP_ETH_TYPE, Ethernet.TYPE_IPV4)
668 .build())
Yi Tseng0b809722017-11-03 10:23:26 -0700669 .build();
Daniele Moro5a2de712019-09-24 14:34:07 -0700670 TrafficSelector selectorIpv6 = selectorBuilder
671 .add(PiCriterion.builder()
Wailok Shumfb7e7872021-06-18 17:30:08 +0800672 .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, ETH_TYPE_EXACT_MASK)
Daniele Moro5a2de712019-09-24 14:34:07 -0700673 .matchExact(FabricConstants.HDR_IP_ETH_TYPE, Ethernet.TYPE_IPV6)
674 .build())
675 .build();
676 flowRules.add(DefaultFlowRule.builder()
677 .withPriority(PRIORITY + 1)
678 .withSelector(selectorIpv4)
679 .withTreatment(treatment)
680 .fromApp(APP_ID)
681 .forDevice(DEVICE_ID)
682 .makePermanent()
683 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
684 .build());
685 flowRules.add(DefaultFlowRule.builder()
686 .withPriority(PRIORITY + 1)
687 .withSelector(selectorIpv6)
688 .withTreatment(treatment)
689 .fromApp(APP_ID)
690 .forDevice(DEVICE_ID)
691 .makePermanent()
692 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
693 .build());
694 return flowRules;
695 }
696
697 private ObjectiveTranslation buildExpectedTranslation(Collection<FlowRule> flowRules)
698 throws FabricPipelinerException {
699 ObjectiveTranslation.Builder expectedTranslationBuilder = ObjectiveTranslation.builder();
700 for (FlowRule flowRule : flowRules) {
701 expectedTranslationBuilder.addFlowRule(flowRule);
702 }
703 return expectedTranslationBuilder.build();
Yi Tseng0b809722017-11-03 10:23:26 -0700704 }
705}