blob: f3de7b731435ee5dea7284e2684f863530292a2d [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);
68 FlowRule flowRuleExpected = buildExpectedVlanInPortRule(PORT_1,
69 VlanId.NONE,
70 VLAN_100,
71 FabricConstants.TBL_INGRESS_PORT_VLAN_ID);
72 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
73
74 // forwarding classifier ipv4
75 actualFlowRule = flowRulesInstalled.get(1);
76 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
77 ROUTER_MAC,
78 Ethernet.TYPE_IPV4,
79 FWD_IPV4_UNICAST);
80 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
81
82 // forwarding classifier ipv6
83 actualFlowRule = flowRulesInstalled.get(2);
84 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
85 ROUTER_MAC,
86 Ethernet.TYPE_IPV6,
87 FWD_IPV6_UNICAST);
88 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
89
90 // forwarding classifier mpls
91 actualFlowRule = flowRulesInstalled.get(3);
92 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
93 ROUTER_MAC,
94 Ethernet.MPLS_UNICAST,
95 FWD_MPLS);
96 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
97 }
98
99 /**
100 * Creates one rule for ingress_port_vlan table and one rule for
101 * fwd_classifier table (IPv4 multicast) when the condition is ipv4
102 * multicast mac address.
103 */
104 @Test
105 public void testIpv4MulticastFwdClass() {
106 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
107 .pushVlan()
108 .setVlanId(VLAN_100)
109 .build();
110 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
111 .permit()
112 .withPriority(PRIORITY)
113 .withKey(Criteria.matchInPort(PORT_1))
114 .addCondition(Criteria.matchEthDst(MacAddress.IPV4_MULTICAST))
115 .addCondition(Criteria.matchVlanId(VlanId.NONE))
116 .withMeta(treatment)
117 .fromApp(APP_ID)
118 .makePermanent()
119 .add();
120 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
121 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
122 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
123
124 assertTrue(groupsInstalled.isEmpty());
125
126 // in port vlan flow rule
127 FlowRule actualFlowRule = flowRulesInstalled.get(0);
128 FlowRule flowRuleExpected = buildExpectedVlanInPortRule(PORT_1,
129 VlanId.NONE,
130 VLAN_100,
131 FabricConstants.TBL_INGRESS_PORT_VLAN_ID);
132 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
133
134 // forwarding classifier
135 actualFlowRule = flowRulesInstalled.get(1);
136 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
137 MacAddress.IPV4_MULTICAST,
138 Ethernet.TYPE_IPV4,
139 FWD_IPV4_MULTICAST);
140 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
141 }
142
143 /**
144 * Creates one rule for ingress_port_vlan table and one rule for
145 * fwd_classifier table (IPv6 multicast) when the condition is ipv6
146 * multicast mac address.
147 */
148 @Test
149 public void testIpv6MulticastFwdClass() {
150 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
151 .pushVlan()
152 .setVlanId(VLAN_100)
153 .build();
154 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
155 .permit()
156 .withPriority(PRIORITY)
157 .withKey(Criteria.matchInPort(PORT_1))
158 .addCondition(Criteria.matchEthDst(MacAddress.IPV6_MULTICAST))
159 .addCondition(Criteria.matchVlanId(VlanId.NONE))
160 .withMeta(treatment)
161 .fromApp(APP_ID)
162 .makePermanent()
163 .add();
164 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
165 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
166 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
167
168 assertTrue(groupsInstalled.isEmpty());
169
170 // in port vlan flow rule
171 FlowRule actualFlowRule = flowRulesInstalled.get(0);
172 FlowRule flowRuleExpected = buildExpectedVlanInPortRule(PORT_1,
173 VlanId.NONE,
174 VLAN_100,
175 FabricConstants.TBL_INGRESS_PORT_VLAN_ID);
176 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
177
178 // forwarding classifier
179 actualFlowRule = flowRulesInstalled.get(1);
180 flowRuleExpected = buildExpectedFwdClassifierRule(PORT_1,
181 MacAddress.IPV6_MULTICAST,
182 Ethernet.TYPE_IPV6,
183 FWD_IPV6_MULTICAST);
184 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
185 }
186
187 /**
188 * Creates only one rule for ingress_port_vlan table if there is no condition
189 * of destination mac address.
190 * The packet will be handled by bridging table by default.
191 */
192 @Test
193 public void testFwdBridging() {
194 FilteringObjective filteringObjective = buildFilteringObjective(null);
195 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
196 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
197 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
198
199 assertTrue(groupsInstalled.isEmpty());
200
201 // in port vlan flow rule
202 FlowRule actualFlowRule = flowRulesInstalled.get(0);
203 FlowRule flowRuleExpected = buildExpectedVlanInPortRule(PORT_1,
204 VlanId.NONE,
205 VLAN_100,
206 FabricConstants.TBL_INGRESS_PORT_VLAN_ID);
207 assertTrue(flowRuleExpected.exactMatch(actualFlowRule));
208
209 // No rules in forwarding classifier, will do default action: set fwd type to bridging
210 }
211
212 /**
213 * We supports only PERMIT type of filtering objective.
214 */
215 @Test
216 public void testUnsupportedObjective() {
217 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
218 .deny()
219 .withKey(Criteria.matchInPort(PORT_1))
220 .addCondition(Criteria.matchVlanId(VLAN_100))
221 .fromApp(APP_ID)
222 .makePermanent()
223 .add();
224
225 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
226 pipeliner.pipelinerFilter.filter(filteringObjective);
227
228 List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
229 List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
230
231 assertTrue(flowRulesInstalled.isEmpty());
232 assertTrue(groupsInstalled.isEmpty());
233
234 assertTrue(result.error().isPresent());
235 ObjectiveError error = result.error().get();
236 assertEquals(ObjectiveError.UNSUPPORTED, error);
237 }
238
239 /**
240 * Incorrect filtering key or filtering conditions test.
241 */
242 @Test
243 public void badParamTest() {
244 // Filtering objective should contains filtering key
245 FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
246 .permit()
247 .addCondition(Criteria.matchVlanId(VLAN_100))
248 .fromApp(APP_ID)
249 .makePermanent()
250 .add();
251
252 PipelinerTranslationResult result = pipeliner.pipelinerFilter.filter(filteringObjective);
253 pipeliner.pipelinerFilter.filter(filteringObjective);
254
255 assertTrue(result.error().isPresent());
256 ObjectiveError error = result.error().get();
257 assertEquals(ObjectiveError.BADPARAMS, error);
258
259 // Filtering objective should use in_port as key
260 filteringObjective = DefaultFilteringObjective.builder()
261 .permit()
262 .withKey(Criteria.matchEthDst(ROUTER_MAC))
263 .addCondition(Criteria.matchVlanId(VLAN_100))
264 .withMeta(DefaultTrafficTreatment.emptyTreatment())
265 .fromApp(APP_ID)
266 .makePermanent()
267 .add();
268
269 result = pipeliner.pipelinerFilter.filter(filteringObjective);
270 pipeliner.pipelinerFilter.filter(filteringObjective);
271
272 assertTrue(result.error().isPresent());
273 error = result.error().get();
274 assertEquals(ObjectiveError.BADPARAMS, error);
275 }
276
277 /* Utilities */
278
279 private FilteringObjective buildFilteringObjective(MacAddress dstMac) {
280 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
281 .pushVlan()
282 .setVlanId(VLAN_100)
283 .build();
284 DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder()
285 .permit()
286 .withPriority(PRIORITY)
287 .withKey(Criteria.matchInPort(PORT_1));
288 if (dstMac != null) {
289 builder.addCondition(Criteria.matchEthDst(dstMac));
290 }
291
292 builder.addCondition(Criteria.matchVlanId(VlanId.NONE))
293 .withMeta(treatment)
294 .fromApp(APP_ID)
295 .makePermanent();
296 return builder.add();
297 }
298
299 private FlowRule buildExpectedVlanInPortRule(PortNumber inPort, VlanId vlanId,
300 VlanId internalVlan,
301 TableId tableId) {
302
303 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
304 .matchInPort(inPort);
305 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
306 if (vlanId == null || vlanId.equals(VlanId.NONE)) {
307 selector.matchPi(VLAN_INVALID);
308 treatment.pushVlan();
309 treatment.setVlanId(internalVlan);
310 } else {
311 selector.matchPi(VLAN_VALID);
312 selector.matchVlanId(vlanId);
313 }
314
315 return DefaultFlowRule.builder()
316 .withPriority(PRIORITY)
317 .withSelector(selector.build())
318 .withTreatment(treatment.build())
319 .fromApp(APP_ID)
320 .forDevice(DEVICE_ID)
321 .makePermanent()
322 .forTable(tableId)
323 .build();
324 }
325
326 private FlowRule buildExpectedFwdClassifierRule(PortNumber inPort,
327 MacAddress dstMac,
328 short ethType,
329 byte fwdClass) {
330 TrafficSelector selector = DefaultTrafficSelector.builder()
331 .matchEthDst(dstMac)
332 .matchInPort(inPort)
333 .matchEthType(ethType)
334 .build();
335 PiActionParam classParam = new PiActionParam(FabricConstants.ACT_PRM_FWD_TYPE_ID,
336 ImmutableByteSequence.copyFrom(fwdClass));
337 PiAction fwdClassifierAction = PiAction.builder()
338 .withId(FabricConstants.ACT_SET_FORWARDING_TYPE_ID)
339 .withParameter(classParam)
340 .build();
341 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
342 .piTableAction(fwdClassifierAction)
343 .build();
344
345 return DefaultFlowRule.builder()
346 .withPriority(PRIORITY)
347 .withSelector(selector)
348 .withTreatment(treatment)
349 .fromApp(APP_ID)
350 .forDevice(DEVICE_ID)
351 .makePermanent()
352 .forTable(FabricConstants.TBL_FWD_CLASSIFIER_ID)
353 .build();
354 }
355}