blob: b6b9808f30cde015513910b2c77e10b11f26e8a3 [file] [log] [blame]
kishoredb79dc02016-03-07 16:24:55 +05301/*
2 * Copyright 2015 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 */
16package org.onosproject.routing.impl;
17
18import static org.easymock.EasyMock.createMock;
19import static org.easymock.EasyMock.expect;
20import static org.easymock.EasyMock.expectLastCall;
21import static org.easymock.EasyMock.replay;
22import static org.easymock.EasyMock.verify;
23import static org.slf4j.LoggerFactory.getLogger;
24
25import java.util.ArrayList;
26import java.util.Collections;
27import java.util.List;
28import java.util.Objects;
29import java.util.Set;
30
31import org.easymock.EasyMock;
32import org.junit.Before;
33import org.junit.Test;
34import org.onlab.packet.EthType;
35import org.onlab.packet.Ip4Address;
36import org.onlab.packet.IpAddress;
37import org.onlab.packet.IpPrefix;
38import org.onlab.packet.MacAddress;
39import org.onlab.packet.VlanId;
40import org.onosproject.core.ApplicationId;
41import org.onosproject.core.CoreService;
42import org.onosproject.core.CoreServiceAdapter;
43import org.onosproject.incubator.net.intf.Interface;
44import org.onosproject.incubator.net.intf.InterfaceService;
45import org.onosproject.mastership.MastershipService;
46import org.onosproject.mastership.MastershipServiceAdapter;
47import org.onosproject.net.ConnectPoint;
48import org.onosproject.net.Device;
49import org.onosproject.net.DeviceId;
50import org.onosproject.net.NetTestTools;
51import org.onosproject.net.PortNumber;
52import org.onosproject.net.config.Config;
53import org.onosproject.net.config.NetworkConfigEvent;
54import org.onosproject.net.config.NetworkConfigEvent.Type;
55import org.onosproject.net.config.NetworkConfigListener;
56import org.onosproject.net.config.NetworkConfigService;
57import org.onosproject.net.config.NetworkConfigServiceAdapter;
58import org.onosproject.net.device.DeviceEvent;
59import org.onosproject.net.device.DeviceListener;
60import org.onosproject.net.device.DeviceService;
61import org.onosproject.net.device.DeviceServiceAdapter;
62import org.onosproject.net.flow.DefaultTrafficSelector;
63import org.onosproject.net.flow.DefaultTrafficTreatment;
64import org.onosproject.net.flow.TrafficSelector;
65import org.onosproject.net.flow.TrafficTreatment;
66import org.onosproject.net.flowobjective.DefaultForwardingObjective;
67import org.onosproject.net.flowobjective.DefaultNextObjective;
68import org.onosproject.net.flowobjective.FlowObjectiveService;
69import org.onosproject.net.flowobjective.ForwardingObjective;
70import org.onosproject.net.flowobjective.NextObjective;
71import org.onosproject.net.host.HostListener;
72import org.onosproject.net.host.HostService;
73import org.onosproject.net.host.HostServiceAdapter;
74import org.onosproject.net.host.InterfaceIpAddress;
75import org.onosproject.net.intent.AbstractIntentTest;
76import org.onosproject.routing.RoutingService;
77import org.onosproject.routing.config.RouterConfig;
78import org.slf4j.Logger;
79
80import com.google.common.collect.Sets;
81
82/**
83 * UnitTests for ControlPlaneRedirectManager.
84 */
85public class ControlPlaneRedirectManagerTest extends AbstractIntentTest {
86
87 private final Logger log = getLogger(getClass());
88
89 private DeviceService deviceService;
90 private FlowObjectiveService flowObjectiveService;
91 private NetworkConfigService networkConfigService;
92 private final Set<Interface> interfaces = Sets.newHashSet();
93 static Device dev3 = NetTestTools.device("0000000000000001");
94 private static final int OSPF_IP_PROTO = 0x59;
95 private CoreService coreService = new TestCoreService();
96 private InterfaceService interfaceService;
97 private static final ApplicationId APPID = TestApplicationId.create("org.onosproject.cpredirect");
98
99 /**
100 * Interface Configuration.
101 *
102 **/
103 private ConnectPoint controlPlaneConnectPoint = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
104 PortNumber.portNumber(1));
105 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
106 PortNumber.portNumber(1));
107
108 private static final ConnectPoint SW1_ETH2 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
109 PortNumber.portNumber(2));
110
111 private static final ConnectPoint SW1_ETH3 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
112 PortNumber.portNumber(3));
113 protected HostService hostService;
114
115 private ControlPlaneRedirectManager controlPlaneRedirectManager = new ControlPlaneRedirectManager();;
116 private RouterConfig routerConfig = new TestRouterConfig();
117 private NetworkConfigListener networkConfigListener;
118 private DeviceListener deviceListener;
119 private MastershipService mastershipService = new InternalMastershipServiceTest();
120 private HostListener hostListener;
121
122 /**
123 * @throws java.lang.Exception
124 */
125 @Override
126 @Before
127 public void setUp() throws Exception {
128 super.setUp();
129 interfaceService = createMock(InterfaceService.class);
130 networkConfigListener = createMock(NetworkConfigListener.class);
131 hostService = new TestHostService();
132 deviceService = new TestDeviceService();
133 deviceListener = createMock(DeviceListener.class);
134 hostListener = createMock(HostListener.class);
135 hostService.addListener(hostListener);
136 deviceService.addListener(deviceListener);
137 setUpInterfaceService();
138 networkConfigService = new TestNetworkConfigService();
139 networkConfigService.addListener(networkConfigListener);
140 flowObjectiveService = createMock(FlowObjectiveService.class);
141 setUpFlowObjectiveService();
142
143 controlPlaneRedirectManager.coreService = coreService;
144 controlPlaneRedirectManager.flowObjectiveService = flowObjectiveService;
145 controlPlaneRedirectManager.networkConfigService = networkConfigService;
146 controlPlaneRedirectManager.interfaceService = interfaceService;
147 controlPlaneRedirectManager.deviceService = deviceService;
148 controlPlaneRedirectManager.hostService = hostService;
149 controlPlaneRedirectManager.mastershipService = mastershipService;
150 controlPlaneRedirectManager.activate();
151 verify(flowObjectiveService);
152 }
153 /**
154 * setup flow Configuration for all configured Interfaces.
155 *
156 **/
157 private void setUpFlowObjectiveService() {
158
159 expect(flowObjectiveService.allocateNextId()).andReturn(1).anyTimes();
160 DeviceId deviceId = controlPlaneConnectPoint.deviceId();
161 PortNumber controlPlanePort = controlPlaneConnectPoint.port();
162 int cpNextId, intfNextId;
163 for (Interface intf : interfaceService.getInterfaces()) {
164 for (InterfaceIpAddress ip : intf.ipAddresses()) {
165 if (intf.vlan() == VlanId.NONE) {
166 // cpNextId = 1;
167 // intfNextId = 1;
168 cpNextId = createNextObjective(deviceId, controlPlanePort,
169 VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), true);
170 intfNextId = createNextObjective(deviceId, intf.connectPoint().port(),
171 VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), true);
172 } else {
173 // cpNextId = 1;
174 // intfNextId = 1;
175
176 cpNextId = createNextObjective(deviceId, controlPlanePort, intf.vlan(), false);
177 intfNextId = createNextObjective(deviceId, intf.connectPoint().port(), intf.vlan(), false);
178 }
179 TrafficSelector toSelector = DefaultTrafficSelector.builder().matchInPort(intf.connectPoint().port())
180 .matchEthDst(intf.mac()).matchEthType(EthType.EtherType.IPV4.ethType().toShort())
181 .matchVlanId(intf.vlan()).matchIPDst(ip.ipAddress().toIpPrefix()).build();
182 flowObjectiveService.forward(deviceId, buildForwardingObjective(toSelector, null, cpNextId, true));
183 expectLastCall().once();
184 // IPv4 from router
185 TrafficSelector fromSelector = DefaultTrafficSelector.builder().matchInPort(controlPlanePort)
186 .matchEthSrc(intf.mac()).matchVlanId(intf.vlan())
187 .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
188 .matchIPSrc(ip.ipAddress().toIpPrefix()).build();
189 flowObjectiveService.forward(deviceId, buildForwardingObjective(fromSelector, null, intfNextId, true));
190 expectLastCall().once();
191 // ARP to router
192 toSelector = DefaultTrafficSelector.builder().matchInPort(intf.connectPoint().port())
193 .matchEthType(EthType.EtherType.ARP.ethType().toShort()).matchVlanId(intf.vlan()).build();
194
195 TrafficTreatment puntTreatment = DefaultTrafficTreatment.builder().punt().build();
196 flowObjectiveService.forward(deviceId,
197 buildForwardingObjective(toSelector, puntTreatment, cpNextId, true));
198 expectLastCall().once();
199 // ARP from router
200 fromSelector = DefaultTrafficSelector.builder().matchInPort(controlPlanePort).matchEthSrc(intf.mac())
201 .matchVlanId(intf.vlan()).matchEthType(EthType.EtherType.ARP.ethType().toShort())
202 .matchArpSpa(ip.ipAddress().getIp4Address()).build();
203 flowObjectiveService.forward(deviceId,
204 buildForwardingObjective(fromSelector, puntTreatment, intfNextId, true));
205 expectLastCall().once();
206
207 }
208 updateOspfForwarding(intf);
209 }
210
211 replay(flowObjectiveService);
212 }
213
214 /**
215 * setup expectations on flowobjectService.forward for ospfForwarding.
216 *
217 **/
218 private void updateOspfForwarding(Interface intf) {
219 // OSPF to router
220 TrafficSelector toSelector = DefaultTrafficSelector.builder().matchInPort(intf.connectPoint().port())
221 .matchEthType(EthType.EtherType.IPV4.ethType().toShort()).matchVlanId(intf.vlan())
222 .matchIPProtocol((byte) OSPF_IP_PROTO).build();
223
224 PortNumber controlPlanePort = controlPlaneConnectPoint.port();
225 DeviceId deviceId = controlPlaneConnectPoint.deviceId();
226 int cpNextId;
227 if (intf.vlan() == VlanId.NONE) {
228 cpNextId = createNextObjective(deviceId, controlPlanePort,
229 VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), true);
230 } else {
231 cpNextId = createNextObjective(deviceId, controlPlanePort, intf.vlan(), false);
232 }
233 log.debug("ospf flows intf:{} nextid:{}", intf, cpNextId);
234 flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(),
235 buildForwardingObjective(toSelector, null, cpNextId, true));
236 expectLastCall().once();
237 }
238
239 /**
240 * setup expectations on flowObjectiveService.next for NextObjective.
241 *
242 **/
243 private int createNextObjective(DeviceId deviceId, PortNumber portNumber, VlanId vlanId, boolean popVlan) {
244
245 NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder().withId(1)
246 .withType(NextObjective.Type.SIMPLE).fromApp(APPID);
247
248 TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
249 if (popVlan) {
250 ttBuilder.popVlan();
251 }
252 ttBuilder.setOutput(portNumber);
253
254 // setup metadata to pass to nextObjective - indicate the vlan on egress
255 // if needed by the switch pipeline.
256 TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
257 metabuilder.matchVlanId(vlanId);
258
259 nextObjBuilder.withMeta(metabuilder.build());
260 nextObjBuilder.addTreatment(ttBuilder.build());
261 log.debug("Submited next objective {} in device {} for port/vlan {}/{}", 1, deviceId, portNumber, vlanId);
262 flowObjectiveService.next(deviceId, nextObjBuilder.add());
263 expectLastCall().once();
264 return 1;
265 }
266
267 /**
268 * setup Interface expectation for all Testcases.
269 *
270 **/
271 private void setUpInterfaceService() {
272
273 Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
274 interfaceIpAddresses1
275 .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"), IpPrefix.valueOf("192.168.10.0/24")));
276 Interface sw1Eth1 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH1, interfaceIpAddresses1,
277 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE);
278 interfaces.add(sw1Eth1);
279
280 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
281 interfaceIpAddresses2
282 .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"), IpPrefix.valueOf("192.168.20.0/24")));
283 Interface sw1Eth2 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH2, interfaceIpAddresses2,
284 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE);
285 interfaces.add(sw1Eth2);
286
287 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
288 interfaceIpAddresses3
289 .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"), IpPrefix.valueOf("192.168.30.0/24")));
290 Interface sw1Eth3 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH3, interfaceIpAddresses3,
291 MacAddress.valueOf("00:00:00:00:00:03"), VlanId.NONE);
292 interfaces.add(sw1Eth3);
293
294 expect(interfaceService.getInterfacesByPort(SW1_ETH1)).andReturn(Collections.singleton(sw1Eth1)).anyTimes();
295 expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.10.1"))).andReturn(sw1Eth1).anyTimes();
296 expect(interfaceService.getInterfacesByPort(SW1_ETH2)).andReturn(Collections.singleton(sw1Eth2)).anyTimes();
297 expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.20.1"))).andReturn(sw1Eth2).anyTimes();
298
299 expect(interfaceService.getInterfacesByPort(SW1_ETH3)).andReturn(Collections.singleton(sw1Eth3)).anyTimes();
300 expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.30.1"))).andReturn(sw1Eth3).anyTimes();
301 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
302 replay(interfaceService);
303 interfaceService.getInterfaces();
304 verify(interfaceService);
305 }
306
307 /**
308 * Tests adding new Device to a controlplane.
309 *
310 * @throws SecurityException
311 * @throws NoSuchFieldException
312 * @throws IllegalAccessException
313 * @throws IllegalArgumentException
314 */
315
316 @Test
317 public void testAddDevice()
318 throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
319
320 ConnectPoint sw1eth4 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(4));
321 Set<InterfaceIpAddress> interfaceIpAddresses4 = Sets.newHashSet();
322 interfaceIpAddresses4
323 .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24")));
324
325 Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses4,
326 MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
327 interfaces.add(sw1Eth4);
328 EasyMock.reset(interfaceService);
329 expect(interfaceService.getInterfacesByPort(sw1eth4)).andReturn(Collections.singleton(sw1Eth4)).anyTimes();
330 expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.40.1"))).andReturn(sw1Eth4).anyTimes();
331 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
332 replay(interfaceService);
333 interfaceService.getInterfaces();
334 EasyMock.reset(flowObjectiveService);
335 setUpFlowObjectiveService();
336 deviceListener.event(new DeviceEvent(DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED, dev3));
337 deviceService.addListener(deviceListener);
338
339 verify(flowObjectiveService);
340 }
341
342 /**
343 * Tests adding while updating the networkConfig.
344 *
345 * @throws SecurityException
346 * @throws NoSuchFieldException
347 * @throws IllegalAccessException
348 * @throws IllegalArgumentException
349 */
350 @Test
351 public void testUpdateNetworkConfig()
352 throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
353
354 ConnectPoint sw1eth4 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(4));
355 Set<InterfaceIpAddress> interfaceIpAddresses4 = Sets.newHashSet();
356 interfaceIpAddresses4
357 .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24")));
358
359 Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses4,
360 MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
361 interfaces.add(sw1Eth4);
362 EasyMock.reset(interfaceService);
363 expect(interfaceService.getInterfacesByPort(sw1eth4)).andReturn(Collections.singleton(sw1Eth4)).anyTimes();
364 expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.40.1"))).andReturn(sw1Eth4).anyTimes();
365 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
366 replay(interfaceService);
367 interfaceService.getInterfaces();
368 EasyMock.reset(flowObjectiveService);
369 setUpFlowObjectiveService();
370 networkConfigListener
371 .event(new NetworkConfigEvent(Type.CONFIG_UPDATED, dev3, RoutingService.ROUTER_CONFIG_CLASS));
372 // deviceService.addListener(deviceListener);
373 networkConfigService.addListener(networkConfigListener);
374 verify(flowObjectiveService);
375 }
376
377
378 private ForwardingObjective buildForwardingObjective(TrafficSelector selector, TrafficTreatment treatment,
379 int nextId, boolean add) {
380 DefaultForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder();
381 fobBuilder.withSelector(selector);
382 if (treatment != null) {
383 fobBuilder.withTreatment(treatment);
384 }
385 if (nextId != -1) {
386 fobBuilder.nextStep(nextId);
387 }
388 fobBuilder.fromApp(APPID).withPriority(40001).withFlag(ForwardingObjective.Flag.VERSATILE);
389
390 return add ? fobBuilder.add() : fobBuilder.remove();
391 }
392
393 /**
394 * @param intf
395 */
396
397 private class TestCoreService extends CoreServiceAdapter {
398 @Override
399 public ApplicationId getAppId(String name) {
400 return APPID;
401 }
402
403 @Override
404 public ApplicationId registerApplication(String name) {
405 // TODO Auto-generated method stub
406 return new TestApplicationId(name);
407 }
408
409 }
410
411 private class TestDeviceService extends DeviceServiceAdapter {
412
413 @Override
414 public boolean isAvailable(DeviceId deviceId) {
415 // TODO Auto-generated method stub
416 boolean flag = false;
417 if (deviceId.equals(controlPlaneConnectPoint.deviceId())) {
418 flag = true;
419 }
420 return flag;
421 }
422
423 @Override
424 public void addListener(DeviceListener listener) {
425 // TODO Auto-generated method stub
426 ControlPlaneRedirectManagerTest.this.deviceListener = listener;
427 }
428
429 }
430
431 private class TestHostService extends HostServiceAdapter {
432
433 @Override
434 public void addListener(HostListener listener) {
435 // TODO Auto-generated method stub
436 ControlPlaneRedirectManagerTest.this.hostListener = listener;
437 }
438
439 }
440
441 private class TestRouterConfig extends RouterConfig {
442
443 @Override
444 public ConnectPoint getControlPlaneConnectPoint() {
445 // TODO Auto-generated method stub
446 return controlPlaneConnectPoint;
447 }
448
449 @Override
450 public boolean getOspfEnabled() {
451 // TODO Auto-generated method stub
452 return true;
453 }
454
455 @Override
456 public List<String> getInterfaces() {
457 // TODO Auto-generated method stub
458
459 ArrayList<String> interfaces = new ArrayList<>();
460 interfaces.add("of:0000000000000001");
461 interfaces.add("of:0000000000000001/2");
462 interfaces.add("of:0000000000000001/3");
463 return interfaces;
464 }
465
466 }
467
468 private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
469
470 @Override
471 public void addListener(NetworkConfigListener listener) {
472 // TODO Auto-generated method stub
473 ControlPlaneRedirectManagerTest.this.networkConfigListener = listener;
474 }
475
476 @Override
477 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
478 // TODO Auto-generated method stub
479
480 return (C) ControlPlaneRedirectManagerTest.this.routerConfig;
481 }
482
483 }
484
485 private static class TestApplicationId implements ApplicationId {
486
487 private final String name;
488 private final short id;
489
490 public TestApplicationId(String name) {
491 this.name = name;
492 this.id = (short) Objects.hash(name);
493 }
494
495 public static ApplicationId create(String name) {
496 return new TestApplicationId(name);
497 }
498
499 @Override
500 public short id() {
501 return id;
502 }
503
504 @Override
505 public String name() {
506 return name;
507 }
508
509 @Override
510 public int hashCode() {
511 final int prime = 31;
512 int result = 1;
513 result = prime * result + id;
514 result = prime * result + ((name == null) ? 0 : name.hashCode());
515 return result;
516 }
517
518 @Override
519 public boolean equals(Object obj) {
520 if (this == obj) {
521 return true;
522 }
523 if (obj == null) {
524 return false;
525 }
526 if (getClass() != obj.getClass()) {
527 return false;
528 }
529 TestApplicationId other = (TestApplicationId) obj;
530 if (id != other.id) {
531 return false;
532 }
533 if (name == null) {
534 if (other.name != null) {
535 return false;
536 }
537 } else if (!name.equals(other.name)) {
538 return false;
539 }
540 return true;
541 }
542 }
543
544 private class InternalMastershipServiceTest extends MastershipServiceAdapter {
545
546 @Override
547 public boolean isLocalMaster(DeviceId deviceId) {
548 // TODO Auto-generated method stub
549 boolean flag = deviceId.equals(controlPlaneConnectPoint.deviceId());
550 return flag;
551 }
552
553 }
554}