|
@@ -617,7 +617,8 @@ struct sk_buff {
|
|
|
|
|
|
kmemcheck_bitfield_begin(flags3);
|
|
|
__u8 csum_level:2;
|
|
|
- /* 14 bit hole */
|
|
|
+ __u8 csum_bad:1;
|
|
|
+ /* 13 bit hole */
|
|
|
kmemcheck_bitfield_end(flags3);
|
|
|
|
|
|
__be16 inner_protocol;
|
|
@@ -2825,6 +2826,21 @@ static inline void __skb_incr_checksum_unnecessary(struct sk_buff *skb)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static inline void __skb_mark_checksum_bad(struct sk_buff *skb)
|
|
|
+{
|
|
|
+ /* Mark current checksum as bad (typically called from GRO
|
|
|
+ * path). In the case that ip_summed is CHECKSUM_NONE
|
|
|
+ * this must be the first checksum encountered in the packet.
|
|
|
+ * When ip_summed is CHECKSUM_UNNECESSARY, this is the first
|
|
|
+ * checksum after the last one validated. For UDP, a zero
|
|
|
+ * checksum can not be marked as bad.
|
|
|
+ */
|
|
|
+
|
|
|
+ if (skb->ip_summed == CHECKSUM_NONE ||
|
|
|
+ skb->ip_summed == CHECKSUM_UNNECESSARY)
|
|
|
+ skb->csum_bad = 1;
|
|
|
+}
|
|
|
+
|
|
|
/* Check if we need to perform checksum complete validation.
|
|
|
*
|
|
|
* Returns true if checksum complete is needed, false otherwise
|
|
@@ -2866,6 +2882,9 @@ static inline __sum16 __skb_checksum_validate_complete(struct sk_buff *skb,
|
|
|
skb->csum_valid = 1;
|
|
|
return 0;
|
|
|
}
|
|
|
+ } else if (skb->csum_bad) {
|
|
|
+ /* ip_summed == CHECKSUM_NONE in this case */
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
skb->csum = psum;
|
|
@@ -2923,6 +2942,26 @@ static inline __wsum null_compute_pseudo(struct sk_buff *skb, int proto)
|
|
|
#define skb_checksum_simple_validate(skb) \
|
|
|
__skb_checksum_validate(skb, 0, true, false, 0, null_compute_pseudo)
|
|
|
|
|
|
+static inline bool __skb_checksum_convert_check(struct sk_buff *skb)
|
|
|
+{
|
|
|
+ return (skb->ip_summed == CHECKSUM_NONE &&
|
|
|
+ skb->csum_valid && !skb->csum_bad);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void __skb_checksum_convert(struct sk_buff *skb,
|
|
|
+ __sum16 check, __wsum pseudo)
|
|
|
+{
|
|
|
+ skb->csum = ~pseudo;
|
|
|
+ skb->ip_summed = CHECKSUM_COMPLETE;
|
|
|
+}
|
|
|
+
|
|
|
+#define skb_checksum_try_convert(skb, proto, check, compute_pseudo) \
|
|
|
+do { \
|
|
|
+ if (__skb_checksum_convert_check(skb)) \
|
|
|
+ __skb_checksum_convert(skb, check, \
|
|
|
+ compute_pseudo(skb, proto)); \
|
|
|
+} while (0)
|
|
|
+
|
|
|
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
|
|
void nf_conntrack_destroy(struct nf_conntrack *nfct);
|
|
|
static inline void nf_conntrack_put(struct nf_conntrack *nfct)
|