blob: 0d3c8cc678d378c6e51f6ffe1cf265d9e7ef766b [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;
Yoonseon Han33821fb2017-02-24 13:40:44 +090042import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070043import org.onosproject.incubator.net.virtual.VirtualPort;
44import org.onosproject.net.ConnectPoint;
45import org.onosproject.net.DefaultAnnotations;
46import org.onosproject.net.DefaultDevice;
47import org.onosproject.net.DefaultLink;
48import org.onosproject.net.DefaultPath;
49import org.onosproject.net.DefaultPort;
50import org.onosproject.net.Device;
51import org.onosproject.net.DeviceId;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070052import org.onosproject.net.HostId;
53import org.onosproject.net.HostLocation;
54import org.onosproject.net.Link;
55import org.onosproject.net.Path;
56import org.onosproject.net.Port;
57import org.onosproject.net.PortNumber;
58import org.onosproject.net.device.DeviceServiceAdapter;
59import org.onosproject.net.flow.DefaultFlowEntry;
60import org.onosproject.net.flow.DefaultFlowRule;
61import org.onosproject.net.flow.DefaultTrafficSelector;
62import org.onosproject.net.flow.DefaultTrafficTreatment;
63import org.onosproject.net.flow.FlowEntry;
64import org.onosproject.net.flow.FlowRule;
yoonseon322c9c32016-12-07 16:47:02 -080065import org.onosproject.net.flow.FlowRuleServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070066import org.onosproject.net.flow.TrafficSelector;
67import org.onosproject.net.flow.TrafficTreatment;
68import org.onosproject.net.flow.instructions.Instruction;
69import org.onosproject.net.flow.instructions.L2ModificationInstruction;
70import org.onosproject.net.provider.ProviderId;
yoonseon322c9c32016-12-07 16:47:02 -080071import org.onosproject.net.topology.LinkWeigher;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070072import org.onosproject.net.topology.LinkWeight;
73import org.onosproject.net.topology.Topology;
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -080074import org.onosproject.net.topology.TopologyServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070075
76import java.util.HashSet;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070077import java.util.Set;
yoonseon322c9c32016-12-07 16:47:02 -080078import java.util.concurrent.atomic.AtomicLong;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070079import java.util.stream.Collectors;
80
81import static org.junit.Assert.assertEquals;
82
83public class DefaultVirtualFlowRuleProviderTest {
84 private static final ProviderId PID = new ProviderId("of", "foo");
85
86 private static final DeviceId DID1 = DeviceId.deviceId("of:001");
87 private static final DeviceId DID2 = DeviceId.deviceId("of:002");
88 private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
89 private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);
90
91 private static final DefaultAnnotations ANNOTATIONS =
92 DefaultAnnotations.builder().set("foo", "bar").build();
93
94 private static final Device DEV1 =
95 new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
96 private static final Device DEV2 =
97 new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
98 private static final Port PORT11 =
99 new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
100 private static final Port PORT12 =
101 new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
102 private static final Port PORT21 =
103 new DefaultPort(DEV2, PORT_NUM1, true, ANNOTATIONS);
104 private static final Port PORT22 =
105 new DefaultPort(DEV2, PORT_NUM2, true, ANNOTATIONS);
106
107 private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
108 private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
109 private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM1);
110 private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM2);
111 private static final Link LINK1 = DefaultLink.builder()
112 .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();
113
114 private static final NetworkId VNET_ID = NetworkId.networkId(1);
115 private static final DeviceId VDID = DeviceId.deviceId("of:100");
116
117 private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
118 VNET_ID, TenantId.tenantId("t1"));
119 private static final VirtualDevice VDEV =
120 new DefaultVirtualDevice(VNET_ID, VDID);
121 private static final VirtualPort VPORT1 =
122 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM1, CP11);
123 private static final VirtualPort VPORT2 =
124 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM2, CP22);
125
126 private static final int TIMEOUT = 10;
127
128
129 protected DefaultVirtualFlowRuleProvider virtualProvider;
130
131 private ApplicationId vAppId;
132
133 @Before
134 public void setUp() {
135 virtualProvider = new DefaultVirtualFlowRuleProvider();
136
137 virtualProvider.deviceService = new TestDeviceService();
138 virtualProvider.coreService = new TestCoreService();
139 virtualProvider.virtualNetworkAdminService =
140 new TestVirtualNetworkAdminService();
141 virtualProvider.topologyService = new TestTopologyService();
142 virtualProvider.flowRuleService = new TestFlowRuleService();
143 virtualProvider.providerRegistryService = new VirtualProviderManager();
144
145 virtualProvider.activate();
146 vAppId = new TestApplicationId(0, "Virtual App");
147 }
148
149 @After
150 public void tearDown() {
151 virtualProvider.deactivate();
152 virtualProvider.deviceService = null;
153 virtualProvider.coreService = null;
154 }
155
156 @Test
157 public void virtualizeFlowRuleWithInPort() {
158 TrafficSelector ts = DefaultTrafficSelector.builder()
159 .matchInPort(PORT_NUM1).build();
160 TrafficTreatment tr = DefaultTrafficTreatment.builder()
161 .setOutput(PORT_NUM2).build();
162
163 FlowRule r1 = DefaultFlowRule.builder()
164 .forDevice(VDID)
165 .withSelector(ts)
166 .withTreatment(tr)
167 .withPriority(10)
168 .fromApp(vAppId)
169 .makeTemporary(TIMEOUT)
170 .build();
171
172 virtualProvider.applyFlowRule(VNET_ID, r1);
173
174 assertEquals("2 rules should exist", 2,
175 virtualProvider.flowRuleService.getFlowRuleCount());
176
177 Set<FlowEntry> phyRules = new HashSet<>();
178 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
179 phyRules.add(i);
180 }
181 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
182 phyRules.add(i);
183 }
184
185 FlowRule in = null;
186 FlowRule out = null;
187
188 for (FlowRule rule : phyRules) {
189
190 L2ModificationInstruction i = (L2ModificationInstruction)
191 rule.treatment().allInstructions().get(0);
192
193 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
194 in = rule;
195 } else {
196 out = rule;
197 }
198
199 }
200
201 assertEquals(DID1, in.deviceId());
202 assertEquals(DID2, out.deviceId());
203 }
204
205 @Test
206 public void virtualizeFlowRuleWithoutInPort() {
207 TrafficSelector ts = DefaultTrafficSelector.builder().build();
208 TrafficTreatment tr = DefaultTrafficTreatment.builder()
209 .setOutput(PORT_NUM2).build();
210
211 FlowRule r1 = DefaultFlowRule.builder()
212 .forDevice(VDID)
213 .withSelector(ts)
214 .withTreatment(tr)
215 .withPriority(10)
216 .fromApp(vAppId)
217 .makeTemporary(TIMEOUT)
218 .build();
219
220 virtualProvider.applyFlowRule(VNET_ID, r1);
221
222 assertEquals("3 rules should exist", 3,
223 virtualProvider.flowRuleService.getFlowRuleCount());
224
225 FlowRule inFromDID1 = null;
226 FlowRule inFromDID2 = null;
227 FlowRule out = null;
228
229 Set<FlowEntry> phyRules = new HashSet<>();
230 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
231 phyRules.add(i);
232 }
233 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
234 phyRules.add(i);
235 }
236
237 for (FlowRule rule : phyRules) {
238 for (Instruction inst : rule.treatment().allInstructions()) {
239 if (inst.type() == Instruction.Type.L2MODIFICATION) {
240 L2ModificationInstruction i = (L2ModificationInstruction) inst;
241 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
242 inFromDID1 = rule;
243 break;
244 } else {
245 out = rule;
246 break;
247 }
248 } else {
249 inFromDID2 = rule;
250 break;
251 }
252 }
253 }
254
255 assertEquals(DID1, inFromDID1.deviceId());
256 assertEquals(DID2, inFromDID2.deviceId());
257 assertEquals(DID2, out.deviceId());
258 }
259
260 @Test
261 public void removeVirtualizeFlowRule() {
262 TrafficSelector ts = DefaultTrafficSelector.builder().build();
263 TrafficTreatment tr = DefaultTrafficTreatment.builder()
264 .setOutput(PORT_NUM2).build();
265
266 FlowRule r1 = DefaultFlowRule.builder()
267 .forDevice(VDID)
268 .withSelector(ts)
269 .withTreatment(tr)
270 .withPriority(10)
271 .fromApp(vAppId)
272 .makeTemporary(TIMEOUT)
273 .build();
274
275 virtualProvider.removeFlowRule(VNET_ID, r1);
276
277 assertEquals("0 rules should exist", 0,
278 virtualProvider.flowRuleService.getFlowRuleCount());
279 }
280
281
282 private static class TestDeviceService extends DeviceServiceAdapter {
283 @Override
284 public int getDeviceCount() {
285 return 2;
286 }
287
288 @Override
289 public Iterable<Device> getDevices() {
290 return ImmutableList.of(DEV1, DEV2);
291 }
292
293 @Override
294 public Iterable<Device> getAvailableDevices() {
295 return getDevices();
296 }
297
298 @Override
299 public Device getDevice(DeviceId deviceId) {
300 return deviceId.equals(DID2) ? DEV2 : DEV1;
301 }
302 }
303
yoonseon322c9c32016-12-07 16:47:02 -0800304 private static class TestCoreService extends CoreServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700305
306 @Override
307 public ApplicationId registerApplication(String name) {
308 return new TestApplicationId(1, name);
309 }
310
311 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700312 public IdGenerator getIdGenerator(String topic) {
yoonseon322c9c32016-12-07 16:47:02 -0800313 return new IdGenerator() {
314 private AtomicLong counter = new AtomicLong(0);
315
316 @Override
317 public long getNewId() {
318 return counter.getAndIncrement();
319 }
320 };
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700321 }
322 }
323
324 private static class TestApplicationId extends DefaultApplicationId {
325 public TestApplicationId(int id, String name) {
326 super(id, name);
327 }
328 }
329
330 private static class TestVirtualNetworkAdminService
331 implements VirtualNetworkAdminService {
332
333 @Override
334 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
335 return null;
336 }
337
338 @Override
339 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
340 return ImmutableSet.of(VDEV);
341 }
342
343 @Override
344 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
345 return null;
346 }
347
348 @Override
349 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
350 return null;
351 }
352
353 @Override
354 public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
355 DeviceId deviceId) {
356 return ImmutableSet.of(VPORT1, VPORT2);
357 }
358
359 @Override
360 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
361 return null;
362 }
363
364 @Override
365 public ServiceDirectory getServiceDirectory() {
366 return null;
367 }
368
369 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800370 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
371 return null;
372 }
373
374 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700375 public void registerTenantId(TenantId tenantId) {
376
377 }
378
379 @Override
380 public void unregisterTenantId(TenantId tenantId) {
381
382 }
383
384 @Override
385 public Set<TenantId> getTenantIds() {
386 return null;
387 }
388
389 @Override
390 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
391 return null;
392 }
393
394 @Override
395 public void removeVirtualNetwork(NetworkId networkId) {
396
397 }
398
399 @Override
400 public VirtualDevice createVirtualDevice(NetworkId networkId,
401 DeviceId deviceId) {
402 return null;
403 }
404
405 @Override
406 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
407
408 }
409
410 @Override
411 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
412 MacAddress mac, VlanId vlan,
413 HostLocation location,
414 Set<IpAddress> ips) {
415 return null;
416 }
417
418 @Override
419 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
420
421 }
422
423 @Override
424 public VirtualLink createVirtualLink(NetworkId networkId,
425 ConnectPoint src, ConnectPoint dst) {
426 return null;
427 }
428
429 @Override
430 public void removeVirtualLink(NetworkId networkId,
431 ConnectPoint src, ConnectPoint dst) {
432
433 }
434
435 @Override
436 public VirtualPort createVirtualPort(NetworkId networkId,
437 DeviceId deviceId,
438 PortNumber portNumber,
439 ConnectPoint realizedBy) {
440 return null;
441 }
442
443 @Override
444 public void bindVirtualPort(NetworkId networkId,
445 DeviceId deviceId,
446 PortNumber portNumber,
447 ConnectPoint realizedBy) {
448
449 }
450
451 @Override
452 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
453 PortNumber portNumber) {
454
455 }
Yoonseon Han33821fb2017-02-24 13:40:44 +0900456
457 @Override
458 public void addListener(VirtualNetworkListener listener) {
459
460 }
461
462 @Override
463 public void removeListener(VirtualNetworkListener listener) {
464
465 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700466 }
467
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -0800468 private static class TestTopologyService extends TopologyServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700469
470 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700471 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
472 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
473 100, ANNOTATIONS);
474 return ImmutableSet.of(path);
475 }
476
477 @Override
478 public Set<Path> getPaths(Topology topology, DeviceId src,
479 DeviceId dst, LinkWeight weight) {
480 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
481 100, ANNOTATIONS);
482 return ImmutableSet.of(path);
483 }
484
485 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800486 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
487 LinkWeigher weigher) {
488 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
489 100, ANNOTATIONS);
490 return ImmutableSet.of(path);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700491 }
492
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700493 }
494
yoonseon322c9c32016-12-07 16:47:02 -0800495 private static class TestFlowRuleService extends FlowRuleServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700496 static Set<FlowRule> ruleCollection = new HashSet<>();
497
498 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700499 public int getFlowRuleCount() {
500 return ruleCollection.size();
501 }
502
503 @Override
504 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
505 return ruleCollection.stream()
506 .filter(r -> r.deviceId().equals(deviceId))
507 .map(r -> new DefaultFlowEntry(r))
508 .collect(Collectors.toSet());
509 }
510
511 @Override
512 public void applyFlowRules(FlowRule... flowRules) {
513 for (FlowRule rule : flowRules) {
514 ruleCollection.add(rule);
515 }
516 }
517
518 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700519 public void removeFlowRules(FlowRule... flowRules) {
520 Set<FlowRule> candidates = new HashSet<>();
521 for (FlowRule rule : flowRules) {
522 ruleCollection.stream()
523 .filter(r -> r.exactMatch(rule))
524 .forEach(candidates::add);
525 }
526 ruleCollection.removeAll(candidates);
527 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700528 }
529}