alshabib

link discovery no longer need a parsed packet

......@@ -80,4 +80,9 @@ public final class DefaultPacketContext implements PacketContext {
return pktin.getInPort().getPortNumber();
}
@Override
public byte[] unparsed() {
return pktin.getData().clone();
}
}
......
......@@ -44,6 +44,12 @@ public interface PacketContext {
public Ethernet parsed();
/**
* Provide an unparsed copy of the data.
* @return the unparsed form of the payload.
*/
public byte[] unparsed();
/**
* Provide the dpid of the switch where the packet in arrived.
* @return the dpid of the switch.
*/
......
......@@ -41,247 +41,244 @@ public class OpenFlowControllerImpl implements OpenFlowController {
new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
protected Set<OpenFlowSwitchListener> ofEventListener =
new HashSet<>();
protected List<PacketListener> ofPacketListener =
new ArrayList<>();
private final Controller ctrl = new Controller();
@Activate
public void activate() {
ctrl.start(agent);
}
@Deactivate
public void deactivate() {
ctrl.stop();
}
@Override
public Iterable<OpenFlowSwitch> getSwitches() {
return connectedSwitches.values();
}
@Override
public Iterable<OpenFlowSwitch> getMasterSwitches() {
return activeMasterSwitches.values();
}
@Override
public Iterable<OpenFlowSwitch> getEqualSwitches() {
return activeEqualSwitches.values();
}
@Override
public OpenFlowSwitch getSwitch(Dpid dpid) {
return connectedSwitches.get(dpid);
}
@Override
public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
return activeMasterSwitches.get(dpid);
}
@Override
public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
return activeEqualSwitches.get(dpid);
}
@Override
public void addListener(OpenFlowSwitchListener listener) {
if (!ofEventListener.contains(listener)) {
this.ofEventListener.add(listener);
}
}
@Override
public void removeListener(OpenFlowSwitchListener listener) {
this.ofEventListener.remove(listener);
}
@Override
public void addPacketListener(int priority, PacketListener listener) {
ofPacketListener.add(priority, listener);
}
@Override
public void removePacketListener(PacketListener listener) {
ofPacketListener.remove(listener);
}
@Override
public void write(Dpid dpid, OFMessage msg) {
this.getSwitch(dpid).sendMsg(msg);
}
@Override
public void processPacket(Dpid dpid, OFMessage msg) {
switch (msg.getType()) {
case PORT_STATUS:
for (OpenFlowSwitchListener l : ofEventListener) {
l.portChanged(dpid, (OFPortStatus) msg);
}
break;
case PACKET_IN:
for (PacketListener p : ofPacketListener) {
//TODO fix me!
p.handlePacket(DefaultPacketContext
.packetContextFromPacketIn(this.getSwitch(dpid),
(OFPacketIn) msg));
}
break;
default:
log.warn("Handling message type {} not yet implemented {}",
msg.getType(), msg);
}
}
@Override
public void setRole(Dpid dpid, RoleState role) {
getSwitch(dpid).setRole(role);
}
/**
* Implementation of an OpenFlow Agent which is responsible for
* keeping track of connected switches and the state in which
* they are.
*/
public class OpenFlowSwitchAgent implements OpenFlowAgent {
private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
private final Lock switchLock = new ReentrantLock();
@Override
public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
if (connectedSwitches.get(dpid) != null) {
log.error("Trying to add connectedSwitch but found a previous "
+ "value for dpid: {}", dpid);
return false;
} else {
log.error("Added switch {}", dpid);
connectedSwitches.put(dpid, sw);
for (OpenFlowSwitchListener l : ofEventListener) {
l.switchAdded(dpid);
}
return true;
}
}
@Override
public boolean validActivation(Dpid dpid) {
if (connectedSwitches.get(dpid) == null) {
log.error("Trying to activate switch but is not in "
+ "connected switches: dpid {}. Aborting ..",
dpid);
return false;
}
if (activeMasterSwitches.get(dpid) != null ||
activeEqualSwitches.get(dpid) != null) {
log.error("Trying to activate switch but it is already "
+ "activated: dpid {}. Found in activeMaster: {} "
+ "Found in activeEqual: {}. Aborting ..", new Object[]{
dpid,
(activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
(activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
return false;
}
return true;
}
@Override
public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
switchLock.lock();
try {
if (!validActivation(dpid)) {
return false;
}
activeMasterSwitches.put(dpid, sw);
return true;
} finally {
switchLock.unlock();
}
}
@Override
public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
switchLock.lock();
try {
if (!validActivation(dpid)) {
return false;
}
activeEqualSwitches.put(dpid, sw);
log.info("Added Activated EQUAL Switch {}", dpid);
return true;
} finally {
switchLock.unlock();
}
}
@Override
public void transitionToMasterSwitch(Dpid dpid) {
switchLock.lock();
try {
if (activeMasterSwitches.containsKey(dpid)) {
return;
}
OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
if (sw == null) {
sw = getSwitch(dpid);
if (sw == null) {
log.error("Transition to master called on sw {}, but switch "
+ "was not found in controller-cache", dpid);
return;
}
}
log.info("Transitioned switch {} to MASTER", dpid);
activeMasterSwitches.put(dpid, sw);
} finally {
switchLock.unlock();
}
}
@Override
public void transitionToEqualSwitch(Dpid dpid) {
switchLock.lock();
try {
if (activeEqualSwitches.containsKey(dpid)) {
return;
}
OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
if (sw == null) {
log.error("Transition to equal called on sw {}, but switch "
+ "was not found in controller-cache", dpid);
return;
}
log.info("Transitioned switch {} to EQUAL", dpid);
activeEqualSwitches.put(dpid, sw);
} finally {
switchLock.unlock();
}
}
@Override
public void removeConnectedSwitch(Dpid dpid) {
connectedSwitches.remove(dpid);
OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
if (sw == null) {
sw = activeEqualSwitches.remove(dpid);
}
for (OpenFlowSwitchListener l : ofEventListener) {
l.switchRemoved(dpid);
}
}
@Override
public void processMessage(Dpid dpid, OFMessage m) {
processPacket(dpid, m);
}
protected Set<OpenFlowSwitchListener> ofEventListener = new HashSet<>();
protected List<PacketListener> ofPacketListener = new ArrayList<>();
private final Controller ctrl = new Controller();
@Activate
public void activate() {
ctrl.start(agent);
}
@Deactivate
public void deactivate() {
ctrl.stop();
}
@Override
public Iterable<OpenFlowSwitch> getSwitches() {
return connectedSwitches.values();
}
@Override
public Iterable<OpenFlowSwitch> getMasterSwitches() {
return activeMasterSwitches.values();
}
@Override
public Iterable<OpenFlowSwitch> getEqualSwitches() {
return activeEqualSwitches.values();
}
@Override
public OpenFlowSwitch getSwitch(Dpid dpid) {
return connectedSwitches.get(dpid);
}
@Override
public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
return activeMasterSwitches.get(dpid);
}
@Override
public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
return activeEqualSwitches.get(dpid);
}
@Override
public void addListener(OpenFlowSwitchListener listener) {
if (!ofEventListener.contains(listener)) {
this.ofEventListener.add(listener);
}
}
@Override
public void removeListener(OpenFlowSwitchListener listener) {
this.ofEventListener.remove(listener);
}
@Override
public void addPacketListener(int priority, PacketListener listener) {
ofPacketListener.add(priority, listener);
}
@Override
public void removePacketListener(PacketListener listener) {
ofPacketListener.remove(listener);
}
@Override
public void write(Dpid dpid, OFMessage msg) {
this.getSwitch(dpid).sendMsg(msg);
}
@Override
public void processPacket(Dpid dpid, OFMessage msg) {
switch (msg.getType()) {
case PORT_STATUS:
for (OpenFlowSwitchListener l : ofEventListener) {
l.portChanged(dpid, (OFPortStatus) msg);
}
break;
case PACKET_IN:
for (PacketListener p : ofPacketListener) {
p.handlePacket(DefaultPacketContext
.packetContextFromPacketIn(this.getSwitch(dpid),
(OFPacketIn) msg));
}
break;
default:
log.warn("Handling message type {} not yet implemented {}",
msg.getType(), msg);
}
}
@Override
public void setRole(Dpid dpid, RoleState role) {
getSwitch(dpid).setRole(role);
}
/**
* Implementation of an OpenFlow Agent which is responsible for
* keeping track of connected switches and the state in which
* they are.
*/
public class OpenFlowSwitchAgent implements OpenFlowAgent {
private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
private final Lock switchLock = new ReentrantLock();
@Override
public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
if (connectedSwitches.get(dpid) != null) {
log.error("Trying to add connectedSwitch but found a previous "
+ "value for dpid: {}", dpid);
return false;
} else {
log.error("Added switch {}", dpid);
connectedSwitches.put(dpid, sw);
for (OpenFlowSwitchListener l : ofEventListener) {
l.switchAdded(dpid);
}
return true;
}
}
@Override
public boolean validActivation(Dpid dpid) {
if (connectedSwitches.get(dpid) == null) {
log.error("Trying to activate switch but is not in "
+ "connected switches: dpid {}. Aborting ..",
dpid);
return false;
}
if (activeMasterSwitches.get(dpid) != null ||
activeEqualSwitches.get(dpid) != null) {
log.error("Trying to activate switch but it is already "
+ "activated: dpid {}. Found in activeMaster: {} "
+ "Found in activeEqual: {}. Aborting ..", new Object[]{
dpid,
(activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
(activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
return false;
}
return true;
}
@Override
public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
switchLock.lock();
try {
if (!validActivation(dpid)) {
return false;
}
activeMasterSwitches.put(dpid, sw);
return true;
} finally {
switchLock.unlock();
}
}
@Override
public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
switchLock.lock();
try {
if (!validActivation(dpid)) {
return false;
}
activeEqualSwitches.put(dpid, sw);
log.info("Added Activated EQUAL Switch {}", dpid);
return true;
} finally {
switchLock.unlock();
}
}
@Override
public void transitionToMasterSwitch(Dpid dpid) {
switchLock.lock();
try {
if (activeMasterSwitches.containsKey(dpid)) {
return;
}
OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
if (sw == null) {
sw = getSwitch(dpid);
if (sw == null) {
log.error("Transition to master called on sw {}, but switch "
+ "was not found in controller-cache", dpid);
return;
}
}
log.info("Transitioned switch {} to MASTER", dpid);
activeMasterSwitches.put(dpid, sw);
} finally {
switchLock.unlock();
}
}
@Override
public void transitionToEqualSwitch(Dpid dpid) {
switchLock.lock();
try {
if (activeEqualSwitches.containsKey(dpid)) {
return;
}
OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
if (sw == null) {
log.error("Transition to equal called on sw {}, but switch "
+ "was not found in controller-cache", dpid);
return;
}
log.info("Transitioned switch {} to EQUAL", dpid);
activeEqualSwitches.put(dpid, sw);
} finally {
switchLock.unlock();
}
}
@Override
public void removeConnectedSwitch(Dpid dpid) {
connectedSwitches.remove(dpid);
OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
if (sw == null) {
sw = activeEqualSwitches.remove(dpid);
}
for (OpenFlowSwitchListener l : ofEventListener) {
l.switchRemoved(dpid);
}
}
@Override
public void processMessage(Dpid dpid, OFMessage m) {
processPacket(dpid, m);
}
}
}
......
......@@ -21,9 +21,9 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
......@@ -85,6 +85,7 @@ public class LinkDiscovery implements TimerTask {
private final boolean useBDDP;
private final OpenFlowController ctrl;
private final LinkProviderService linkProvider;
private final Map<Integer, OFPortDesc> ports;
/**
* Instantiates discovery manager for the given physical switch. Creates a
......@@ -103,6 +104,7 @@ public class LinkDiscovery implements TimerTask {
this.linkProvider = providerService;
this.slowPorts = Collections.synchronizedSet(new HashSet<Integer>());
this.fastPorts = Collections.synchronizedSet(new HashSet<Integer>());
this.ports = new ConcurrentHashMap<>();
this.portProbeCount = new HashMap<Integer, AtomicInteger>();
this.lldpPacket = new ONLabLddp();
this.lldpPacket.setSwitch(this.sw.getId());
......@@ -140,7 +142,7 @@ public class LinkDiscovery implements TimerTask {
*/
public void addPort(final OFPortDesc port) {
// Ignore ports that are not on this switch, or already booted. */
this.ports.put(port.getPortNo().getPortNumber(), port);
synchronized (this) {
this.log.debug("sending init probe to port {}",
port.getPortNo().getPortNumber());
......@@ -274,12 +276,10 @@ public class LinkDiscovery implements TimerTask {
* Handles an incoming LLDP packet. Creates link in topology and sends ACK
* to port where LLDP originated.
*/
@SuppressWarnings("rawtypes")
public void handleLLDP(final Ethernet eth, Integer inPort) {
final byte[] pkt = eth.serialize();
public void handleLLDP(final byte[] pkt, Integer inPort) {
if (ONLabLddp.isOVXLLDP(pkt)) {
short ethType = ONLabLddp.isOVXLLDP(pkt);
if (ethType == Ethernet.TYPE_LLDP || ethType == Ethernet.TYPE_BSN) {
final Integer dstPort = inPort;
final DPIDandPort dp = ONLabLddp.parseLLDP(pkt);
final OpenFlowSwitch srcSwitch = ctrl.getSwitch(new Dpid(dp.getDpid()));
......@@ -296,7 +296,7 @@ public class LinkDiscovery implements TimerTask {
DeviceId.deviceId("of:" + Long.toHexString(sw.getId())),
PortNumber.portNumber(dstPort));
LinkDescription ld;
if (eth.getEtherType() == Ethernet.TYPE_BSN) {
if (ethType == Ethernet.TYPE_BSN) {
ld = new DefaultLinkDescription(src, dst, Type.INDIRECT);
} else {
ld = new DefaultLinkDescription(src, dst, Type.DIRECT);
......@@ -307,13 +307,8 @@ public class LinkDiscovery implements TimerTask {
}
}
private OFPortDesc findPort(List<OFPortDesc> ports, Integer inPort) {
for (OFPortDesc p : ports) {
if (p.getPortNo().getPortNumber() == inPort) {
return p;
}
}
return null;
private OFPortDesc findPort(Integer inPort) {
return ports.get(inPort);
}
/**
......@@ -333,7 +328,7 @@ public class LinkDiscovery implements TimerTask {
final Integer portNumber = fastIterator.next();
final int probeCount = this.portProbeCount.get(portNumber)
.getAndIncrement();
OFPortDesc port = findPort(this.sw.getPorts(), portNumber);
OFPortDesc port = findPort(portNumber);
if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) {
this.log.debug("sending fast probe to port");
......@@ -368,7 +363,7 @@ public class LinkDiscovery implements TimerTask {
if (this.slowIterator.hasNext()) {
final int portNumber = this.slowIterator.next();
this.log.debug("sending slow probe to port {}", portNumber);
OFPortDesc port = findPort(this.sw.getPorts(), portNumber);
OFPortDesc port = findPort(portNumber);
OFPacketOut pkt = this.createLLDPPacketOut(port);
this.sendMsg(pkt);
......
......@@ -87,7 +87,7 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
if (ld == null) {
return;
}
ld.handleLLDP(pktCtx.parsed(),
ld.handleLLDP(pktCtx.unparsed(),
pktCtx.inPort());
}
......
......@@ -30,7 +30,6 @@ import org.slf4j.LoggerFactory;
* Refer to IEEE Std 802.1ABTM-2009 for more information.
*
*/
@SuppressWarnings("rawtypes")
public class ONLabLddp extends LLDP {
private static final Logger log = LoggerFactory.getLogger(ONLabLddp.class);
......@@ -308,28 +307,34 @@ public class ONLabLddp extends LLDP {
* @param packet
* @return
*/
public static boolean isOVXLLDP(byte[] packet) {
public static short isOVXLLDP(byte[] packet) {
if (packet.length < OVX_LLDP_SIZE) {
return false;
return -1;
}
// Extra offset due to VLAN tag
final ByteBuffer bb = ByteBuffer.wrap(packet);
int offset = 0;
if (bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_LLDP
&& bb.getShort(ETHERTYPE_OFFSET) != Ethernet.TYPE_BSN) {
short ethType = bb.getShort(ETHERTYPE_OFFSET);
if (ethType != Ethernet.TYPE_LLDP
&& ethType != Ethernet.TYPE_BSN) {
offset = 4;
ethType = bb.getShort(ETHERTYPE_OFFSET + offset);
if (ethType != Ethernet.TYPE_LLDP
&& ethType != Ethernet.TYPE_BSN) {
return -1;
}
}
// Compare packet's organizationally specific TLVs to the expected
// values
for (int i = 0; i < OUI_TLV.length; i++) {
if (packet[NAME_TLV_OFFSET + offset + i] != OUI_TLV[i]) {
return false;
return -1;
}
}
return true;
return ethType;
}
/**
......