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"); } }