blob: 71e45b1d5ecb8ff5d885fdb4ff8286f3c3d9cbab [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;
Yi Tseng0b809722017-11-03 10:23:26 -070047
48/**
49 * Test cases for fabric.p4 pipeline filtering control block.
50 */
Carmelo Cascone2388cc12021-05-26 19:30:30 +020051public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTest {
Yi Tseng0b809722017-11-03 10:23:26 -070052
Daniele Moro7c3a0022019-07-12 13:38:34 -070053 public static final byte[] ONE = {1};
54 public static final byte[] ZERO = {0};
Daniele Moro5a2de712019-09-24 14:34:07 -070055 public static final short EXACT_MATCH_ETH_TYPE = (short) 0xFFFF;
Carmelo Casconeb5324e72018-11-25 02:26:32 -080056 private FilteringObjectiveTranslator translator;
57
58 @Before
59 public void setup() {
60 super.doSetup();
61 translator = new FilteringObjectiveTranslator(DEVICE_ID, capabilitiesHashed);
62 }
63
Yi Tseng0b809722017-11-03 10:23:26 -070064 /**
65 * Creates one rule for ingress_port_vlan table and 3 rules for
Carmelo Cascone356ab8b2019-09-25 01:02:53 -070066 * fwd_classifier table (IPv4, IPv6 and MPLS unicast) when the condition is
67 * VLAN + MAC.
Yi Tseng0b809722017-11-03 10:23:26 -070068 */
69 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -080070 public void testRouterMacAndVlanFilter() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -070071 FilteringObjective filteringObjective = buildFilteringObjective(ROUTER_MAC);
Carmelo Casconeb5324e72018-11-25 02:26:32 -080072 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -070073 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -070074 // in port vlan flow rule
Daniele Moro5a2de712019-09-24 14:34:07 -070075 expectedFlowRules.add(buildExpectedVlanInPortRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -070076 PORT_1,
77 VlanId.NONE,
78 VlanId.NONE,
79 VLAN_100,
Daniele Moro5a2de712019-09-24 14:34:07 -070080 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Yi Tseng0b809722017-11-03 10:23:26 -070081
82 // forwarding classifier ipv4
Daniele Moro5a2de712019-09-24 14:34:07 -070083 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -070084 PORT_1,
85 ROUTER_MAC,
86 null,
87 Ethernet.TYPE_IPV4,
Daniele Moro5a2de712019-09-24 14:34:07 -070088 FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
Yi Tseng0b809722017-11-03 10:23:26 -070089
90 // forwarding classifier ipv6
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_IPV6,
Daniele Moro5a2de712019-09-24 14:34:07 -070096 FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
Yi Tseng0b809722017-11-03 10:23:26 -070097
98 // forwarding classifier mpls
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.MPLS_UNICAST,
Daniele Moro5a2de712019-09-24 14:34:07 -0700104 FilteringObjectiveTranslator.FWD_MPLS));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800105
Daniele Moro5a2de712019-09-24 14:34:07 -0700106// ObjectiveTranslation.Builder expectedTranslationBuilder = ObjectiveTranslation.builder()
107// .addFlowRule(inportFlowRuleExpected);
108// for (FlowRule flowRule : classifierV4FlowRuleExpected) {
109// expectedTranslationBuilder.addFlowRule(flowRule);
110// }
111// for (FlowRule flowRule : classifierV6FlowRuleExpected) {
112// expectedTranslationBuilder.addFlowRule(flowRule);
113// }
114// for (FlowRule flowRule : classifierMplsFlowRuleExpected) {
115// expectedTranslationBuilder.addFlowRule(flowRule);
116// }
117 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800118
119 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700120 }
121
122 /**
123 * Creates one rule for ingress_port_vlan table and one rule for
124 * fwd_classifier table (IPv4 multicast) when the condition is ipv4
125 * multicast mac address.
126 */
127 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800128 public void testIpv4MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700129 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
130 .pushVlan()
131 .setVlanId(VLAN_100)
132 .build();
133 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
134 .permit()
135 .withPriority(PRIORITY)
136 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700137 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST, MacAddress.IPV4_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700138 .addCondition(Criteria.matchVlanId(VlanId.NONE))
139 .withMeta(treatment)
140 .fromApp(APP_ID)
141 .makePermanent()
142 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800143 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -0700144 List<FlowRule> expectedFlowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -0700145 // in port vlan flow rule
Daniele Moro5a2de712019-09-24 14:34:07 -0700146 expectedFlowRules.add(buildExpectedVlanInPortRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700147 PORT_1,
148 VlanId.NONE,
149 VlanId.NONE,
150 VLAN_100,
Daniele Moro5a2de712019-09-24 14:34:07 -0700151 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Yi Tseng0b809722017-11-03 10:23:26 -0700152
153 // forwarding classifier
Daniele Moro5a2de712019-09-24 14:34:07 -0700154 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700155 PORT_1,
156 MacAddress.IPV4_MULTICAST,
157 MacAddress.IPV4_MULTICAST_MASK,
158 Ethernet.TYPE_IPV4,
Daniele Moro5a2de712019-09-24 14:34:07 -0700159 FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800160
Daniele Moro5a2de712019-09-24 14:34:07 -0700161 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800162
163 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700164 }
165
166 /**
167 * Creates one rule for ingress_port_vlan table and one rule for
168 * fwd_classifier table (IPv6 multicast) when the condition is ipv6
169 * multicast mac address.
170 */
171 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800172 public void testIpv6MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700173 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
174 .pushVlan()
175 .setVlanId(VLAN_100)
176 .build();
177 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
178 .permit()
179 .withPriority(PRIORITY)
180 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700181 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST, MacAddress.IPV6_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700182 .addCondition(Criteria.matchVlanId(VlanId.NONE))
183 .withMeta(treatment)
184 .fromApp(APP_ID)
185 .makePermanent()
186 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800187 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -0700188 Collection<FlowRule> flowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -0700189 // in port vlan flow rule
Daniele Moro5a2de712019-09-24 14:34:07 -0700190 flowRules.add(buildExpectedVlanInPortRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700191 PORT_1,
192 VlanId.NONE,
193 VlanId.NONE,
194 VLAN_100,
Daniele Moro5a2de712019-09-24 14:34:07 -0700195 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Yi Tseng0b809722017-11-03 10:23:26 -0700196
Daniele Moro5a2de712019-09-24 14:34:07 -0700197 flowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700198 PORT_1,
199 MacAddress.IPV6_MULTICAST,
200 MacAddress.IPV6_MULTICAST_MASK,
201 Ethernet.TYPE_IPV6,
Daniele Moro5a2de712019-09-24 14:34:07 -0700202 FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800203
Daniele Moro5a2de712019-09-24 14:34:07 -0700204 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(flowRules);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800205
206 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700207 }
208
209 /**
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700210 * Creates only one rule for ingress_port_vlan table if there is no
211 * condition of destination mac address. The packet will be handled by
212 * bridging table by default.
Yi Tseng0b809722017-11-03 10:23:26 -0700213 */
214 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800215 public void testFwdBridging() throws Exception {
Yi Tseng0b809722017-11-03 10:23:26 -0700216 FilteringObjective filteringObjective = buildFilteringObjective(null);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800217 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700218
219 // in port vlan flow rule
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700220 FlowRule flowRuleExpected = buildExpectedVlanInPortRule(
221 PORT_1,
222 VlanId.NONE,
223 VlanId.NONE,
224 VLAN_100,
225 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700226
227 // No rules in forwarding classifier, will do default action: set fwd type to bridging
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800228
229 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
230 .addFlowRule(flowRuleExpected)
231 .build();
232
233 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700234 }
235
236 /**
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800237 * Test DENY objective.
Yi Tseng0b809722017-11-03 10:23:26 -0700238 */
239 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800240 public void testDenyObjective() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700241 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
242 .deny()
243 .withKey(Criteria.matchInPort(PORT_1))
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800244 .addCondition(Criteria.matchVlanId(VlanId.NONE))
Yi Tseng0b809722017-11-03 10:23:26 -0700245 .fromApp(APP_ID)
246 .makePermanent()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800247 .withPriority(PRIORITY)
Yi Tseng0b809722017-11-03 10:23:26 -0700248 .add();
249
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800250 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700251
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800252 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
253 .matchInPort(PORT_1)
Daniele Moro7c3a0022019-07-12 13:38:34 -0700254 .matchPi(buildPiCriterionVlan(null, null));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800255 PiAction piAction = PiAction.builder()
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700256 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_DENY)
257 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800258 FlowRule expectedFlowRule = DefaultFlowRule.builder()
259 .withPriority(PRIORITY)
260 .withSelector(selector.build())
261 .withTreatment(DefaultTrafficTreatment.builder()
262 .piTableAction(piAction).build())
263 .fromApp(APP_ID)
264 .forDevice(DEVICE_ID)
265 .makePermanent()
266 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)
267 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700268
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800269 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
270 .addFlowRule(expectedFlowRule)
271 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700272
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800273 assertEquals(expectedTranslation, actualTranslation);
274
Yi Tseng0b809722017-11-03 10:23:26 -0700275 }
276
277 /**
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700278 * Test double VLAN pop filtering objective Creates one rule for
279 * ingress_port_vlan table and 3 rules for fwd_classifier table (IPv4, IPv6
280 * and MPLS unicast) when the condition is MAC + VLAN + INNER_VLAN.
Daniele Morof51d0c12019-07-30 10:43:10 -0700281 */
282 @Test
283 public void testPopVlan() throws FabricPipelinerException {
284 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
285 .withKey(Criteria.matchInPort(PORT_1))
286 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
287 .addCondition(Criteria.matchVlanId(VLAN_100))
288 .addCondition(Criteria.matchInnerVlanId(VLAN_200))
289 .withPriority(PRIORITY)
290 .fromApp(APP_ID)
291 .withMeta(DefaultTrafficTreatment.builder()
292 .popVlan()
293 .build())
294 .permit()
295 .add();
296 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Daniele Moro5a2de712019-09-24 14:34:07 -0700297 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
Daniele Morof51d0c12019-07-30 10:43:10 -0700298 // Ingress port vlan rule
Daniele Moro5a2de712019-09-24 14:34:07 -0700299 expectedFlowRules.add(buildExpectedVlanInPortRule(
Daniele Morof51d0c12019-07-30 10:43:10 -0700300 PORT_1, VLAN_100, VLAN_200, VlanId.NONE,
Daniele Moro5a2de712019-09-24 14:34:07 -0700301 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
Daniele Morof51d0c12019-07-30 10:43:10 -0700302 // Forwarding classifier rules (ipv6, ipv4, mpls)
Daniele Moro5a2de712019-09-24 14:34:07 -0700303 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700304 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV4,
Daniele Moro5a2de712019-09-24 14:34:07 -0700305 FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
306 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700307 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV6,
Daniele Moro5a2de712019-09-24 14:34:07 -0700308 FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
309 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
Carmelo Cascone356ab8b2019-09-25 01:02:53 -0700310 PORT_1, ROUTER_MAC, null, Ethernet.MPLS_UNICAST,
Daniele Moro5a2de712019-09-24 14:34:07 -0700311 FilteringObjectiveTranslator.FWD_MPLS));
312 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
Daniele Morof51d0c12019-07-30 10:43:10 -0700313
314 assertEquals(expectedTranslation, actualTranslation);
315 }
316
317 /**
Yi Tseng0b809722017-11-03 10:23:26 -0700318 * Incorrect filtering key or filtering conditions test.
319 */
320 @Test
321 public void badParamTest() {
322 // Filtering objective should contains filtering key
323 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
324 .permit()
325 .addCondition(Criteria.matchVlanId(VLAN_100))
326 .fromApp(APP_ID)
327 .makePermanent()
328 .add();
329
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800330 ObjectiveTranslation result1 = translator.translate(filteringObjective);
331 assertError(ObjectiveError.BADPARAMS, result1);
Yi Tseng0b809722017-11-03 10:23:26 -0700332
333 // Filtering objective should use in_port as key
334 filteringObjective = DefaultFilteringObjective.builder()
335 .permit()
336 .withKey(Criteria.matchEthDst(ROUTER_MAC))
337 .addCondition(Criteria.matchVlanId(VLAN_100))
338 .withMeta(DefaultTrafficTreatment.emptyTreatment())
339 .fromApp(APP_ID)
340 .makePermanent()
341 .add();
342
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800343 ObjectiveTranslation result2 = translator.translate(filteringObjective);
344 assertError(ObjectiveError.BADPARAMS, result2);
Yi Tseng0b809722017-11-03 10:23:26 -0700345 }
346
pierventre167d4482021-01-08 17:35:47 +0100347 /**
348 * Test port update scenarios for filtering objective. Creates only one rule for
349 * ingress_port_vlan table.
350 */
351 @Test
352 public void testPortUpdate() throws FabricPipelinerException {
353 // Tagged port scenario
354 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
355 .withKey(Criteria.matchInPort(PORT_1))
356 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
357 .addCondition(Criteria.matchVlanId(VLAN_100))
358 .withPriority(PRIORITY)
359 .fromApp(APP_ID)
360 .withMeta(DefaultTrafficTreatment.builder()
361 .writeMetadata(2, 0xffffffffffffffffL)
362 .build())
363 .permit()
364 .add();
365 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
366 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
367 // Ingress port vlan rule
368 expectedFlowRules.add(buildExpectedVlanInPortRule(
369 PORT_1, VLAN_100, null, VlanId.NONE,
370 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
371 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
372 assertEquals(expectedTranslation, actualTranslation);
373
374 // Untagged port scenario
375 filteringObjective = DefaultFilteringObjective.builder()
376 .withKey(Criteria.matchInPort(PORT_1))
377 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
378 .addCondition(Criteria.matchVlanId(VlanId.NONE))
379 .withPriority(PRIORITY)
380 .fromApp(APP_ID)
381 .withMeta(DefaultTrafficTreatment.builder()
382 .pushVlan()
383 .setVlanId(VLAN_200)
384 .writeMetadata(2, 0xffffffffffffffffL)
385 .build())
386 .permit()
387 .add();
388 actualTranslation = translator.translate(filteringObjective);
389 expectedFlowRules = Lists.newArrayList();
390 // Ingress port vlan rule
391 expectedFlowRules.add(buildExpectedVlanInPortRule(
392 PORT_1, VlanId.NONE, null, VLAN_200,
393 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
394 expectedTranslation = buildExpectedTranslation(expectedFlowRules);
395 assertEquals(expectedTranslation, actualTranslation);
396 }
397
Wailok Shum4f51bde2021-06-11 22:48:41 +0800398 /**
399 * Test no more ports scenario for filtering objective.
400 */
401 @Test
402 public void testNoMorePorts() throws FabricPipelinerException {
403 // Tagged port scenario
404 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
405 .withKey(Criteria.matchInPort(PORT_1))
406 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
407 .addCondition(Criteria.matchVlanId(VLAN_100))
408 .withPriority(PRIORITY)
409 .fromApp(APP_ID)
410 .withMeta(DefaultTrafficTreatment.builder().wipeDeferred().build())
411 .permit()
412 .add();
413 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
414 Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
415 // Ingress port vlan rule
416 expectedFlowRules.add(buildExpectedVlanInPortRule(
417 PORT_1, VLAN_100, null, VlanId.NONE,
418 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
419 // forwarding classifier ipv4
420 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
421 PORT_1,
422 ROUTER_MAC,
423 null,
424 Ethernet.TYPE_IPV4,
425 FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
426 // forwarding classifier ipv6
427 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
428 PORT_1,
429 ROUTER_MAC,
430 null,
431 Ethernet.TYPE_IPV6,
432 FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
433 // forwarding classifier mpls
434 expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
435 PORT_1,
436 ROUTER_MAC,
437 null,
438 Ethernet.MPLS_UNICAST,
439 FilteringObjectiveTranslator.FWD_MPLS));
440
441 ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
442 assertEquals(expectedTranslation, actualTranslation);
443 }
444
Yi Tseng0b809722017-11-03 10:23:26 -0700445 /* Utilities */
446
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800447 private void assertError(ObjectiveError error, ObjectiveTranslation actualTranslation) {
448 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.ofError(error);
449 assertEquals(expectedTranslation, actualTranslation);
450 }
451
Yi Tseng0b809722017-11-03 10:23:26 -0700452 private FilteringObjective buildFilteringObjective(MacAddress dstMac) {
453 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
454 .pushVlan()
455 .setVlanId(VLAN_100)
456 .build();
457 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder()
458 .permit()
459 .withPriority(PRIORITY)
460 .withKey(Criteria.matchInPort(PORT_1));
461 if (dstMac != null) {
462 builder.addCondition(Criteria.matchEthDst(dstMac));
463 }
464
465 builder.addCondition(Criteria.matchVlanId(VlanId.NONE))
466 .withMeta(treatment)
467 .fromApp(APP_ID)
468 .makePermanent();
469 return builder.add();
470 }
471
Daniele Moro7c3a0022019-07-12 13:38:34 -0700472 private FlowRule buildExpectedVlanInPortRule(PortNumber inPort,
473 VlanId vlanId,
474 VlanId innerVlanId,
Yi Tseng0b809722017-11-03 10:23:26 -0700475 VlanId internalVlan,
476 TableId tableId) {
477
478 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
479 .matchInPort(inPort);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800480 PiAction piAction;
Daniele Moro7c3a0022019-07-12 13:38:34 -0700481 selector.matchPi(buildPiCriterionVlan(vlanId, innerVlanId));
482 if (!vlanValid(vlanId)) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800483 piAction = PiAction.builder()
484 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
485 .withParameter(new PiActionParam(
486 FabricConstants.VLAN_ID, internalVlan.toShort()))
487 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700488 } else {
Yi Tseng0b809722017-11-03 10:23:26 -0700489 selector.matchVlanId(vlanId);
Daniele Morof51d0c12019-07-30 10:43:10 -0700490 if (vlanValid(innerVlanId)) {
491 selector.matchInnerVlanId(innerVlanId);
492 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800493 piAction = PiAction.builder()
494 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
495 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700496 }
497
498 return DefaultFlowRule.builder()
499 .withPriority(PRIORITY)
500 .withSelector(selector.build())
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800501 .withTreatment(DefaultTrafficTreatment.builder()
502 .piTableAction(piAction).build())
Yi Tseng0b809722017-11-03 10:23:26 -0700503 .fromApp(APP_ID)
504 .forDevice(DEVICE_ID)
505 .makePermanent()
506 .forTable(tableId)
507 .build();
508 }
509
Daniele Moro7c3a0022019-07-12 13:38:34 -0700510 private boolean vlanValid(VlanId vlanId) {
511 return (vlanId != null && !vlanId.equals(VlanId.NONE));
512 }
513
514 private PiCriterion buildPiCriterionVlan(VlanId vlanId,
515 VlanId innerVlanId) {
516 PiCriterion.Builder piCriterionBuilder = PiCriterion.builder()
517 .matchExact(FabricConstants.HDR_VLAN_IS_VALID,
518 vlanValid(vlanId) ? ONE : ZERO);
519 return piCriterionBuilder.build();
520 }
521
Daniele Moro5a2de712019-09-24 14:34:07 -0700522 private Collection<FlowRule> buildExpectedFwdClassifierRule(PortNumber inPort,
523 MacAddress dstMac,
524 MacAddress dstMacMask,
525 short ethType,
526 byte fwdClass) {
Yi Tseng43ee7e82018-04-12 16:37:34 +0800527 PiActionParam classParam = new PiActionParam(FabricConstants.FWD_TYPE,
Yi Tseng0b809722017-11-03 10:23:26 -0700528 ImmutableByteSequence.copyFrom(fwdClass));
529 PiAction fwdClassifierAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800530 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE)
Yi Tseng0b809722017-11-03 10:23:26 -0700531 .withParameter(classParam)
532 .build();
533 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
534 .piTableAction(fwdClassifierAction)
535 .build();
536
Daniele Moro5a2de712019-09-24 14:34:07 -0700537 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder()
538 .matchInPort(inPort);
539 if (dstMacMask != null) {
540 sbuilder.matchEthDstMasked(dstMac, dstMacMask);
541 } else {
542 sbuilder.matchEthDstMasked(dstMac, MacAddress.EXACT_MASK);
543 }
544 // Special case for MPLS UNICAST forwarding, need to build 2 rules for MPLS+IPv4 and MPLS+IPv6
545 if (ethType == Ethernet.MPLS_UNICAST) {
546 return buildExpectedFwdClassifierRulesMpls(fwdClassifierAction, treatment, sbuilder);
547 }
548 sbuilder.matchPi(PiCriterion.builder()
549 .matchExact(FabricConstants.HDR_IP_ETH_TYPE, ethType)
550 .build());
551 TrafficSelector selector = sbuilder.build();
552 return List.of(DefaultFlowRule.builder()
553 .withPriority(PRIORITY)
554 .withSelector(selector)
555 .withTreatment(treatment)
556 .fromApp(APP_ID)
557 .forDevice(DEVICE_ID)
558 .makePermanent()
559 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
560 .build());
561 }
562
563 private Collection<FlowRule> buildExpectedFwdClassifierRulesMpls(PiAction fwdClassifierAction,
564 TrafficTreatment treatment,
565 TrafficSelector.Builder selectorBuilder) {
566
567 Collection<FlowRule> flowRules = Lists.newArrayList();
568 TrafficSelector selectorIpv4 = selectorBuilder
569 .add(PiCriterion.builder()
570 .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, EXACT_MATCH_ETH_TYPE)
571 .matchExact(FabricConstants.HDR_IP_ETH_TYPE, Ethernet.TYPE_IPV4)
572 .build())
Yi Tseng0b809722017-11-03 10:23:26 -0700573 .build();
Daniele Moro5a2de712019-09-24 14:34:07 -0700574 TrafficSelector selectorIpv6 = selectorBuilder
575 .add(PiCriterion.builder()
576 .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, EXACT_MATCH_ETH_TYPE)
577 .matchExact(FabricConstants.HDR_IP_ETH_TYPE, Ethernet.TYPE_IPV6)
578 .build())
579 .build();
580 flowRules.add(DefaultFlowRule.builder()
581 .withPriority(PRIORITY + 1)
582 .withSelector(selectorIpv4)
583 .withTreatment(treatment)
584 .fromApp(APP_ID)
585 .forDevice(DEVICE_ID)
586 .makePermanent()
587 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
588 .build());
589 flowRules.add(DefaultFlowRule.builder()
590 .withPriority(PRIORITY + 1)
591 .withSelector(selectorIpv6)
592 .withTreatment(treatment)
593 .fromApp(APP_ID)
594 .forDevice(DEVICE_ID)
595 .makePermanent()
596 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
597 .build());
598 return flowRules;
599 }
600
601 private ObjectiveTranslation buildExpectedTranslation(Collection<FlowRule> flowRules)
602 throws FabricPipelinerException {
603 ObjectiveTranslation.Builder expectedTranslationBuilder = ObjectiveTranslation.builder();
604 for (FlowRule flowRule : flowRules) {
605 expectedTranslationBuilder.addFlowRule(flowRule);
606 }
607 return expectedTranslationBuilder.build();
Yi Tseng0b809722017-11-03 10:23:26 -0700608 }
609}