/* * * IP checksum routines * * Copyright (C) Original authors of ../asm-i386/checksum.h * Copyright (C) 1996-1999 Russell King */ #include unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); /* * This is a version of ip_compute_csum() optimized for IP headers, * which always checksum on 4 octet boundaries. */ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) { unsigned int sum, tmp1; __asm__ __volatile__( " mov %1, %%r2\n\t" " ld (%%r2, 0), %0\n\t" " add %%r2, 4, %%r2\n\t" " ld (%%r2, 0), %3\n\t" " add %%r2, 4, %%r2\n\t" " sub %2, 5, %2\n\t" " add %0, %3, %0\n\t" " adc %0, 0, %0\n\t" " ld (%%r2, 0), %3\n\t" " add %%r2, 4, %%r2\n\t" " add %0, %3, %0\n\t" " adc %0, 0, %0\n\t" " ld (%%r2, 0), %3\n\t" " add %%r2, 4, %%r2\n\t" " add %0, %3, %0\n\t" " adc %0, 0, %0\n\t" "1: ld (%%r2, 0), %3\n\t" " add %%r2, 4, %%r2\n\t" " add %0, %3, %0\n\t" " adc %0, 0, %0\n\t" " tst %2, 15\n\t" " jz 2f\n\t" " sub %2, 1, %2\n\t" " jmp 1b\n\t" "2: mov %0, %3\n\t" " asl 16, %3\n\t" " add %0, %3, %0\n\t" " jnc 3f\n\t" " add %0, 0x10000, %0\n\t" "3: xor %0, 0xFFFFFFFF, %0\n\t" " lsr 16, %0\n\t" : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1) : "1" (iph), "2" (ihl) : "%r2" ); return sum; } /* * Fold a partial checksum without adding pseudo headers */ unsigned int csum_fold(unsigned int sum) { __asm__ __volatile__( " mov %0, %%r2\n\t" " asl 16, %%r2\n\t" " add %%r2, %0, %0\n\t" " jnc 1f\n\t" " add %0, 0x10000, %0\n\t" "1: \n\t" : "=r" (sum) : "0" (sum) : "%r2" ); return (~sum) >> 16; } unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned int proto, unsigned int sum) { __asm__ __volatile__( " add %0, %2, %0\n\t" " adc %0, %3, %0\n\t" " adc %0, %4, %0\n\t" " adc %0, %5, %0\n\t" " adc %0, 0, %0\n\t" : "=&r"(sum) : "0" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len) << 16), "r" (proto << 8) ); return sum; } /* * computes the checksum of the TCP/UDP pseudo-header * returns a 16-bit checksum, already complemented */ unsigned short int csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned int proto, unsigned int sum) { __asm__ __volatile__( " add %0, %2, %0\n\t" " adc %0, %3, %0\n\t" " adc %0, %4, %0\n\t" " adc %0, %5, %0\n\t" " adc %0, 0, %0\n\t" " mov %0, %%r2\n\t" " asl 16, %%r2\n\t" " add %%r2, %0, %0\n\t" " jnc 1f\n\t" " add %0, 0x10000, %0\n\t" "1: xor %0, 0xFFFFFFFF, %0\n\t" : "=&r"(sum) : "0" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len)<<16), "r" (proto << 8) : "%r2"); return sum >> 16; } unsigned short int ip_compute_csum(unsigned char *buff,int len) { return csum_fold(csum_partial(buff,len,0)); } /* by lbh 2003/03/05 */