blob: f40741fd0d7ac9b67aa65be06a7c671e640f6ae2 [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 Cascone36d5e7a2019-09-25 01:02:53 -070017package org.onosproject.pipelines.fabric.impl.behaviour.pipeliner;
Yi Tseng0b809722017-11-03 10:23:26 -070018
Carmelo Casconeb5324e72018-11-25 02:26:32 -080019import org.junit.Before;
Yi Tseng0b809722017-11-03 10:23:26 -070020import org.junit.Test;
21import org.onlab.packet.Ethernet;
22import org.onlab.packet.MacAddress;
23import org.onlab.packet.VlanId;
24import org.onlab.util.ImmutableByteSequence;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.flow.DefaultFlowRule;
27import org.onosproject.net.flow.DefaultTrafficSelector;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.FlowRule;
30import org.onosproject.net.flow.TableId;
31import org.onosproject.net.flow.TrafficSelector;
32import org.onosproject.net.flow.TrafficTreatment;
33import org.onosproject.net.flow.criteria.Criteria;
Daniele Moro7c3a0022019-07-12 13:38:34 -070034import org.onosproject.net.flow.criteria.PiCriterion;
Yi Tseng0b809722017-11-03 10:23:26 -070035import org.onosproject.net.flowobjective.DefaultFilteringObjective;
36import org.onosproject.net.flowobjective.FilteringObjective;
37import org.onosproject.net.flowobjective.ObjectiveError;
Yi Tseng0b809722017-11-03 10:23:26 -070038import org.onosproject.net.pi.runtime.PiAction;
39import org.onosproject.net.pi.runtime.PiActionParam;
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -070040import org.onosproject.pipelines.fabric.impl.behaviour.FabricConstants;
Yi Tseng0b809722017-11-03 10:23:26 -070041
Yi Tseng0b809722017-11-03 10:23:26 -070042import static org.junit.Assert.assertEquals;
Yi Tseng0b809722017-11-03 10:23:26 -070043
44/**
45 * Test cases for fabric.p4 pipeline filtering control block.
46 */
47public class FabricFilteringPipelinerTest extends FabricPipelinerTest {
48
Daniele Moro7c3a0022019-07-12 13:38:34 -070049 public static final byte[] ONE = {1};
50 public static final byte[] ZERO = {0};
Carmelo Casconeb5324e72018-11-25 02:26:32 -080051 private FilteringObjectiveTranslator translator;
52
53 @Before
54 public void setup() {
55 super.doSetup();
56 translator = new FilteringObjectiveTranslator(DEVICE_ID, capabilitiesHashed);
57 }
58
Yi Tseng0b809722017-11-03 10:23:26 -070059 /**
60 * Creates one rule for ingress_port_vlan table and 3 rules for
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -070061 * fwd_classifier table (IPv4, IPv6 and MPLS unicast) when the condition is
62 * VLAN + MAC.
Yi Tseng0b809722017-11-03 10:23:26 -070063 */
64 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -080065 public void testRouterMacAndVlanFilter() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -070066 FilteringObjective filteringObjective = buildFilteringObjective(ROUTER_MAC);
Carmelo Casconeb5324e72018-11-25 02:26:32 -080067 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -070068
69 // in port vlan flow rule
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -070070 FlowRule inportFlowRuleExpected = buildExpectedVlanInPortRule(
71 PORT_1,
72 VlanId.NONE,
73 VlanId.NONE,
74 VLAN_100,
75 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -070076
77 // forwarding classifier ipv4
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -070078 FlowRule classifierV4FlowRuleExpected = buildExpectedFwdClassifierRule(
79 PORT_1,
80 ROUTER_MAC,
81 null,
82 Ethernet.TYPE_IPV4,
83 FilteringObjectiveTranslator.FWD_IPV4_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -070084
85 // forwarding classifier ipv6
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -070086 FlowRule classifierV6FlowRuleExpected = buildExpectedFwdClassifierRule(
87 PORT_1,
88 ROUTER_MAC,
89 null,
90 Ethernet.TYPE_IPV6,
91 FilteringObjectiveTranslator.FWD_IPV6_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -070092
93 // forwarding classifier mpls
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -070094 FlowRule classifierMplsFlowRuleExpected = buildExpectedFwdClassifierRule(
95 PORT_1,
96 ROUTER_MAC,
97 null,
98 Ethernet.MPLS_UNICAST,
99 FilteringObjectiveTranslator.FWD_MPLS);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800100
101 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
102 .addFlowRule(inportFlowRuleExpected)
103 .addFlowRule(classifierV4FlowRuleExpected)
104 .addFlowRule(classifierV6FlowRuleExpected)
105 .addFlowRule(classifierMplsFlowRuleExpected)
106 .build();
107
108 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700109 }
110
111 /**
112 * Creates one rule for ingress_port_vlan table and one rule for
113 * fwd_classifier table (IPv4 multicast) when the condition is ipv4
114 * multicast mac address.
115 */
116 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800117 public void testIpv4MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700118 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
119 .pushVlan()
120 .setVlanId(VLAN_100)
121 .build();
122 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
123 .permit()
124 .withPriority(PRIORITY)
125 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700126 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST, MacAddress.IPV4_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700127 .addCondition(Criteria.matchVlanId(VlanId.NONE))
128 .withMeta(treatment)
129 .fromApp(APP_ID)
130 .makePermanent()
131 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800132 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700133
134 // in port vlan flow rule
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700135 FlowRule inportFlowRuleExpected = buildExpectedVlanInPortRule(
136 PORT_1,
137 VlanId.NONE,
138 VlanId.NONE,
139 VLAN_100,
140 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700141
142 // forwarding classifier
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700143 FlowRule classifierFlowRuleExpected = buildExpectedFwdClassifierRule(
144 PORT_1,
145 MacAddress.IPV4_MULTICAST,
146 MacAddress.IPV4_MULTICAST_MASK,
147 Ethernet.TYPE_IPV4,
148 FilteringObjectiveTranslator.FWD_IPV4_ROUTING);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800149
150 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
151 .addFlowRule(inportFlowRuleExpected)
152 .addFlowRule(classifierFlowRuleExpected)
153 .build();
154
155 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700156 }
157
158 /**
159 * Creates one rule for ingress_port_vlan table and one rule for
160 * fwd_classifier table (IPv6 multicast) when the condition is ipv6
161 * multicast mac address.
162 */
163 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800164 public void testIpv6MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700165 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
166 .pushVlan()
167 .setVlanId(VLAN_100)
168 .build();
169 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
170 .permit()
171 .withPriority(PRIORITY)
172 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700173 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST, MacAddress.IPV6_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700174 .addCondition(Criteria.matchVlanId(VlanId.NONE))
175 .withMeta(treatment)
176 .fromApp(APP_ID)
177 .makePermanent()
178 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800179 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700180
181 // in port vlan flow rule
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700182 FlowRule inportFlowRuleExpected = buildExpectedVlanInPortRule(
183 PORT_1,
184 VlanId.NONE,
185 VlanId.NONE,
186 VLAN_100,
187 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700188
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700189 FlowRule classifierFlowRuleExpected = buildExpectedFwdClassifierRule(
190 PORT_1,
191 MacAddress.IPV6_MULTICAST,
192 MacAddress.IPV6_MULTICAST_MASK,
193 Ethernet.TYPE_IPV6,
194 FilteringObjectiveTranslator.FWD_IPV6_ROUTING);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800195
196 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
197 .addFlowRule(inportFlowRuleExpected)
198 .addFlowRule(classifierFlowRuleExpected)
199 .build();
200
201 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700202 }
203
204 /**
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700205 * Creates only one rule for ingress_port_vlan table if there is no
206 * condition of destination mac address. The packet will be handled by
207 * bridging table by default.
Yi Tseng0b809722017-11-03 10:23:26 -0700208 */
209 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800210 public void testFwdBridging() throws Exception {
Yi Tseng0b809722017-11-03 10:23:26 -0700211 FilteringObjective filteringObjective = buildFilteringObjective(null);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800212 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700213
214 // in port vlan flow rule
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700215 FlowRule flowRuleExpected = buildExpectedVlanInPortRule(
216 PORT_1,
217 VlanId.NONE,
218 VlanId.NONE,
219 VLAN_100,
220 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700221
222 // No rules in forwarding classifier, will do default action: set fwd type to bridging
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800223
224 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
225 .addFlowRule(flowRuleExpected)
226 .build();
227
228 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700229 }
230
231 /**
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800232 * Test DENY objective.
Yi Tseng0b809722017-11-03 10:23:26 -0700233 */
234 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800235 public void testDenyObjective() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700236 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
237 .deny()
238 .withKey(Criteria.matchInPort(PORT_1))
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800239 .addCondition(Criteria.matchVlanId(VlanId.NONE))
Yi Tseng0b809722017-11-03 10:23:26 -0700240 .fromApp(APP_ID)
241 .makePermanent()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800242 .withPriority(PRIORITY)
Yi Tseng0b809722017-11-03 10:23:26 -0700243 .add();
244
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800245 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700246
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800247 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
248 .matchInPort(PORT_1)
Daniele Moro7c3a0022019-07-12 13:38:34 -0700249 .matchPi(buildPiCriterionVlan(null, null));
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800250 PiAction piAction = PiAction.builder()
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700251 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_DENY)
252 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800253 FlowRule expectedFlowRule = DefaultFlowRule.builder()
254 .withPriority(PRIORITY)
255 .withSelector(selector.build())
256 .withTreatment(DefaultTrafficTreatment.builder()
257 .piTableAction(piAction).build())
258 .fromApp(APP_ID)
259 .forDevice(DEVICE_ID)
260 .makePermanent()
261 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)
262 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700263
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800264 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
265 .addFlowRule(expectedFlowRule)
266 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700267
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800268 assertEquals(expectedTranslation, actualTranslation);
269
Yi Tseng0b809722017-11-03 10:23:26 -0700270 }
271
272 /**
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700273 * Test double VLAN pop filtering objective Creates one rule for
274 * ingress_port_vlan table and 3 rules for fwd_classifier table (IPv4, IPv6
275 * and MPLS unicast) when the condition is MAC + VLAN + INNER_VLAN.
Daniele Moro77ef35c2019-07-30 10:43:10 -0700276 */
277 @Test
278 public void testPopVlan() throws FabricPipelinerException {
279 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
280 .withKey(Criteria.matchInPort(PORT_1))
281 .addCondition(Criteria.matchEthDst(ROUTER_MAC))
282 .addCondition(Criteria.matchVlanId(VLAN_100))
283 .addCondition(Criteria.matchInnerVlanId(VLAN_200))
284 .withPriority(PRIORITY)
285 .fromApp(APP_ID)
286 .withMeta(DefaultTrafficTreatment.builder()
287 .popVlan()
288 .build())
289 .permit()
290 .add();
291 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
292
293 // Ingress port vlan rule
294 FlowRule inportFlowRuleExpected = buildExpectedVlanInPortRule(
295 PORT_1, VLAN_100, VLAN_200, VlanId.NONE,
296 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
297 // Forwarding classifier rules (ipv6, ipv4, mpls)
298 FlowRule classifierV4FlowRuleExpected = buildExpectedFwdClassifierRule(
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700299 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV4,
Daniele Moro77ef35c2019-07-30 10:43:10 -0700300 FilteringObjectiveTranslator.FWD_IPV4_ROUTING);
301 FlowRule classifierV6FlowRuleExpected = buildExpectedFwdClassifierRule(
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700302 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV6,
Daniele Moro77ef35c2019-07-30 10:43:10 -0700303 FilteringObjectiveTranslator.FWD_IPV6_ROUTING);
304 FlowRule classifierMplsFlowRuleExpected = buildExpectedFwdClassifierRule(
Carmelo Cascone36d5e7a2019-09-25 01:02:53 -0700305 PORT_1, ROUTER_MAC, null, Ethernet.MPLS_UNICAST,
Daniele Moro77ef35c2019-07-30 10:43:10 -0700306 FilteringObjectiveTranslator.FWD_MPLS);
307 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
308 .addFlowRule(inportFlowRuleExpected)
309 .addFlowRule(classifierV4FlowRuleExpected)
310 .addFlowRule(classifierV6FlowRuleExpected)
311 .addFlowRule(classifierMplsFlowRuleExpected)
312 .build();
313
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
Daniele Moro7c3a0022019-07-12 13:38:34 -0700347 /**
348 * Test the mapping between EtherType and conditions.
349 */
350 @Test
351 public void testMappingEthType() {
352 PiCriterion expectedMappingDefault = PiCriterion.builder()
353 .matchExact(FabricConstants.HDR_IS_MPLS, ZERO)
354 .matchExact(FabricConstants.HDR_IS_IPV4, ZERO)
355 .matchExact(FabricConstants.HDR_IS_IPV6, ZERO)
356 .build();
357 PiCriterion expectedMappingIpv6 = PiCriterion.builder()
358 .matchExact(FabricConstants.HDR_IS_MPLS, ZERO)
359 .matchExact(FabricConstants.HDR_IS_IPV4, ZERO)
360 .matchExact(FabricConstants.HDR_IS_IPV6, ONE)
361 .build();
362 PiCriterion expectedMappingIpv4 = PiCriterion.builder()
363 .matchExact(FabricConstants.HDR_IS_MPLS, ZERO)
364 .matchExact(FabricConstants.HDR_IS_IPV4, ONE)
365 .matchExact(FabricConstants.HDR_IS_IPV6, ZERO)
366 .build();
367 PiCriterion expectedMappingMpls = PiCriterion.builder()
368 .matchExact(FabricConstants.HDR_IS_MPLS, ONE)
369 .matchExact(FabricConstants.HDR_IS_IPV4, ZERO)
370 .matchExact(FabricConstants.HDR_IS_IPV6, ZERO)
371 .build();
372
373
374 PiCriterion actualMappingIpv6 = FilteringObjectiveTranslator.mapEthTypeFwdClassifier(Ethernet.TYPE_IPV6);
375 assertEquals(expectedMappingIpv6, actualMappingIpv6);
376
377 PiCriterion actualMappingIpv4 = FilteringObjectiveTranslator.mapEthTypeFwdClassifier(Ethernet.TYPE_IPV4);
378 assertEquals(expectedMappingIpv4, actualMappingIpv4);
379
380 PiCriterion actualMappingMpls = FilteringObjectiveTranslator.mapEthTypeFwdClassifier(Ethernet.MPLS_UNICAST);
381 assertEquals(expectedMappingMpls, actualMappingMpls);
382
383 PiCriterion actualMapping = FilteringObjectiveTranslator.mapEthTypeFwdClassifier(Ethernet.TYPE_ARP);
384 assertEquals(expectedMappingDefault, actualMapping);
385
386
387 }
388
Yi Tseng0b809722017-11-03 10:23:26 -0700389 /* Utilities */
390
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800391 private void assertError(ObjectiveError error, ObjectiveTranslation actualTranslation) {
392 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.ofError(error);
393 assertEquals(expectedTranslation, actualTranslation);
394 }
395
Yi Tseng0b809722017-11-03 10:23:26 -0700396 private FilteringObjective buildFilteringObjective(MacAddress dstMac) {
397 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
398 .pushVlan()
399 .setVlanId(VLAN_100)
400 .build();
401 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder()
402 .permit()
403 .withPriority(PRIORITY)
404 .withKey(Criteria.matchInPort(PORT_1));
405 if (dstMac != null) {
406 builder.addCondition(Criteria.matchEthDst(dstMac));
407 }
408
409 builder.addCondition(Criteria.matchVlanId(VlanId.NONE))
410 .withMeta(treatment)
411 .fromApp(APP_ID)
412 .makePermanent();
413 return builder.add();
414 }
415
Daniele Moro7c3a0022019-07-12 13:38:34 -0700416 private FlowRule buildExpectedVlanInPortRule(PortNumber inPort,
417 VlanId vlanId,
418 VlanId innerVlanId,
Yi Tseng0b809722017-11-03 10:23:26 -0700419 VlanId internalVlan,
420 TableId tableId) {
421
422 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
423 .matchInPort(inPort);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800424 PiAction piAction;
Daniele Moro7c3a0022019-07-12 13:38:34 -0700425 selector.matchPi(buildPiCriterionVlan(vlanId, innerVlanId));
426 if (!vlanValid(vlanId)) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800427 piAction = PiAction.builder()
428 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
429 .withParameter(new PiActionParam(
430 FabricConstants.VLAN_ID, internalVlan.toShort()))
431 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700432 } else {
Yi Tseng0b809722017-11-03 10:23:26 -0700433 selector.matchVlanId(vlanId);
Daniele Moro77ef35c2019-07-30 10:43:10 -0700434 if (vlanValid(innerVlanId)) {
435 selector.matchInnerVlanId(innerVlanId);
436 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800437 piAction = PiAction.builder()
438 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
439 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700440 }
441
442 return DefaultFlowRule.builder()
443 .withPriority(PRIORITY)
444 .withSelector(selector.build())
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800445 .withTreatment(DefaultTrafficTreatment.builder()
446 .piTableAction(piAction).build())
Yi Tseng0b809722017-11-03 10:23:26 -0700447 .fromApp(APP_ID)
448 .forDevice(DEVICE_ID)
449 .makePermanent()
450 .forTable(tableId)
451 .build();
452 }
453
Daniele Moro7c3a0022019-07-12 13:38:34 -0700454 private boolean vlanValid(VlanId vlanId) {
455 return (vlanId != null && !vlanId.equals(VlanId.NONE));
456 }
457
458 private PiCriterion buildPiCriterionVlan(VlanId vlanId,
459 VlanId innerVlanId) {
460 PiCriterion.Builder piCriterionBuilder = PiCriterion.builder()
461 .matchExact(FabricConstants.HDR_VLAN_IS_VALID,
462 vlanValid(vlanId) ? ONE : ZERO);
463 return piCriterionBuilder.build();
464 }
465
Yi Tseng0b809722017-11-03 10:23:26 -0700466 private FlowRule buildExpectedFwdClassifierRule(PortNumber inPort,
467 MacAddress dstMac,
Charles Chan384aea22018-08-23 22:08:02 -0700468 MacAddress dstMacMask,
Yi Tseng0b809722017-11-03 10:23:26 -0700469 short ethType,
470 byte fwdClass) {
Charles Chan384aea22018-08-23 22:08:02 -0700471 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder()
Yi Tseng0b809722017-11-03 10:23:26 -0700472 .matchInPort(inPort)
Daniele Moro7c3a0022019-07-12 13:38:34 -0700473 .matchPi(FilteringObjectiveTranslator.mapEthTypeFwdClassifier(ethType));
Charles Chan384aea22018-08-23 22:08:02 -0700474 if (dstMacMask != null) {
475 sbuilder.matchEthDstMasked(dstMac, dstMacMask);
476 } else {
477 sbuilder.matchEthDstMasked(dstMac, MacAddress.EXACT_MASK);
478 }
479 TrafficSelector selector = sbuilder.build();
480
Yi Tseng43ee7e82018-04-12 16:37:34 +0800481 PiActionParam classParam = new PiActionParam(FabricConstants.FWD_TYPE,
Yi Tseng0b809722017-11-03 10:23:26 -0700482 ImmutableByteSequence.copyFrom(fwdClass));
483 PiAction fwdClassifierAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800484 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE)
Yi Tseng0b809722017-11-03 10:23:26 -0700485 .withParameter(classParam)
486 .build();
487 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
488 .piTableAction(fwdClassifierAction)
489 .build();
490
491 return DefaultFlowRule.builder()
492 .withPriority(PRIORITY)
493 .withSelector(selector)
494 .withTreatment(treatment)
495 .fromApp(APP_ID)
496 .forDevice(DEVICE_ID)
497 .makePermanent()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800498 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
Yi Tseng0b809722017-11-03 10:23:26 -0700499 .build();
500 }
501}