Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 1 | /* |
| 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 Cascone | 356ab8b | 2019-09-25 01:02:53 -0700 | [diff] [blame] | 17 | package org.onosproject.pipelines.fabric.impl.behaviour.pipeliner; |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 18 | |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 19 | import com.google.common.collect.ImmutableList; |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 20 | import org.junit.Before; |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 21 | import org.junit.Test; |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 22 | import org.onosproject.net.PortNumber; |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 23 | import org.onosproject.net.flow.DefaultFlowRule; |
| 24 | import org.onosproject.net.flow.DefaultTrafficSelector; |
| 25 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 26 | import org.onosproject.net.flow.FlowRule; |
| 27 | import org.onosproject.net.flow.TrafficSelector; |
| 28 | import org.onosproject.net.flow.TrafficTreatment; |
| 29 | import org.onosproject.net.flow.criteria.PiCriterion; |
| 30 | import org.onosproject.net.flowobjective.DefaultNextObjective; |
| 31 | import org.onosproject.net.flowobjective.NextObjective; |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 32 | import org.onosproject.net.group.DefaultGroupBucket; |
| 33 | import org.onosproject.net.group.DefaultGroupDescription; |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 34 | import org.onosproject.net.group.DefaultGroupKey; |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 35 | import org.onosproject.net.group.GroupBucket; |
| 36 | import org.onosproject.net.group.GroupBuckets; |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 37 | import org.onosproject.net.group.GroupDescription; |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 38 | import org.onosproject.net.group.GroupKey; |
| 39 | import org.onosproject.net.pi.runtime.PiAction; |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 40 | import org.onosproject.net.pi.runtime.PiActionParam; |
Carmelo Cascone | cb4327a | 2018-09-11 15:17:23 -0700 | [diff] [blame] | 41 | import org.onosproject.net.pi.runtime.PiActionProfileGroupId; |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 42 | import org.onosproject.net.pi.runtime.PiGroupKey; |
Carmelo Cascone | b1f5cfd | 2020-12-04 16:54:24 -0800 | [diff] [blame] | 43 | import org.onosproject.pipelines.fabric.FabricConstants; |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 44 | |
| 45 | import java.util.List; |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 46 | import java.util.stream.Collectors; |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 47 | |
| 48 | import static org.junit.Assert.assertEquals; |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 49 | import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.outputPort; |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 50 | |
| 51 | /** |
| 52 | * Test cases for fabric.p4 pipeline next control block. |
| 53 | */ |
Carmelo Cascone | db34737 | 2021-05-26 19:30:30 +0200 | [diff] [blame^] | 54 | public class NextObjectiveTranslatorTest extends BaseObjectiveTranslatorTest { |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 55 | |
| 56 | private NextObjectiveTranslator translatorHashed; |
| 57 | private NextObjectiveTranslator translatorSimple; |
| 58 | |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 59 | private FlowRule vlanMetaFlowRule; |
| 60 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 61 | @Before |
| 62 | public void setup() { |
| 63 | super.doSetup(); |
| 64 | |
| 65 | translatorHashed = new NextObjectiveTranslator(DEVICE_ID, capabilitiesHashed); |
| 66 | translatorSimple = new NextObjectiveTranslator(DEVICE_ID, capabilitiesSimple); |
| 67 | |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 68 | PiCriterion nextIdCriterion = PiCriterion.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 69 | .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1) |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 70 | .build(); |
| 71 | TrafficSelector selector = DefaultTrafficSelector.builder() |
| 72 | .matchPi(nextIdCriterion) |
| 73 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 74 | PiAction piAction = PiAction.builder() |
| 75 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN) |
| 76 | .withParameter(new PiActionParam(FabricConstants.VLAN_ID, VLAN_100.toShort())) |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 77 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 78 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 79 | .piTableAction(piAction) |
| 80 | .build(); |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 81 | vlanMetaFlowRule = DefaultFlowRule.builder() |
| 82 | .withSelector(selector) |
| 83 | .withTreatment(treatment) |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 84 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN) |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 85 | .makePermanent() |
| 86 | // FIXME: currently next objective doesn't support priority, ignore this |
| 87 | .withPriority(0) |
| 88 | .forDevice(DEVICE_ID) |
| 89 | .fromApp(APP_ID) |
| 90 | .build(); |
| 91 | } |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 92 | |
| 93 | /** |
| 94 | * Test program output rule for Simple table. |
| 95 | */ |
| 96 | @Test |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 97 | public void testSimpleOutput() throws FabricPipelinerException { |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 98 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 99 | .setOutput(PORT_1) |
| 100 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 101 | PiAction piAction = PiAction.builder() |
| 102 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE) |
| 103 | .withParameter(new PiActionParam( |
| 104 | FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 105 | .build(); |
| 106 | testSimple(treatment, piAction); |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | /** |
| 110 | * Test program set vlan and output rule for Simple table. |
| 111 | */ |
| 112 | @Test |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 113 | public void testSimpleOutputWithVlanTranslation() throws FabricPipelinerException { |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 114 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 115 | .setVlanId(VLAN_100) |
| 116 | .setOutput(PORT_1) |
| 117 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 118 | PiAction piAction = PiAction.builder() |
| 119 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE) |
| 120 | .withParameter(new PiActionParam( |
| 121 | FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 122 | .build(); |
| 123 | testSimple(treatment, piAction); |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 124 | } |
| 125 | |
Yi Tseng | dbe0560 | 2017-11-17 18:02:43 -0800 | [diff] [blame] | 126 | /** |
| 127 | * Test program set mac and output rule for Simple table. |
| 128 | */ |
| 129 | @Test |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 130 | public void testSimpleOutputWithMacTranslation() throws FabricPipelinerException { |
Yi Tseng | dbe0560 | 2017-11-17 18:02:43 -0800 | [diff] [blame] | 131 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 132 | .setEthSrc(ROUTER_MAC) |
| 133 | .setEthDst(HOST_MAC) |
| 134 | .setOutput(PORT_1) |
| 135 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 136 | PiAction piAction = PiAction.builder() |
| 137 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_SIMPLE) |
| 138 | .withParameter(new PiActionParam( |
| 139 | FabricConstants.SMAC, ROUTER_MAC.toBytes())) |
| 140 | .withParameter(new PiActionParam( |
| 141 | FabricConstants.DMAC, HOST_MAC.toBytes())) |
| 142 | .withParameter(new PiActionParam( |
| 143 | FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 144 | .build(); |
| 145 | testSimple(treatment, piAction); |
Yi Tseng | dbe0560 | 2017-11-17 18:02:43 -0800 | [diff] [blame] | 146 | } |
| 147 | |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 148 | /** |
| 149 | * Test program set mac, set vlan, and output rule for Simple table. |
| 150 | */ |
| 151 | @Test |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 152 | public void testSimpleOutputWithVlanAndMacTranslation() throws FabricPipelinerException { |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 153 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 154 | .setEthSrc(ROUTER_MAC) |
| 155 | .setEthDst(HOST_MAC) |
| 156 | .setVlanId(VLAN_100) |
| 157 | .setOutput(PORT_1) |
| 158 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 159 | PiAction piAction = PiAction.builder() |
| 160 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_SIMPLE) |
| 161 | .withParameter(new PiActionParam( |
| 162 | FabricConstants.SMAC, ROUTER_MAC.toBytes())) |
| 163 | .withParameter(new PiActionParam( |
| 164 | FabricConstants.DMAC, HOST_MAC.toBytes())) |
| 165 | .withParameter(new PiActionParam( |
| 166 | FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 167 | .build(); |
| 168 | testSimple(treatment, piAction); |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 169 | } |
| 170 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 171 | private void testSimple(TrafficTreatment treatment, PiAction piAction) throws FabricPipelinerException { |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 172 | NextObjective nextObjective = DefaultNextObjective.builder() |
| 173 | .withId(NEXT_ID_1) |
| 174 | .withPriority(PRIORITY) |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 175 | .withMeta(VLAN_META) |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 176 | .addTreatment(treatment) |
| 177 | .withType(NextObjective.Type.SIMPLE) |
| 178 | .makePermanent() |
| 179 | .fromApp(APP_ID) |
| 180 | .add(); |
| 181 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 182 | ObjectiveTranslation actualTranslation = translatorSimple.translate(nextObjective); |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 183 | |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 184 | // Simple table |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 185 | PiCriterion nextIdCriterion = PiCriterion.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 186 | .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 187 | .build(); |
| 188 | TrafficSelector nextIdSelector = DefaultTrafficSelector.builder() |
| 189 | .matchPi(nextIdCriterion) |
| 190 | .build(); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 191 | FlowRule expectedFlowRule = DefaultFlowRule.builder() |
| 192 | .forDevice(DEVICE_ID) |
| 193 | .fromApp(APP_ID) |
| 194 | .makePermanent() |
| 195 | // FIXME: currently next objective doesn't support priority, ignore this |
| 196 | .withPriority(0) |
Yi Tseng | 43ee7e8 | 2018-04-12 16:37:34 +0800 | [diff] [blame] | 197 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 198 | .withSelector(nextIdSelector) |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 199 | .withTreatment(DefaultTrafficTreatment.builder() |
| 200 | .piTableAction(piAction).build()) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 201 | .build(); |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 202 | // Expected egress VLAN_PUSH flow rule. |
| 203 | final PortNumber outPort = outputPort(treatment); |
| 204 | PiCriterion egressVlanTableMatch = PiCriterion.builder() |
| 205 | .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong()) |
| 206 | .build(); |
| 207 | TrafficSelector selectorForEgressVlan = DefaultTrafficSelector.builder() |
| 208 | .matchPi(egressVlanTableMatch) |
| 209 | .matchVlanId(VLAN_100) |
| 210 | .build(); |
| 211 | PiAction piActionForEgressVlan = PiAction.builder() |
| 212 | .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_PUSH_VLAN) |
| 213 | .build(); |
| 214 | TrafficTreatment treatmentForEgressVlan = DefaultTrafficTreatment.builder() |
| 215 | .piTableAction(piActionForEgressVlan) |
| 216 | .build(); |
| 217 | FlowRule expectedEgressVlanPushRule = DefaultFlowRule.builder() |
| 218 | .withSelector(selectorForEgressVlan) |
| 219 | .withTreatment(treatmentForEgressVlan) |
| 220 | .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN) |
| 221 | .makePermanent() |
| 222 | .withPriority(nextObjective.priority()) |
| 223 | .forDevice(DEVICE_ID) |
| 224 | .fromApp(APP_ID) |
| 225 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 226 | |
| 227 | ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder() |
| 228 | .addFlowRule(vlanMetaFlowRule) |
| 229 | .addFlowRule(expectedFlowRule) |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 230 | .addFlowRule(expectedEgressVlanPushRule) |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 231 | .build(); |
| 232 | |
| 233 | assertEquals(expectedTranslation, actualTranslation); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 234 | } |
| 235 | |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 236 | /** |
Daniele Moro | f51d0c1 | 2019-07-30 10:43:10 -0700 | [diff] [blame] | 237 | * Test Route and Push Next Objective (set mac, set double vlan and output port). |
| 238 | */ |
| 239 | @Test |
| 240 | public void testRouteAndPushNextObjective() throws FabricPipelinerException { |
| 241 | TrafficTreatment routeAndPushTreatment = DefaultTrafficTreatment.builder() |
| 242 | .setEthSrc(ROUTER_MAC) |
| 243 | .setEthDst(HOST_MAC) |
| 244 | .setOutput(PORT_1) |
| 245 | .setVlanId(VLAN_100) |
| 246 | .pushVlan() |
| 247 | .setVlanId(VLAN_200) |
| 248 | .build(); |
| 249 | |
| 250 | NextObjective nextObjective = DefaultNextObjective.builder() |
| 251 | .withId(NEXT_ID_1) |
| 252 | .withPriority(PRIORITY) |
| 253 | .addTreatment(routeAndPushTreatment) |
| 254 | .withType(NextObjective.Type.SIMPLE) |
| 255 | .makePermanent() |
| 256 | .fromApp(APP_ID) |
| 257 | .add(); |
| 258 | |
| 259 | ObjectiveTranslation actualTranslation = translatorSimple.translate(nextObjective); |
| 260 | |
| 261 | PiAction piActionRouting = PiAction.builder() |
| 262 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_SIMPLE) |
| 263 | .withParameter(new PiActionParam( |
| 264 | FabricConstants.SMAC, ROUTER_MAC.toBytes())) |
| 265 | .withParameter(new PiActionParam( |
| 266 | FabricConstants.DMAC, HOST_MAC.toBytes())) |
| 267 | .withParameter(new PiActionParam( |
| 268 | FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 269 | .build(); |
| 270 | |
| 271 | PiAction piActionPush = PiAction.builder() |
| 272 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_DOUBLE_VLAN) |
| 273 | .withParameter(new PiActionParam( |
| 274 | FabricConstants.INNER_VLAN_ID, VLAN_100.toShort())) |
| 275 | .withParameter(new PiActionParam( |
| 276 | FabricConstants.OUTER_VLAN_ID, VLAN_200.toShort())) |
| 277 | .build(); |
| 278 | |
| 279 | |
| 280 | TrafficSelector nextIdSelector = DefaultTrafficSelector.builder() |
| 281 | .matchPi(PiCriterion.builder() |
| 282 | .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1) |
| 283 | .build()) |
| 284 | .build(); |
| 285 | FlowRule expectedFlowRuleRouting = DefaultFlowRule.builder() |
| 286 | .forDevice(DEVICE_ID) |
| 287 | .fromApp(APP_ID) |
| 288 | .makePermanent() |
| 289 | // FIXME: currently next objective doesn't support priority, ignore this |
| 290 | .withPriority(0) |
| 291 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_SIMPLE) |
| 292 | .withSelector(nextIdSelector) |
| 293 | .withTreatment(DefaultTrafficTreatment.builder() |
| 294 | .piTableAction(piActionRouting).build()) |
| 295 | .build(); |
| 296 | FlowRule expectedFlowRuleDoublePush = DefaultFlowRule.builder() |
| 297 | .withSelector(nextIdSelector) |
| 298 | .withTreatment(DefaultTrafficTreatment.builder() |
| 299 | .piTableAction(piActionPush) |
| 300 | .build()) |
| 301 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN) |
| 302 | .makePermanent() |
| 303 | // FIXME: currently next objective doesn't support priority, ignore this |
| 304 | .withPriority(0) |
| 305 | .forDevice(DEVICE_ID) |
| 306 | .fromApp(APP_ID) |
| 307 | .build(); |
| 308 | |
| 309 | ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder() |
| 310 | .addFlowRule(expectedFlowRuleDoublePush) |
| 311 | .addFlowRule(expectedFlowRuleRouting) |
| 312 | .build(); |
| 313 | |
| 314 | |
| 315 | assertEquals(expectedTranslation, actualTranslation); |
| 316 | } |
| 317 | |
| 318 | /** |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 319 | * Test program ecmp output group for Hashed table. |
| 320 | */ |
| 321 | @Test |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 322 | public void testHashedOutput() throws Exception { |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 323 | PiAction piAction1 = PiAction.builder() |
| 324 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED) |
| 325 | .withParameter(new PiActionParam( |
| 326 | FabricConstants.SMAC, ROUTER_MAC.toBytes())) |
| 327 | .withParameter(new PiActionParam( |
| 328 | FabricConstants.DMAC, HOST_MAC.toBytes())) |
| 329 | .withParameter(new PiActionParam( |
| 330 | FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 331 | .build(); |
| 332 | PiAction piAction2 = PiAction.builder() |
| 333 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED) |
| 334 | .withParameter(new PiActionParam( |
| 335 | FabricConstants.SMAC, ROUTER_MAC.toBytes())) |
| 336 | .withParameter(new PiActionParam( |
| 337 | FabricConstants.DMAC, HOST_MAC.toBytes())) |
| 338 | .withParameter(new PiActionParam( |
| 339 | FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 340 | .build(); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 341 | TrafficTreatment treatment1 = DefaultTrafficTreatment.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 342 | .piTableAction(piAction1) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 343 | .build(); |
| 344 | TrafficTreatment treatment2 = DefaultTrafficTreatment.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 345 | .piTableAction(piAction2) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 346 | .build(); |
| 347 | |
| 348 | NextObjective nextObjective = DefaultNextObjective.builder() |
| 349 | .withId(NEXT_ID_1) |
| 350 | .withPriority(PRIORITY) |
Yi Tseng | 20f9e7b | 2018-05-24 23:27:39 +0800 | [diff] [blame] | 351 | .withMeta(VLAN_META) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 352 | .addTreatment(treatment1) |
| 353 | .addTreatment(treatment2) |
| 354 | .withType(NextObjective.Type.HASHED) |
| 355 | .makePermanent() |
| 356 | .fromApp(APP_ID) |
| 357 | .add(); |
| 358 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 359 | ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 360 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 361 | // Expected hashed table flow rule. |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 362 | PiCriterion nextIdCriterion = PiCriterion.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 363 | .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 364 | .build(); |
| 365 | TrafficSelector nextIdSelector = DefaultTrafficSelector.builder() |
| 366 | .matchPi(nextIdCriterion) |
| 367 | .build(); |
Carmelo Cascone | cb4327a | 2018-09-11 15:17:23 -0700 | [diff] [blame] | 368 | PiActionProfileGroupId actionGroupId = PiActionProfileGroupId.of(NEXT_ID_1); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 369 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 370 | .piTableAction(actionGroupId) |
| 371 | .build(); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 372 | FlowRule expectedFlowRule = DefaultFlowRule.builder() |
| 373 | .forDevice(DEVICE_ID) |
| 374 | .fromApp(APP_ID) |
| 375 | .makePermanent() |
| 376 | // FIXME: currently next objective doesn't support priority, ignore this |
| 377 | .withPriority(0) |
Yi Tseng | 43ee7e8 | 2018-04-12 16:37:34 +0800 | [diff] [blame] | 378 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_HASHED) |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 379 | .withSelector(nextIdSelector) |
| 380 | .withTreatment(treatment) |
| 381 | .build(); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 382 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 383 | // Expected group |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 384 | List<TrafficTreatment> treatments = ImmutableList.of(treatment1, treatment2); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 385 | List<GroupBucket> buckets = treatments.stream() |
| 386 | .map(DefaultGroupBucket::createSelectGroupBucket) |
| 387 | .collect(Collectors.toList()); |
| 388 | GroupBuckets groupBuckets = new GroupBuckets(buckets); |
Yi Tseng | 43ee7e8 | 2018-04-12 16:37:34 +0800 | [diff] [blame] | 389 | PiGroupKey groupKey = new PiGroupKey(FabricConstants.FABRIC_INGRESS_NEXT_HASHED, |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 390 | FabricConstants.FABRIC_INGRESS_NEXT_HASHED_SELECTOR, |
Yi Tseng | 43ee7e8 | 2018-04-12 16:37:34 +0800 | [diff] [blame] | 391 | NEXT_ID_1); |
Yi Tseng | 1b154bd | 2017-11-20 17:48:19 -0800 | [diff] [blame] | 392 | GroupDescription expectedGroup = new DefaultGroupDescription( |
| 393 | DEVICE_ID, |
| 394 | GroupDescription.Type.SELECT, |
| 395 | groupBuckets, |
| 396 | groupKey, |
| 397 | NEXT_ID_1, |
| 398 | APP_ID |
| 399 | ); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 400 | |
| 401 | ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder() |
| 402 | .addFlowRule(expectedFlowRule) |
| 403 | .addFlowRule(vlanMetaFlowRule) |
| 404 | .addGroup(expectedGroup) |
| 405 | .build(); |
| 406 | |
| 407 | assertEquals(expectedTranslation, actualTranslation); |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 408 | |
| 409 | } |
| 410 | |
| 411 | /** |
| 412 | * Test program output group for Broadcast table. |
| 413 | */ |
| 414 | @Test |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 415 | public void testBroadcastOutput() throws FabricPipelinerException { |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 416 | TrafficTreatment treatment1 = DefaultTrafficTreatment.builder() |
| 417 | .setOutput(PORT_1) |
| 418 | .build(); |
| 419 | TrafficTreatment treatment2 = DefaultTrafficTreatment.builder() |
| 420 | .popVlan() |
| 421 | .setOutput(PORT_2) |
| 422 | .build(); |
| 423 | NextObjective nextObjective = DefaultNextObjective.builder() |
| 424 | .withId(NEXT_ID_1) |
| 425 | .withPriority(PRIORITY) |
| 426 | .addTreatment(treatment1) |
| 427 | .addTreatment(treatment2) |
| 428 | .withMeta(VLAN_META) |
| 429 | .withType(NextObjective.Type.BROADCAST) |
| 430 | .makePermanent() |
| 431 | .fromApp(APP_ID) |
| 432 | .add(); |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 433 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 434 | ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective); |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 435 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 436 | // Should generate 3 flows: |
| 437 | // - Multicast table flow that matches on next-id and set multicast group (1) |
| 438 | // - Egress VLAN pop handling for treatment2 (0) |
| 439 | // - Next VLAN flow (2) |
| 440 | // And 2 groups: |
| 441 | // - Multicast group |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 442 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 443 | // Expected multicast table flow rule. |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 444 | PiCriterion nextIdCriterion = PiCriterion.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 445 | .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1) |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 446 | .build(); |
| 447 | TrafficSelector nextIdSelector = DefaultTrafficSelector.builder() |
| 448 | .matchPi(nextIdCriterion) |
| 449 | .build(); |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 450 | PiAction setMcGroupAction = PiAction.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 451 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_MCAST_GROUP_ID) |
| 452 | .withParameter(new PiActionParam( |
| 453 | FabricConstants.GROUP_ID, NEXT_ID_1)) |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 454 | .build(); |
| 455 | TrafficTreatment treatment = DefaultTrafficTreatment.builder() |
| 456 | .piTableAction(setMcGroupAction) |
| 457 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 458 | FlowRule expectedHashedFlowRule = DefaultFlowRule.builder() |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 459 | .forDevice(DEVICE_ID) |
| 460 | .fromApp(APP_ID) |
| 461 | .makePermanent() |
| 462 | .withPriority(nextObjective.priority()) |
| 463 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_MULTICAST) |
| 464 | .withSelector(nextIdSelector) |
| 465 | .withTreatment(treatment) |
| 466 | .build(); |
| 467 | |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 468 | // Expected egress VLAN_PUSH flow rule. |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 469 | PiCriterion egressVlanTableMatch = PiCriterion.builder() |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 470 | .matchExact(FabricConstants.HDR_EG_PORT, PORT_1.toLong()) |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 471 | .build(); |
| 472 | TrafficSelector selectorForEgressVlan = DefaultTrafficSelector.builder() |
| 473 | .matchPi(egressVlanTableMatch) |
| 474 | .matchVlanId(VLAN_100) |
| 475 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 476 | PiAction piActionForEgressVlan = PiAction.builder() |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 477 | .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_PUSH_VLAN) |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 478 | .build(); |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 479 | TrafficTreatment treatmentForEgressVlan = DefaultTrafficTreatment.builder() |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 480 | .piTableAction(piActionForEgressVlan) |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 481 | .build(); |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 482 | FlowRule expectedEgressVlanPushRule = DefaultFlowRule.builder() |
| 483 | .withSelector(selectorForEgressVlan) |
| 484 | .withTreatment(treatmentForEgressVlan) |
| 485 | .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN) |
| 486 | .makePermanent() |
| 487 | .withPriority(nextObjective.priority()) |
| 488 | .forDevice(DEVICE_ID) |
| 489 | .fromApp(APP_ID) |
| 490 | .build(); |
| 491 | // Expected egress VLAN POP flow rule. |
| 492 | egressVlanTableMatch = PiCriterion.builder() |
| 493 | .matchExact(FabricConstants.HDR_EG_PORT, PORT_2.toLong()) |
| 494 | .build(); |
| 495 | selectorForEgressVlan = DefaultTrafficSelector.builder() |
| 496 | .matchPi(egressVlanTableMatch) |
| 497 | .matchVlanId(VLAN_100) |
| 498 | .build(); |
| 499 | piActionForEgressVlan = PiAction.builder() |
| 500 | .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN) |
| 501 | .build(); |
| 502 | treatmentForEgressVlan = DefaultTrafficTreatment.builder() |
| 503 | .piTableAction(piActionForEgressVlan) |
| 504 | .build(); |
| 505 | FlowRule expectedEgressVlanPopRule = DefaultFlowRule.builder() |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 506 | .withSelector(selectorForEgressVlan) |
| 507 | .withTreatment(treatmentForEgressVlan) |
| 508 | .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN) |
| 509 | .makePermanent() |
| 510 | .withPriority(nextObjective.priority()) |
| 511 | .forDevice(DEVICE_ID) |
| 512 | .fromApp(APP_ID) |
| 513 | .build(); |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 514 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 515 | // Expected ALL group. |
| 516 | TrafficTreatment allGroupTreatment1 = DefaultTrafficTreatment.builder() |
Carmelo Cascone | 5813681 | 2018-07-19 03:40:16 +0200 | [diff] [blame] | 517 | .setOutput(PORT_1) |
| 518 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 519 | TrafficTreatment allGroupTreatment2 = DefaultTrafficTreatment.builder() |
Carmelo Cascone | 5813681 | 2018-07-19 03:40:16 +0200 | [diff] [blame] | 520 | .setOutput(PORT_2) |
| 521 | .build(); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 522 | List<TrafficTreatment> allTreatments = ImmutableList.of( |
| 523 | allGroupTreatment1, allGroupTreatment2); |
| 524 | List<GroupBucket> allBuckets = allTreatments.stream() |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 525 | .map(DefaultGroupBucket::createAllGroupBucket) |
| 526 | .collect(Collectors.toList()); |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 527 | GroupBuckets allGroupBuckets = new GroupBuckets(allBuckets); |
| 528 | GroupKey allGroupKey = new DefaultGroupKey(FabricPipeliner.KRYO.serialize(NEXT_ID_1)); |
| 529 | GroupDescription expectedAllGroup = new DefaultGroupDescription( |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 530 | DEVICE_ID, |
| 531 | GroupDescription.Type.ALL, |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 532 | allGroupBuckets, |
| 533 | allGroupKey, |
Esin Karaman | 24fda8a | 2018-01-26 11:52:28 +0000 | [diff] [blame] | 534 | NEXT_ID_1, |
| 535 | APP_ID |
| 536 | ); |
Yi Tseng | 15ab4b0 | 2018-09-14 11:14:43 -0700 | [diff] [blame] | 537 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 538 | ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder() |
| 539 | .addFlowRule(expectedHashedFlowRule) |
| 540 | .addFlowRule(vlanMetaFlowRule) |
pierventre | cfd08de | 2020-12-15 17:34:54 +0100 | [diff] [blame] | 541 | .addFlowRule(expectedEgressVlanPushRule) |
| 542 | .addFlowRule(expectedEgressVlanPopRule) |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 543 | .addGroup(expectedAllGroup) |
| 544 | .build(); |
Yi Tseng | 15ab4b0 | 2018-09-14 11:14:43 -0700 | [diff] [blame] | 545 | |
Carmelo Cascone | b5324e7 | 2018-11-25 02:26:32 -0800 | [diff] [blame] | 546 | assertEquals(expectedTranslation, actualTranslation); |
Yi Tseng | 15ab4b0 | 2018-09-14 11:14:43 -0700 | [diff] [blame] | 547 | } |
Carmelo Cascone | 45cc086 | 2018-11-26 11:50:41 -0800 | [diff] [blame] | 548 | |
| 549 | /** |
| 550 | * Test XConnect NextObjective. |
| 551 | * |
| 552 | * @throws FabricPipelinerException |
| 553 | */ |
| 554 | @Test |
| 555 | public void testXconnectOutput() throws FabricPipelinerException { |
| 556 | TrafficTreatment treatment1 = DefaultTrafficTreatment.builder() |
| 557 | .setOutput(PORT_1) |
| 558 | .build(); |
| 559 | TrafficTreatment treatment2 = DefaultTrafficTreatment.builder() |
| 560 | .setOutput(PORT_2) |
| 561 | .build(); |
| 562 | NextObjective nextObjective = DefaultNextObjective.builder() |
| 563 | .withId(NEXT_ID_1) |
| 564 | .withPriority(PRIORITY) |
| 565 | .addTreatment(treatment1) |
| 566 | .addTreatment(treatment2) |
| 567 | .withType(NextObjective.Type.BROADCAST) |
| 568 | .makePermanent() |
| 569 | .fromApp(XCONNECT_APP_ID) |
| 570 | .add(); |
| 571 | |
| 572 | ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective); |
| 573 | |
| 574 | // Should generate 2 flows for the xconnect table. |
| 575 | |
| 576 | // Expected multicast table flow rule. |
| 577 | PiCriterion nextIdCriterion = PiCriterion.builder() |
| 578 | .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1) |
| 579 | .build(); |
| 580 | TrafficSelector xcSelector1 = DefaultTrafficSelector.builder() |
| 581 | .matchPi(nextIdCriterion) |
| 582 | .matchInPort(PORT_1) |
| 583 | .build(); |
| 584 | TrafficTreatment xcTreatment1 = DefaultTrafficTreatment.builder() |
| 585 | .piTableAction(PiAction.builder() |
| 586 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_XCONNECT) |
| 587 | .withParameter(new PiActionParam(FabricConstants.PORT_NUM, PORT_2.toLong())) |
| 588 | .build()) |
| 589 | .build(); |
| 590 | TrafficSelector xcSelector2 = DefaultTrafficSelector.builder() |
| 591 | .matchPi(nextIdCriterion) |
| 592 | .matchInPort(PORT_2) |
| 593 | .build(); |
| 594 | TrafficTreatment xcTreatment2 = DefaultTrafficTreatment.builder() |
| 595 | .piTableAction(PiAction.builder() |
| 596 | .withId(FabricConstants.FABRIC_INGRESS_NEXT_OUTPUT_XCONNECT) |
| 597 | .withParameter(new PiActionParam(FabricConstants.PORT_NUM, PORT_1.toLong())) |
| 598 | .build()) |
| 599 | .build(); |
| 600 | |
| 601 | FlowRule expectedXcFlowRule1 = DefaultFlowRule.builder() |
| 602 | .forDevice(DEVICE_ID) |
| 603 | .fromApp(XCONNECT_APP_ID) |
| 604 | .makePermanent() |
| 605 | .withPriority(nextObjective.priority()) |
| 606 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT) |
| 607 | .withSelector(xcSelector1) |
| 608 | .withTreatment(xcTreatment1) |
| 609 | .build(); |
| 610 | FlowRule expectedXcFlowRule2 = DefaultFlowRule.builder() |
| 611 | .forDevice(DEVICE_ID) |
| 612 | .fromApp(XCONNECT_APP_ID) |
| 613 | .makePermanent() |
| 614 | .withPriority(nextObjective.priority()) |
| 615 | .forTable(FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT) |
| 616 | .withSelector(xcSelector2) |
| 617 | .withTreatment(xcTreatment2) |
| 618 | .build(); |
| 619 | |
| 620 | ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder() |
| 621 | .addFlowRule(expectedXcFlowRule1) |
| 622 | .addFlowRule(expectedXcFlowRule2) |
| 623 | .build(); |
| 624 | |
| 625 | assertEquals(expectedTranslation, actualTranslation); |
| 626 | } |
Yi Tseng | 0b80972 | 2017-11-03 10:23:26 -0700 | [diff] [blame] | 627 | } |