tom

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

......@@ -9,7 +9,7 @@ import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.flow.Instructions;
import org.onlab.onos.net.flow.instructions.Instructions;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.packet.InboundPacket;
import org.onlab.onos.net.packet.PacketContext;
......
......@@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.onlab.onos.net.flow.instructions.Instruction;
import org.slf4j.Logger;
@SuppressWarnings("rawtypes")
......
......@@ -2,6 +2,8 @@ package org.onlab.onos.net.flow;
import java.util.List;
import org.onlab.onos.net.flow.instructions.Instruction;
/**
* Abstraction of network traffic treatment.
*/
......
package org.onlab.onos.net.flow;
package org.onlab.onos.net.flow.instructions;
/**
* Abstraction of a single traffic treatment step.
......
package org.onlab.onos.net.flow;
package org.onlab.onos.net.flow.instructions;
import static com.google.common.base.Preconditions.checkNotNull;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.SubType;
import org.onlab.packet.MACAddress;
/**
* Factory class for creating various traffic treatment instructions.
*/
public final class Instructions {
// Ban construction
private Instructions() {}
......@@ -23,12 +27,52 @@ public final class Instructions {
return new OutputInstruction(number);
}
// TODO: Move these out into separate classes and to flow.instruction package
/**
* Creates a drop instruction.
* @return drop instruction
*/
public static DropInstruction createDrop() {
return new DropInstruction();
}
// TODO: add create methods
/**
* Creates a l2 src modification.
* @param addr the mac address to modify to.
* @return a l2 modification
*/
public static L2ModificationInstruction modL2Src(MACAddress addr) {
checkNotNull(addr, "Src l2 address cannot be null");
return new ModEtherInstruction(SubType.L2_SRC, addr);
}
/**
* Creates a L2 dst modification.
* @param addr the mac address to modify to.
* @return a L2 modification
*/
public static L2ModificationInstruction modL2Dst(MACAddress addr) {
checkNotNull(addr, "Dst l2 address cannot be null");
return new L2ModificationInstruction.ModEtherInstruction(SubType.L2_DST, addr);
}
/**
* Creates a L2 type modification.
* @param l2Type the type to change to
* @return a L2 modifications
*/
public static L2ModificationInstruction modL2Type(Short l2Type) {
checkNotNull(l2Type, "L2 type cannot be null");
return new L2ModificationInstruction.ModEtherTypeInstruction(l2Type);
}
public static L2ModificationInstruction modVlanId(Short vlanId) {
checkNotNull(vlanId, "VLAN id cannot be null");
return new L2ModificationInstruction.ModVlanIdInstruction(vlanId);
}
/*
* Output instructions
*/
public static final class DropInstruction implements Instruction {
@Override
......
package org.onlab.onos.net.flow.instructions;
import org.onlab.packet.MACAddress;
/**
* Abstraction of a single traffic treatment step.
* @param <T> the type parameter for the instruction
*/
public abstract class L2ModificationInstruction implements Instruction {
/**
* Represents the type of traffic treatment.
*/
public enum SubType {
/**
* Ether src modification.
*/
L2_SRC,
/**
* Ether dst modification.
*/
L2_DST,
/**
* Ethertype modification.
*/
L2_TYPE,
/**
* VLAN id modification.
*/
VLAN_ID,
/**
* VLAN priority modification.
*/
VLAN_PCP
}
// TODO: Create factory class 'Instructions' that will have various factory
// to create specific instructions.
/**
* Returns the subtype of the modification instruction.
* @return type of instruction
*/
public abstract SubType subtype();
@Override
public Type type() {
return Type.MODIFICATION;
}
/**
* Represents a L2 src/dst modification instruction.
*/
public static final class ModEtherInstruction extends L2ModificationInstruction {
private final SubType subtype;
private final MACAddress mac;
public ModEtherInstruction(SubType subType, MACAddress addr) {
this.subtype = subType;
this.mac = addr;
}
@Override
public SubType subtype() {
return this.subtype;
}
public MACAddress mac() {
return this.mac;
}
}
/**
* Represents a L2 type modification instruction.
*/
public static final class ModEtherTypeInstruction extends L2ModificationInstruction {
public final short l2Type;
public ModEtherTypeInstruction(short l2Type) {
this.l2Type = l2Type;
}
@Override
public SubType subtype() {
return SubType.L2_TYPE;
}
public short l2Type() {
return this.l2Type;
}
}
/**
* Represents a VLAN id modification instruction.
*/
public static final class ModVlanIdInstruction extends L2ModificationInstruction {
public final Short vlanId;
public ModVlanIdInstruction(Short vlanId) {
this.vlanId = vlanId;
}
@Override
public SubType subtype() {
return SubType.VLAN_ID;
}
public Short vlanId() {
return this.vlanId;
}
}
}
......@@ -59,7 +59,7 @@ public class DefaultTopologyProviderTest {
private void validateSubmission() {
assertNotNull("registration expected", providerService);
assertEquals("incorrect providert", provider, providerService.provider());
assertEquals("incorrect provider", provider, providerService.provider());
assertNotNull("topo change should be submitted", providerService.graphDesc);
assertEquals("incorrect vertex count", 6, providerService.graphDesc.vertexes().size());
assertEquals("incorrect edge count", 10, providerService.graphDesc.edges().size());
......
......@@ -77,6 +77,11 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
this.dpid = dp;
}
public AbstractOpenFlowSwitch(Dpid dpid, OFDescStatsReply desc) {
this.dpid = dpid;
this.desc = desc;
}
//************************
// Channel related
//************************
......
......@@ -11,6 +11,7 @@ import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriverFactory;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -57,7 +58,7 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory {
log.warn("DriverManager could not identify switch desc: {}. "
+ "Assigning AbstractOpenFlowSwich", desc);
return new AbstractOpenFlowSwitch(dpid) {
return new AbstractOpenFlowSwitch(dpid, desc) {
@Override
public void write(List<OFMessage> msgs) {
......@@ -85,6 +86,15 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory {
public boolean isDriverHandshakeComplete() {
return true;
}
@Override
public List<OFPortDesc> getPorts() {
if (this.factory().getVersion() == OFVersion.OF_10) {
return Collections.unmodifiableList(features.getPorts());
} else {
return Collections.unmodifiableList(ports.getEntries());
}
}
};
}
......
package org.onlab.onos.provider.of.host.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
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.HostId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.host.HostDescription;
import org.onlab.onos.net.host.HostProvider;
import org.onlab.onos.net.host.HostProviderRegistry;
import org.onlab.onos.net.host.HostProviderService;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.ClusterId;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.Topology;
import org.onlab.onos.net.topology.TopologyCluster;
import org.onlab.onos.net.topology.TopologyGraph;
import org.onlab.onos.net.topology.TopologyListener;
import org.onlab.onos.net.topology.TopologyService;
import org.onlab.onos.of.controller.Dpid;
import org.onlab.onos.of.controller.OpenFlowController;
import org.onlab.onos.of.controller.OpenFlowPacketContext;
import org.onlab.onos.of.controller.OpenFlowSwitch;
import org.onlab.onos.of.controller.OpenFlowSwitchListener;
import org.onlab.onos.of.controller.PacketListener;
import org.onlab.onos.of.controller.RoleState;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MACAddress;
import org.onlab.packet.VLANID;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.types.OFPort;
public class OpenFlowHostProviderTest {
private static final Integer INPORT = 10;
private static final Dpid DPID1 = new Dpid(100);
private static final Dpid DPID2 = new Dpid(200);
private static final Dpid DPID3 = new Dpid(300);
private static final VLANID VLAN = VLANID.vlanId();
private static final MACAddress MAC = MACAddress.valueOf("00:00:11:00:00:01");
private static final MACAddress BCMAC = MACAddress.valueOf("ff:ff:ff:ff:ff:ff");
private static byte [] IP = new byte [] { 10,0,0,1 };
private OpenFlowHostProvider provider = new OpenFlowHostProvider();
private TestHostRegistry hostService = new TestHostRegistry();
private TestController controller = new TestController();
private TestTopologyService topoService = new TestTopologyService();
private TestHostProviderService providerService;
@Before
public void setUp() {
provider.providerRegistry = hostService;
provider.controller = controller;
provider.topologyService = topoService;
provider.activate();
}
@Test
public void basics() {
assertNotNull("registration expected", providerService);
assertEquals("incorrect provider", provider, providerService.provider());
}
@Test
public void events() {
// new host
controller.processPacket(DPID1, null);
assertNotNull("new host expected", providerService.added);
assertNull("host motion unexpected", providerService.moved);
// the host moved to new switch
controller.processPacket(DPID2, null);
assertNotNull("host motion expected", providerService.moved);
// the host was misheard on a spine
controller.processPacket(DPID3, null);
assertNull("host misheard on spine switch", providerService.spine);
}
@After
public void tearDown() {
provider.deactivate();
provider.providerRegistry = null;
provider.controller = null;
}
private class TestHostRegistry implements HostProviderRegistry {
@Override
public HostProviderService register(HostProvider provider) {
providerService = new TestHostProviderService(provider);
return providerService;
}
@Override
public void unregister(HostProvider provider) {
}
@Override
public Set<ProviderId> getProviders() {
return null;
}
}
private class TestHostProviderService
extends AbstractProviderService<HostProvider>
implements HostProviderService {
Dpid added = null;
Dpid moved = null;
Dpid spine = null;
protected TestHostProviderService(HostProvider provider) {
super(provider);
}
@Override
public void hostDetected(HostId hostId, HostDescription hostDescription) {
Dpid descr = Dpid.dpid(hostDescription.location().deviceId().uri());
if (added == null) {
added = descr;
} else if ((moved == null) && !descr.equals(added)) {
moved = descr;
} else {
spine = descr;
}
}
@Override
public void hostVanished(HostId hostId) {
}
}
private class TestController implements OpenFlowController {
PacketListener pktListener;
@Override
public Iterable<OpenFlowSwitch> getSwitches() {
return null;
}
@Override
public Iterable<OpenFlowSwitch> getMasterSwitches() {
return null;
}
@Override
public Iterable<OpenFlowSwitch> getEqualSwitches() {
return null;
}
@Override
public OpenFlowSwitch getSwitch(Dpid dpid) {
return null;
}
@Override
public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
return null;
}
@Override
public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
return null;
}
@Override
public void addListener(OpenFlowSwitchListener listener) {
}
@Override
public void removeListener(OpenFlowSwitchListener listener) {
}
@Override
public void addPacketListener(int priority, PacketListener listener) {
pktListener = listener;
}
@Override
public void removePacketListener(PacketListener listener) {
}
@Override
public void write(Dpid dpid, OFMessage msg) {
}
@Override
public void processPacket(Dpid dpid, OFMessage msg) {
OpenFlowPacketContext ctx =
new TestPacketContext(dpid);
pktListener.handlePacket(ctx);
}
@Override
public void setRole(Dpid dpid, RoleState role) {
}
}
private class TestTopologyService implements TopologyService {
@Override
public Topology currentTopology() {
return null;
}
@Override
public boolean isLatest(Topology topology) {
return false;
}
@Override
public TopologyGraph getGraph(Topology topology) {
return null;
}
@Override
public Set<TopologyCluster> getClusters(Topology topology) {
return null;
}
@Override
public TopologyCluster getCluster(Topology topology, ClusterId clusterId) {
return null;
}
@Override
public Set<DeviceId> getClusterDevices(Topology topology,
TopologyCluster cluster) {
return null;
}
@Override
public Set<Link> getClusterLinks(Topology topology,
TopologyCluster cluster) {
return null;
}
@Override
public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
return null;
}
@Override
public Set<Path> getPaths(Topology topology, DeviceId src,
DeviceId dst, LinkWeight weight) {
return null;
}
@Override
public boolean isInfrastructure(Topology topology,
ConnectPoint connectPoint) {
//simulate DPID3 as an infrastructure switch
if (Dpid.dpid(connectPoint.deviceId().uri()).equals(DPID3)) {
return true;
}
return false;
}
@Override
public boolean isBroadcastPoint(Topology topology,
ConnectPoint connectPoint) {
return false;
}
@Override
public void addListener(TopologyListener listener) {
}
@Override
public void removeListener(TopologyListener listener) {
}
}
private class TestPacketContext implements OpenFlowPacketContext {
protected Dpid swid;
public TestPacketContext(Dpid dpid) {
swid = dpid;
}
@Override
public boolean blocked() {
return false;
}
@Override
public void send() {
}
@Override
public void build(OFPort outPort) {
}
@Override
public void build(Ethernet ethFrame, OFPort outPort) {
}
@Override
public Ethernet parsed() {
// just things we (and serializers) need
ARP arp = new ARP();
arp.setSenderProtocolAddress(IP)
.setSenderHardwareAddress(MAC.toBytes())
.setTargetHardwareAddress(BCMAC.toBytes())
.setTargetProtocolAddress(IP);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_ARP)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC.toBytes())
.setDestinationMACAddress(BCMAC.getAddress())
.setPayload(arp);
return eth;
}
@Override
public byte[] unparsed() {
return null;
}
@Override
public Dpid dpid() {
return swid;
}
@Override
public Integer inPort() {
return INPORT;
}
}
}
......@@ -5,9 +5,9 @@ import static org.slf4j.LoggerFactory.getLogger;
import java.util.List;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.flow.Instruction;
import org.onlab.onos.net.flow.Instruction.Type;
import org.onlab.onos.net.flow.Instructions.OutputInstruction;
import org.onlab.onos.net.flow.instructions.Instruction;
import org.onlab.onos.net.flow.instructions.Instruction.Type;
import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
import org.onlab.onos.net.packet.DefaultPacketContext;
import org.onlab.onos.net.packet.InboundPacket;
import org.onlab.onos.net.packet.OutboundPacket;
......