blob: 8e11e6fe72f8b3e6e9a397628966ed1779a9ae95 [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;
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080033import org.onosproject.net.TenantId;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070034import 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.Topology;
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -080066import org.onosproject.net.topology.TopologyServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070067
Yoonseon Hanc8089db2017-03-22 20:22:12 +090068import java.util.Arrays;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070069import java.util.HashSet;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070070import java.util.Set;
71import java.util.stream.Collectors;
72
73import static org.junit.Assert.assertEquals;
74
75public class DefaultVirtualFlowRuleProviderTest {
76 private static final ProviderId PID = new ProviderId("of", "foo");
77
78 private static final DeviceId DID1 = DeviceId.deviceId("of:001");
79 private static final DeviceId DID2 = DeviceId.deviceId("of:002");
80 private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
81 private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);
82
83 private static final DefaultAnnotations ANNOTATIONS =
84 DefaultAnnotations.builder().set("foo", "bar").build();
85
86 private static final Device DEV1 =
87 new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
88 private static final Device DEV2 =
89 new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
90 private static final Port PORT11 =
91 new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
92 private static final Port PORT12 =
93 new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
94 private static final Port PORT21 =
95 new DefaultPort(DEV2, PORT_NUM1, true, ANNOTATIONS);
96 private static final Port PORT22 =
97 new DefaultPort(DEV2, PORT_NUM2, true, ANNOTATIONS);
98
99 private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
100 private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
101 private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM1);
102 private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM2);
103 private static final Link LINK1 = DefaultLink.builder()
104 .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();
105
106 private static final NetworkId VNET_ID = NetworkId.networkId(1);
107 private static final DeviceId VDID = DeviceId.deviceId("of:100");
108
109 private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
110 VNET_ID, TenantId.tenantId("t1"));
111 private static final VirtualDevice VDEV =
112 new DefaultVirtualDevice(VNET_ID, VDID);
113 private static final VirtualPort VPORT1 =
114 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM1, CP11);
115 private static final VirtualPort VPORT2 =
116 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM2, CP22);
117
118 private static final int TIMEOUT = 10;
119
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700120 protected DefaultVirtualFlowRuleProvider virtualProvider;
121
122 private ApplicationId vAppId;
123
124 @Before
125 public void setUp() {
126 virtualProvider = new DefaultVirtualFlowRuleProvider();
127
128 virtualProvider.deviceService = new TestDeviceService();
129 virtualProvider.coreService = new TestCoreService();
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900130 virtualProvider.vnService =
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700131 new TestVirtualNetworkAdminService();
132 virtualProvider.topologyService = new TestTopologyService();
133 virtualProvider.flowRuleService = new TestFlowRuleService();
134 virtualProvider.providerRegistryService = new VirtualProviderManager();
135
136 virtualProvider.activate();
137 vAppId = new TestApplicationId(0, "Virtual App");
138 }
139
140 @After
141 public void tearDown() {
142 virtualProvider.deactivate();
143 virtualProvider.deviceService = null;
144 virtualProvider.coreService = null;
145 }
146
147 @Test
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900148 public void devirtualizeFlowRuleWithInPort() {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700149 TrafficSelector ts = DefaultTrafficSelector.builder()
150 .matchInPort(PORT_NUM1).build();
151 TrafficTreatment tr = DefaultTrafficTreatment.builder()
152 .setOutput(PORT_NUM2).build();
153
154 FlowRule r1 = DefaultFlowRule.builder()
155 .forDevice(VDID)
156 .withSelector(ts)
157 .withTreatment(tr)
158 .withPriority(10)
159 .fromApp(vAppId)
160 .makeTemporary(TIMEOUT)
161 .build();
162
163 virtualProvider.applyFlowRule(VNET_ID, r1);
164
165 assertEquals("2 rules should exist", 2,
166 virtualProvider.flowRuleService.getFlowRuleCount());
167
168 Set<FlowEntry> phyRules = new HashSet<>();
169 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
170 phyRules.add(i);
171 }
172 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
173 phyRules.add(i);
174 }
175
176 FlowRule in = null;
177 FlowRule out = null;
178
179 for (FlowRule rule : phyRules) {
180
181 L2ModificationInstruction i = (L2ModificationInstruction)
182 rule.treatment().allInstructions().get(0);
183
184 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
185 in = rule;
186 } else {
187 out = rule;
188 }
189
190 }
191
192 assertEquals(DID1, in.deviceId());
193 assertEquals(DID2, out.deviceId());
194 }
195
196 @Test
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900197 public void devirtualizeFlowRuleWithoutInPort() {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700198 TrafficSelector ts = DefaultTrafficSelector.builder().build();
199 TrafficTreatment tr = DefaultTrafficTreatment.builder()
200 .setOutput(PORT_NUM2).build();
201
202 FlowRule r1 = DefaultFlowRule.builder()
203 .forDevice(VDID)
204 .withSelector(ts)
205 .withTreatment(tr)
206 .withPriority(10)
207 .fromApp(vAppId)
208 .makeTemporary(TIMEOUT)
209 .build();
210
211 virtualProvider.applyFlowRule(VNET_ID, r1);
212
213 assertEquals("3 rules should exist", 3,
214 virtualProvider.flowRuleService.getFlowRuleCount());
215
216 FlowRule inFromDID1 = null;
217 FlowRule inFromDID2 = null;
218 FlowRule out = null;
219
220 Set<FlowEntry> phyRules = new HashSet<>();
221 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
222 phyRules.add(i);
223 }
224 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
225 phyRules.add(i);
226 }
227
228 for (FlowRule rule : phyRules) {
229 for (Instruction inst : rule.treatment().allInstructions()) {
230 if (inst.type() == Instruction.Type.L2MODIFICATION) {
231 L2ModificationInstruction i = (L2ModificationInstruction) inst;
232 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
233 inFromDID1 = rule;
234 break;
235 } else {
236 out = rule;
237 break;
238 }
239 } else {
240 inFromDID2 = rule;
241 break;
242 }
243 }
244 }
245
246 assertEquals(DID1, inFromDID1.deviceId());
247 assertEquals(DID2, inFromDID2.deviceId());
248 assertEquals(DID2, out.deviceId());
249 }
250
251 @Test
252 public void removeVirtualizeFlowRule() {
253 TrafficSelector ts = DefaultTrafficSelector.builder().build();
254 TrafficTreatment tr = DefaultTrafficTreatment.builder()
255 .setOutput(PORT_NUM2).build();
256
257 FlowRule r1 = DefaultFlowRule.builder()
258 .forDevice(VDID)
259 .withSelector(ts)
260 .withTreatment(tr)
261 .withPriority(10)
262 .fromApp(vAppId)
263 .makeTemporary(TIMEOUT)
264 .build();
265
266 virtualProvider.removeFlowRule(VNET_ID, r1);
267
268 assertEquals("0 rules should exist", 0,
269 virtualProvider.flowRuleService.getFlowRuleCount());
270 }
271
272
273 private static class TestDeviceService extends DeviceServiceAdapter {
274 @Override
275 public int getDeviceCount() {
276 return 2;
277 }
278
279 @Override
280 public Iterable<Device> getDevices() {
281 return ImmutableList.of(DEV1, DEV2);
282 }
283
284 @Override
285 public Iterable<Device> getAvailableDevices() {
286 return getDevices();
287 }
288
289 @Override
290 public Device getDevice(DeviceId deviceId) {
291 return deviceId.equals(DID2) ? DEV2 : DEV1;
292 }
293 }
294
yoonseon322c9c32016-12-07 16:47:02 -0800295 private static class TestCoreService extends CoreServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700296
297 @Override
298 public ApplicationId registerApplication(String name) {
299 return new TestApplicationId(1, name);
300 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700301 }
302
303 private static class TestApplicationId extends DefaultApplicationId {
304 public TestApplicationId(int id, String name) {
305 super(id, name);
306 }
307 }
308
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900309 private class TestVirtualNetworkAdminService
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700310 extends VirtualNetworkAdminServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700311
312 @Override
313 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
314 return ImmutableSet.of(VDEV);
315 }
316
317 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700318 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
Harold Huang7362e672017-04-19 10:00:11 +0800319 return new HashSet<>();
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700320 }
321
322 @Override
323 public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
324 DeviceId deviceId) {
325 return ImmutableSet.of(VPORT1, VPORT2);
326 }
327
328 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800329 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900330 return vAppId;
yoonseon322c9c32016-12-07 16:47:02 -0800331 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700332 }
333
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -0800334 private static class TestTopologyService extends TopologyServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700335
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800336 Weight oneHundred = ScalarWeight.toWeight(100);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700337 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700338 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
339 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800340 oneHundred, ANNOTATIONS);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700341 return ImmutableSet.of(path);
342 }
343
344 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800345 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
346 LinkWeigher weigher) {
347 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800348 oneHundred, ANNOTATIONS);
yoonseon322c9c32016-12-07 16:47:02 -0800349 return ImmutableSet.of(path);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700350 }
351
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700352 }
353
yoonseon322c9c32016-12-07 16:47:02 -0800354 private static class TestFlowRuleService extends FlowRuleServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700355 static Set<FlowRule> ruleCollection = new HashSet<>();
356
357 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700358 public int getFlowRuleCount() {
359 return ruleCollection.size();
360 }
361
362 @Override
363 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
364 return ruleCollection.stream()
365 .filter(r -> r.deviceId().equals(deviceId))
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900366 .map(DefaultFlowEntry::new)
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700367 .collect(Collectors.toSet());
368 }
369
370 @Override
371 public void applyFlowRules(FlowRule... flowRules) {
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900372 ruleCollection.addAll(Arrays.asList(flowRules));
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700373 }
374
375 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700376 public void removeFlowRules(FlowRule... flowRules) {
377 Set<FlowRule> candidates = new HashSet<>();
378 for (FlowRule rule : flowRules) {
379 ruleCollection.stream()
380 .filter(r -> r.exactMatch(rule))
381 .forEach(candidates::add);
382 }
383 ruleCollection.removeAll(candidates);
384 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700385 }
386}