Occasional TCP checksum errors with qdisc

Occasional TCP checksum errors with qdisc

Post by Chris Edward » Sun, 27 Oct 2002 10:50:08


I've been developing a kernel module which acts as a queuing discipline,
and modifies TCP packets to include an extra option. This obviously
involves updating the checksums. It looked like it was all working fine,
but occasionally packets get the wrong TCP checksum! I've only been able to
reproduce this when talking to a remote solaris 8 machine. Running gigs
of data against local Linux machines produces nothing! The IP checksum
is always correct, even though it too is modified.

Most of the code was taken from the ipt_TCPMSS module, which performs a
similar task. I've included the relevant bit of code below:. I can send
the full module if that helps.

Also, I've tried performing a full checksum on the packet and that
seemed to produce the same checksums as the code below, and obviously
that didn't work!

Any help would be greatly appreciated!! I suspect something happens with
qdiscs which I don't know about. The strange thing is that it very
rarely causes problems.


        if (skb_tailroom(skb) >= TCPOLEN_QSIZE &&
                        skb->len <= (sch->dev->mtu - TCPOLEN_QSIZE)) {
                struct tcphdr *tcph;
                struct iphdr *iph;
                u_int16_t tcplen, newtotlen, oldval;
                u_int16_t pofq;

                u_int8_t *opt;

                iph = skb->nh.iph;
                tcplen = skb->len - iph->ihl * 4;

                tcph = (void *) iph + iph->ihl * 4;

                skb_put(skb, TCPOLEN_QSIZE);

                opt = (u_int8_t *) tcph + sizeof(struct tcphdr);
                memmove(opt + TCPOLEN_QSIZE, opt,
                                tcplen - sizeof(struct tcphdr));

                tcph->check = cheat_check(htons(tcplen) ^ 0xFFFF,
                                htons(tcplen + TCPOLEN_QSIZE),

                tcplen += TCPOLEN_QSIZE;

                /* Fill the extra 4 bytes with our option. */
                opt[0] = TCPO_QSIZE;
                opt[1] = TCPOLEN_QSIZE;

                pofq = evaluatepq(sch);
                opt[2] = (pofq & 0xff00) >> 8;
                opt[3] = (pofq & 0x00ff);

                tcph->check = cheat_check(~0, *((u_int32_t *) opt),

                oldval = ((u_int16_t *) tcph)[6];
                tcph->doff += TCPOLEN_QSIZE / 4;

                tcph->check = cheat_check(oldval ^ 0xFFFF,
                                ((u_int16_t *) tcph)[6], tcph->check);

                newtotlen = htons(ntohs(iph->tot_len) + 4);
                iph->check = cheat_check(iph->tot_len ^ 0xFFFF,
                                newtotlen, iph->check);
                iph->tot_len = newtotlen;

                /* We need to invalidate the existing checksum, in case
                 * hardware has already produced one. */
                skb->ip_summed = CHECKSUM_NONE;

                return skb;


hippo 18:32:01 up 7 days, 22:47,  6 users,  load average: 0.00, 0.00, 0.00
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


1. IP MASQ : TCP/UDP checksum errors

Hi all

Ive been using ip mascarading for over a year now, and it has never
given me any troubles at all with 0 maintainance and everything.

But just recently, ive been getting these messages in the dmesg
command output

MASQ: failed TCP/UDP checksum from!
MASQ: failed TCP/UDP checksum from!
MASQ: failed TCP/UDP checksum from!

Its not just these addresses, but lots of others too.

I only started to notice this because i play ultima online a lot, and
i seem to be losing my connection a fair bit (ussually in the middle
of a battle!), which is very frustrating.

Does anyone know what could be causing this error.  I will supply any
more info if it is required.  Im not sure if its to do with my serial
port or not, but here setserial output (for a 56k modem)

/dev/modem, Line 3, UART: 16550A, Port: 0x02e8, IRQ: 3
        Baud_base: 115200, close_delay: 50, divisor: 0
        closing_wait: 3000, closing_wait2: infinte
        Flags: spd_vhi

Please help me, im fed up of alomost dying in UO all the time ! :)

Thanks in advance

2. Problem setting up X : [screen sections]

3. TCP Checksum error with WD8013WC on FreeBSD-2.2.5 (driver ed0)

4. libc_r MFC

5. IP masquerading : TCP/UDP checksum errors

6. Stack corruption!

7. TCP Checksum Errors

8. Help

9. TCP checksum errors in Solaris 2.4

10. 2.5.65 ipv6 TCP checksum errors (capture attached)

11. strange masquerading error: failed TCP/UDP checksum for x.x.x.x!

12. MASQ: Getting frequent TCP/UDP checksum errors

13. TCP/UDP checksum error with IP masquerading