This is an old revision of the document!


Port wscale branch against current gPXE master

Recent TCP updates is a lot different from previous base of wscale branch.

Hit a GCC optimization trap

For the following code
#include <stdio.h>

struct foo {
        char huge_gap[0x4005d0];
        int v;
};

void store_and_print(int *val, struct foo *f)
{
        *val = f->v;
        if ( !f ) {
                printf("Value is wrong.\n");
        } else {
                printf("Value is correct.\n");
        }
}

int main()
{
        int unidentified_value;

        printf("%p\n", main);
        store_and_print(&unidentified_value, NULL);

        return 0;
}

The value 0x4005d0 is from printf(“%p\n”, main); in order to get an mapped memory address to prevent Segment fault error while running.

The output if compiled with ''-O2''
$ ./null_deref_optimized_away
0x4005d0
Value is correct.
$ 

And its assembly code:

void store_and_print(int *val, struct foo *f)
{
        *val = f->v;
  4005b0:       8b 86 d0 05 40 00       mov    0x4005d0(%rsi),%eax
  4005b6:       89 07                   mov    %eax,(%rdi)
        if ( !f ) {
                printf("Value is wrong.\n");
        } else {
                printf("Value is correct.\n");
  4005b8:       bf ec 06 40 00          mov    $0x4006ec,%edi
  4005bd:       e9 c6 fe ff ff          jmpq   400488 <puts@plt>
  4005c2:       66 66 66 66 66 2e 0f    nopw   %cs:0x0(%rax,%rax,1)
  4005c9:       1f 84 00 00 00 00 00

00000000004005d0 <main>:
        }
}
The output if compiled with ''-O2 -fno-delete-null-pointer-checks''
$ ./null_deref_optimized_away
0x4005d0
Value is wrong.
$ 

And its assembly code:

00000000004005b0 <store_and_print>:
        int v;
};

void store_and_print(int *val, struct foo *f)
{
        *val = f->v;
  4005b0:       8b 86 d0 05 40 00       mov    0x4005d0(%rsi),%eax
        if ( !f ) {
  4005b6:       48 85 f6                test   %rsi,%rsi
        int v;
};

void store_and_print(int *val, struct foo *f)
{
        *val = f->v;
  4005b9:       89 07                   mov    %eax,(%rdi)
        if ( !f ) {
  4005bb:       74 13                   je     4005d0 <store_and_print+0x20>
                printf("Value is wrong.\n");
        } else {
                printf("Value is correct.\n");
  4005bd:       bf 0c 07 40 00          mov    $0x40070c,%edi
  4005c2:       e9 c1 fe ff ff          jmpq   400488 <puts@plt>
  4005c7:       66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  4005ce:       00 00

void store_and_print(int *val, struct foo *f)
{
        *val = f->v;
        if ( !f ) {
                printf("Value is wrong.\n");
  4005d0:       bf fc 06 40 00          mov    $0x4006fc,%edi
  4005d5:       e9 ae fe ff ff          jmpq   400488 <puts@plt>
  4005da:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

00000000004005e0 <main>:
                printf("Value is correct.\n");
        }
}

Adding some facilities for testing convenience

  • Add a command to modify TCP window size at runtime.
  • print “\b%c” instead of “.” in monojob, keep the console clean.
  • Add a pause command.

wscale2 testing branch

tcpfix2 testing branch

Window size difference

Window Size tcpfix2 branch wscale2 branch sackws2 branch
KVM TAP/NAT Native KVM TAP/NAT Native KVM TAP/NAT Native
8K 16KB/s 16KB/s 16KB/s 16KB/s KB/s KB/s
16K 43KB/s 43KB/s 41KB/s 41KB/s KB/s KB/s
32K 94KB/s 93KB/s 90KB/s 91KB/s KB/s KB/s
64K 198KB/s 192KB/s 187KB/s 187KB/s KB/s KB/s
128K 374KB/s 374KB/s KB/s KB/s
256K 470KB/s 742KB/s KB/s KB/s
512K 450KB/s [1]344KB/s KB/s KB/s
1024K 498KB/s [1]403KB/s KB/s KB/s

[1]: While TCP rx window is large enough to hit the bandwidth limit(1MB/s), packets start to drop. According to captured data, the retransmittion is very slow. The sending host wait a long time for transmit next missing packet required by client. This issue should be able to fixed with Selective ACK support.


QR Code
QR Code soc:2010:cooldavid:journal:week12 (generated for current page)