ANLAB-KAIST / Packet-IO-Engine

A high-performance and batching-oriented device driver for Intel 82598/82599-based network interface cards, the work is done in cooperation with ANLAB and NDSL.
http://shader.kaist.edu/packetshader/io_engine/
Other
144 stars 43 forks source link

there is not a one-to-one correspondence between a packet and the length #12

Open ghost opened 11 years ago

ghost commented 11 years ago

I modify the packet generator like this to send the random size packet:

         chunk.queue.ifindex = devices_registered[i];
         working = 1;

+        int offset = 0;

      for (j = 0; j < chunk_size; j++) {
+            
+            packet_size = rand() % 2 + 400;

              chunk.info[j].len = packet_size;
//        chunk.info[j].offset = j * PS_ALIGN(packet_size, 64);
+            chunk.info[j].offset = offset;
+           offset = PS_ALIGN(offset + packet_size, 64);

             if (num_flows == 0){

then I run the command like this: ./packet_generator -i xge0 -p 512 -s 64

I use the libpcap reading the packet at another mechine, use the libnids processing the packet, I find some packet's cap_length - linkoffset is less than ip header's ip total length , like this:

  caplen - linkoffset < ntohs(iph->ip_len)

But the length is not random, it is also the packet we build, it's length should be 401 , but when I receive, it is 400.

For help!!!

ghost commented 11 years ago

no one find this?

achimnol commented 11 years ago

Sorry for late response. Could you test using the latest pspgen instead of packet_generator? e.g., ./pspgen -i xge0 -f 0 -v 4 -p 402 --min-pkt-size 400 (this will generate packets with length 400 and 401 bytes including the Ethernet header.)

In our test with rxdump running at another machine connected over a 10G switch, it looks working fine. I have no experience on libnids, so please explain more about "cap length" and "link offset" means here.

ghost commented 11 years ago

Thanks, I will test the pspgen program. The caplen is the chunk.info[i].len from ps_recv_chunk() , the link offset is the Ethernet header length 14

ghost commented 11 years ago

I test it, I find it if I use ethtool -A xge0 rx on at the tx module, this problem is appear when rx ring is full. I think the tx processing Pause frame has a bug.

ghost commented 11 years ago

If I turn on the flow control at the install.py, I the length problem is appear

 -        execute('ethtool -A %s autoneg off rx off tx off' % ifname)
 +        execute('ethtool -A %s autoneg on rx on tx on' % ifname)
     execute('ifconfig %s %s.%d.%s netmask 255.255.255.0 mtu 1500' % (ifname, opts.ip_prefix, i, opts.postfix), True)

The length error could also appear at echo , if we add the check length code like this: diff --git a/samples/echo/echo.c b/samples/echo/echo.c index cf71405..e637ad4 100644 --- a/samples/echo/echo.c +++ b/samples/echo/echo.c @@ -11,7 +11,12 @@

include

 #include <sys/wait.h>
+#include <arpa/inet.h>
+#include <linux/ip.h>

 #include "psio.h"

@@ -28,6 +33,51 @@ struct ps_handle handles[PS_MAX_CPUS];
 int my_cpu;
 int sink;

+////////////////////////////////////////////////////////////////
+
+static int check_packet_content(char *data, int len)
+{
+ //int len = info[i].len;
+ //char *data = pkt + 64;
+
+ char *orig_data = data;
+ int linkoffset = 12;
+ int skblen;
+ struct iphdr *iph;
+
+ data = orig_data + linkoffset;
+ if (data[0] == 8 && data[1] == 0) {
+ /* Regular ethernet */
+ linkoffset += 2;
+ } else if (data[0] == 0x81 && data[1] == 0) {
+ linkoffset += 4 + 2;
+ } else {
+ linkoffset = -1;
+ printf("[%s] linkoffset = -1\n", __func__);
+ return 1;
+ }
+
+ data = orig_data + linkoffset;
+ iph = (struct iphdr *)data;
+
+ skblen = len - linkoffset;
+ if (skblen != ntohs(iph->tot_len)) {
+ printf("[%s] skblen=%d iplen=%hd\n", __func__, skblen,
+ ntohs(iph->tot_len));
+ return 1;
+ } else {
+ static int count = 0;
+
+ if (++count % 10000 == 0) {
+ printf("%d skblen=%d iplen=%d\n", count,
+ skblen, ntohs(iph->tot_len));
+ }
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////

@@ -208,12 +262,13 @@ void echo()

  assert(ps_alloc_chunk(handle, &chunk) == 0);

- chunk.recv_blocking = 1;
+ chunk.recv_blocking = 0;

  for (;;) {
  int ret;

  chunk.cnt = 64;
+ usleep(12000);
  ret = ps_recv_chunk(handle, &chunk);

  if (ret < 0) {
@@ -226,11 +281,17 @@ void echo()
  assert(0);
  }

- if (!sink) {
- chunk.cnt = ret;
- ret = ps_send_chunk(handle, &chunk);
- assert(ret >= 0);
+ for (i = 0; i < ret; i++) {
+ int len = chunk.info[i].len;
+ char *data = chunk.buf + chunk.info[i].offset;
+ check_packet_content(data, len);
  }

}

done: