blob: d8ae05dcd1fd94a9c02f46e5a9fbc09d205a475f [file] [log] [blame]
Yoonseon Hanc70b4e02016-10-20 15:24:33 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.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;
24import org.onlab.osgi.ServiceDirectory;
25import org.onlab.packet.IpAddress;
26import org.onlab.packet.MacAddress;
27import org.onlab.packet.VlanId;
28import org.onosproject.core.ApplicationId;
yoonseon322c9c32016-12-07 16:47:02 -080029import org.onosproject.core.CoreServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070030import org.onosproject.core.DefaultApplicationId;
31import org.onosproject.core.IdGenerator;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070032import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
33import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
34import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
35import org.onosproject.incubator.net.virtual.NetworkId;
36import org.onosproject.incubator.net.virtual.TenantId;
37import org.onosproject.incubator.net.virtual.VirtualDevice;
38import org.onosproject.incubator.net.virtual.VirtualHost;
39import org.onosproject.incubator.net.virtual.VirtualLink;
40import org.onosproject.incubator.net.virtual.VirtualNetwork;
41import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
42import org.onosproject.incubator.net.virtual.VirtualPort;
43import org.onosproject.net.ConnectPoint;
44import org.onosproject.net.DefaultAnnotations;
45import org.onosproject.net.DefaultDevice;
46import org.onosproject.net.DefaultLink;
47import org.onosproject.net.DefaultPath;
48import org.onosproject.net.DefaultPort;
49import org.onosproject.net.Device;
50import org.onosproject.net.DeviceId;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070051import org.onosproject.net.HostId;
52import org.onosproject.net.HostLocation;
53import org.onosproject.net.Link;
54import org.onosproject.net.Path;
55import org.onosproject.net.Port;
56import org.onosproject.net.PortNumber;
57import org.onosproject.net.device.DeviceServiceAdapter;
58import org.onosproject.net.flow.DefaultFlowEntry;
59import org.onosproject.net.flow.DefaultFlowRule;
60import org.onosproject.net.flow.DefaultTrafficSelector;
61import org.onosproject.net.flow.DefaultTrafficTreatment;
62import org.onosproject.net.flow.FlowEntry;
63import org.onosproject.net.flow.FlowRule;
yoonseon322c9c32016-12-07 16:47:02 -080064import org.onosproject.net.flow.FlowRuleServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070065import org.onosproject.net.flow.TrafficSelector;
66import org.onosproject.net.flow.TrafficTreatment;
67import org.onosproject.net.flow.instructions.Instruction;
68import org.onosproject.net.flow.instructions.L2ModificationInstruction;
69import org.onosproject.net.provider.ProviderId;
yoonseon322c9c32016-12-07 16:47:02 -080070import org.onosproject.net.topology.LinkWeigher;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070071import org.onosproject.net.topology.LinkWeight;
72import org.onosproject.net.topology.Topology;
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -080073import org.onosproject.net.topology.TopologyServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070074
75import java.util.HashSet;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070076import java.util.Set;
yoonseon322c9c32016-12-07 16:47:02 -080077import java.util.concurrent.atomic.AtomicLong;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070078import java.util.stream.Collectors;
79
80import static org.junit.Assert.assertEquals;
81
82public class DefaultVirtualFlowRuleProviderTest {
83 private static final ProviderId PID = new ProviderId("of", "foo");
84
85 private static final DeviceId DID1 = DeviceId.deviceId("of:001");
86 private static final DeviceId DID2 = DeviceId.deviceId("of:002");
87 private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
88 private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);
89
90 private static final DefaultAnnotations ANNOTATIONS =
91 DefaultAnnotations.builder().set("foo", "bar").build();
92
93 private static final Device DEV1 =
94 new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
95 private static final Device DEV2 =
96 new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
97 private static final Port PORT11 =
98 new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
99 private static final Port PORT12 =
100 new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
101 private static final Port PORT21 =
102 new DefaultPort(DEV2, PORT_NUM1, true, ANNOTATIONS);
103 private static final Port PORT22 =
104 new DefaultPort(DEV2, PORT_NUM2, true, ANNOTATIONS);
105
106 private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
107 private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
108 private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM1);
109 private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM2);
110 private static final Link LINK1 = DefaultLink.builder()
111 .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();
112
113 private static final NetworkId VNET_ID = NetworkId.networkId(1);
114 private static final DeviceId VDID = DeviceId.deviceId("of:100");
115
116 private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
117 VNET_ID, TenantId.tenantId("t1"));
118 private static final VirtualDevice VDEV =
119 new DefaultVirtualDevice(VNET_ID, VDID);
120 private static final VirtualPort VPORT1 =
121 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM1, CP11);
122 private static final VirtualPort VPORT2 =
123 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM2, CP22);
124
125 private static final int TIMEOUT = 10;
126
127
128 protected DefaultVirtualFlowRuleProvider virtualProvider;
129
130 private ApplicationId vAppId;
131
132 @Before
133 public void setUp() {
134 virtualProvider = new DefaultVirtualFlowRuleProvider();
135
136 virtualProvider.deviceService = new TestDeviceService();
137 virtualProvider.coreService = new TestCoreService();
138 virtualProvider.virtualNetworkAdminService =
139 new TestVirtualNetworkAdminService();
140 virtualProvider.topologyService = new TestTopologyService();
141 virtualProvider.flowRuleService = new TestFlowRuleService();
142 virtualProvider.providerRegistryService = new VirtualProviderManager();
143
144 virtualProvider.activate();
145 vAppId = new TestApplicationId(0, "Virtual App");
146 }
147
148 @After
149 public void tearDown() {
150 virtualProvider.deactivate();
151 virtualProvider.deviceService = null;
152 virtualProvider.coreService = null;
153 }
154
155 @Test
156 public void virtualizeFlowRuleWithInPort() {
157 TrafficSelector ts = DefaultTrafficSelector.builder()
158 .matchInPort(PORT_NUM1).build();
159 TrafficTreatment tr = DefaultTrafficTreatment.builder()
160 .setOutput(PORT_NUM2).build();
161
162 FlowRule r1 = DefaultFlowRule.builder()
163 .forDevice(VDID)
164 .withSelector(ts)
165 .withTreatment(tr)
166 .withPriority(10)
167 .fromApp(vAppId)
168 .makeTemporary(TIMEOUT)
169 .build();
170
171 virtualProvider.applyFlowRule(VNET_ID, r1);
172
173 assertEquals("2 rules should exist", 2,
174 virtualProvider.flowRuleService.getFlowRuleCount());
175
176 Set<FlowEntry> phyRules = new HashSet<>();
177 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
178 phyRules.add(i);
179 }
180 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
181 phyRules.add(i);
182 }
183
184 FlowRule in = null;
185 FlowRule out = null;
186
187 for (FlowRule rule : phyRules) {
188
189 L2ModificationInstruction i = (L2ModificationInstruction)
190 rule.treatment().allInstructions().get(0);
191
192 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
193 in = rule;
194 } else {
195 out = rule;
196 }
197
198 }
199
200 assertEquals(DID1, in.deviceId());
201 assertEquals(DID2, out.deviceId());
202 }
203
204 @Test
205 public void virtualizeFlowRuleWithoutInPort() {
206 TrafficSelector ts = DefaultTrafficSelector.builder().build();
207 TrafficTreatment tr = DefaultTrafficTreatment.builder()
208 .setOutput(PORT_NUM2).build();
209
210 FlowRule r1 = DefaultFlowRule.builder()
211 .forDevice(VDID)
212 .withSelector(ts)
213 .withTreatment(tr)
214 .withPriority(10)
215 .fromApp(vAppId)
216 .makeTemporary(TIMEOUT)
217 .build();
218
219 virtualProvider.applyFlowRule(VNET_ID, r1);
220
221 assertEquals("3 rules should exist", 3,
222 virtualProvider.flowRuleService.getFlowRuleCount());
223
224 FlowRule inFromDID1 = null;
225 FlowRule inFromDID2 = null;
226 FlowRule out = null;
227
228 Set<FlowEntry> phyRules = new HashSet<>();
229 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
230 phyRules.add(i);
231 }
232 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
233 phyRules.add(i);
234 }
235
236 for (FlowRule rule : phyRules) {
237 for (Instruction inst : rule.treatment().allInstructions()) {
238 if (inst.type() == Instruction.Type.L2MODIFICATION) {
239 L2ModificationInstruction i = (L2ModificationInstruction) inst;
240 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
241 inFromDID1 = rule;
242 break;
243 } else {
244 out = rule;
245 break;
246 }
247 } else {
248 inFromDID2 = rule;
249 break;
250 }
251 }
252 }
253
254 assertEquals(DID1, inFromDID1.deviceId());
255 assertEquals(DID2, inFromDID2.deviceId());
256 assertEquals(DID2, out.deviceId());
257 }
258
259 @Test
260 public void removeVirtualizeFlowRule() {
261 TrafficSelector ts = DefaultTrafficSelector.builder().build();
262 TrafficTreatment tr = DefaultTrafficTreatment.builder()
263 .setOutput(PORT_NUM2).build();
264
265 FlowRule r1 = DefaultFlowRule.builder()
266 .forDevice(VDID)
267 .withSelector(ts)
268 .withTreatment(tr)
269 .withPriority(10)
270 .fromApp(vAppId)
271 .makeTemporary(TIMEOUT)
272 .build();
273
274 virtualProvider.removeFlowRule(VNET_ID, r1);
275
276 assertEquals("0 rules should exist", 0,
277 virtualProvider.flowRuleService.getFlowRuleCount());
278 }
279
280
281 private static class TestDeviceService extends DeviceServiceAdapter {
282 @Override
283 public int getDeviceCount() {
284 return 2;
285 }
286
287 @Override
288 public Iterable<Device> getDevices() {
289 return ImmutableList.of(DEV1, DEV2);
290 }
291
292 @Override
293 public Iterable<Device> getAvailableDevices() {
294 return getDevices();
295 }
296
297 @Override
298 public Device getDevice(DeviceId deviceId) {
299 return deviceId.equals(DID2) ? DEV2 : DEV1;
300 }
301 }
302
yoonseon322c9c32016-12-07 16:47:02 -0800303 private static class TestCoreService extends CoreServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700304
305 @Override
306 public ApplicationId registerApplication(String name) {
307 return new TestApplicationId(1, name);
308 }
309
310 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700311 public IdGenerator getIdGenerator(String topic) {
yoonseon322c9c32016-12-07 16:47:02 -0800312 return new IdGenerator() {
313 private AtomicLong counter = new AtomicLong(0);
314
315 @Override
316 public long getNewId() {
317 return counter.getAndIncrement();
318 }
319 };
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700320 }
321 }
322
323 private static class TestApplicationId extends DefaultApplicationId {
324 public TestApplicationId(int id, String name) {
325 super(id, name);
326 }
327 }
328
329 private static class TestVirtualNetworkAdminService
330 implements VirtualNetworkAdminService {
331
332 @Override
333 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
334 return null;
335 }
336
337 @Override
338 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
339 return ImmutableSet.of(VDEV);
340 }
341
342 @Override
343 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
344 return null;
345 }
346
347 @Override
348 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
349 return null;
350 }
351
352 @Override
353 public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
354 DeviceId deviceId) {
355 return ImmutableSet.of(VPORT1, VPORT2);
356 }
357
358 @Override
359 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
360 return null;
361 }
362
363 @Override
364 public ServiceDirectory getServiceDirectory() {
365 return null;
366 }
367
368 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800369 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
370 return null;
371 }
372
373 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700374 public void registerTenantId(TenantId tenantId) {
375
376 }
377
378 @Override
379 public void unregisterTenantId(TenantId tenantId) {
380
381 }
382
383 @Override
384 public Set<TenantId> getTenantIds() {
385 return null;
386 }
387
388 @Override
389 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
390 return null;
391 }
392
393 @Override
394 public void removeVirtualNetwork(NetworkId networkId) {
395
396 }
397
398 @Override
399 public VirtualDevice createVirtualDevice(NetworkId networkId,
400 DeviceId deviceId) {
401 return null;
402 }
403
404 @Override
405 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
406
407 }
408
409 @Override
410 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
411 MacAddress mac, VlanId vlan,
412 HostLocation location,
413 Set<IpAddress> ips) {
414 return null;
415 }
416
417 @Override
418 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
419
420 }
421
422 @Override
423 public VirtualLink createVirtualLink(NetworkId networkId,
424 ConnectPoint src, ConnectPoint dst) {
425 return null;
426 }
427
428 @Override
429 public void removeVirtualLink(NetworkId networkId,
430 ConnectPoint src, ConnectPoint dst) {
431
432 }
433
434 @Override
435 public VirtualPort createVirtualPort(NetworkId networkId,
436 DeviceId deviceId,
437 PortNumber portNumber,
438 ConnectPoint realizedBy) {
439 return null;
440 }
441
442 @Override
443 public void bindVirtualPort(NetworkId networkId,
444 DeviceId deviceId,
445 PortNumber portNumber,
446 ConnectPoint realizedBy) {
447
448 }
449
450 @Override
451 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
452 PortNumber portNumber) {
453
454 }
455 }
456
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -0800457 private static class TestTopologyService extends TopologyServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700458
459 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700460 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
461 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
462 100, ANNOTATIONS);
463 return ImmutableSet.of(path);
464 }
465
466 @Override
467 public Set<Path> getPaths(Topology topology, DeviceId src,
468 DeviceId dst, LinkWeight weight) {
469 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
470 100, ANNOTATIONS);
471 return ImmutableSet.of(path);
472 }
473
474 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800475 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
476 LinkWeigher weigher) {
477 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
478 100, ANNOTATIONS);
479 return ImmutableSet.of(path);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700480 }
481
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700482 }
483
yoonseon322c9c32016-12-07 16:47:02 -0800484 private static class TestFlowRuleService extends FlowRuleServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700485 static Set<FlowRule> ruleCollection = new HashSet<>();
486
487 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700488 public int getFlowRuleCount() {
489 return ruleCollection.size();
490 }
491
492 @Override
493 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
494 return ruleCollection.stream()
495 .filter(r -> r.deviceId().equals(deviceId))
496 .map(r -> new DefaultFlowEntry(r))
497 .collect(Collectors.toSet());
498 }
499
500 @Override
501 public void applyFlowRules(FlowRule... flowRules) {
502 for (FlowRule rule : flowRules) {
503 ruleCollection.add(rule);
504 }
505 }
506
507 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700508 public void removeFlowRules(FlowRule... flowRules) {
509 Set<FlowRule> candidates = new HashSet<>();
510 for (FlowRule rule : flowRules) {
511 ruleCollection.stream()
512 .filter(r -> r.exactMatch(rule))
513 .forEach(candidates::add);
514 }
515 ruleCollection.removeAll(candidates);
516 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700517 }
518}