Michele Santuari
Committed by Gerrit Code Review

fix egress packet treatment ONOS-3467

Change-Id: Ia88568d0ed8f1a982479e5212495923d55238d7b
...@@ -38,6 +38,7 @@ import org.onosproject.net.flow.TrafficSelector; ...@@ -38,6 +38,7 @@ import org.onosproject.net.flow.TrafficSelector;
38 import org.onosproject.net.flow.TrafficTreatment; 38 import org.onosproject.net.flow.TrafficTreatment;
39 import org.onosproject.net.flow.criteria.Criterion; 39 import org.onosproject.net.flow.criteria.Criterion;
40 import org.onosproject.net.flow.criteria.VlanIdCriterion; 40 import org.onosproject.net.flow.criteria.VlanIdCriterion;
41 +import org.onosproject.net.flow.instructions.L2ModificationInstruction;
41 import org.onosproject.net.intent.FlowRuleIntent; 42 import org.onosproject.net.intent.FlowRuleIntent;
42 import org.onosproject.net.intent.Intent; 43 import org.onosproject.net.intent.Intent;
43 import org.onosproject.net.intent.IntentCompiler; 44 import org.onosproject.net.intent.IntentCompiler;
...@@ -221,16 +222,28 @@ public class PathIntentCompiler implements IntentCompiler<PathIntent> { ...@@ -221,16 +222,28 @@ public class PathIntentCompiler implements IntentCompiler<PathIntent> {
221 .matchInPort(prev.port()) 222 .matchInPort(prev.port())
222 .matchVlanId(prevVlanId).build(); 223 .matchVlanId(prevVlanId).build();
223 TrafficTreatment.Builder egressTreat = DefaultTrafficTreatment.builder(intent.treatment()); 224 TrafficTreatment.Builder egressTreat = DefaultTrafficTreatment.builder(intent.treatment());
224 - if (vlanCriterion.isPresent()) { 225 +
225 - egressTreat.setVlanId(vlanCriterion.get().vlanId()); 226 + Optional<L2ModificationInstruction.ModVlanIdInstruction> modVlanIdInstruction = intent.treatment()
226 - } else { 227 + .allInstructions().stream().filter(
227 - egressTreat.popVlan(); 228 + instruction -> instruction instanceof L2ModificationInstruction.ModVlanIdInstruction)
229 + .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x).findAny();
230 +
231 + Optional<L2ModificationInstruction.PopVlanInstruction> popVlanInstruction = intent.treatment()
232 + .allInstructions().stream().filter(
233 + instruction -> instruction instanceof L2ModificationInstruction.PopVlanInstruction)
234 + .map(x -> (L2ModificationInstruction.PopVlanInstruction) x).findAny();
235 +
236 + if (!modVlanIdInstruction.isPresent() && !popVlanInstruction.isPresent()) {
237 + if (vlanCriterion.isPresent()) {
238 + egressTreat.setVlanId(vlanCriterion.get().vlanId());
239 + } else {
240 + egressTreat.popVlan();
241 + }
228 } 242 }
229 243
230 rules.add(createFlowRule(egressSelector, 244 rules.add(createFlowRule(egressSelector,
231 egressTreat.build(), prev, link.src(), intent.priority(), true)); 245 egressTreat.build(), prev, link.src(), intent.priority(), true));
232 } 246 }
233 -
234 } 247 }
235 return rules; 248 return rules;
236 249
......
...@@ -72,6 +72,13 @@ public class PathIntentCompilerTest { ...@@ -72,6 +72,13 @@ public class PathIntentCompilerTest {
72 72
73 private final TrafficSelector selector = DefaultTrafficSelector.builder().build(); 73 private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
74 private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); 74 private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
75 + private final VlanId ingressVlan = VlanId.vlanId(((short) 101));
76 + private final TrafficSelector vlanSelector = DefaultTrafficSelector.builder()
77 + .matchVlanId(ingressVlan).build();
78 + private final VlanId egressVlan = VlanId.vlanId((short) 100);
79 + private final TrafficTreatment vlanTreatment = DefaultTrafficTreatment.builder()
80 + .setVlanId(egressVlan).build();
81 +
75 private final ApplicationId appId = new TestApplicationId("test"); 82 private final ApplicationId appId = new TestApplicationId("test");
76 private final ProviderId pid = new ProviderId("of", "test"); 83 private final ProviderId pid = new ProviderId("of", "test");
77 private final ConnectPoint d1p1 = connectPoint("s1", 0); 84 private final ConnectPoint d1p1 = connectPoint("s1", 0);
...@@ -91,6 +98,7 @@ public class PathIntentCompilerTest { ...@@ -91,6 +98,7 @@ public class PathIntentCompilerTest {
91 private final int hops = links.size() - 1; 98 private final int hops = links.size() - 1;
92 private PathIntent intent; 99 private PathIntent intent;
93 private PathIntent constraintIntent; 100 private PathIntent constraintIntent;
101 + private PathIntent constrainIngressEgressVlanIntent;
94 102
95 /** 103 /**
96 * Configures objects used in all the test cases. 104 * Configures objects used in all the test cases.
...@@ -113,6 +121,7 @@ public class PathIntentCompilerTest { ...@@ -113,6 +121,7 @@ public class PathIntentCompilerTest {
113 .priority(PRIORITY) 121 .priority(PRIORITY)
114 .path(new DefaultPath(pid, links, hops)) 122 .path(new DefaultPath(pid, links, hops))
115 .build(); 123 .build();
124 + //Intent with VLAN encap without egress VLAN
116 constraintIntent = PathIntent.builder() 125 constraintIntent = PathIntent.builder()
117 .appId(APP_ID) 126 .appId(APP_ID)
118 .selector(selector) 127 .selector(selector)
...@@ -121,6 +130,15 @@ public class PathIntentCompilerTest { ...@@ -121,6 +130,15 @@ public class PathIntentCompilerTest {
121 .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN))) 130 .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
122 .path(new DefaultPath(pid, links, hops)) 131 .path(new DefaultPath(pid, links, hops))
123 .build(); 132 .build();
133 + //Intent with VLAN encap with ingress and egress VLAN
134 + constrainIngressEgressVlanIntent = PathIntent.builder()
135 + .appId(APP_ID)
136 + .selector(vlanSelector)
137 + .treatment(vlanTreatment)
138 + .priority(PRIORITY)
139 + .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
140 + .path(new DefaultPath(pid, links, hops))
141 + .build();
124 intentExtensionService = createMock(IntentExtensionService.class); 142 intentExtensionService = createMock(IntentExtensionService.class);
125 intentExtensionService.registerCompiler(PathIntent.class, sut); 143 intentExtensionService.registerCompiler(PathIntent.class, sut);
126 intentExtensionService.unregisterCompiler(PathIntent.class); 144 intentExtensionService.unregisterCompiler(PathIntent.class);
...@@ -187,7 +205,7 @@ public class PathIntentCompilerTest { ...@@ -187,7 +205,7 @@ public class PathIntentCompilerTest {
187 205
188 /** 206 /**
189 * Tests the compilation behavior of the path intent compiler in case of 207 * Tests the compilation behavior of the path intent compiler in case of
190 - * encasulation costraint {@link EncapsulationConstraint}. 208 + * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}.
191 */ 209 */
192 @Test 210 @Test
193 public void testEncapCompile() { 211 public void testEncapCompile() {
...@@ -229,6 +247,61 @@ public class PathIntentCompilerTest { ...@@ -229,6 +247,61 @@ public class PathIntentCompilerTest {
229 sut.deactivate(); 247 sut.deactivate();
230 } 248 }
231 249
250 + /**
251 + * Tests the compilation behavior of the path intent compiler in case of
252 + * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}.
253 + * This test includes a selector to match a VLAN at the ingress and a treatment to set VLAN at the egress.
254 + */
255 + @Test
256 + public void testEncapIngressEgressVlansCompile() {
257 + sut.activate();
258 +
259 + List<Intent> compiled = sut.compile(constrainIngressEgressVlanIntent,
260 + Collections.emptyList(), Collections.emptySet());
261 + assertThat(compiled, hasSize(1));
262 +
263 + Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
264 + assertThat(rules, hasSize(3));
265 +
266 + FlowRule rule1 = rules.stream()
267 + .filter(x -> x.deviceId().equals(d1p0.deviceId()))
268 + .findFirst()
269 + .get();
270 + assertThat(rule1.deviceId(), is(d1p0.deviceId()));
271 + assertThat(rule1.priority(), is(intent.priority()));
272 + verifyEncapSelector(rule1.selector(), d1p0, ingressVlan);
273 + VlanId vlanToEncap = verifyEncapTreatment(rule1.treatment(), d1p1, true, false);
274 +
275 + FlowRule rule2 = rules.stream()
276 + .filter(x -> x.deviceId().equals(d2p0.deviceId()))
277 + .findFirst()
278 + .get();
279 + assertThat(rule2.deviceId(), is(d2p0.deviceId()));
280 + assertThat(rule2.priority(), is(intent.priority()));
281 + verifyEncapSelector(rule2.selector(), d2p0, vlanToEncap);
282 + verifyEncapTreatment(rule2.treatment(), d2p1, false, false);
283 +
284 + FlowRule rule3 = rules.stream()
285 + .filter(x -> x.deviceId().equals(d3p0.deviceId()))
286 + .findFirst()
287 + .get();
288 + assertThat(rule3.deviceId(), is(d3p1.deviceId()));
289 + assertThat(rule3.priority(), is(intent.priority()));
290 + verifyEncapSelector(rule3.selector(), d3p1, vlanToEncap);
291 + Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule3.treatment().allInstructions().stream()
292 + .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
293 + .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
294 + .collect(Collectors.toSet());
295 + assertThat(rule3.treatment().allInstructions().stream()
296 + .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
297 + .collect(Collectors.toSet()), hasSize(1));
298 + assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
299 + assertThat(rule3.treatment().allInstructions().stream()
300 + .filter(treat -> treat instanceof L2ModificationInstruction.PopVlanInstruction)
301 + .collect(Collectors.toSet()), hasSize(0));
302 +
303 + sut.deactivate();
304 + }
232 305
233 private VlanId verifyEncapTreatment(TrafficTreatment trafficTreatment, 306 private VlanId verifyEncapTreatment(TrafficTreatment trafficTreatment,
234 ConnectPoint egress, boolean isIngress, boolean isEgress) { 307 ConnectPoint egress, boolean isIngress, boolean isEgress) {
......