/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __UM_CHECKSUM_H
#define __UM_CHECKSUM_H
#include <linux/string.h>
#include <linux/in6.h>
#include <linux/uaccess.h>
/*
* computes the checksum of a memory block at buff , length len ,
* and adds in " sum " ( 32 - bit )
*
* returns a 32 - bit number suitable for feeding into itself
* or csum_tcpudp_magic
*
* this function must be called with even lengths , except
* for the last fragment , which may be odd
*
* it ' s best to have buff aligned on a 32 - bit boundary
*/
extern __wsum csum_partial(const void *buff, int len, __wsum sum);
/* Do not call this directly. Declared for export type visibility. */
extern __visible __wsum csum_partial_copy_generic(const void *src, void *dst, int len);
/**
* csum_fold - Fold and invert a 32 bit checksum .
* sum : 32 bit unfolded sum
*
* Fold a 32 bit running checksum to 16 bit and invert it . This is usually
* the last step before putting a checksum into a packet .
* Make sure not to mix with 64 bit checksums .
*/
static inline __sum16 csum_fold(__wsum sum)
{
__asm__(
" addl %1,%0\n"
" adcl $0xffff,%0"
: "=r" (sum)
: "r" ((__force u32)sum << 16 ),
"0" ((__force u32)sum & 0 xffff0000)
);
return (__force __sum16)(~(__force u32)sum >> 16 );
}
/**
* csum_tcpup_nofold - Compute an IPv4 pseudo header checksum .
* @ saddr : source address
* @ daddr : destination address
* @ len : length of packet
* @ proto : ip protocol of packet
* @ sum : initial sum to be added in ( 32 bit unfolded )
*
* Returns the pseudo header checksum the input data . Result is
* 32 bit unfolded .
*/
static inline __wsum
csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,
__u8 proto, __wsum sum)
{
asm (" addl %1, %0\n"
" adcl %2, %0\n"
" adcl %3, %0\n"
" adcl $0, %0\n"
: "=r" (sum)
: "g" (daddr), "g" (saddr), "g" ((len + proto) << 8 ), "0" (sum));
return sum;
}
/*
* computes the checksum of the TCP / UDP pseudo - header
* returns a 16 - bit checksum , already complemented
*/
static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
__u32 len, __u8 proto,
__wsum sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
/**
* ip_fast_csum - Compute the IPv4 header checksum efficiently .
* iph : ipv4 header
* ihl : length of header / 4
*/
static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum;
asm ( " movl (%1), %0\n"
" subl $4, %2\n"
" jbe 2f\n"
" addl 4(%1), %0\n"
" adcl 8(%1), %0\n"
" adcl 12(%1), %0\n"
"1: adcl 16(%1), %0\n"
" lea 4(%1), %1\n"
" decl %2\n"
" jne 1b\n"
" adcl $0, %0\n"
" movl %0, %2\n"
" shrl $16, %0\n"
" addw %w2, %w0\n"
" adcl $0, %0\n"
" notl %0\n"
"2:"
/* Since the input registers which are loaded with iph and ipl
are modified , we must also specify them as outputs , or gcc
will assume they contain their original values. */
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory" );
return (__force __sum16)sum;
}
#ifdef CONFIG_X86_32
# include "checksum_32.h"
#else
# include "checksum_64.h"
#endif
#endif
Messung V0.5 in Prozent C=94 H=87 G=90
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland