blob: 3bdab992efd7812055eb843e8cc6391506ef2172 [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
17package org.onosproject.pipelines.fabric.pipeliner;
18
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;
34import org.onosproject.net.flowobjective.DefaultFilteringObjective;
35import org.onosproject.net.flowobjective.FilteringObjective;
36import org.onosproject.net.flowobjective.ObjectiveError;
Yi Tseng0b809722017-11-03 10:23:26 -070037import org.onosproject.net.pi.runtime.PiAction;
38import org.onosproject.net.pi.runtime.PiActionParam;
39import org.onosproject.pipelines.fabric.FabricConstants;
40
Yi Tseng0b809722017-11-03 10:23:26 -070041import static org.junit.Assert.assertEquals;
Yi Tseng0b809722017-11-03 10:23:26 -070042
43/**
44 * Test cases for fabric.p4 pipeline filtering control block.
45 */
46public class FabricFilteringPipelinerTest extends FabricPipelinerTest {
47
Carmelo Casconeb5324e72018-11-25 02:26:32 -080048 private FilteringObjectiveTranslator translator;
49
50 @Before
51 public void setup() {
52 super.doSetup();
53 translator = new FilteringObjectiveTranslator(DEVICE_ID, capabilitiesHashed);
54 }
55
Yi Tseng0b809722017-11-03 10:23:26 -070056 /**
57 * Creates one rule for ingress_port_vlan table and 3 rules for
58 * fwd_classifier table (IPv4, IPv6 and MPLS unicast) when
59 * the condition is VLAN + MAC.
60 */
61 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -080062 public void testRouterMacAndVlanFilter() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -070063 FilteringObjective filteringObjective = buildFilteringObjective(ROUTER_MAC);
Carmelo Casconeb5324e72018-11-25 02:26:32 -080064 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -070065
66 // in port vlan flow rule
Carmelo Casconeb5324e72018-11-25 02:26:32 -080067 FlowRule inportFlowRuleExpected =
Yi Tseng43ee7e82018-04-12 16:37:34 +080068 buildExpectedVlanInPortRule(PORT_1,
69 VlanId.NONE,
70 VLAN_100,
71 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -070072
73 // forwarding classifier ipv4
Carmelo Casconeb5324e72018-11-25 02:26:32 -080074 FlowRule classifierV4FlowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
Yi Tseng0b809722017-11-03 10:23:26 -070075 ROUTER_MAC,
Charles Chan384aea22018-08-23 22:08:02 -070076 null,
Yi Tseng0b809722017-11-03 10:23:26 -070077 Ethernet.TYPE_IPV4,
Carmelo Casconeb5324e72018-11-25 02:26:32 -080078 FilteringObjectiveTranslator.FWD_IPV4_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -070079
80 // forwarding classifier ipv6
Carmelo Casconeb5324e72018-11-25 02:26:32 -080081 FlowRule classifierV6FlowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
Yi Tseng0b809722017-11-03 10:23:26 -070082 ROUTER_MAC,
Charles Chan384aea22018-08-23 22:08:02 -070083 null,
Yi Tseng0b809722017-11-03 10:23:26 -070084 Ethernet.TYPE_IPV6,
Carmelo Casconeb5324e72018-11-25 02:26:32 -080085 FilteringObjectiveTranslator.FWD_IPV6_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -070086
87 // forwarding classifier mpls
Carmelo Casconeb5324e72018-11-25 02:26:32 -080088 FlowRule classifierMplsFlowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
Yi Tseng0b809722017-11-03 10:23:26 -070089 ROUTER_MAC,
Charles Chan384aea22018-08-23 22:08:02 -070090 null,
Yi Tseng0b809722017-11-03 10:23:26 -070091 Ethernet.MPLS_UNICAST,
Carmelo Casconeb5324e72018-11-25 02:26:32 -080092 FilteringObjectiveTranslator.FWD_MPLS);
93
94 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
95 .addFlowRule(inportFlowRuleExpected)
96 .addFlowRule(classifierV4FlowRuleExpected)
97 .addFlowRule(classifierV6FlowRuleExpected)
98 .addFlowRule(classifierMplsFlowRuleExpected)
99 .build();
100
101 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700102 }
103
104 /**
105 * Creates one rule for ingress_port_vlan table and one rule for
106 * fwd_classifier table (IPv4 multicast) when the condition is ipv4
107 * multicast mac address.
108 */
109 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800110 public void testIpv4MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700111 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
112 .pushVlan()
113 .setVlanId(VLAN_100)
114 .build();
115 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
116 .permit()
117 .withPriority(PRIORITY)
118 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700119 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST, MacAddress.IPV4_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700120 .addCondition(Criteria.matchVlanId(VlanId.NONE))
121 .withMeta(treatment)
122 .fromApp(APP_ID)
123 .makePermanent()
124 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800125 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700126
127 // in port vlan flow rule
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800128 FlowRule inportFlowRuleExpected =
Yi Tseng43ee7e82018-04-12 16:37:34 +0800129 buildExpectedVlanInPortRule(PORT_1,
130 VlanId.NONE,
131 VLAN_100,
132 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700133
134 // forwarding classifier
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800135 FlowRule classifierFlowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
Yi Tseng0b809722017-11-03 10:23:26 -0700136 MacAddress.IPV4_MULTICAST,
Charles Chan384aea22018-08-23 22:08:02 -0700137 MacAddress.IPV4_MULTICAST_MASK,
Yi Tseng0b809722017-11-03 10:23:26 -0700138 Ethernet.TYPE_IPV4,
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800139 FilteringObjectiveTranslator.FWD_IPV4_ROUTING);
140
141 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
142 .addFlowRule(inportFlowRuleExpected)
143 .addFlowRule(classifierFlowRuleExpected)
144 .build();
145
146 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700147 }
148
149 /**
150 * Creates one rule for ingress_port_vlan table and one rule for
151 * fwd_classifier table (IPv6 multicast) when the condition is ipv6
152 * multicast mac address.
153 */
154 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800155 public void testIpv6MulticastFwdClass() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700156 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
157 .pushVlan()
158 .setVlanId(VLAN_100)
159 .build();
160 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
161 .permit()
162 .withPriority(PRIORITY)
163 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700164 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST, MacAddress.IPV6_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700165 .addCondition(Criteria.matchVlanId(VlanId.NONE))
166 .withMeta(treatment)
167 .fromApp(APP_ID)
168 .makePermanent()
169 .add();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800170 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700171
172 // in port vlan flow rule
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800173 FlowRule inportFlowRuleExpected =
Yi Tseng43ee7e82018-04-12 16:37:34 +0800174 buildExpectedVlanInPortRule(PORT_1,
175 VlanId.NONE,
176 VLAN_100,
177 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700178
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800179 FlowRule classifierFlowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
Yi Tseng0b809722017-11-03 10:23:26 -0700180 MacAddress.IPV6_MULTICAST,
Charles Chan384aea22018-08-23 22:08:02 -0700181 MacAddress.IPV6_MULTICAST_MASK,
Yi Tseng0b809722017-11-03 10:23:26 -0700182 Ethernet.TYPE_IPV6,
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800183 FilteringObjectiveTranslator.FWD_IPV6_ROUTING);
184
185 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
186 .addFlowRule(inportFlowRuleExpected)
187 .addFlowRule(classifierFlowRuleExpected)
188 .build();
189
190 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700191 }
192
193 /**
194 * Creates only one rule for ingress_port_vlan table if there is no condition
195 * of destination mac address.
196 * The packet will be handled by bridging table by default.
197 */
198 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800199 public void testFwdBridging() throws Exception {
Yi Tseng0b809722017-11-03 10:23:26 -0700200 FilteringObjective filteringObjective = buildFilteringObjective(null);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800201 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700202
203 // in port vlan flow rule
Yi Tseng43ee7e82018-04-12 16:37:34 +0800204 FlowRule flowRuleExpected =
205 buildExpectedVlanInPortRule(PORT_1,
206 VlanId.NONE,
207 VLAN_100,
208 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700209
210 // No rules in forwarding classifier, will do default action: set fwd type to bridging
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800211
212 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
213 .addFlowRule(flowRuleExpected)
214 .build();
215
216 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700217 }
218
219 /**
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800220 * Test DENY objective.
Yi Tseng0b809722017-11-03 10:23:26 -0700221 */
222 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800223 public void testDenyObjective() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700224 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
225 .deny()
226 .withKey(Criteria.matchInPort(PORT_1))
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800227 .addCondition(Criteria.matchVlanId(VlanId.NONE))
Yi Tseng0b809722017-11-03 10:23:26 -0700228 .fromApp(APP_ID)
229 .makePermanent()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800230 .withPriority(PRIORITY)
Yi Tseng0b809722017-11-03 10:23:26 -0700231 .add();
232
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800233 ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700234
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800235 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
236 .matchInPort(PORT_1)
237 .matchPi(VLAN_INVALID);
238 PiAction piAction = PiAction.builder()
239 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_DENY)
240 .build();
241 FlowRule expectedFlowRule = DefaultFlowRule.builder()
242 .withPriority(PRIORITY)
243 .withSelector(selector.build())
244 .withTreatment(DefaultTrafficTreatment.builder()
245 .piTableAction(piAction).build())
246 .fromApp(APP_ID)
247 .forDevice(DEVICE_ID)
248 .makePermanent()
249 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)
250 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700251
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800252 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
253 .addFlowRule(expectedFlowRule)
254 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700255
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800256 assertEquals(expectedTranslation, actualTranslation);
257
Yi Tseng0b809722017-11-03 10:23:26 -0700258 }
259
260 /**
261 * Incorrect filtering key or filtering conditions test.
262 */
263 @Test
264 public void badParamTest() {
265 // Filtering objective should contains filtering key
266 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
267 .permit()
268 .addCondition(Criteria.matchVlanId(VLAN_100))
269 .fromApp(APP_ID)
270 .makePermanent()
271 .add();
272
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800273 ObjectiveTranslation result1 = translator.translate(filteringObjective);
274 assertError(ObjectiveError.BADPARAMS, result1);
Yi Tseng0b809722017-11-03 10:23:26 -0700275
276 // Filtering objective should use in_port as key
277 filteringObjective = DefaultFilteringObjective.builder()
278 .permit()
279 .withKey(Criteria.matchEthDst(ROUTER_MAC))
280 .addCondition(Criteria.matchVlanId(VLAN_100))
281 .withMeta(DefaultTrafficTreatment.emptyTreatment())
282 .fromApp(APP_ID)
283 .makePermanent()
284 .add();
285
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800286 ObjectiveTranslation result2 = translator.translate(filteringObjective);
287 assertError(ObjectiveError.BADPARAMS, result2);
Yi Tseng0b809722017-11-03 10:23:26 -0700288 }
289
290 /* Utilities */
291
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800292 private void assertError(ObjectiveError error, ObjectiveTranslation actualTranslation) {
293 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.ofError(error);
294 assertEquals(expectedTranslation, actualTranslation);
295 }
296
Yi Tseng0b809722017-11-03 10:23:26 -0700297 private FilteringObjective buildFilteringObjective(MacAddress dstMac) {
298 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
299 .pushVlan()
300 .setVlanId(VLAN_100)
301 .build();
302 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder()
303 .permit()
304 .withPriority(PRIORITY)
305 .withKey(Criteria.matchInPort(PORT_1));
306 if (dstMac != null) {
307 builder.addCondition(Criteria.matchEthDst(dstMac));
308 }
309
310 builder.addCondition(Criteria.matchVlanId(VlanId.NONE))
311 .withMeta(treatment)
312 .fromApp(APP_ID)
313 .makePermanent();
314 return builder.add();
315 }
316
317 private FlowRule buildExpectedVlanInPortRule(PortNumber inPort, VlanId vlanId,
318 VlanId internalVlan,
319 TableId tableId) {
320
321 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
322 .matchInPort(inPort);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800323 PiAction piAction;
Yi Tseng0b809722017-11-03 10:23:26 -0700324 if (vlanId == null || vlanId.equals(VlanId.NONE)) {
325 selector.matchPi(VLAN_INVALID);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800326 piAction = PiAction.builder()
327 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
328 .withParameter(new PiActionParam(
329 FabricConstants.VLAN_ID, internalVlan.toShort()))
330 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700331 } else {
332 selector.matchPi(VLAN_VALID);
333 selector.matchVlanId(vlanId);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800334 piAction = PiAction.builder()
335 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
336 .build();
Yi Tseng0b809722017-11-03 10:23:26 -0700337 }
338
339 return DefaultFlowRule.builder()
340 .withPriority(PRIORITY)
341 .withSelector(selector.build())
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800342 .withTreatment(DefaultTrafficTreatment.builder()
343 .piTableAction(piAction).build())
Yi Tseng0b809722017-11-03 10:23:26 -0700344 .fromApp(APP_ID)
345 .forDevice(DEVICE_ID)
346 .makePermanent()
347 .forTable(tableId)
348 .build();
349 }
350
351 private FlowRule buildExpectedFwdClassifierRule(PortNumber inPort,
352 MacAddress dstMac,
Charles Chan384aea22018-08-23 22:08:02 -0700353 MacAddress dstMacMask,
Yi Tseng0b809722017-11-03 10:23:26 -0700354 short ethType,
355 byte fwdClass) {
Charles Chan384aea22018-08-23 22:08:02 -0700356 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder()
Yi Tseng0b809722017-11-03 10:23:26 -0700357 .matchInPort(inPort)
Charles Chan384aea22018-08-23 22:08:02 -0700358 .matchEthType(ethType);
359 if (dstMacMask != null) {
360 sbuilder.matchEthDstMasked(dstMac, dstMacMask);
361 } else {
362 sbuilder.matchEthDstMasked(dstMac, MacAddress.EXACT_MASK);
363 }
364 TrafficSelector selector = sbuilder.build();
365
Yi Tseng43ee7e82018-04-12 16:37:34 +0800366 PiActionParam classParam = new PiActionParam(FabricConstants.FWD_TYPE,
Yi Tseng0b809722017-11-03 10:23:26 -0700367 ImmutableByteSequence.copyFrom(fwdClass));
368 PiAction fwdClassifierAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800369 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE)
Yi Tseng0b809722017-11-03 10:23:26 -0700370 .withParameter(classParam)
371 .build();
372 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
373 .piTableAction(fwdClassifierAction)
374 .build();
375
376 return DefaultFlowRule.builder()
377 .withPriority(PRIORITY)
378 .withSelector(selector)
379 .withTreatment(treatment)
380 .fromApp(APP_ID)
381 .forDevice(DEVICE_ID)
382 .makePermanent()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800383 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
Yi Tseng0b809722017-11-03 10:23:26 -0700384 .build();
385 }
386}