Hi Mark,
In our program using Jnetpcap, Some of the packets are lost while using
pcap.loop(-1, handler, "jNetPcap rocks!");
Our requirement is to capture all the packets from n/w card and write the payload to file.
The following is our code snippet
PcapPacketHandler handler = new PcapPacketHandler() {
public void nextPacket(PcapPacket packet, String user) {
pktdata = packet.getHeader(new Tcp());
if(pktdata != null && pktdata.getPayloadLength()>0)
fos.write(pktdata.getPayload());
}
}
We simulate 1MBps throughput and capture the packets thro jnetpcap program as well as wireshark. We found lot of packet are lost while compare to wireshark.
Kindly help us to resolve the problem and explain how loop method works(will it continue to read new arrival of packets from kernel buffer) while packethandler(nextpacket()) is processing the available packets in Jscanner.
Thanks in Advance,
Shyamala
Hi and welcome
1Mbps should not be a problem for libpcap. You are however doing lots of IO within the loop. So a few suggestions.
1) Don't create a new Tcp object everytime in the loop. Put it as a private (see http://jnetpcap.com/faq1)
2) JHeader.getPayload() copies packet data out of of native memory into a byte[] only to be written to an IO stream.
3) move IO write out of the loop, or atleast buffer it some before committing to a IO write, if you are concerned about performance.
4) Also you could consider using java.nio Channels to speed up and minimize amount of copies. For that you would need to use ByteBufferHandler and a tcp filter to make sure you are only processing tcp packets. i.e.
PcapBpfProgram program = new PcapBpfProgram();
String expression = "tcp";
int optimize = 0; // 0 = false
int netmask = 0xFFFFFF00; // 255.255.255.0
if (pcap.compile(program, expression, optimize, netmask) != Pcap.OK) {
System.err.println(pcap.getErr());
return;
}
if (pcap.setFilter(program) != Pcap.OK) {
System.err.println(pcap.getErr());
return;
}
Right now, you are doing a native memory to java byte[] copy and then serial IO based byte[] write to a stream all in the loop for every packet. That can't be good for performance.
For maximum performance I would suggest doing some buffering. You can create a large java.nio.ByteBuffer and copy data into it using ByteBuffer copy methods. You can also do all of this with a JBuffer and its transferTo methods.
What wireshark does, is it captures live raw packets into memory and when the capture stops decodes them afterwards. Your code is capturing all packets, scanning, allocating a tcp object, decoding the tcp header, copying its payload from native memory to byte[], performing a serial IO write for every loop cycle.
Before you get too deep into this, I would suggest just trying a pcap dumper example and see if it can keep up. The dumper example doesn't do any decoding and simply dumps raw packets to an output file. That should give you a benchmark to start with.
Thank you very much Mark.
That was a great idea and Pcapdumper with filters works without any packet loss and we do all the payload activites at offline.
But the Pcapdumper also captures 0 length tcp packets (Payload of the packets are empty) which makes the file size huge. We tried some of the capture filters like 'greater' which only supports for the packet length (not for the payload length)
Do we have any filter option to discard those packets?
A quick google search discovers the following filter:
(ip[2:2] - ((ip[0] & 0x0f) * 4) - (tcp[12] & 0xf0) / 4)) != 0
Hope that helps.
Hi Mark,
Again we are facing the same packet loss issue for 4MBps throughput simulation.
We are simply capturing and dumping the packets using PcapDumper and we set buffer size(using setBuff()) and JScanner's DEFAULT_BLOCKSIZE to 2MB.Still we are losing 400 packets while comparing to Wireshark.
Kindly help us to resolve this problem.
Which handler are you using with your pcap-dump (PcapPacketHandler, JBufferHandler or ByteBufferHandler)? For just dumping packets, you want to use the low level handler that doesn't do any processing of the received packets such as JBufferHandler or ByteBufferHandler. JBufferHandler is the most efficient out of all of them.
For testing purposes, you may also want to just see if the JBufferHandler is able to keep up with incoming packet stream without dumping it to a file. Just increment a packet counter and print it out when you are done and compare it with number of packets captured using Wireshark. If the machine running jnetpcap is not able to keepup with just capturing packets, then its not going to be able to keep up when it also has to write them to a disk.
I made a new build available for download. It adds 2 new methods to Pcap class that add a specialized dumper loop and dispatch methods:
Pcap.loop(int count, PcapDumper)
Pcap.dispatch(int count, PcapDumper)
Notice they do not take a Handler parameter as they supply their own native handler that bypasses entering java environment until the loop is complete. Another words, it provides its own native handler that hands off packets to PcapDumper all in native space as efficiently as it possibly can.
You may want to try that one out and see if it helps with the performance problem. These 2 methods were on the drawing board for a while so I decided to add them in since we have a perfect opportunity to test them out thoroughly.