diff options
author | David S. Miller <davem@davemloft.net> | 2014-08-29 23:41:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-29 23:41:17 -0400 |
commit | 030824e039d6702ee309bf7441c446038d6a43f7 (patch) | |
tree | db4c97c3124d1e3902ef43d65f0e93524008561c /net | |
parent | 96d49225a49536359e984fc4f21a87252aad8959 (diff) | |
parent | 71d7a2772510a05a2cec4d005f984043827718e1 (diff) |
Merge branch 'csums-next'
Tom Herbert says:
====================
net: Checksum offload changes - Part VI
I am working on overhauling RX checksum offload. Goals of this effort
are:
- Specify what exactly it means when driver returns CHECKSUM_UNNECESSARY
- Preserve CHECKSUM_COMPLETE through encapsulation layers
- Don't do skb_checksum more than once per packet
- Unify GRO and non-GRO csum verification as much as possible
- Unify the checksum functions (checksum_init)
- Simplify code
What is in this sixth patch set:
- Clarify the specific requirements of devices returning
CHECKSUM_UNNECESSARY (comments in skbuff.h).
- Add csum_level field to skbuff. This is used to express how
many checksums are covered by CHECKSUM_UNNECESSARY (stores n - 1).
- Change __skb_checksum_validate_needed to "consume" each checksum
as indicated by csum_level as layers of the the packet are parsed.
- Remove skb_pop_rcv_encapsulation, no longer needed in the new
csum_level model.
- Allow GRO path to "consume" checksums provided in CHECKSUM_UNNECESSARY
and to report new verfied checksums for use in normal path fallback.
- Add proper support to SCTP to accept CHECKSUM_UNNECESSARY to validate
header CRC.
- Modify drivers to set skb->csum_level instead of setting
skb->encapsulation to indicate validation of an encapsulated
checksum on receive.
v2:
Allocate a new 16 bits for flags in skbuff.
Please review carefully and test if possible, mucking with basic
checksum functions is always a little precarious :-)
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 24 | ||||
-rw-r--r-- | net/ipv4/gre_demux.c | 1 | ||||
-rw-r--r-- | net/ipv4/gre_offload.c | 7 | ||||
-rw-r--r-- | net/ipv4/udp_offload.c | 5 | ||||
-rw-r--r-- | net/sctp/input.c | 8 |
5 files changed, 27 insertions, 18 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 26d296c2447c..a6077ef56345 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3962,13 +3962,6 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
3962 | 3962 | ||
3963 | gro_list_prepare(napi, skb); | 3963 | gro_list_prepare(napi, skb); |
3964 | 3964 | ||
3965 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | ||
3966 | NAPI_GRO_CB(skb)->csum = skb->csum; | ||
3967 | NAPI_GRO_CB(skb)->csum_valid = 1; | ||
3968 | } else { | ||
3969 | NAPI_GRO_CB(skb)->csum_valid = 0; | ||
3970 | } | ||
3971 | |||
3972 | rcu_read_lock(); | 3965 | rcu_read_lock(); |
3973 | list_for_each_entry_rcu(ptype, head, list) { | 3966 | list_for_each_entry_rcu(ptype, head, list) { |
3974 | if (ptype->type != type || !ptype->callbacks.gro_receive) | 3967 | if (ptype->type != type || !ptype->callbacks.gro_receive) |
@@ -3980,7 +3973,22 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
3980 | NAPI_GRO_CB(skb)->flush = 0; | 3973 | NAPI_GRO_CB(skb)->flush = 0; |
3981 | NAPI_GRO_CB(skb)->free = 0; | 3974 | NAPI_GRO_CB(skb)->free = 0; |
3982 | NAPI_GRO_CB(skb)->udp_mark = 0; | 3975 | NAPI_GRO_CB(skb)->udp_mark = 0; |
3983 | NAPI_GRO_CB(skb)->encapsulation = 0; | 3976 | |
3977 | /* Setup for GRO checksum validation */ | ||
3978 | switch (skb->ip_summed) { | ||
3979 | case CHECKSUM_COMPLETE: | ||
3980 | NAPI_GRO_CB(skb)->csum = skb->csum; | ||
3981 | NAPI_GRO_CB(skb)->csum_valid = 1; | ||
3982 | NAPI_GRO_CB(skb)->csum_cnt = 0; | ||
3983 | break; | ||
3984 | case CHECKSUM_UNNECESSARY: | ||
3985 | NAPI_GRO_CB(skb)->csum_cnt = skb->csum_level + 1; | ||
3986 | NAPI_GRO_CB(skb)->csum_valid = 0; | ||
3987 | break; | ||
3988 | default: | ||
3989 | NAPI_GRO_CB(skb)->csum_cnt = 0; | ||
3990 | NAPI_GRO_CB(skb)->csum_valid = 0; | ||
3991 | } | ||
3984 | 3992 | ||
3985 | pp = ptype->callbacks.gro_receive(&napi->gro_list, skb); | 3993 | pp = ptype->callbacks.gro_receive(&napi->gro_list, skb); |
3986 | break; | 3994 | break; |
diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index 7c1a8ff974dd..0485bf7f8f03 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c | |||
@@ -125,7 +125,6 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
125 | *csum_err = true; | 125 | *csum_err = true; |
126 | return -EINVAL; | 126 | return -EINVAL; |
127 | } | 127 | } |
128 | skb_pop_rcv_encapsulation(skb); | ||
129 | options++; | 128 | options++; |
130 | } | 129 | } |
131 | 130 | ||
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index d1bd16937d93..a4d7965fb880 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
@@ -172,12 +172,9 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /* Don't bother verifying checksum if we're going to flush anyway. */ | 174 | /* Don't bother verifying checksum if we're going to flush anyway. */ |
175 | if (greh->flags & GRE_CSUM) { | 175 | if ((greh->flags & GRE_CSUM) && !NAPI_GRO_CB(skb)->flush && |
176 | if (!NAPI_GRO_CB(skb)->flush && | 176 | skb_gro_checksum_simple_validate(skb)) |
177 | skb_gro_checksum_simple_validate(skb)) | ||
178 | goto out_unlock; | 177 | goto out_unlock; |
179 | NAPI_GRO_CB(skb)->encapsulation++; | ||
180 | } | ||
181 | 178 | ||
182 | flush = 0; | 179 | flush = 0; |
183 | 180 | ||
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 8ed460e3753c..a6adff98382a 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -238,12 +238,13 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, | |||
238 | int flush = 1; | 238 | int flush = 1; |
239 | 239 | ||
240 | if (NAPI_GRO_CB(skb)->udp_mark || | 240 | if (NAPI_GRO_CB(skb)->udp_mark || |
241 | (!skb->encapsulation && !NAPI_GRO_CB(skb)->csum_valid)) | 241 | (skb->ip_summed != CHECKSUM_PARTIAL && |
242 | NAPI_GRO_CB(skb)->csum_cnt == 0 && | ||
243 | !NAPI_GRO_CB(skb)->csum_valid)) | ||
242 | goto out; | 244 | goto out; |
243 | 245 | ||
244 | /* mark that this skb passed once through the udp gro layer */ | 246 | /* mark that this skb passed once through the udp gro layer */ |
245 | NAPI_GRO_CB(skb)->udp_mark = 1; | 247 | NAPI_GRO_CB(skb)->udp_mark = 1; |
246 | NAPI_GRO_CB(skb)->encapsulation++; | ||
247 | 248 | ||
248 | rcu_read_lock(); | 249 | rcu_read_lock(); |
249 | uo_priv = rcu_dereference(udp_offload_base); | 250 | uo_priv = rcu_dereference(udp_offload_base); |
diff --git a/net/sctp/input.c b/net/sctp/input.c index c1b991294516..b6493b3f11a9 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -133,9 +133,13 @@ int sctp_rcv(struct sk_buff *skb) | |||
133 | __skb_pull(skb, skb_transport_offset(skb)); | 133 | __skb_pull(skb, skb_transport_offset(skb)); |
134 | if (skb->len < sizeof(struct sctphdr)) | 134 | if (skb->len < sizeof(struct sctphdr)) |
135 | goto discard_it; | 135 | goto discard_it; |
136 | if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) && | 136 | |
137 | sctp_rcv_checksum(net, skb) < 0) | 137 | skb->csum_valid = 0; /* Previous value not applicable */ |
138 | if (skb_csum_unnecessary(skb)) | ||
139 | __skb_decr_checksum_unnecessary(skb); | ||
140 | else if (!sctp_checksum_disable && sctp_rcv_checksum(net, skb) < 0) | ||
138 | goto discard_it; | 141 | goto discard_it; |
142 | skb->csum_valid = 1; | ||
139 | 143 | ||
140 | skb_pull(skb, sizeof(struct sctphdr)); | 144 | skb_pull(skb, sizeof(struct sctphdr)); |
141 | 145 | ||