Showing posts with label network. Show all posts
Showing posts with label network. Show all posts

February 1, 2012

How to build jNetPcap library


Access to the source code of jNetPcap
 
jNetPcap source code is located under SVN control.
To access the repository you can use TortoiseSVN client.
Then you can get the source code using following link:https://jnetpcap.svn.sourceforge.net/svnroot/jnetpcap/jnetpcap/trunk

Preparation

The library should be linked statically with the libraries LIBGCC_S_DW2-1.DLL and LIBSTDC++-6.DLL which is located in bin folder of MinGW. The default build.xml doesn't contain necessary options. So before to start build procedure you need to update the build.xml file.

Both sections with compilation options for 32 and 64 bits platforms should be updated.

Find section "comp-jni-win32" and "comp-jni-win64" and update the section <exec executable...> inside both of them. The following lines should be added there "<arg value="-static" />"
So in result section <exec executable..."> should look like this code:

 <exec executable="${compiler.ld.cmd}">
   <arg value="-shared" />
   <arg value="-g" />
   <arg value="-Wl,--add-stdcall-alias" />
   <arg value="-static" />
   <arg line="-o ${jni.build.filepath}" />
   <arg line="${jni.obj.files}" />
   <arg line="-L ${pcap.lib.dir}" />
   <arg line="-l ${pcap.lib.name}" />
   <arg line="-l ${ms.lib.name}" />
</exec>

How to build jNetPcap library for 32-bits platform

Download and install Apache Ant building software.
It could be taken from the official site. To install it you need just open zip archive and extract the files into any directory. Then you need to create Environment variable ANT_HOME with the path to the ant directory. It is also necessary to add the path to ant bins into the PATH environment variable.

Download and install compiler MinGW.
It could be taken from the official site. During the setup you need to select "Download latest repository catalogues". It is important at least for Windows XP. Then you need to update the PATH environment variable again and add the path to MinGW bins there.

Build the jNetPcap library
Go into the jnetpcap directory with the source code and run the following command to get the complete list of possible targets:
ant help
You need to compile jnetpcap.jar and jnetpcap.dll files. Execute the following command one by one.
ant comp-java
ant build-jar
ant comp-jni

 
How to build jNetPcap library for 64-bits platform


Download and install Apache Ant building software.
It could be taken from the official site. To install it you need just open zip archive and extract the files into any directory. Then you need to create Environment variable ANT_HOME with the path to the ant directory. It is also necessary to add the path to ant bins into the PATH environment variable.

Download and install compiler MinGW64.
It could be taken from the official site. But there is no binaries ready to execute. You can find there only source code and you will need to compile the compiler yourself. The compilation procedure is enough complicated.
So it would be much faster to get already build binaries from another site. You can use Windows XP/2003 x64 binaries for Windows 7. It is ok.

Build the jNetPcap library
Go into the jnetpcap directory with the source code and run the following command to get the complete list of possible targets:
ant help

You need to compile jnetpcap.jar and jnetpcap.dll files. Execute the following command one by one.
ant comp-java
ant build-jar
ant comp-jni

November 26, 2011

Performance analysis of jNetPcap library

We are working on creation of VoIP sniffer application which must to capture RTP packets and SIP messages. We had to make the performance analysis to find the quickest way to free internal jNetPcap ring buffer and avoid network packets loss. Our application is used on multi core PCs, e.g. Xeon E5630.

For analysis of the performance jVisualVM profiler 1.3.3. was used. For the test I used trace pcap file with 262000 network packets including 1500 RTP packets and some small number of SIP messages. So useful traffic was just 1%.

Our first implementation of a capture thread was like following:

public void nextPacket(final PcapPacket packet, final String unused) {
   
    NetworkPacket outputPacket = null;
    boolean tcp = false;

    try {
        if ((packet.hasHeader(updHeader) || (tcp=packet.hasHeader(tcpHeader))) && !packet.hasHeader(icmpHeader)) {
           
            if (packet.hasHeader(rtpHeader)) {
                if ( packet.hasHeader(ipHeader) ) {
                    outputPacket = new RtpPacket(ipHeader, updHeader, rtpHeader);
                }
            } else if (packet.hasHeader(sipHeader)) {
                if ( packet.hasHeader(ipHeader) ) {
                    if (tcp) {
                        outputPacket = new SipPacket(ipHeader, tcpHeader, sipHeader);
                    } else {
                        outputPacket = new SipPacket(ipHeader, updHeader, sipHeader);
                    }
                }
            }

        if (outputPacket != null) {
            if (!packetProcessingQueue.offer(outputPacket)) {
                logger.error("packetProcessingQueue is full when packet [{}] is received", packet.getFrameNumber());
            }
        }

    } catch (ExceptionBadPacket e) {
        logger.info("Incorrect packet has been received from JNetPacket", packet.getFrameNumber());
    }
}

The RtpPacket and SipPacket constructors make copy of the network packets payload.
The profiler showed following results.


After that I tried to replace hasHeader() by getHeader() function call. It is less convenient because an user have to compare with null. However this function enabled us to increase the speed twice.


I was sure that the filtering enabled us to get higher speed because we skipped unnecessary packets and copied only useful RTP and SIP packets. However the results was absolutely unexpected for me. jNetPcap library copies network packets faster than checks its type. So most efficient way is to capture ALL network packets into the second thread and make analysis there.

The source code for the capture thread looks like:

public void nextPacket(PcapHeader header, JBuffer buffer, String any) {
   
    PcapPacket packet = new PcapPacket(header,buffer);
   
    if (packet != null) {
        if (!packetProcessingQueue.offer(packet)) {
            logger.error("packetProcessingQueue is full when packet [{}] is received", packet.getFrameNumber());
        }
    }
}