blob: 94bc091d3655ee9cb562dd5444961654c7d86ced [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;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070024import org.onosproject.core.ApplicationId;
yoonseon322c9c32016-12-07 16:47:02 -080025import org.onosproject.core.CoreServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070026import org.onosproject.core.DefaultApplicationId;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070027import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
28import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
29import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
30import org.onosproject.incubator.net.virtual.NetworkId;
31import org.onosproject.incubator.net.virtual.TenantId;
32import org.onosproject.incubator.net.virtual.VirtualDevice;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070033import org.onosproject.incubator.net.virtual.VirtualLink;
34import org.onosproject.incubator.net.virtual.VirtualNetwork;
Yoonseon Hanffcc32f2017-05-03 14:42:17 -070035import org.onosproject.incubator.net.virtual.VirtualNetworkAdminServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070036import org.onosproject.incubator.net.virtual.VirtualPort;
37import org.onosproject.net.ConnectPoint;
38import org.onosproject.net.DefaultAnnotations;
39import org.onosproject.net.DefaultDevice;
40import org.onosproject.net.DefaultLink;
41import org.onosproject.net.DefaultPath;
42import org.onosproject.net.DefaultPort;
43import org.onosproject.net.Device;
44import org.onosproject.net.DeviceId;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070045import org.onosproject.net.Link;
46import org.onosproject.net.Path;
47import org.onosproject.net.Port;
48import org.onosproject.net.PortNumber;
49import org.onosproject.net.device.DeviceServiceAdapter;
50import org.onosproject.net.flow.DefaultFlowEntry;
51import org.onosproject.net.flow.DefaultFlowRule;
52import org.onosproject.net.flow.DefaultTrafficSelector;
53import org.onosproject.net.flow.DefaultTrafficTreatment;
54import org.onosproject.net.flow.FlowEntry;
55import org.onosproject.net.flow.FlowRule;
yoonseon322c9c32016-12-07 16:47:02 -080056import org.onosproject.net.flow.FlowRuleServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070057import org.onosproject.net.flow.TrafficSelector;
58import org.onosproject.net.flow.TrafficTreatment;
59import org.onosproject.net.flow.instructions.Instruction;
60import org.onosproject.net.flow.instructions.L2ModificationInstruction;
61import org.onosproject.net.provider.ProviderId;
yoonseon322c9c32016-12-07 16:47:02 -080062import org.onosproject.net.topology.LinkWeigher;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070063import org.onosproject.net.topology.LinkWeight;
64import org.onosproject.net.topology.Topology;
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -080065import org.onosproject.net.topology.TopologyServiceAdapter;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070066
Yoonseon Hanc8089db2017-03-22 20:22:12 +090067import java.util.Arrays;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070068import java.util.HashSet;
Yoonseon Hanc70b4e02016-10-20 15:24:33 -070069import java.util.Set;
70import java.util.stream.Collectors;
71
72import static org.junit.Assert.assertEquals;
73
74public class DefaultVirtualFlowRuleProviderTest {
75 private static final ProviderId PID = new ProviderId("of", "foo");
76
77 private static final DeviceId DID1 = DeviceId.deviceId("of:001");
78 private static final DeviceId DID2 = DeviceId.deviceId("of:002");
79 private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
80 private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);
81
82 private static final DefaultAnnotations ANNOTATIONS =
83 DefaultAnnotations.builder().set("foo", "bar").build();
84
85 private static final Device DEV1 =
86 new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
87 private static final Device DEV2 =
88 new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
89 private static final Port PORT11 =
90 new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
91 private static final Port PORT12 =
92 new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
93 private static final Port PORT21 =
94 new DefaultPort(DEV2, PORT_NUM1, true, ANNOTATIONS);
95 private static final Port PORT22 =
96 new DefaultPort(DEV2, PORT_NUM2, true, ANNOTATIONS);
97
98 private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
99 private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
100 private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM1);
101 private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM2);
102 private static final Link LINK1 = DefaultLink.builder()
103 .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();
104
105 private static final NetworkId VNET_ID = NetworkId.networkId(1);
106 private static final DeviceId VDID = DeviceId.deviceId("of:100");
107
108 private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
109 VNET_ID, TenantId.tenantId("t1"));
110 private static final VirtualDevice VDEV =
111 new DefaultVirtualDevice(VNET_ID, VDID);
112 private static final VirtualPort VPORT1 =
113 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM1, CP11);
114 private static final VirtualPort VPORT2 =
115 new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM2, CP22);
116
117 private static final int TIMEOUT = 10;
118
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700119 protected DefaultVirtualFlowRuleProvider virtualProvider;
120
121 private ApplicationId vAppId;
122
123 @Before
124 public void setUp() {
125 virtualProvider = new DefaultVirtualFlowRuleProvider();
126
127 virtualProvider.deviceService = new TestDeviceService();
128 virtualProvider.coreService = new TestCoreService();
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900129 virtualProvider.vnService =
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700130 new TestVirtualNetworkAdminService();
131 virtualProvider.topologyService = new TestTopologyService();
132 virtualProvider.flowRuleService = new TestFlowRuleService();
133 virtualProvider.providerRegistryService = new VirtualProviderManager();
134
135 virtualProvider.activate();
136 vAppId = new TestApplicationId(0, "Virtual App");
137 }
138
139 @After
140 public void tearDown() {
141 virtualProvider.deactivate();
142 virtualProvider.deviceService = null;
143 virtualProvider.coreService = null;
144 }
145
146 @Test
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900147 public void devirtualizeFlowRuleWithInPort() {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700148 TrafficSelector ts = DefaultTrafficSelector.builder()
149 .matchInPort(PORT_NUM1).build();
150 TrafficTreatment tr = DefaultTrafficTreatment.builder()
151 .setOutput(PORT_NUM2).build();
152
153 FlowRule r1 = DefaultFlowRule.builder()
154 .forDevice(VDID)
155 .withSelector(ts)
156 .withTreatment(tr)
157 .withPriority(10)
158 .fromApp(vAppId)
159 .makeTemporary(TIMEOUT)
160 .build();
161
162 virtualProvider.applyFlowRule(VNET_ID, r1);
163
164 assertEquals("2 rules should exist", 2,
165 virtualProvider.flowRuleService.getFlowRuleCount());
166
167 Set<FlowEntry> phyRules = new HashSet<>();
168 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
169 phyRules.add(i);
170 }
171 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
172 phyRules.add(i);
173 }
174
175 FlowRule in = null;
176 FlowRule out = null;
177
178 for (FlowRule rule : phyRules) {
179
180 L2ModificationInstruction i = (L2ModificationInstruction)
181 rule.treatment().allInstructions().get(0);
182
183 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
184 in = rule;
185 } else {
186 out = rule;
187 }
188
189 }
190
191 assertEquals(DID1, in.deviceId());
192 assertEquals(DID2, out.deviceId());
193 }
194
195 @Test
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900196 public void devirtualizeFlowRuleWithoutInPort() {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700197 TrafficSelector ts = DefaultTrafficSelector.builder().build();
198 TrafficTreatment tr = DefaultTrafficTreatment.builder()
199 .setOutput(PORT_NUM2).build();
200
201 FlowRule r1 = DefaultFlowRule.builder()
202 .forDevice(VDID)
203 .withSelector(ts)
204 .withTreatment(tr)
205 .withPriority(10)
206 .fromApp(vAppId)
207 .makeTemporary(TIMEOUT)
208 .build();
209
210 virtualProvider.applyFlowRule(VNET_ID, r1);
211
212 assertEquals("3 rules should exist", 3,
213 virtualProvider.flowRuleService.getFlowRuleCount());
214
215 FlowRule inFromDID1 = null;
216 FlowRule inFromDID2 = null;
217 FlowRule out = null;
218
219 Set<FlowEntry> phyRules = new HashSet<>();
220 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
221 phyRules.add(i);
222 }
223 for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
224 phyRules.add(i);
225 }
226
227 for (FlowRule rule : phyRules) {
228 for (Instruction inst : rule.treatment().allInstructions()) {
229 if (inst.type() == Instruction.Type.L2MODIFICATION) {
230 L2ModificationInstruction i = (L2ModificationInstruction) inst;
231 if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
232 inFromDID1 = rule;
233 break;
234 } else {
235 out = rule;
236 break;
237 }
238 } else {
239 inFromDID2 = rule;
240 break;
241 }
242 }
243 }
244
245 assertEquals(DID1, inFromDID1.deviceId());
246 assertEquals(DID2, inFromDID2.deviceId());
247 assertEquals(DID2, out.deviceId());
248 }
249
250 @Test
251 public void removeVirtualizeFlowRule() {
252 TrafficSelector ts = DefaultTrafficSelector.builder().build();
253 TrafficTreatment tr = DefaultTrafficTreatment.builder()
254 .setOutput(PORT_NUM2).build();
255
256 FlowRule r1 = DefaultFlowRule.builder()
257 .forDevice(VDID)
258 .withSelector(ts)
259 .withTreatment(tr)
260 .withPriority(10)
261 .fromApp(vAppId)
262 .makeTemporary(TIMEOUT)
263 .build();
264
265 virtualProvider.removeFlowRule(VNET_ID, r1);
266
267 assertEquals("0 rules should exist", 0,
268 virtualProvider.flowRuleService.getFlowRuleCount());
269 }
270
271
272 private static class TestDeviceService extends DeviceServiceAdapter {
273 @Override
274 public int getDeviceCount() {
275 return 2;
276 }
277
278 @Override
279 public Iterable<Device> getDevices() {
280 return ImmutableList.of(DEV1, DEV2);
281 }
282
283 @Override
284 public Iterable<Device> getAvailableDevices() {
285 return getDevices();
286 }
287
288 @Override
289 public Device getDevice(DeviceId deviceId) {
290 return deviceId.equals(DID2) ? DEV2 : DEV1;
291 }
292 }
293
yoonseon322c9c32016-12-07 16:47:02 -0800294 private static class TestCoreService extends CoreServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700295
296 @Override
297 public ApplicationId registerApplication(String name) {
298 return new TestApplicationId(1, name);
299 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700300 }
301
302 private static class TestApplicationId extends DefaultApplicationId {
303 public TestApplicationId(int id, String name) {
304 super(id, name);
305 }
306 }
307
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900308 private class TestVirtualNetworkAdminService
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700309 extends VirtualNetworkAdminServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700310
311 @Override
312 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
313 return ImmutableSet.of(VDEV);
314 }
315
316 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700317 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
Harold Huang7362e672017-04-19 10:00:11 +0800318 return new HashSet<>();
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700319 }
320
321 @Override
322 public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
323 DeviceId deviceId) {
324 return ImmutableSet.of(VPORT1, VPORT2);
325 }
326
327 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800328 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900329 return vAppId;
yoonseon322c9c32016-12-07 16:47:02 -0800330 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700331 }
332
Yuta HIGUCHI03c234e2017-01-23 17:21:34 -0800333 private static class TestTopologyService extends TopologyServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700334
335 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700336 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
337 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
338 100, ANNOTATIONS);
339 return ImmutableSet.of(path);
340 }
341
342 @Override
343 public Set<Path> getPaths(Topology topology, DeviceId src,
344 DeviceId dst, LinkWeight weight) {
345 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
346 100, ANNOTATIONS);
347 return ImmutableSet.of(path);
348 }
349
350 @Override
yoonseon322c9c32016-12-07 16:47:02 -0800351 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
352 LinkWeigher weigher) {
353 DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
354 100, ANNOTATIONS);
355 return ImmutableSet.of(path);
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700356 }
357
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700358 }
359
yoonseon322c9c32016-12-07 16:47:02 -0800360 private static class TestFlowRuleService extends FlowRuleServiceAdapter {
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700361 static Set<FlowRule> ruleCollection = new HashSet<>();
362
363 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700364 public int getFlowRuleCount() {
365 return ruleCollection.size();
366 }
367
368 @Override
369 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
370 return ruleCollection.stream()
371 .filter(r -> r.deviceId().equals(deviceId))
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900372 .map(DefaultFlowEntry::new)
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700373 .collect(Collectors.toSet());
374 }
375
376 @Override
377 public void applyFlowRules(FlowRule... flowRules) {
Yoonseon Hanc8089db2017-03-22 20:22:12 +0900378 ruleCollection.addAll(Arrays.asList(flowRules));
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700379 }
380
381 @Override
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700382 public void removeFlowRules(FlowRule... flowRules) {
383 Set<FlowRule> candidates = new HashSet<>();
384 for (FlowRule rule : flowRules) {
385 ruleCollection.stream()
386 .filter(r -> r.exactMatch(rule))
387 .forEach(candidates::add);
388 }
389 ruleCollection.removeAll(candidates);
390 }
Yoonseon Hanc70b4e02016-10-20 15:24:33 -0700391 }
392}