link provider tests
Change-Id: I074d067a1432c874fa0e1674423df046d4c31086
diff --git a/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java b/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
new file mode 100644
index 0000000..7fca158
--- /dev/null
+++ b/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
@@ -0,0 +1,471 @@
+package org.onlab.onos.provider.of.link.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.link.LinkDescription;
+import org.onlab.onos.net.link.LinkProvider;
+import org.onlab.onos.net.link.LinkProviderRegistry;
+import org.onlab.onos.net.link.LinkProviderService;
+import org.onlab.onos.net.provider.AbstractProviderService;
+import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.openflow.controller.Dpid;
+import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
+import org.onlab.onos.openflow.controller.OpenFlowSwitch;
+import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
+import org.onlab.onos.openflow.controller.OpenflowControllerAdapter;
+import org.onlab.onos.openflow.controller.PacketListener;
+import org.onlab.onos.openflow.controller.RoleState;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.ONLabLddp;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortConfig;
+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 com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class OpenFlowLinkProviderTest {
+
+
+ private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
+ private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
+
+ private static final Dpid DPID2 = Dpid.dpid(DID2.uri());
+ private static final Dpid DPID1 = Dpid.dpid(DID1.uri());
+
+ private static final OFPortDesc PD1 = portDesc(1, true);
+ private static final OFPortDesc PD2 = portDesc(2, true);
+ private static final OFPortDesc PD3 = portDesc(1, true);
+ private static final OFPortDesc PD4 = portDesc(2, true);
+
+ private static final List<OFPortDesc> PLIST1 = Lists.newArrayList(PD1, PD2);
+ private static final List<OFPortDesc> PLIST2 = Lists.newArrayList(PD3, PD4);
+
+ private static final TestOpenFlowSwitch SW1 = new TestOpenFlowSwitch(DPID1, PLIST1);
+ private static final TestOpenFlowSwitch SW2 = new TestOpenFlowSwitch(DPID2, PLIST2);
+
+ private final OpenFlowLinkProvider provider = new OpenFlowLinkProvider();
+ private final TestLinkRegistry linkService = new TestLinkRegistry();
+ private final TestController controller = new TestController();
+
+ private TestLinkProviderService providerService;
+ private TestPacketContext pktCtx;
+
+ @Before
+ public void setUp() {
+ pktCtx = new TestPacketContext(DPID2);
+ provider.providerRegistry = linkService;
+ controller.switchMap.put(DPID1, SW1);
+ controller.switchMap.put(DPID2, SW2);
+ provider.controller = controller;
+ provider.activate();
+ }
+
+ @Test
+ public void basics() {
+ assertNotNull("registration expected", providerService);
+ assertEquals("incorrect provider", provider, providerService.provider());
+ }
+
+ @Test
+ public void switchAdd() {
+ controller.listener.switchAdded(DPID1);
+ assertFalse("Device not added", provider.discoverers.isEmpty());
+ }
+
+ @Test
+ public void switchRemove() {
+ controller.listener.switchAdded(DPID1);
+ controller.listener.switchRemoved(DPID1);
+
+ assertTrue("Discoverer is not gone", provider.discoverers.isEmpty());
+ assertTrue("Device is not gone.", vanishedDpid(DPID1));
+ }
+
+ @Test
+ public void portUp() {
+ controller.listener.switchAdded(DPID1);
+ controller.listener.portChanged(DPID1, portStatus(true, 3));
+
+ assertTrue("Port not added to discoverer",
+ provider.discoverers.get(DPID1).ports.containsKey(3));
+ }
+
+ @Test
+ public void portDown() {
+ controller.listener.switchAdded(DPID1);
+ controller.listener.portChanged(DPID1, portStatus(false, 1));
+
+ assertFalse("Port added to discoverer",
+ provider.discoverers.get(DPID1).ports.containsKey(1));
+ assertTrue("Port is not gone.", vanishedPort((long) 1));
+ }
+
+ @Test
+ public void portUnknown() {
+ controller.listener.switchAdded(DPID1);
+ controller.listener.portChanged(DPID2, portStatus(false, 1));
+
+ assertNull("DPID exists",
+ provider.discoverers.get(DPID2));
+ }
+
+ @Test
+ public void unknownPktCtx() {
+ controller.pktListener.handlePacket(pktCtx);
+
+ assertFalse("Context should still be free", pktCtx.isHandled());
+ }
+
+ @Test
+ public void knownPktCtx() {
+ controller.listener.switchAdded(DPID1);
+ controller.listener.switchAdded(DPID2);
+
+ controller.pktListener.handlePacket(pktCtx);
+
+ assertTrue("Link not detected", detectedLink(DPID1, DPID2));
+
+ }
+
+
+ @After
+ public void tearDown() {
+ provider.deactivate();
+ provider.providerRegistry = null;
+ provider.controller = null;
+ }
+
+ private OFPortStatus portStatus(boolean up, int port) {
+ OFPortDesc desc = portDesc(port, up);
+ OFPortStatus status = OFFactoryVer10.INSTANCE.buildPortStatus()
+ .setDesc(desc)
+ .setReason(up ? OFPortReason.ADD : OFPortReason.DELETE).build();
+ return status;
+
+ }
+
+ private static OFPortDesc portDesc(int port, boolean up) {
+ OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
+ builder.setPortNo(OFPort.of(port));
+ if (!up) {
+ builder.setConfig(Collections.singleton(OFPortConfig.PORT_DOWN));
+ }
+ return builder.build();
+ }
+
+ private boolean vanishedDpid(Dpid... dpids) {
+ for (int i = 0; i < dpids.length; i++) {
+ if (!providerService.vanishedDpid.contains(dpids[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean vanishedPort(Long... ports) {
+ for (int i = 0; i < ports.length; i++) {
+ if (!providerService.vanishedPort.contains(ports[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean detectedLink(Dpid src, Dpid dst) {
+ for (Dpid key : providerService.discoveredLinks.keySet()) {
+ if (key.equals(src)) {
+ return providerService.discoveredLinks.get(src).equals(dst);
+ }
+ }
+ return false;
+ }
+
+
+ private class TestLinkRegistry implements LinkProviderRegistry {
+
+ @Override
+ public LinkProviderService register(LinkProvider provider) {
+ providerService = new TestLinkProviderService(provider);
+ return providerService;
+ }
+
+ @Override
+ public void unregister(LinkProvider provider) {
+ }
+
+ @Override
+ public Set<ProviderId> getProviders() {
+ return null;
+ }
+
+ }
+
+ private class TestLinkProviderService
+ extends AbstractProviderService<LinkProvider>
+ implements LinkProviderService {
+
+ List<Dpid> vanishedDpid = Lists.newLinkedList();
+ List<Long> vanishedPort = Lists.newLinkedList();
+ Map<Dpid, Dpid> discoveredLinks = Maps.newHashMap();
+
+ protected TestLinkProviderService(LinkProvider provider) {
+ super(provider);
+ }
+
+ @Override
+ public void linkDetected(LinkDescription linkDescription) {
+ Dpid sDpid = Dpid.dpid(linkDescription.src().deviceId().uri());
+ Dpid dDpid = Dpid.dpid(linkDescription.dst().deviceId().uri());
+ discoveredLinks.put(sDpid, dDpid);
+ }
+
+ @Override
+ public void linkVanished(LinkDescription linkDescription) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void linksVanished(ConnectPoint connectPoint) {
+ vanishedPort.add(connectPoint.port().toLong());
+
+ }
+
+ @Override
+ public void linksVanished(DeviceId deviceId) {
+ vanishedDpid.add(Dpid.dpid(deviceId.uri()));
+ }
+
+
+ }
+
+ private class TestController extends OpenflowControllerAdapter {
+ PacketListener pktListener;
+ OpenFlowSwitchListener listener;
+ Map<Dpid, OpenFlowSwitch> switchMap = new HashMap<Dpid, OpenFlowSwitch>();
+
+ @Override
+ public void addPacketListener(int priority, PacketListener listener) {
+ pktListener = listener;
+ }
+
+ @Override
+ public void removePacketListener(PacketListener listener) {
+ pktListener = null;
+ }
+
+ @Override
+ public void addListener(OpenFlowSwitchListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void removeListener(OpenFlowSwitchListener listener) {
+ this.listener = null;
+ }
+
+ @Override
+ public void processPacket(Dpid dpid, OFMessage msg) {
+ OpenFlowPacketContext ctx = new TestPacketContext(dpid);
+ pktListener.handlePacket(ctx);
+ }
+
+ @Override
+ public Iterable<OpenFlowSwitch> getSwitches() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public OpenFlowSwitch getSwitch(Dpid dpid) {
+ return switchMap.get(dpid);
+ }
+ }
+
+
+
+ private class TestPacketContext implements OpenFlowPacketContext {
+
+ protected Dpid swid;
+ protected boolean blocked = false;
+
+ public TestPacketContext(Dpid dpid) {
+ swid = dpid;
+ }
+
+ @Override
+ public boolean block() {
+ blocked = true;
+ return blocked;
+ }
+
+ @Override
+ public void send() {
+ }
+
+ @Override
+ public void build(OFPort outPort) {
+ }
+
+ @Override
+ public void build(Ethernet ethFrame, OFPort outPort) {
+ }
+
+ @Override
+ public Ethernet parsed() {
+ return null;
+ }
+
+ @Override
+ public byte[] unparsed() {
+ ONLabLddp lldp = new ONLabLddp();
+ lldp.setSwitch(DPID1.value());
+
+ Ethernet ethPacket = new Ethernet();
+ ethPacket.setEtherType(Ethernet.TYPE_LLDP);
+ ethPacket.setDestinationMACAddress(ONLabLddp.LLDP_NICIRA);
+ ethPacket.setPayload(lldp);
+ ethPacket.setPad(true);
+
+
+ lldp.setPort(PD1.getPortNo().getPortNumber());
+ ethPacket.setSourceMACAddress(PD1.getHwAddr().getBytes());
+ return ethPacket.serialize();
+
+ }
+
+ @Override
+ public Dpid dpid() {
+ return swid;
+ }
+
+ @Override
+ public Integer inPort() {
+ return PD3.getPortNo().getPortNumber();
+ }
+
+ @Override
+ public boolean isHandled() {
+ return blocked;
+ }
+
+ @Override
+ public boolean isBuffered() {
+ return false;
+ }
+
+ }
+
+ private static class TestOpenFlowSwitch implements OpenFlowSwitch {
+
+ private final List<OFPortDesc> ports;
+ private final Dpid dpid;
+
+ public TestOpenFlowSwitch(Dpid dpid, List<OFPortDesc> ports) {
+ this.ports = ports;
+ this.dpid = dpid;
+ }
+
+ 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 ports;
+ }
+
+ @Override
+ public OFFactory factory() {
+ return factory;
+ }
+
+ @Override
+ public String getStringId() {
+ return null;
+ }
+
+ @Override
+ public long getId() {
+ return dpid.value();
+ }
+
+ @Override
+ public String manfacturerDescription() {
+ 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 void disconnectSwitch() {
+ }
+
+ @Override
+ public void returnRoleAssertFailure(RoleState role) {
+ }
+
+ }
+}