diff --git a/src/main/java/net/floodlightcontroller/cpanalyzer/CPAnalyzer.java b/src/main/java/net/floodlightcontroller/cpanalyzer/CPAnalyzer.java new file mode 100644 index 0000000000000000000000000000000000000000..f0af40eefdfd6f29e522fd928940743553ddb50f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/cpanalyzer/CPAnalyzer.java @@ -0,0 +1,155 @@ +package net.floodlightcontroller.cpanalyzer; + +import java.util.Collection; +import java.util.Map; + +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +import net.floodlightcontroller.core.FloodlightContext; +import net.floodlightcontroller.core.IFloodlightProviderService; +import net.floodlightcontroller.core.IOFMessageListener; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.internal.Controller; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.packet.ARP; +import net.floodlightcontroller.packet.Ethernet; +import net.floodlightcontroller.packet.IPacket; +import net.floodlightcontroller.packet.IPv4; +import net.floodlightcontroller.packet.IPv6; +import net.floodlightcontroller.packet.LLDP; +import net.floodlightcontroller.util.OFMessageUtils; + +/** + * A simple module for debugging the control plane. Simply fill in the stuff you + * want printed for the message type you're interested in, if more than just + * packet-in/packet-out. + * + * Note that some types (like echos) are handled in the lower-level handshake + * handler, so you won't be able to receive them here. Only types passed up to + * modules or from modules written to switches will be shown. + * + * To view the logs, enable TRACE logging for net.floodlightcontroller.cpanalyzer. + * + * @author rizard + * + */ +public class CPAnalyzer implements ICPAnalyzerService, IFloodlightModule, IOFMessageListener { + private static final Logger log = LoggerFactory.getLogger(CPAnalyzer.class); + + @Override + public String getName() { + return "cpanalyzer"; + } + + @Override + public boolean isCallbackOrderingPrereq(OFType type, String name) { + return false; /* none should receive before us */ + } + + @Override + public boolean isCallbackOrderingPostreq(OFType type, String name) { + return true; /* all should receive after us */ + } + + @Override + public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { + if (log.isTraceEnabled()) { + switch (msg.getType()) { + case PACKET_IN: + Ethernet eth = (Ethernet) cntx.getStorage().get(Controller.CONTEXT_PI_PAYLOAD); + if (eth == null) { + break; + } + StringBuilder sb = new StringBuilder(); + sb.append("PacketIn from ").append("sw=").append(sw.getId().toString()).append(", pt=") + .append(OFMessageUtils.getInPort((OFPacketIn) msg).getPortNumber()); + log.trace(displayFrame(eth, sb).toString()); + break; + case PACKET_OUT: + final OFPacketOut po = (OFPacketOut) msg; + sb = new StringBuilder(); + sb.append("PacketOut to ").append("sw=").append(sw.getId().toString()).append(", pt=") + .append(po.getActions().toString()); + eth = new Ethernet(); + eth.deserialize(po.getData(), 0, po.getData().length); + + log.trace(displayFrame(eth, sb).toString()); + break; + default: + break; + } + } + return Command.CONTINUE; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + return ImmutableSet.of(ICPAnalyzerService.class); + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { + return ImmutableMap.of(ICPAnalyzerService.class, this); + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + return ImmutableSet.of(IFloodlightProviderService.class); /* for registration */ + } + + @Override + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + } + + @Override + public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { + final IFloodlightProviderService flps = context.getServiceImpl(IFloodlightProviderService.class); + if (flps != null) { + for (OFType t : OFType.values()) { + flps.addOFMessageListener(t, this); + } + } + } + + private static StringBuilder displayFrame(final Ethernet eth, final StringBuilder sb) { + sb.append("\n\t").append("L2 src=").append(eth.getSourceMACAddress().toString()).append(", dst=") + .append(eth.getDestinationMACAddress().toString()).append(", vlan=").append(eth.getVlanID()) + .append(", ethtype=").append(eth.getEtherType().toString()); + final IPacket l3 = eth.getPayload(); + if (l3 instanceof IPv4) { + final IPv4 ipv4 = (IPv4) l3; + sb.append("\n\t").append("L3 src=").append(ipv4.getSourceAddress().toString()).append(", dst=") + .append(ipv4.getDestinationAddress().toString()).append(", ttl=").append(ipv4.getTtl()) + .append(", proto=").append(ipv4.getProtocol().toString()); + } else if (l3 instanceof IPv6) { + final IPv6 ipv6 = (IPv6) l3; + sb.append("\n\t").append("L3 src=").append(ipv6.getSourceAddress().toString()).append(", dst=") + .append(ipv6.getDestinationAddress().toString()).append(", label=").append(ipv6.getFlowLabel()) + .append(", proto=").append(ipv6.getNextHeader().toString()); + } else if (l3 instanceof LLDP) { + final LLDP lldp = (LLDP) l3; + sb.append("\n\t").append("L3 chid=").append(String.valueOf(lldp.getChassisId().getValue())) + .append(", ptid=").append(String.valueOf(lldp.getPortId().getValue())); + } else if (l3 instanceof ARP) { + final ARP arp = (ARP) l3; + sb.append("\n\t").append("L3 smac=").append(arp.getSenderHardwareAddress().toString()).append(", sip=") + .append(arp.getSenderProtocolAddress().toString()).append(", tmac=") + .append(arp.getTargetHardwareAddress().toString()).append(", sip=") + .append(arp.getTargetProtocolAddress().toString()); + } else { + sb.append("\n\t").append("L3 deserialized=").append(l3.toString()); + } + return sb.append("/n/n"); + } +} diff --git a/src/main/java/net/floodlightcontroller/cpanalyzer/ICPAnalyzerService.java b/src/main/java/net/floodlightcontroller/cpanalyzer/ICPAnalyzerService.java new file mode 100644 index 0000000000000000000000000000000000000000..60a8e4a8f311fc39ffb3ce06116b20519e1be595 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/cpanalyzer/ICPAnalyzerService.java @@ -0,0 +1,7 @@ +package net.floodlightcontroller.cpanalyzer; + +import net.floodlightcontroller.core.module.IFloodlightService; + +public interface ICPAnalyzerService extends IFloodlightService { + +} diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule index 3568e34bdbca7c5cbcb9655805595a976baed327..e4eb25c9303f9a299a3e854dbadeb1833fc3c725 100644 --- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule +++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule @@ -27,4 +27,5 @@ net.floodlightcontroller.accesscontrollist.ACL net.floodlightcontroller.dhcpserver.DHCPServer net.floodlightcontroller.learningswitch.LearningSwitch net.floodlightcontroller.statistics.StatisticsCollector -net.floodlightcontroller.routing.RoutingManager \ No newline at end of file +net.floodlightcontroller.routing.RoutingManager +net.floodlightcontroller.cpanalyzer.CPAnalyzer \ No newline at end of file