blob: 91c92ff2b278924fc10c6ba28bb8a3574799eb33 [file] [log] [blame]
/*
* Copyright 2014-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.provider.of.device.impl;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.driver.DriverServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.OpenFlowClassifierListener;
import org.onosproject.openflow.controller.OpenFlowController;
import org.onosproject.openflow.controller.OpenFlowEventListener;
import org.onosproject.openflow.controller.OpenFlowMessageListener;
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitchListener;
import org.onosproject.openflow.controller.PacketListener;
import org.onosproject.openflow.controller.RoleState;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortReason;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
import org.projectfloodlight.openflow.types.OFPort;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import static org.junit.Assert.*;
import static org.onosproject.net.Device.Type.SWITCH;
import static org.onosproject.net.MastershipRole.*;
public class OpenFlowDeviceProviderTest {
private static final ProviderId PID = new ProviderId("of", "test");
private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
private static final Dpid DPID1 = Dpid.dpid(DID1.uri());
private static final OFPortDesc PD1 = portDesc(1);
private static final OFPortDesc PD2 = portDesc(2);
private static final OFPortDesc PD3 = portDesc(3);
private static final List<OFPortDesc> PLIST = Lists.newArrayList(PD1, PD2);
private static final Device DEV1 =
new DefaultDevice(PID, DID1, SWITCH, "", "", "", "", null);
private static final TestOpenFlowSwitch SW1 = new TestOpenFlowSwitch();
private final OpenFlowDeviceProvider provider = new OpenFlowDeviceProvider();
private final TestDeviceRegistry registry = new TestDeviceRegistry();
private final TestController controller = new TestController();
@Before
public void startUp() {
provider.providerRegistry = registry;
provider.controller = controller;
provider.cfgService = new ComponentConfigAdapter();
provider.driverService = new DriverServiceAdapter();
provider.deviceService = new DeviceServiceAdapter();
controller.switchMap.put(DPID1, SW1);
provider.activate(null);
assertNotNull("provider should be registered", registry.provider);
assertNotNull("listener should be registered", controller.listener);
assertEquals("devices not added", 1, registry.connected.size());
assertEquals("ports not added", 2, registry.ports.get(DID1).size());
}
@After
public void tearDown() {
provider.deactivate(null);
assertNull("listener should be removed", controller.listener);
provider.controller = null;
provider.providerRegistry = null;
}
@Test
public void roleChanged() {
provider.roleChanged(DID1, MASTER);
assertEquals("Should be MASTER", RoleState.MASTER, controller.roleMap.get(DPID1));
provider.roleChanged(DID1, STANDBY);
assertEquals("Should be EQUAL", RoleState.EQUAL, controller.roleMap.get(DPID1));
provider.roleChanged(DID1, NONE);
assertEquals("Should be SLAVE", RoleState.SLAVE, controller.roleMap.get(DPID1));
}
//sending a features req, msg will be added to sent
@Test
public void triggerProbe() {
int cur = SW1.sent.size();
provider.triggerProbe(DID1);
assertEquals("OF message not sent", cur + 1, SW1.sent.size());
}
//test receiving features reply
@Test
public void switchChanged() {
controller.listener.switchChanged(DPID1);
Collection<PortDescription> updatedDescr = registry.ports.values();
for (PortDescription pd : updatedDescr) {
assertNotNull("Switch change not handled by the provider service", pd);
}
}
@Test
public void switchRemoved() {
controller.listener.switchRemoved(DPID1);
assertTrue("device not removed", registry.connected.isEmpty());
}
@Test
public void portChanged() {
OFPortStatus stat = SW1.factory().buildPortStatus()
.setReason(OFPortReason.ADD)
.setDesc(PD3)
.build();
controller.listener.portChanged(DPID1, stat);
assertNotNull("never went throught the provider service", registry.descr);
assertEquals("port status unhandled", 3, registry.ports.get(DID1).size());
}
@Test
public void receivedRoleReply() {
// check translation capabilities
controller.listener.receivedRoleReply(DPID1, RoleState.MASTER, RoleState.MASTER);
assertEquals("wrong role reported", DPID1, registry.roles.get(MASTER));
controller.listener.receivedRoleReply(DPID1, RoleState.EQUAL, RoleState.MASTER);
assertEquals("wrong role reported", DPID1, registry.roles.get(STANDBY));
controller.listener.receivedRoleReply(DPID1, RoleState.SLAVE, RoleState.MASTER);
assertEquals("wrong role reported", DPID1, registry.roles.get(NONE));
}
private static OFPortDesc portDesc(int port) {
OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
builder.setPortNo(OFPort.of(port));
return builder.build();
}
private class TestDeviceRegistry implements DeviceProviderRegistry {
DeviceProvider provider;
Set<DeviceId> connected = new HashSet<>();
Multimap<DeviceId, PortDescription> ports = HashMultimap.create();
PortDescription descr = null;
Map<MastershipRole, Dpid> roles = new HashMap<>();
@Override
public DeviceProviderService register(DeviceProvider provider) {
this.provider = provider;
return new TestProviderService();
}
@Override
public void unregister(DeviceProvider provider) {
}
@Override
public Set<ProviderId> getProviders() {
return null;
}
private class TestProviderService implements DeviceProviderService {
@Override
public DeviceProvider provider() {
return null;
}
@Override
public void deviceConnected(DeviceId deviceId,
DeviceDescription deviceDescription) {
connected.add(deviceId);
}
@Override
public void deviceDisconnected(DeviceId deviceId) {
connected.remove(deviceId);
ports.removeAll(deviceId);
}
@Override
public void updatePorts(DeviceId deviceId,
List<PortDescription> portDescriptions) {
for (PortDescription p : portDescriptions) {
ports.put(deviceId, p);
}
}
@Override
public void portStatusChanged(DeviceId deviceId,
PortDescription portDescription) {
ports.put(deviceId, portDescription);
descr = portDescription;
}
@Override
public void receivedRoleReply(DeviceId deviceId,
MastershipRole requested, MastershipRole response) {
roles.put(requested, Dpid.dpid(deviceId.uri()));
}
@Override
public void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics) {
}
}
}
private class TestController implements OpenFlowController {
OpenFlowSwitchListener listener = null;
Map<Dpid, RoleState> roleMap = new HashMap<Dpid, RoleState>();
Map<Dpid, OpenFlowSwitch> switchMap = new HashMap<Dpid, OpenFlowSwitch>();
@Override
public Iterable<OpenFlowSwitch> getSwitches() {
return switchMap.values();
}
@Override
public Iterable<OpenFlowSwitch> getMasterSwitches() {
return ImmutableSet.of();
}
@Override
public Iterable<OpenFlowSwitch> getEqualSwitches() {
return null;
}
@Override
public OpenFlowSwitch getSwitch(Dpid dpid) {
return switchMap.get(dpid);
}
@Override
public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
return null;
}
@Override
public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
return null;
}
@Override
public void addListener(OpenFlowSwitchListener listener) {
this.listener = listener;
}
@Override
public void removeListener(OpenFlowSwitchListener listener) {
this.listener = null;
}
@Override
public void addMessageListener(OpenFlowMessageListener listener) {
}
@Override
public void removeMessageListener(OpenFlowMessageListener listener) {
}
@Override
public void addPacketListener(int priority, PacketListener listener) {
}
@Override
public void removePacketListener(PacketListener listener) {
}
@Override
public void addEventListener(OpenFlowEventListener listener) {
}
@Override
public void removeEventListener(OpenFlowEventListener listener) {
}
@Override
public void write(Dpid dpid, OFMessage msg) {
}
@Override
public CompletableFuture<OFMessage> writeResponse(Dpid dpid, OFMessage msg) {
return null;
}
@Override
public void processPacket(Dpid dpid, OFMessage msg) {
}
@Override
public void setRole(Dpid dpid, RoleState role) {
roleMap.put(dpid, role);
}
@Override
public void removeClassifierListener(OpenFlowClassifierListener listener) {
}
@Override
public void addClassifierListener(OpenFlowClassifierListener listener) {
}
}
private static class TestOpenFlowSwitch implements OpenFlowSwitch {
RoleState state;
List<OFMessage> sent = new ArrayList<OFMessage>();
OFFactory factory = OFFactoryVer10.INSTANCE;
@Override
public void sendMsg(OFMessage msg) {
sent.add(msg);
}
@Override
public void sendMsg(List<OFMessage> msgs) {
}
@Override
public void handleMessage(OFMessage fromSwitch) {
}
@Override
public void setRole(RoleState role) {
state = role;
}
@Override
public RoleState getRole() {
return state;
}
@Override
public List<OFPortDesc> getPorts() {
return PLIST;
}
@Override
public OFMeterFeatures getMeterFeatures() {
return null;
}
@Override
public OFFactory factory() {
return factory;
}
@Override
public String getStringId() {
return null;
}
@Override
public long getId() {
return DPID1.value();
}
@Override
public String manufacturerDescription() {
return null;
}
@Override
public String datapathDescription() {
return null;
}
@Override
public String hardwareDescription() {
return null;
}
@Override
public String softwareDescription() {
return null;
}
@Override
public String serialNumber() {
return null;
}
@Override
public boolean isConnected() {
return true;
}
@Override
public void disconnectSwitch() {
}
@Override
public Device.Type deviceType() {
return Device.Type.SWITCH;
}
@Override
public void returnRoleReply(RoleState requested, RoleState response) {
}
@Override
public String channelId() {
return "1.2.3.4:1";
}
}
}