linux/include/net/ip6_checksum.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 * INET         An implementation of the TCP/IP protocol suite for the LINUX
   4 *              operating system.  INET is implemented using the  BSD Socket
   5 *              interface as the means of communication with the user level.
   6 *
   7 *              Checksumming functions for IPv6
   8 *
   9 * Authors:     Jorge Cwik, <jorge@laser.satlink.net>
  10 *              Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  11 *              Borrows very liberally from tcp.c and ip.c, see those
  12 *              files for more names.
  13 */
  14
  15/*
  16 *      Fixes:
  17 *
  18 *      Ralf Baechle                    :       generic ipv6 checksum
  19 *      <ralf@waldorf-gmbh.de>
  20 */
  21
  22#ifndef _CHECKSUM_IPV6_H
  23#define _CHECKSUM_IPV6_H
  24
  25#include <asm/types.h>
  26#include <asm/byteorder.h>
  27#include <net/ip.h>
  28#include <asm/checksum.h>
  29#include <linux/in6.h>
  30#include <linux/tcp.h>
  31#include <linux/ipv6.h>
  32
  33#ifndef _HAVE_ARCH_IPV6_CSUM
  34__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
  35                        const struct in6_addr *daddr,
  36                        __u32 len, __u8 proto, __wsum csum);
  37#endif
  38
  39static inline __wsum ip6_compute_pseudo(struct sk_buff *skb, int proto)
  40{
  41        return ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
  42                                            &ipv6_hdr(skb)->daddr,
  43                                            skb->len, proto, 0));
  44}
  45
  46static inline __wsum ip6_gro_compute_pseudo(struct sk_buff *skb, int proto)
  47{
  48        const struct ipv6hdr *iph = skb_gro_network_header(skb);
  49
  50        return ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
  51                                            skb_gro_len(skb), proto, 0));
  52}
  53
  54static __inline__ __sum16 tcp_v6_check(int len,
  55                                   const struct in6_addr *saddr,
  56                                   const struct in6_addr *daddr,
  57                                   __wsum base)
  58{
  59        return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
  60}
  61
  62static inline void __tcp_v6_send_check(struct sk_buff *skb,
  63                                       const struct in6_addr *saddr,
  64                                       const struct in6_addr *daddr)
  65{
  66        struct tcphdr *th = tcp_hdr(skb);
  67
  68        if (skb->ip_summed == CHECKSUM_PARTIAL) {
  69                th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
  70                skb->csum_start = skb_transport_header(skb) - skb->head;
  71                skb->csum_offset = offsetof(struct tcphdr, check);
  72        } else {
  73                th->check = tcp_v6_check(skb->len, saddr, daddr,
  74                                         csum_partial(th, th->doff << 2,
  75                                                      skb->csum));
  76        }
  77}
  78
  79static inline void tcp_v6_gso_csum_prep(struct sk_buff *skb)
  80{
  81        struct ipv6hdr *ipv6h = ipv6_hdr(skb);
  82        struct tcphdr *th = tcp_hdr(skb);
  83
  84        ipv6h->payload_len = 0;
  85        th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
  86}
  87
  88static inline __sum16 udp_v6_check(int len,
  89                                   const struct in6_addr *saddr,
  90                                   const struct in6_addr *daddr,
  91                                   __wsum base)
  92{
  93        return csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, base);
  94}
  95
  96void udp6_set_csum(bool nocheck, struct sk_buff *skb,
  97                   const struct in6_addr *saddr,
  98                   const struct in6_addr *daddr, int len);
  99
 100int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto);
 101#endif
 102