blob: 6647a83d07f90585eb5d7a8bab666ecabbfb3a40 [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
Yi Tseng1b154bd2017-11-20 17:48:19 -080019import com.google.common.collect.ImmutableList;
Carmelo Casconeb5324e72018-11-25 02:26:32 -080020import org.junit.Before;
Yi Tseng0b809722017-11-03 10:23:26 -070021import org.junit.Test;
pierventre48e78822020-12-15 17:34:54 +010022import org.onosproject.net.PortNumber;
Yi Tseng0b809722017-11-03 10:23:26 -070023import org.onosproject.net.flow.DefaultFlowRule;
24import org.onosproject.net.flow.DefaultTrafficSelector;
25import org.onosproject.net.flow.DefaultTrafficTreatment;
26import org.onosproject.net.flow.FlowRule;
27import org.onosproject.net.flow.TrafficSelector;
28import org.onosproject.net.flow.TrafficTreatment;
29import org.onosproject.net.flow.criteria.PiCriterion;
30import org.onosproject.net.flowobjective.DefaultNextObjective;
31import org.onosproject.net.flowobjective.NextObjective;
Yi Tseng1b154bd2017-11-20 17:48:19 -080032import org.onosproject.net.group.DefaultGroupBucket;
33import org.onosproject.net.group.DefaultGroupDescription;
Esin Karaman24fda8a2018-01-26 11:52:28 +000034import org.onosproject.net.group.DefaultGroupKey;
Yi Tseng1b154bd2017-11-20 17:48:19 -080035import org.onosproject.net.group.GroupBucket;
36import org.onosproject.net.group.GroupBuckets;
Yi Tseng0b809722017-11-03 10:23:26 -070037import org.onosproject.net.group.GroupDescription;
Esin Karaman24fda8a2018-01-26 11:52:28 +000038import org.onosproject.net.group.GroupKey;
39import org.onosproject.net.pi.runtime.PiAction;
Esin Karaman24fda8a2018-01-26 11:52:28 +000040import org.onosproject.net.pi.runtime.PiActionParam;
Carmelo Casconecb4327a2018-09-11 15:17:23 -070041import org.onosproject.net.pi.runtime.PiActionProfileGroupId;
Yi Tseng1b154bd2017-11-20 17:48:19 -080042import org.onosproject.net.pi.runtime.PiGroupKey;
Carmelo Cascone2102bfb2020-12-04 16:54:24 -080043import org.onosproject.pipelines.fabric.FabricConstants;
Yi Tseng0b809722017-11-03 10:23:26 -070044
45import java.util.List;
Yi Tseng1b154bd2017-11-20 17:48:19 -080046import java.util.stream.Collectors;
Yi Tseng0b809722017-11-03 10:23:26 -070047
48import static org.junit.Assert.assertEquals;
pierventre48e78822020-12-15 17:34:54 +010049import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.outputPort;
Yi Tseng0b809722017-11-03 10:23:26 -070050
51/**
52 * Test cases for fabric.p4 pipeline next control block.
53 */
Carmelo Cascone2388cc12021-05-26 19:30:30 +020054public class NextObjectiveTranslatorTest extends BaseObjectiveTranslatorTest {
Carmelo Casconeb5324e72018-11-25 02:26:32 -080055
56 private NextObjectiveTranslator translatorHashed;
57 private NextObjectiveTranslator translatorSimple;
58
Yi Tseng20f9e7b2018-05-24 23:27:39 +080059 private FlowRule vlanMetaFlowRule;
Wailok Shumfb7e7872021-06-18 17:30:08 +080060 private FlowRule mplsFlowRule;
Yi Tseng20f9e7b2018-05-24 23:27:39 +080061
Carmelo Casconeb5324e72018-11-25 02:26:32 -080062 @Before
63 public void setup() {
64 super.doSetup();
65
66 translatorHashed = new NextObjectiveTranslator(DEVICE_ID, capabilitiesHashed);
67 translatorSimple = new NextObjectiveTranslator(DEVICE_ID, capabilitiesSimple);
68
Yi Tseng20f9e7b2018-05-24 23:27:39 +080069 PiCriterion nextIdCriterion = PiCriterion.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -080070 .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
Yi Tseng20f9e7b2018-05-24 23:27:39 +080071 .build();
72 TrafficSelector selector = DefaultTrafficSelector.builder()
73 .matchPi(nextIdCriterion)
74 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -080075 PiAction piAction = PiAction.builder()
Wailok Shumfb7e7872021-06-18 17:30:08 +080076 .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_VLAN)
Carmelo Casconeb5324e72018-11-25 02:26:32 -080077 .withParameter(new PiActionParam(FabricConstants.VLAN_ID, VLAN_100.toShort()))
Yi Tseng20f9e7b2018-05-24 23:27:39 +080078 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -080079 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
80 .piTableAction(piAction)
81 .build();
Yi Tseng20f9e7b2018-05-24 23:27:39 +080082 vlanMetaFlowRule = DefaultFlowRule.builder()
83 .withSelector(selector)
84 .withTreatment(treatment)
Wailok Shumfb7e7872021-06-18 17:30:08 +080085 .forTable(FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_VLAN)
86 .makePermanent()
87 // FIXME: currently next objective doesn't support priority, ignore this
88 .withPriority(0)
89 .forDevice(DEVICE_ID)
90 .fromApp(APP_ID)
91 .build();
92 piAction = PiAction.builder()
93 .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_MPLS_LABEL)
94 .withParameter(new PiActionParam(FabricConstants.LABEL, MPLS_10.toInt()))
95 .build();
96 treatment = DefaultTrafficTreatment.builder()
97 .piTableAction(piAction)
98 .build();
99 mplsFlowRule = DefaultFlowRule.builder()
100 .withSelector(selector)
101 .withTreatment(treatment)
102 .forTable(FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_MPLS)
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800103 .makePermanent()
104 // FIXME: currently next objective doesn't support priority, ignore this
105 .withPriority(0)
106 .forDevice(DEVICE_ID)
107 .fromApp(APP_ID)
108 .build();
109 }
Yi Tseng0b809722017-11-03 10:23:26 -0700110
111 /**
Wailok Shumfb7e7872021-06-18 17:30:08 +0800112 * Test program mpls ecmp output group for Hashed table.
113 */
114 @Test
115 public void testMplsHashedOutput() throws Exception {
116 TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
117 .setEthSrc(ROUTER_MAC)
118 .setEthDst(SPINE1_MAC)
119 .pushMpls()
120 .copyTtlOut()
121 .setMpls(MPLS_10)
122 .popVlan()
123 .setOutput(PORT_1)
124 .build();
125 TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
126 .setEthSrc(ROUTER_MAC)
127 .setEthDst(SPINE2_MAC)
128 .pushMpls()
129 .copyTtlOut()
130 .setMpls(MPLS_10)
131 .popVlan()
132 .setOutput(PORT_2)
133 .build();
134
135 NextObjective nextObjective = DefaultNextObjective.builder()
136 .withId(NEXT_ID_1)
137 .withPriority(PRIORITY)
138 .withMeta(VLAN_META)
139 .addTreatment(treatment1)
140 .addTreatment(treatment2)
141 .withType(NextObjective.Type.HASHED)
142 .makePermanent()
143 .fromApp(APP_ID)
144 .add();
145
146 ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective);
147
148 // Expected hashed table flow rule.
149 PiCriterion nextIdCriterion = PiCriterion.builder()
150 .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
151 .build();
152 TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
153 .matchPi(nextIdCriterion)
154 .build();
155 PiActionProfileGroupId actionGroupId = PiActionProfileGroupId.of(NEXT_ID_1);
156 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
157 .piTableAction(actionGroupId)
158 .build();
159 FlowRule expectedFlowRule = DefaultFlowRule.builder()
160 .forDevice(DEVICE_ID)
161 .fromApp(APP_ID)
162 .makePermanent()
163 // FIXME: currently next objective doesn't support priority, ignore this
164 .withPriority(0)
165 .forTable(FabricConstants.FABRIC_INGRESS_NEXT_HASHED)
166 .withSelector(nextIdSelector)
167 .withTreatment(treatment)
168 .build();
169
170 // First egress rule - port1
171 PortNumber outPort = outputPort(treatment1);
172 PiCriterion egressVlanTableMatch = PiCriterion.builder()
173 .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong())
174 .build();
175 TrafficSelector selectorForEgressVlan = DefaultTrafficSelector.builder()
176 .matchPi(egressVlanTableMatch)
177 .matchVlanId(VLAN_100)
178 .build();
179 PiAction piActionForEgressVlan = PiAction.builder()
180 .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN)
181 .build();
182 TrafficTreatment treatmentForEgressVlan = DefaultTrafficTreatment.builder()
183 .piTableAction(piActionForEgressVlan)
184 .build();
185 FlowRule expectedEgressVlanPopRule1 = DefaultFlowRule.builder()
186 .withSelector(selectorForEgressVlan)
187 .withTreatment(treatmentForEgressVlan)
188 .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
189 .makePermanent()
190 .withPriority(nextObjective.priority())
191 .forDevice(DEVICE_ID)
192 .fromApp(APP_ID)
193 .build();
194
195 // Second egress rule - port2
196 outPort = outputPort(treatment2);
197 egressVlanTableMatch = PiCriterion.builder()
198 .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong())
199 .build();
200 selectorForEgressVlan = DefaultTrafficSelector.builder()
201 .matchPi(egressVlanTableMatch)
202 .matchVlanId(VLAN_100)
203 .build();
204 FlowRule expectedEgressVlanPopRule2 = DefaultFlowRule.builder()
205 .withSelector(selectorForEgressVlan)
206 .withTreatment(treatmentForEgressVlan)
207 .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
208 .makePermanent()
209 .withPriority(nextObjective.priority())
210 .forDevice(DEVICE_ID)
211 .fromApp(APP_ID)
212 .build();
213
214 // Expected group
215 PiAction piAction1 = PiAction.builder()
216 .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
217 .withParameter(new PiActionParam(
218 FabricConstants.SMAC, ROUTER_MAC.toBytes()))
219 .withParameter(new PiActionParam(
220 FabricConstants.DMAC, SPINE1_MAC.toBytes()))
221 .withParameter(new PiActionParam(
222 FabricConstants.PORT_NUM, PORT_1.toLong()))
223 .build();
224 PiAction piAction2 = PiAction.builder()
225 .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
226 .withParameter(new PiActionParam(
227 FabricConstants.SMAC, ROUTER_MAC.toBytes()))
228 .withParameter(new PiActionParam(
229 FabricConstants.DMAC, SPINE2_MAC.toBytes()))
230 .withParameter(new PiActionParam(
231 FabricConstants.PORT_NUM, PORT_2.toLong()))
232 .build();
233 treatment1 = DefaultTrafficTreatment.builder()
234 .piTableAction(piAction1)
235 .build();
236 treatment2 = DefaultTrafficTreatment.builder()
237 .piTableAction(piAction2)
238 .build();
239 List<TrafficTreatment> treatments = ImmutableList.of(treatment1, treatment2);
240 List<GroupBucket> buckets = treatments.stream()
241 .map(DefaultGroupBucket::createSelectGroupBucket)
242 .collect(Collectors.toList());
243 GroupBuckets groupBuckets = new GroupBuckets(buckets);
244 PiGroupKey groupKey = new PiGroupKey(FabricConstants.FABRIC_INGRESS_NEXT_HASHED,
245 FabricConstants.FABRIC_INGRESS_NEXT_HASHED_SELECTOR,
246 NEXT_ID_1);
247 GroupDescription expectedGroup = new DefaultGroupDescription(
248 DEVICE_ID,
249 GroupDescription.Type.SELECT,
250 groupBuckets,
251 groupKey,
252 NEXT_ID_1,
253 APP_ID
254 );
255
256 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
257 .addFlowRule(expectedFlowRule)
258 .addFlowRule(vlanMetaFlowRule)
259 .addFlowRule(mplsFlowRule)
260 .addGroup(expectedGroup)
261 .addFlowRule(expectedEgressVlanPopRule1)
262 .addFlowRule(expectedEgressVlanPopRule2)
263 .build();
264
265 assertEquals(expectedTranslation, actualTranslation);
266 }
267
268 // TODO: add profile with simple next or remove tests
269 /**
Yi Tseng0b809722017-11-03 10:23:26 -0700270 * Test program output rule for Simple table.
271 */
272 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800273 public void testSimpleOutput() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700274 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
275 .setOutput(PORT_1)
276 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800277 PiAction piAction = PiAction.builder()
278 .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE)
279 .withParameter(new PiActionParam(
280 FabricConstants.PORT_NUM, PORT_1.toLong()))
281 .build();
282 testSimple(treatment, piAction);
Yi Tseng0b809722017-11-03 10:23:26 -0700283 }
284
285 /**
286 * Test program set vlan and output rule for Simple table.
287 */
288 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800289 public void testSimpleOutputWithVlanTranslation() throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700290 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
291 .setVlanId(VLAN_100)
292 .setOutput(PORT_1)
293 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800294 PiAction piAction = PiAction.builder()
295 .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE)
296 .withParameter(new PiActionParam(
297 FabricConstants.PORT_NUM, PORT_1.toLong()))
298 .build();
299 testSimple(treatment, piAction);
Yi Tseng0b809722017-11-03 10:23:26 -0700300 }
301
Yi Tsengdbe05602017-11-17 18:02:43 -0800302 /**
303 * Test program set mac and output rule for Simple table.
304 */
305 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800306 public void testSimpleOutputWithMacTranslation() throws FabricPipelinerException {
Yi Tsengdbe05602017-11-17 18:02:43 -0800307 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
308 .setEthSrc(ROUTER_MAC)
309 .setEthDst(HOST_MAC)
310 .setOutput(PORT_1)
311 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800312 PiAction piAction = PiAction.builder()
313 .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_SIMPLE)
314 .withParameter(new PiActionParam(
315 FabricConstants.SMAC, ROUTER_MAC.toBytes()))
316 .withParameter(new PiActionParam(
317 FabricConstants.DMAC, HOST_MAC.toBytes()))
318 .withParameter(new PiActionParam(
319 FabricConstants.PORT_NUM, PORT_1.toLong()))
320 .build();
321 testSimple(treatment, piAction);
Yi Tsengdbe05602017-11-17 18:02:43 -0800322 }
323
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800324 /**
325 * Test program set mac, set vlan, and output rule for Simple table.
326 */
327 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800328 public void testSimpleOutputWithVlanAndMacTranslation() throws FabricPipelinerException {
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800329 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
330 .setEthSrc(ROUTER_MAC)
331 .setEthDst(HOST_MAC)
332 .setVlanId(VLAN_100)
333 .setOutput(PORT_1)
334 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800335 PiAction piAction = PiAction.builder()
336 .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_SIMPLE)
337 .withParameter(new PiActionParam(
338 FabricConstants.SMAC, ROUTER_MAC.toBytes()))
339 .withParameter(new PiActionParam(
340 FabricConstants.DMAC, HOST_MAC.toBytes()))
341 .withParameter(new PiActionParam(
342 FabricConstants.PORT_NUM, PORT_1.toLong()))
343 .build();
344 testSimple(treatment, piAction);
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800345 }
346
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800347 private void testSimple(TrafficTreatment treatment, PiAction piAction) throws FabricPipelinerException {
Yi Tseng0b809722017-11-03 10:23:26 -0700348 NextObjective nextObjective = DefaultNextObjective.builder()
349 .withId(NEXT_ID_1)
350 .withPriority(PRIORITY)
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800351 .withMeta(VLAN_META)
Yi Tseng0b809722017-11-03 10:23:26 -0700352 .addTreatment(treatment)
353 .withType(NextObjective.Type.SIMPLE)
354 .makePermanent()
355 .fromApp(APP_ID)
356 .add();
357
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800358 ObjectiveTranslation actualTranslation = translatorSimple.translate(nextObjective);
Yi Tseng0b809722017-11-03 10:23:26 -0700359
Yi Tseng1b154bd2017-11-20 17:48:19 -0800360 // Simple table
Yi Tseng0b809722017-11-03 10:23:26 -0700361 PiCriterion nextIdCriterion = PiCriterion.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800362 .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800363 .build();
364 TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
365 .matchPi(nextIdCriterion)
366 .build();
Yi Tseng1b154bd2017-11-20 17:48:19 -0800367 FlowRule expectedFlowRule = DefaultFlowRule.builder()
368 .forDevice(DEVICE_ID)
369 .fromApp(APP_ID)
370 .makePermanent()
371 // FIXME: currently next objective doesn't support priority, ignore this
372 .withPriority(0)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800373 .forTable(FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800374 .withSelector(nextIdSelector)
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800375 .withTreatment(DefaultTrafficTreatment.builder()
376 .piTableAction(piAction).build())
Yi Tseng1b154bd2017-11-20 17:48:19 -0800377 .build();
pierventre48e78822020-12-15 17:34:54 +0100378 // Expected egress VLAN_PUSH flow rule.
379 final PortNumber outPort = outputPort(treatment);
380 PiCriterion egressVlanTableMatch = PiCriterion.builder()
381 .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong())
382 .build();
383 TrafficSelector selectorForEgressVlan = DefaultTrafficSelector.builder()
384 .matchPi(egressVlanTableMatch)
385 .matchVlanId(VLAN_100)
386 .build();
387 PiAction piActionForEgressVlan = PiAction.builder()
388 .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_PUSH_VLAN)
389 .build();
390 TrafficTreatment treatmentForEgressVlan = DefaultTrafficTreatment.builder()
391 .piTableAction(piActionForEgressVlan)
392 .build();
393 FlowRule expectedEgressVlanPushRule = DefaultFlowRule.builder()
394 .withSelector(selectorForEgressVlan)
395 .withTreatment(treatmentForEgressVlan)
396 .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
397 .makePermanent()
398 .withPriority(nextObjective.priority())
399 .forDevice(DEVICE_ID)
400 .fromApp(APP_ID)
401 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800402
403 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
404 .addFlowRule(vlanMetaFlowRule)
405 .addFlowRule(expectedFlowRule)
pierventre48e78822020-12-15 17:34:54 +0100406 .addFlowRule(expectedEgressVlanPushRule)
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800407 .build();
408
409 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng1b154bd2017-11-20 17:48:19 -0800410 }
411
Yi Tseng0b809722017-11-03 10:23:26 -0700412 /**
Daniele Morof51d0c12019-07-30 10:43:10 -0700413 * Test Route and Push Next Objective (set mac, set double vlan and output port).
414 */
415 @Test
416 public void testRouteAndPushNextObjective() throws FabricPipelinerException {
417 TrafficTreatment routeAndPushTreatment = DefaultTrafficTreatment.builder()
418 .setEthSrc(ROUTER_MAC)
419 .setEthDst(HOST_MAC)
420 .setOutput(PORT_1)
421 .setVlanId(VLAN_100)
422 .pushVlan()
423 .setVlanId(VLAN_200)
424 .build();
425
426 NextObjective nextObjective = DefaultNextObjective.builder()
427 .withId(NEXT_ID_1)
428 .withPriority(PRIORITY)
429 .addTreatment(routeAndPushTreatment)
430 .withType(NextObjective.Type.SIMPLE)
431 .makePermanent()
432 .fromApp(APP_ID)
433 .add();
434
435 ObjectiveTranslation actualTranslation = translatorSimple.translate(nextObjective);
436
437 PiAction piActionRouting = PiAction.builder()
438 .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_SIMPLE)
439 .withParameter(new PiActionParam(
440 FabricConstants.SMAC, ROUTER_MAC.toBytes()))
441 .withParameter(new PiActionParam(
442 FabricConstants.DMAC, HOST_MAC.toBytes()))
443 .withParameter(new PiActionParam(
444 FabricConstants.PORT_NUM, PORT_1.toLong()))
445 .build();
446
447 PiAction piActionPush = PiAction.builder()
Wailok Shumfb7e7872021-06-18 17:30:08 +0800448 .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_DOUBLE_VLAN)
Daniele Morof51d0c12019-07-30 10:43:10 -0700449 .withParameter(new PiActionParam(
450 FabricConstants.INNER_VLAN_ID, VLAN_100.toShort()))
451 .withParameter(new PiActionParam(
452 FabricConstants.OUTER_VLAN_ID, VLAN_200.toShort()))
453 .build();
454
455
456 TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
457 .matchPi(PiCriterion.builder()
458 .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
459 .build())
460 .build();
461 FlowRule expectedFlowRuleRouting = DefaultFlowRule.builder()
462 .forDevice(DEVICE_ID)
463 .fromApp(APP_ID)
464 .makePermanent()
465 // FIXME: currently next objective doesn't support priority, ignore this
466 .withPriority(0)
467 .forTable(FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE)
468 .withSelector(nextIdSelector)
469 .withTreatment(DefaultTrafficTreatment.builder()
470 .piTableAction(piActionRouting).build())
471 .build();
472 FlowRule expectedFlowRuleDoublePush = DefaultFlowRule.builder()
473 .withSelector(nextIdSelector)
474 .withTreatment(DefaultTrafficTreatment.builder()
475 .piTableAction(piActionPush)
476 .build())
Wailok Shumfb7e7872021-06-18 17:30:08 +0800477 .forTable(FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_VLAN)
Daniele Morof51d0c12019-07-30 10:43:10 -0700478 .makePermanent()
479 // FIXME: currently next objective doesn't support priority, ignore this
480 .withPriority(0)
481 .forDevice(DEVICE_ID)
482 .fromApp(APP_ID)
483 .build();
484
485 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
486 .addFlowRule(expectedFlowRuleDoublePush)
487 .addFlowRule(expectedFlowRuleRouting)
488 .build();
489
490
491 assertEquals(expectedTranslation, actualTranslation);
492 }
493
494 /**
Yi Tseng0b809722017-11-03 10:23:26 -0700495 * Test program ecmp output group for Hashed table.
496 */
497 @Test
Yi Tseng1b154bd2017-11-20 17:48:19 -0800498 public void testHashedOutput() throws Exception {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800499 PiAction piAction1 = PiAction.builder()
500 .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
501 .withParameter(new PiActionParam(
502 FabricConstants.SMAC, ROUTER_MAC.toBytes()))
503 .withParameter(new PiActionParam(
504 FabricConstants.DMAC, HOST_MAC.toBytes()))
505 .withParameter(new PiActionParam(
506 FabricConstants.PORT_NUM, PORT_1.toLong()))
507 .build();
508 PiAction piAction2 = PiAction.builder()
509 .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
510 .withParameter(new PiActionParam(
511 FabricConstants.SMAC, ROUTER_MAC.toBytes()))
512 .withParameter(new PiActionParam(
513 FabricConstants.DMAC, HOST_MAC.toBytes()))
514 .withParameter(new PiActionParam(
515 FabricConstants.PORT_NUM, PORT_1.toLong()))
516 .build();
Yi Tseng1b154bd2017-11-20 17:48:19 -0800517 TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800518 .piTableAction(piAction1)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800519 .build();
520 TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800521 .piTableAction(piAction2)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800522 .build();
523
524 NextObjective nextObjective = DefaultNextObjective.builder()
525 .withId(NEXT_ID_1)
526 .withPriority(PRIORITY)
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800527 .withMeta(VLAN_META)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800528 .addTreatment(treatment1)
529 .addTreatment(treatment2)
530 .withType(NextObjective.Type.HASHED)
531 .makePermanent()
532 .fromApp(APP_ID)
533 .add();
534
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800535 ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective);
Yi Tseng1b154bd2017-11-20 17:48:19 -0800536
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800537 // Expected hashed table flow rule.
Yi Tseng1b154bd2017-11-20 17:48:19 -0800538 PiCriterion nextIdCriterion = PiCriterion.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800539 .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800540 .build();
541 TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
542 .matchPi(nextIdCriterion)
543 .build();
Carmelo Casconecb4327a2018-09-11 15:17:23 -0700544 PiActionProfileGroupId actionGroupId = PiActionProfileGroupId.of(NEXT_ID_1);
Yi Tseng1b154bd2017-11-20 17:48:19 -0800545 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
546 .piTableAction(actionGroupId)
547 .build();
Yi Tseng1b154bd2017-11-20 17:48:19 -0800548 FlowRule expectedFlowRule = DefaultFlowRule.builder()
549 .forDevice(DEVICE_ID)
550 .fromApp(APP_ID)
551 .makePermanent()
552 // FIXME: currently next objective doesn't support priority, ignore this
553 .withPriority(0)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800554 .forTable(FabricConstants.FABRIC_INGRESS_NEXT_HASHED)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800555 .withSelector(nextIdSelector)
556 .withTreatment(treatment)
557 .build();
Yi Tseng1b154bd2017-11-20 17:48:19 -0800558
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800559 // Expected group
Yi Tseng1b154bd2017-11-20 17:48:19 -0800560 List<TrafficTreatment> treatments = ImmutableList.of(treatment1, treatment2);
Yi Tseng1b154bd2017-11-20 17:48:19 -0800561 List<GroupBucket> buckets = treatments.stream()
562 .map(DefaultGroupBucket::createSelectGroupBucket)
563 .collect(Collectors.toList());
564 GroupBuckets groupBuckets = new GroupBuckets(buckets);
Yi Tseng43ee7e82018-04-12 16:37:34 +0800565 PiGroupKey groupKey = new PiGroupKey(FabricConstants.FABRIC_INGRESS_NEXT_HASHED,
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800566 FabricConstants.FABRIC_INGRESS_NEXT_HASHED_SELECTOR,
Yi Tseng43ee7e82018-04-12 16:37:34 +0800567 NEXT_ID_1);
Yi Tseng1b154bd2017-11-20 17:48:19 -0800568 GroupDescription expectedGroup = new DefaultGroupDescription(
569 DEVICE_ID,
570 GroupDescription.Type.SELECT,
571 groupBuckets,
572 groupKey,
573 NEXT_ID_1,
574 APP_ID
575 );
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800576
577 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
578 .addFlowRule(expectedFlowRule)
579 .addFlowRule(vlanMetaFlowRule)
580 .addGroup(expectedGroup)
581 .build();
582
583 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng0b809722017-11-03 10:23:26 -0700584
585 }
586
587 /**
588 * Test program output group for Broadcast table.
589 */
590 @Test
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800591 public void testBroadcastOutput() throws FabricPipelinerException {
Esin Karaman24fda8a2018-01-26 11:52:28 +0000592 TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
593 .setOutput(PORT_1)
594 .build();
595 TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
596 .popVlan()
597 .setOutput(PORT_2)
598 .build();
599 NextObjective nextObjective = DefaultNextObjective.builder()
600 .withId(NEXT_ID_1)
601 .withPriority(PRIORITY)
602 .addTreatment(treatment1)
603 .addTreatment(treatment2)
604 .withMeta(VLAN_META)
605 .withType(NextObjective.Type.BROADCAST)
606 .makePermanent()
607 .fromApp(APP_ID)
608 .add();
Yi Tseng0b809722017-11-03 10:23:26 -0700609
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800610 ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective);
Esin Karaman24fda8a2018-01-26 11:52:28 +0000611
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800612 // Should generate 3 flows:
613 // - Multicast table flow that matches on next-id and set multicast group (1)
614 // - Egress VLAN pop handling for treatment2 (0)
615 // - Next VLAN flow (2)
616 // And 2 groups:
617 // - Multicast group
Esin Karaman24fda8a2018-01-26 11:52:28 +0000618
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800619 // Expected multicast table flow rule.
Esin Karaman24fda8a2018-01-26 11:52:28 +0000620 PiCriterion nextIdCriterion = PiCriterion.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800621 .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
Esin Karaman24fda8a2018-01-26 11:52:28 +0000622 .build();
623 TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
624 .matchPi(nextIdCriterion)
625 .build();
Esin Karaman24fda8a2018-01-26 11:52:28 +0000626 PiAction setMcGroupAction = PiAction.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800627 .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_MCAST_GROUP_ID)
628 .withParameter(new PiActionParam(
629 FabricConstants.GROUP_ID, NEXT_ID_1))
Esin Karaman24fda8a2018-01-26 11:52:28 +0000630 .build();
631 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
632 .piTableAction(setMcGroupAction)
633 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800634 FlowRule expectedHashedFlowRule = DefaultFlowRule.builder()
Esin Karaman24fda8a2018-01-26 11:52:28 +0000635 .forDevice(DEVICE_ID)
636 .fromApp(APP_ID)
637 .makePermanent()
638 .withPriority(nextObjective.priority())
639 .forTable(FabricConstants.FABRIC_INGRESS_NEXT_MULTICAST)
640 .withSelector(nextIdSelector)
641 .withTreatment(treatment)
642 .build();
643
pierventre48e78822020-12-15 17:34:54 +0100644 // Expected egress VLAN_PUSH flow rule.
Esin Karaman24fda8a2018-01-26 11:52:28 +0000645 PiCriterion egressVlanTableMatch = PiCriterion.builder()
pierventre48e78822020-12-15 17:34:54 +0100646 .matchExact(FabricConstants.HDR_EG_PORT, PORT_1.toLong())
Esin Karaman24fda8a2018-01-26 11:52:28 +0000647 .build();
648 TrafficSelector selectorForEgressVlan = DefaultTrafficSelector.builder()
649 .matchPi(egressVlanTableMatch)
650 .matchVlanId(VLAN_100)
651 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800652 PiAction piActionForEgressVlan = PiAction.builder()
pierventre48e78822020-12-15 17:34:54 +0100653 .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_PUSH_VLAN)
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800654 .build();
Esin Karaman24fda8a2018-01-26 11:52:28 +0000655 TrafficTreatment treatmentForEgressVlan = DefaultTrafficTreatment.builder()
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800656 .piTableAction(piActionForEgressVlan)
Esin Karaman24fda8a2018-01-26 11:52:28 +0000657 .build();
pierventre48e78822020-12-15 17:34:54 +0100658 FlowRule expectedEgressVlanPushRule = DefaultFlowRule.builder()
659 .withSelector(selectorForEgressVlan)
660 .withTreatment(treatmentForEgressVlan)
661 .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
662 .makePermanent()
663 .withPriority(nextObjective.priority())
664 .forDevice(DEVICE_ID)
665 .fromApp(APP_ID)
666 .build();
667 // Expected egress VLAN POP flow rule.
668 egressVlanTableMatch = PiCriterion.builder()
669 .matchExact(FabricConstants.HDR_EG_PORT, PORT_2.toLong())
670 .build();
671 selectorForEgressVlan = DefaultTrafficSelector.builder()
672 .matchPi(egressVlanTableMatch)
673 .matchVlanId(VLAN_100)
674 .build();
675 piActionForEgressVlan = PiAction.builder()
676 .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN)
677 .build();
678 treatmentForEgressVlan = DefaultTrafficTreatment.builder()
679 .piTableAction(piActionForEgressVlan)
680 .build();
681 FlowRule expectedEgressVlanPopRule = DefaultFlowRule.builder()
Esin Karaman24fda8a2018-01-26 11:52:28 +0000682 .withSelector(selectorForEgressVlan)
683 .withTreatment(treatmentForEgressVlan)
684 .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
685 .makePermanent()
686 .withPriority(nextObjective.priority())
687 .forDevice(DEVICE_ID)
688 .fromApp(APP_ID)
689 .build();
Esin Karaman24fda8a2018-01-26 11:52:28 +0000690
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800691 // Expected ALL group.
692 TrafficTreatment allGroupTreatment1 = DefaultTrafficTreatment.builder()
Carmelo Cascone58136812018-07-19 03:40:16 +0200693 .setOutput(PORT_1)
694 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800695 TrafficTreatment allGroupTreatment2 = DefaultTrafficTreatment.builder()
Carmelo Cascone58136812018-07-19 03:40:16 +0200696 .setOutput(PORT_2)
697 .build();
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800698 List<TrafficTreatment> allTreatments = ImmutableList.of(
699 allGroupTreatment1, allGroupTreatment2);
700 List<GroupBucket> allBuckets = allTreatments.stream()
Esin Karaman24fda8a2018-01-26 11:52:28 +0000701 .map(DefaultGroupBucket::createAllGroupBucket)
702 .collect(Collectors.toList());
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800703 GroupBuckets allGroupBuckets = new GroupBuckets(allBuckets);
704 GroupKey allGroupKey = new DefaultGroupKey(FabricPipeliner.KRYO.serialize(NEXT_ID_1));
705 GroupDescription expectedAllGroup = new DefaultGroupDescription(
Esin Karaman24fda8a2018-01-26 11:52:28 +0000706 DEVICE_ID,
707 GroupDescription.Type.ALL,
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800708 allGroupBuckets,
709 allGroupKey,
Esin Karaman24fda8a2018-01-26 11:52:28 +0000710 NEXT_ID_1,
711 APP_ID
712 );
Yi Tseng15ab4b02018-09-14 11:14:43 -0700713
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800714 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
715 .addFlowRule(expectedHashedFlowRule)
716 .addFlowRule(vlanMetaFlowRule)
pierventre48e78822020-12-15 17:34:54 +0100717 .addFlowRule(expectedEgressVlanPushRule)
718 .addFlowRule(expectedEgressVlanPopRule)
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800719 .addGroup(expectedAllGroup)
720 .build();
Yi Tseng15ab4b02018-09-14 11:14:43 -0700721
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800722 assertEquals(expectedTranslation, actualTranslation);
Yi Tseng15ab4b02018-09-14 11:14:43 -0700723 }
Carmelo Cascone45cc0862018-11-26 11:50:41 -0800724
725 /**
726 * Test XConnect NextObjective.
727 *
728 * @throws FabricPipelinerException
729 */
730 @Test
731 public void testXconnectOutput() throws FabricPipelinerException {
732 TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
733 .setOutput(PORT_1)
734 .build();
735 TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
736 .setOutput(PORT_2)
737 .build();
738 NextObjective nextObjective = DefaultNextObjective.builder()
739 .withId(NEXT_ID_1)
740 .withPriority(PRIORITY)
741 .addTreatment(treatment1)
742 .addTreatment(treatment2)
743 .withType(NextObjective.Type.BROADCAST)
744 .makePermanent()
745 .fromApp(XCONNECT_APP_ID)
746 .add();
747
748 ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective);
749
750 // Should generate 2 flows for the xconnect table.
751
752 // Expected multicast table flow rule.
753 PiCriterion nextIdCriterion = PiCriterion.builder()
754 .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
755 .build();
756 TrafficSelector xcSelector1 = DefaultTrafficSelector.builder()
757 .matchPi(nextIdCriterion)
758 .matchInPort(PORT_1)
759 .build();
760 TrafficTreatment xcTreatment1 = DefaultTrafficTreatment.builder()
761 .piTableAction(PiAction.builder()
762 .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_XCONNECT)
763 .withParameter(new PiActionParam(FabricConstants.PORT_NUM, PORT_2.toLong()))
764 .build())
765 .build();
766 TrafficSelector xcSelector2 = DefaultTrafficSelector.builder()
767 .matchPi(nextIdCriterion)
768 .matchInPort(PORT_2)
769 .build();
770 TrafficTreatment xcTreatment2 = DefaultTrafficTreatment.builder()
771 .piTableAction(PiAction.builder()
772 .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_XCONNECT)
773 .withParameter(new PiActionParam(FabricConstants.PORT_NUM, PORT_1.toLong()))
774 .build())
775 .build();
776
777 FlowRule expectedXcFlowRule1 = DefaultFlowRule.builder()
778 .forDevice(DEVICE_ID)
779 .fromApp(XCONNECT_APP_ID)
780 .makePermanent()
781 .withPriority(nextObjective.priority())
782 .forTable(FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT)
783 .withSelector(xcSelector1)
784 .withTreatment(xcTreatment1)
785 .build();
786 FlowRule expectedXcFlowRule2 = DefaultFlowRule.builder()
787 .forDevice(DEVICE_ID)
788 .fromApp(XCONNECT_APP_ID)
789 .makePermanent()
790 .withPriority(nextObjective.priority())
791 .forTable(FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT)
792 .withSelector(xcSelector2)
793 .withTreatment(xcTreatment2)
794 .build();
795
796 ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
797 .addFlowRule(expectedXcFlowRule1)
798 .addFlowRule(expectedXcFlowRule2)
799 .build();
800
801 assertEquals(expectedTranslation, actualTranslation);
802 }
Yi Tseng0b809722017-11-03 10:23:26 -0700803}