blob: 9ceb8698e96e9e12c290d8f3fc161b169b786731 [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
19import org.junit.Test;
20import org.onlab.packet.Ethernet;
21import org.onlab.packet.MacAddress;
22import org.onlab.packet.VlanId;
23import org.onlab.util.ImmutableByteSequence;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.flow.DefaultFlowRule;
26import org.onosproject.net.flow.DefaultTrafficSelector;
27import org.onosproject.net.flow.DefaultTrafficTreatment;
28import org.onosproject.net.flow.FlowRule;
29import org.onosproject.net.flow.TableId;
30import org.onosproject.net.flow.TrafficSelector;
31import org.onosproject.net.flow.TrafficTreatment;
32import org.onosproject.net.flow.criteria.Criteria;
33import org.onosproject.net.flowobjective.DefaultFilteringObjective;
34import org.onosproject.net.flowobjective.FilteringObjective;
35import org.onosproject.net.flowobjective.ObjectiveError;
36import org.onosproject.net.group.GroupDescription;
37import org.onosproject.net.pi.runtime.PiAction;
38import org.onosproject.net.pi.runtime.PiActionParam;
39import org.onosproject.pipelines.fabric.FabricConstants;
40
41import java.util.List;
42
43import static org.junit.Assert.assertEquals;
44import static org.junit.Assert.assertTrue;
45
46/**
47 * Test cases for fabric.p4 pipeline filtering control block.
48 */
49public class FabricFilteringPipelinerTest extends FabricPipelinerTest {
50
51 /**
52 * Creates one rule for ingress_port_vlan table and 3 rules for
53 * fwd_classifier table (IPv4, IPv6 and MPLS unicast) when
54 * the condition is VLAN + MAC.
55 */
56 @Test
57 public void testRouterMacAndVlanFilter() {
58 FilteringObjective filteringObjective = buildFilteringObjective(ROUTER_MAC);
59 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
60
61 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
62 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
63
64 assertTrue(groupsInstalled.isEmpty());
65
66 // in port vlan flow rule
67 FlowRule actualFlowRule = flowRulesInstalled.get(0);
Yi Tseng43ee7e82018-04-12 16:37:34 +080068 FlowRule flowRuleExpected =
69 buildExpectedVlanInPortRule(PORT_1,
70 VlanId.NONE,
71 VLAN_100,
72 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -070073 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
74
75 // forwarding classifier ipv4
76 actualFlowRule = flowRulesInstalled.get(1);
77 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
78 ROUTER_MAC,
Charles Chan384aea22018-08-23 22:08:02 -070079 null,
Yi Tseng0b809722017-11-03 10:23:26 -070080 Ethernet.TYPE_IPV4,
Charles Chan384aea22018-08-23 22:08:02 -070081 FabricFilteringPipeliner.FWD_IPV4_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -070082 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
83
84 // forwarding classifier ipv6
85 actualFlowRule = flowRulesInstalled.get(2);
86 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
87 ROUTER_MAC,
Charles Chan384aea22018-08-23 22:08:02 -070088 null,
Yi Tseng0b809722017-11-03 10:23:26 -070089 Ethernet.TYPE_IPV6,
Charles Chan384aea22018-08-23 22:08:02 -070090 FabricFilteringPipeliner.FWD_IPV6_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -070091 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
92
93 // forwarding classifier mpls
94 actualFlowRule = flowRulesInstalled.get(3);
95 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
96 ROUTER_MAC,
Charles Chan384aea22018-08-23 22:08:02 -070097 null,
Yi Tseng0b809722017-11-03 10:23:26 -070098 Ethernet.MPLS_UNICAST,
Charles Chan384aea22018-08-23 22:08:02 -070099 FabricFilteringPipeliner.FWD_MPLS);
Yi Tseng0b809722017-11-03 10:23:26 -0700100 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
101 }
102
103 /**
104 * Creates one rule for ingress_port_vlan table and one rule for
105 * fwd_classifier table (IPv4 multicast) when the condition is ipv4
106 * multicast mac address.
107 */
108 @Test
109 public void testIpv4MulticastFwdClass() {
110 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
111 .pushVlan()
112 .setVlanId(VLAN_100)
113 .build();
114 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
115 .permit()
116 .withPriority(PRIORITY)
117 .withKey(Criteria.matchInPort(PORT_1))
Charles Chan384aea22018-08-23 22:08:02 -0700118 .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST, MacAddress.IPV4_MULTICAST_MASK))
Yi Tseng0b809722017-11-03 10:23:26 -0700119 .addCondition(Criteria.matchVlanId(VlanId.NONE))
120 .withMeta(treatment)
121 .fromApp(APP_ID)
122 .makePermanent()
123 .add();
124 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
125 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
126 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
127
128 assertTrue(groupsInstalled.isEmpty());
129
130 // in port vlan flow rule
131 FlowRule actualFlowRule = flowRulesInstalled.get(0);
Yi Tseng43ee7e82018-04-12 16:37:34 +0800132 FlowRule flowRuleExpected =
133 buildExpectedVlanInPortRule(PORT_1,
134 VlanId.NONE,
135 VLAN_100,
136 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700137 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
138
139 // forwarding classifier
140 actualFlowRule = flowRulesInstalled.get(1);
141 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
142 MacAddress.IPV4_MULTICAST,
Charles Chan384aea22018-08-23 22:08:02 -0700143 MacAddress.IPV4_MULTICAST_MASK,
Yi Tseng0b809722017-11-03 10:23:26 -0700144 Ethernet.TYPE_IPV4,
Charles Chan384aea22018-08-23 22:08:02 -0700145 FabricFilteringPipeliner.FWD_IPV4_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -0700146 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
147 }
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
155 public void testIpv6MulticastFwdClass() {
156 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();
170 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
171 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
172 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
173
174 assertTrue(groupsInstalled.isEmpty());
175
176 // in port vlan flow rule
177 FlowRule actualFlowRule = flowRulesInstalled.get(0);
Yi Tseng43ee7e82018-04-12 16:37:34 +0800178 FlowRule flowRuleExpected =
179 buildExpectedVlanInPortRule(PORT_1,
180 VlanId.NONE,
181 VLAN_100,
182 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700183 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
184
185 // forwarding classifier
186 actualFlowRule = flowRulesInstalled.get(1);
187 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
188 MacAddress.IPV6_MULTICAST,
Charles Chan384aea22018-08-23 22:08:02 -0700189 MacAddress.IPV6_MULTICAST_MASK,
Yi Tseng0b809722017-11-03 10:23:26 -0700190 Ethernet.TYPE_IPV6,
Charles Chan384aea22018-08-23 22:08:02 -0700191 FabricFilteringPipeliner.FWD_IPV6_ROUTING);
Yi Tseng0b809722017-11-03 10:23:26 -0700192 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
193 }
194
195 /**
196 * Creates only one rule for ingress_port_vlan table if there is no condition
197 * of destination mac address.
198 * The packet will be handled by bridging table by default.
199 */
200 @Test
201 public void testFwdBridging() {
202 FilteringObjective filteringObjective = buildFilteringObjective(null);
203 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
204 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
205 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
206
207 assertTrue(groupsInstalled.isEmpty());
208
209 // in port vlan flow rule
210 FlowRule actualFlowRule = flowRulesInstalled.get(0);
Yi Tseng43ee7e82018-04-12 16:37:34 +0800211 FlowRule flowRuleExpected =
212 buildExpectedVlanInPortRule(PORT_1,
213 VlanId.NONE,
214 VLAN_100,
215 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
Yi Tseng0b809722017-11-03 10:23:26 -0700216 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
217
218 // No rules in forwarding classifier, will do default action: set fwd type to bridging
219 }
220
221 /**
222 * We supports only PERMIT type of filtering objective.
223 */
224 @Test
225 public void testUnsupportedObjective() {
226 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
227 .deny()
228 .withKey(Criteria.matchInPort(PORT_1))
229 .addCondition(Criteria.matchVlanId(VLAN_100))
230 .fromApp(APP_ID)
231 .makePermanent()
232 .add();
233
234 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
235 pipeliner.pipelinerFilter.filter(filteringObjective);
236
237 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
238 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
239
240 assertTrue(flowRulesInstalled.isEmpty());
241 assertTrue(groupsInstalled.isEmpty());
242
243 assertTrue(result.error().isPresent());
244 ObjectiveError error = result.error().get();
245 assertEquals(ObjectiveError.UNSUPPORTED, error);
246 }
247
248 /**
249 * Incorrect filtering key or filtering conditions test.
250 */
251 @Test
252 public void badParamTest() {
253 // Filtering objective should contains filtering key
254 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
255 .permit()
256 .addCondition(Criteria.matchVlanId(VLAN_100))
257 .fromApp(APP_ID)
258 .makePermanent()
259 .add();
260
261 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
262 pipeliner.pipelinerFilter.filter(filteringObjective);
263
264 assertTrue(result.error().isPresent());
265 ObjectiveError error = result.error().get();
266 assertEquals(ObjectiveError.BADPARAMS, error);
267
268 // Filtering objective should use in_port as key
269 filteringObjective = DefaultFilteringObjective.builder()
270 .permit()
271 .withKey(Criteria.matchEthDst(ROUTER_MAC))
272 .addCondition(Criteria.matchVlanId(VLAN_100))
273 .withMeta(DefaultTrafficTreatment.emptyTreatment())
274 .fromApp(APP_ID)
275 .makePermanent()
276 .add();
277
278 result = pipeliner.pipelinerFilter.filter(filteringObjective);
279 pipeliner.pipelinerFilter.filter(filteringObjective);
280
281 assertTrue(result.error().isPresent());
282 error = result.error().get();
283 assertEquals(ObjectiveError.BADPARAMS, error);
284 }
285
286 /* Utilities */
287
288 private FilteringObjective buildFilteringObjective(MacAddress dstMac) {
289 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
290 .pushVlan()
291 .setVlanId(VLAN_100)
292 .build();
293 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder()
294 .permit()
295 .withPriority(PRIORITY)
296 .withKey(Criteria.matchInPort(PORT_1));
297 if (dstMac != null) {
298 builder.addCondition(Criteria.matchEthDst(dstMac));
299 }
300
301 builder.addCondition(Criteria.matchVlanId(VlanId.NONE))
302 .withMeta(treatment)
303 .fromApp(APP_ID)
304 .makePermanent();
305 return builder.add();
306 }
307
308 private FlowRule buildExpectedVlanInPortRule(PortNumber inPort, VlanId vlanId,
309 VlanId internalVlan,
310 TableId tableId) {
311
312 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
313 .matchInPort(inPort);
314 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
315 if (vlanId == null || vlanId.equals(VlanId.NONE)) {
316 selector.matchPi(VLAN_INVALID);
317 treatment.pushVlan();
318 treatment.setVlanId(internalVlan);
319 } else {
320 selector.matchPi(VLAN_VALID);
321 selector.matchVlanId(vlanId);
322 }
323
324 return DefaultFlowRule.builder()
325 .withPriority(PRIORITY)
326 .withSelector(selector.build())
327 .withTreatment(treatment.build())
328 .fromApp(APP_ID)
329 .forDevice(DEVICE_ID)
330 .makePermanent()
331 .forTable(tableId)
332 .build();
333 }
334
335 private FlowRule buildExpectedFwdClassifierRule(PortNumber inPort,
336 MacAddress dstMac,
Charles Chan384aea22018-08-23 22:08:02 -0700337 MacAddress dstMacMask,
Yi Tseng0b809722017-11-03 10:23:26 -0700338 short ethType,
339 byte fwdClass) {
Charles Chan384aea22018-08-23 22:08:02 -0700340 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder()
Yi Tseng0b809722017-11-03 10:23:26 -0700341 .matchInPort(inPort)
Charles Chan384aea22018-08-23 22:08:02 -0700342 .matchEthType(ethType);
343 if (dstMacMask != null) {
344 sbuilder.matchEthDstMasked(dstMac, dstMacMask);
345 } else {
346 sbuilder.matchEthDstMasked(dstMac, MacAddress.EXACT_MASK);
347 }
348 TrafficSelector selector = sbuilder.build();
349
Yi Tseng43ee7e82018-04-12 16:37:34 +0800350 PiActionParam classParam = new PiActionParam(FabricConstants.FWD_TYPE,
Yi Tseng0b809722017-11-03 10:23:26 -0700351 ImmutableByteSequence.copyFrom(fwdClass));
352 PiAction fwdClassifierAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800353 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE)
Yi Tseng0b809722017-11-03 10:23:26 -0700354 .withParameter(classParam)
355 .build();
356 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
357 .piTableAction(fwdClassifierAction)
358 .build();
359
360 return DefaultFlowRule.builder()
361 .withPriority(PRIORITY)
362 .withSelector(selector)
363 .withTreatment(treatment)
364 .fromApp(APP_ID)
365 .forDevice(DEVICE_ID)
366 .makePermanent()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800367 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
Yi Tseng0b809722017-11-03 10:23:26 -0700368 .build();
369 }
370}