blob: 72698ae3923daefe6c6c543fdaa790a3e9e017b6 [file] [log] [blame]
Yoonseon Hanc70b4e02016-10-20 15:24:33 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Yoonseon Hanc70b4e02016-10-20 15:24:33 -07003 *
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.incubator.net.virtual.impl.provider;
18
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableSet;
21import org.junit.After;
22import org.junit.Before;
23import org.junit.Test;
Ray Milkeya7cf8c82018-02-08 15:07:06 -080024import org.onlab.graph.ScalarWeight;
25import org.onlab.graph.Weight;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070026import org.onosproject.core.ApplicationId;
yoonseon322c9c32016-12-07 16:47:02 -080027import org.onosproject.core.CoreServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070028import org.onosproject.core.DefaultApplicationId;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070029import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
30import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
31import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
32import org.onosproject.incubator.net.virtual.NetworkId;
33import org.onosproject.incubator.net.virtual.TenantId;
34import org.onosproject.incubator.net.virtual.VirtualDevice;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070035import org.onosproject.incubator.net.virtual.VirtualLink;
36import org.onosproject.incubator.net.virtual.VirtualNetwork;
Yoonseon Hanffcc32f2017-05-03 14:42:17 -070037import org.onosproject.incubator.net.virtual.VirtualNetworkAdminServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070038import org.onosproject.incubator.net.virtual.VirtualPort;
39import org.onosproject.net.ConnectPoint;
40import org.onosproject.net.DefaultAnnotations;
41import org.onosproject.net.DefaultDevice;
42import org.onosproject.net.DefaultLink;
43import org.onosproject.net.DefaultPath;
44import org.onosproject.net.DefaultPort;
45import org.onosproject.net.Device;
46import org.onosproject.net.DeviceId;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070047import org.onosproject.net.Link;
48import org.onosproject.net.Path;
49import org.onosproject.net.Port;
50import org.onosproject.net.PortNumber;
51import org.onosproject.net.device.DeviceServiceAdapter;
52import org.onosproject.net.flow.DefaultFlowEntry;
53import org.onosproject.net.flow.DefaultFlowRule;
54import org.onosproject.net.flow.DefaultTrafficSelector;
55import org.onosproject.net.flow.DefaultTrafficTreatment;
56import org.onosproject.net.flow.FlowEntry;
57import org.onosproject.net.flow.FlowRule;
yoonseon322c9c32016-12-07 16:47:02 -080058import org.onosproject.net.flow.FlowRuleServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070059import org.onosproject.net.flow.TrafficSelector;
60import org.onosproject.net.flow.TrafficTreatment;
61import org.onosproject.net.flow.instructions.Instruction;
62import org.onosproject.net.flow.instructions.L2ModificationInstruction;
63import org.onosproject.net.provider.ProviderId;
yoonseon322c9c32016-12-07 16:47:02 -080064import org.onosproject.net.topology.LinkWeigher;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070065import org.onosproject.net.topology.LinkWeight;
66import org.onosproject.net.topology.Topology;
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -080067import org.onosproject.net.topology.TopologyServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070068
Yoonseon Hanc8089db2017-03-22 20:22:12 +090069import java.util.Arrays;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070070import java.util.HashSet;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070071import java.util.Set;
72import java.util.stream.Collectors;
73
74import static org.junit.Assert.assertEquals;
75
76public class DefaultVirtualFlowRuleProviderTest {
77 private static final ProviderId PID = new ProviderId("of", "foo");
78
79 private static final DeviceId DID1 = DeviceId.deviceId("of:001");
80 private static final DeviceId DID2 = DeviceId.deviceId("of:002");
81 private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
82 private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);
83
84 private static final DefaultAnnotations ANNOTATIONS =
85 DefaultAnnotations.builder().set("foo", "bar").build();
86
87 private static final Device DEV1 =
88 new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
89 private static final Device DEV2 =
90 new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
91 private static final Port PORT11 =
92 new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
93 private static final Port PORT12 =
94 new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
95 private static final Port PORT21 =
96 new DefaultPort(DEV2, PORT_NUM1, true, ANNOTATIONS);
97 private static final Port PORT22 =
98 new DefaultPort(DEV2, PORT_NUM2, true, ANNOTATIONS);
99
100 private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
101 private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
102 private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM1);
103 private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM2);
104 private static final Link LINK1 = DefaultLink.builder()
105 .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();
106
107 private static final NetworkId VNET_ID = NetworkId.networkId(1);
108 private static final DeviceId VDID = DeviceId.deviceId("of:100");
109
110 private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
111 VNET_ID, TenantId.tenantId("t1"));
112 private static final VirtualDevice VDEV =
113 new DefaultVirtualDevice(VNET_ID, VDID);
114 private static final VirtualPort VPORT1 =
115 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM1, CP11);
116 private static final VirtualPort VPORT2 =
117 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM2, CP22);
118
119 private static final int TIMEOUT = 10;
120
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700121 protected DefaultVirtualFlowRuleProvider virtualProvider;
122
123 private ApplicationId vAppId;
124
125 @Before
126 public void setUp() {
127 virtualProvider = new DefaultVirtualFlowRuleProvider();
128
129 virtualProvider.deviceService = new TestDeviceService();
130 virtualProvider.coreService = new TestCoreService();
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900131 virtualProvider.vnService =
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700132 new TestVirtualNetworkAdminService();
133 virtualProvider.topologyService = new TestTopologyService();
134 virtualProvider.flowRuleService = new TestFlowRuleService();
135 virtualProvider.providerRegistryService = new VirtualProviderManager();
136
137 virtualProvider.activate();
138 vAppId = new TestApplicationId(0, "Virtual App");
139 }
140
141 @After
142 public void tearDown() {
143 virtualProvider.deactivate();
144 virtualProvider.deviceService = null;
145 virtualProvider.coreService = null;
146 }
147
148 @Test
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900149 public void devirtualizeFlowRuleWithInPort() {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700150 TrafficSelector ts = DefaultTrafficSelector.builder()
151 .matchInPort(PORT_NUM1).build();
152 TrafficTreatment tr = DefaultTrafficTreatment.builder()
153 .setOutput(PORT_NUM2).build();
154
155 FlowRule r1 = DefaultFlowRule.builder()
156 .forDevice(VDID)
157 .withSelector(ts)
158 .withTreatment(tr)
159 .withPriority(10)
160 .fromApp(vAppId)
161 .makeTemporary(TIMEOUT)
162 .build();
163
164 virtualProvider.applyFlowRule(VNET_ID, r1);
165
166 assertEquals("2 rules should exist", 2,
167 virtualProvider.flowRuleService.getFlowRuleCount());
168
169 Set<FlowEntry> phyRules = new HashSet<>();
170 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
171 phyRules.add(i);
172 }
173 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
174 phyRules.add(i);
175 }
176
177 FlowRule in = null;
178 FlowRule out = null;
179
180 for (FlowRule rule : phyRules) {
181
182 L2ModificationInstruction i = (L2ModificationInstruction)
183 rule.treatment().allInstructions().get(0);
184
185 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
186 in = rule;
187 } else {
188 out = rule;
189 }
190
191 }
192
193 assertEquals(DID1, in.deviceId());
194 assertEquals(DID2, out.deviceId());
195 }
196
197 @Test
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900198 public void devirtualizeFlowRuleWithoutInPort() {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700199 TrafficSelector ts = DefaultTrafficSelector.builder().build();
200 TrafficTreatment tr = DefaultTrafficTreatment.builder()
201 .setOutput(PORT_NUM2).build();
202
203 FlowRule r1 = DefaultFlowRule.builder()
204 .forDevice(VDID)
205 .withSelector(ts)
206 .withTreatment(tr)
207 .withPriority(10)
208 .fromApp(vAppId)
209 .makeTemporary(TIMEOUT)
210 .build();
211
212 virtualProvider.applyFlowRule(VNET_ID, r1);
213
214 assertEquals("3 rules should exist", 3,
215 virtualProvider.flowRuleService.getFlowRuleCount());
216
217 FlowRule inFromDID1 = null;
218 FlowRule inFromDID2 = null;
219 FlowRule out = null;
220
221 Set<FlowEntry> phyRules = new HashSet<>();
222 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
223 phyRules.add(i);
224 }
225 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
226 phyRules.add(i);
227 }
228
229 for (FlowRule rule : phyRules) {
230 for (Instruction inst : rule.treatment().allInstructions()) {
231 if (inst.type() == Instruction.Type.L2MODIFICATION) {
232 L2ModificationInstruction i = (L2ModificationInstruction) inst;
233 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
234 inFromDID1 = rule;
235 break;
236 } else {
237 out = rule;
238 break;
239 }
240 } else {
241 inFromDID2 = rule;
242 break;
243 }
244 }
245 }
246
247 assertEquals(DID1, inFromDID1.deviceId());
248 assertEquals(DID2, inFromDID2.deviceId());
249 assertEquals(DID2, out.deviceId());
250 }
251
252 @Test
253 public void removeVirtualizeFlowRule() {
254 TrafficSelector ts = DefaultTrafficSelector.builder().build();
255 TrafficTreatment tr = DefaultTrafficTreatment.builder()
256 .setOutput(PORT_NUM2).build();
257
258 FlowRule r1 = DefaultFlowRule.builder()
259 .forDevice(VDID)
260 .withSelector(ts)
261 .withTreatment(tr)
262 .withPriority(10)
263 .fromApp(vAppId)
264 .makeTemporary(TIMEOUT)
265 .build();
266
267 virtualProvider.removeFlowRule(VNET_ID, r1);
268
269 assertEquals("0 rules should exist", 0,
270 virtualProvider.flowRuleService.getFlowRuleCount());
271 }
272
273
274 private static class TestDeviceService extends DeviceServiceAdapter {
275 @Override
276 public int getDeviceCount() {
277 return 2;
278 }
279
280 @Override
281 public Iterable<Device> getDevices() {
282 return ImmutableList.of(DEV1, DEV2);
283 }
284
285 @Override
286 public Iterable<Device> getAvailableDevices() {
287 return getDevices();
288 }
289
290 @Override
291 public Device getDevice(DeviceId deviceId) {
292 return deviceId.equals(DID2) ? DEV2 : DEV1;
293 }
294 }
295
yoonseon322c9c32016-12-07 16:47:02 -0800296 private static class TestCoreService extends CoreServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700297
298 @Override
299 public ApplicationId registerApplication(String name) {
300 return new TestApplicationId(1, name);
301 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700302 }
303
304 private static class TestApplicationId extends DefaultApplicationId {
305 public TestApplicationId(int id, String name) {
306 super(id, name);
307 }
308 }
309
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900310 private class TestVirtualNetworkAdminService
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700311 extends VirtualNetworkAdminServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700312
313 @Override
314 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
315 return ImmutableSet.of(VDEV);
316 }
317
318 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700319 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
Harold Huang7362e672017-04-19 10:00:11 +0800320 return new HashSet<>();
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700321 }
322
323 @Override
324 public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
325 DeviceId deviceId) {
326 return ImmutableSet.of(VPORT1, VPORT2);
327 }
328
329 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800330 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900331 return vAppId;
yoonseon322c9c32016-12-07 16:47:02 -0800332 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700333 }
334
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -0800335 private static class TestTopologyService extends TopologyServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700336
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800337 Weight oneHundred = ScalarWeight.toWeight(100);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700338 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700339 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
340 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800341 oneHundred, ANNOTATIONS);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700342 return ImmutableSet.of(path);
343 }
344
345 @Override
346 public Set<Path> getPaths(Topology topology, DeviceId src,
347 DeviceId dst, LinkWeight weight) {
348 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800349 oneHundred, ANNOTATIONS);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700350 return ImmutableSet.of(path);
351 }
352
353 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800354 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
355 LinkWeigher weigher) {
356 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800357 oneHundred, ANNOTATIONS);
yoonseon322c9c32016-12-07 16:47:02 -0800358 return ImmutableSet.of(path);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700359 }
360
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700361 }
362
yoonseon322c9c32016-12-07 16:47:02 -0800363 private static class TestFlowRuleService extends FlowRuleServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700364 static Set<FlowRule> ruleCollection = new HashSet<>();
365
366 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700367 public int getFlowRuleCount() {
368 return ruleCollection.size();
369 }
370
371 @Override
372 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
373 return ruleCollection.stream()
374 .filter(r -> r.deviceId().equals(deviceId))
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900375 .map(DefaultFlowEntry::new)
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700376 .collect(Collectors.toSet());
377 }
378
379 @Override
380 public void applyFlowRules(FlowRule... flowRules) {
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900381 ruleCollection.addAll(Arrays.asList(flowRules));
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700382 }
383
384 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700385 public void removeFlowRules(FlowRule... flowRules) {
386 Set<FlowRule> candidates = new HashSet<>();
387 for (FlowRule rule : flowRules) {
388 ruleCollection.stream()
389 .filter(r -> r.exactMatch(rule))
390 .forEach(candidates::add);
391 }
392 ruleCollection.removeAll(candidates);
393 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700394 }
395}