diff --git a/src/main/java/net/floodlightcontroller/packet/BasePacket.java b/src/main/java/net/floodlightcontroller/packet/BasePacket.java index 4ecfdedddd813b1fbd42a3ad1a2dbc48eafc45ed..eed530c03d2e8047774697bc70032d58eee63981 100644 --- a/src/main/java/net/floodlightcontroller/packet/BasePacket.java +++ b/src/main/java/net/floodlightcontroller/packet/BasePacket.java @@ -17,12 +17,16 @@ package net.floodlightcontroller.packet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * @author David Erickson (daviderickson@cs.stanford.edu) */ public abstract class BasePacket implements IPacket { + public static final Logger log = LoggerFactory.getLogger(BasePacket.class); protected IPacket parent; protected IPacket payload; @@ -113,4 +117,4 @@ public abstract class BasePacket implements IPacket { pkt.setParent(this.parent); return pkt; } -} \ No newline at end of file +} diff --git a/src/main/java/net/floodlightcontroller/packet/Ethernet.java b/src/main/java/net/floodlightcontroller/packet/Ethernet.java index 44a908118d9e649ec0421f5620684a9d967f6519..41f6e56752c1ce0084a638999a02de8f6b2bd91e 100644 --- a/src/main/java/net/floodlightcontroller/packet/Ethernet.java +++ b/src/main/java/net/floodlightcontroller/packet/Ethernet.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import net.floodlightcontroller.core.annotations.LogMessageDoc; import net.floodlightcontroller.util.MACAddress; import org.openflow.util.HexString; @@ -228,9 +229,15 @@ public class Ethernet extends BasePacket { return data; } + @LogMessageDoc(level="INFO", + message="Failed to parse ethernet packet payload", + explanation="Was unable to parse ethernet payload, often caused " + + "by packet truncation. Packet is forwarded as a plain " + + "ethernet packet.", + recommendation=LogMessageDoc.GENERIC_ACTION) @Override public IPacket deserialize(byte[] data, int offset, int length) { - if (length <= 0) + if (length <= 16) // Ethernet packet minium should be 60, this is reasonable return null; ByteBuffer bb = ByteBuffer.wrap(data, offset, length); if (this.destinationMACAddress == null) @@ -261,13 +268,22 @@ public class Ethernet extends BasePacket { Class<? extends IPacket> clazz = Ethernet.etherTypeClassMap.get(this.etherType); try { payload = clazz.newInstance(); + this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); } catch (Exception e) { - throw new RuntimeException("Error parsing payload for Ethernet packet", e); + log.info("Failed to parse ethernet packet {}->{} payload as {}," + + " treat as plain ethernet packet", + new Object[] {this.sourceMACAddress, this.destinationMACAddress, + clazz.getClass().getName()}); + if (log.isDebugEnabled()) { + log.debug("Exception from parsing {}", e); + } + payload = new Data(); + this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); } } else { payload = new Data(); + this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); } - this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); this.payload.setParent(this); return this; } diff --git a/src/main/java/net/floodlightcontroller/packet/IPv4.java b/src/main/java/net/floodlightcontroller/packet/IPv4.java index 76a140ed002bad4ab93db3488a771b2141223376..461d24df972f84a1b6bd3e1d26bb1e4689f327b7 100644 --- a/src/main/java/net/floodlightcontroller/packet/IPv4.java +++ b/src/main/java/net/floodlightcontroller/packet/IPv4.java @@ -26,6 +26,8 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import net.floodlightcontroller.core.annotations.LogMessageDoc; + /** * @author David Erickson (daviderickson@cs.stanford.edu) * @@ -334,6 +336,11 @@ public class IPv4 extends BasePacket { return data; } + @LogMessageDoc(level="INFO", + message="IP fragment detected", + explanation="Packet in is an IP fragment. Controller forwards " + + "it using IP header only. Transport headers are ignored.", + recommendation=LogMessageDoc.GENERIC_ACTION) @Override public IPacket deserialize(byte[] data, int offset, int length) { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); @@ -361,7 +368,8 @@ public class IPv4 extends BasePacket { } IPacket payload; - if (IPv4.protocolClassMap.containsKey(this.protocol)) { + boolean is_frag = ((this.flags & 0x1) != 0) || (this.fragmentOffset != 0); + if (!is_frag && IPv4.protocolClassMap.containsKey(this.protocol)) { Class<? extends IPacket> clazz = IPv4.protocolClassMap.get(this.protocol); try { payload = clazz.newInstance(); @@ -369,6 +377,11 @@ public class IPv4 extends BasePacket { throw new RuntimeException("Error parsing payload for IPv4 packet", e); } } else { + if (is_frag) { + log.info("IPv4 fragment detected {}->{}, forward using IP header only", + fromIPv4Address(this.sourceAddress), + fromIPv4Address(this.destinationAddress)); + } payload = new Data(); } int payloadLength = this.totalLength - this.headerLength * 4; @@ -493,7 +506,7 @@ public class IPv4 extends BasePacket { * @return The IP address separated into bytes. */ public static byte[] toIPv4AddressBytes(int ipAddress) { - return new byte[] { + return new byte[] { (byte)(ipAddress >>> 24), (byte)(ipAddress >>> 16), (byte)(ipAddress >>> 8),