]>
git.proxmox.com Git - mirror_ovs.git/blob - datapath/checksum.h
2 * Copyright (c) 2007-2011 Nicira, Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 #include <linux/skbuff.h>
23 #include <linux/version.h>
25 #include <net/checksum.h>
27 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) || \
28 (defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID))
29 #define NEED_CSUM_NORMALIZE
32 /* These are the same values as the checksum constants in 2.6.22+. */
35 OVS_CSUM_UNNECESSARY
= 1,
36 OVS_CSUM_COMPLETE
= 2,
40 #ifdef NEED_CSUM_NORMALIZE
41 int compute_ip_summed(struct sk_buff
*skb
, bool xmit
);
42 void forward_ip_summed(struct sk_buff
*skb
, bool xmit
);
43 u8
get_ip_summed(struct sk_buff
*skb
);
44 void set_ip_summed(struct sk_buff
*skb
, u8 ip_summed
);
45 void get_skb_csum_pointers(const struct sk_buff
*skb
, u16
*csum_start
,
47 void set_skb_csum_pointers(struct sk_buff
*skb
, u16 csum_start
,
50 static inline int compute_ip_summed(struct sk_buff
*skb
, bool xmit
)
55 static inline void forward_ip_summed(struct sk_buff
*skb
, bool xmit
) { }
57 static inline u8
get_ip_summed(struct sk_buff
*skb
)
59 return skb
->ip_summed
;
62 static inline void set_ip_summed(struct sk_buff
*skb
, u8 ip_summed
)
64 skb
->ip_summed
= ip_summed
;
67 static inline void get_skb_csum_pointers(const struct sk_buff
*skb
,
68 u16
*csum_start
, u16
*csum_offset
)
70 *csum_start
= skb
->csum_start
;
71 *csum_offset
= skb
->csum_offset
;
74 static inline void set_skb_csum_pointers(struct sk_buff
*skb
, u16 csum_start
,
77 skb
->csum_start
= csum_start
;
78 skb
->csum_offset
= csum_offset
;
82 /* This is really compatibility code that belongs in the compat directory.
83 * However, it needs access to our normalized checksum values, so put it here.
85 #if defined(NEED_CSUM_NORMALIZE) || LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
86 #define inet_proto_csum_replace4 rpl_inet_proto_csum_replace4
87 static inline void inet_proto_csum_replace4(__sum16
*sum
, struct sk_buff
*skb
,
88 __be32 from
, __be32 to
,
91 __be32 diff
[] = { ~from
, to
};
93 if (get_ip_summed(skb
) != OVS_CSUM_PARTIAL
) {
94 *sum
= csum_fold(csum_partial((char *)diff
, sizeof(diff
),
96 if (get_ip_summed(skb
) == OVS_CSUM_COMPLETE
&& pseudohdr
)
97 skb
->csum
= ~csum_partial((char *)diff
, sizeof(diff
),
100 *sum
= ~csum_fold(csum_partial((char *)diff
, sizeof(diff
),
105 #if defined(NEED_CSUM_NORMALIZE) || LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
106 #define inet_proto_csum_replace16 rpl_inet_proto_csum_replace16
107 static inline void inet_proto_csum_replace16(__sum16
*sum
,
114 ~from
[0], ~from
[1], ~from
[2], ~from
[3],
115 to
[0], to
[1], to
[2], to
[3],
117 if (get_ip_summed(skb
) != OVS_CSUM_PARTIAL
) {
118 *sum
= csum_fold(csum_partial(diff
, sizeof(diff
),
119 ~csum_unfold(*sum
)));
120 if (get_ip_summed(skb
) == OVS_CSUM_COMPLETE
&& pseudohdr
)
121 skb
->csum
= ~csum_partial(diff
, sizeof(diff
),
123 } else if (pseudohdr
)
124 *sum
= ~csum_fold(csum_partial(diff
, sizeof(diff
),
129 #ifdef NEED_CSUM_NORMALIZE
130 static inline void update_csum_start(struct sk_buff
*skb
, int delta
)
132 if (get_ip_summed(skb
) == OVS_CSUM_PARTIAL
) {
133 u16 csum_start
, csum_offset
;
135 get_skb_csum_pointers(skb
, &csum_start
, &csum_offset
);
136 set_skb_csum_pointers(skb
, csum_start
+ delta
, csum_offset
);
140 static inline int rpl_pskb_expand_head(struct sk_buff
*skb
, int nhead
,
141 int ntail
, gfp_t gfp_mask
)
144 int old_headroom
= skb_headroom(skb
);
146 err
= pskb_expand_head(skb
, nhead
, ntail
, gfp_mask
);
150 update_csum_start(skb
, skb_headroom(skb
) - old_headroom
);
154 #define pskb_expand_head rpl_pskb_expand_head
156 static inline unsigned char *rpl__pskb_pull_tail(struct sk_buff
*skb
,
160 int old_headroom
= skb_headroom(skb
);
162 ret
= __pskb_pull_tail(skb
, delta
);
166 update_csum_start(skb
, skb_headroom(skb
) - old_headroom
);
170 #define __pskb_pull_tail rpl__pskb_pull_tail
173 #endif /* checksum.h */