diff options
author | Tom Herbert <therbert@google.com> | 2015-02-10 19:30:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-11 18:12:13 -0500 |
commit | fe881ef11cf0220f118816181930494d484c4883 (patch) | |
tree | fc3c9744cddeb0bba07c0ed258de06df4eb01487 /net | |
parent | 0ace2ca89cbd6bcdf2b9d2df1fa0fa24ea9d1653 (diff) |
gue: Use checksum partial with remote checksum offload
Change remote checksum handling to set checksum partial as default
behavior. Added an iflink parameter to configure not using
checksum partial (calling csum_partial to update checksum).
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/fou.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index d320f575cc62..ff069f6597ac 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c | |||
@@ -22,14 +22,18 @@ static LIST_HEAD(fou_list); | |||
22 | struct fou { | 22 | struct fou { |
23 | struct socket *sock; | 23 | struct socket *sock; |
24 | u8 protocol; | 24 | u8 protocol; |
25 | u8 flags; | ||
25 | u16 port; | 26 | u16 port; |
26 | struct udp_offload udp_offloads; | 27 | struct udp_offload udp_offloads; |
27 | struct list_head list; | 28 | struct list_head list; |
28 | }; | 29 | }; |
29 | 30 | ||
31 | #define FOU_F_REMCSUM_NOPARTIAL BIT(0) | ||
32 | |||
30 | struct fou_cfg { | 33 | struct fou_cfg { |
31 | u16 type; | 34 | u16 type; |
32 | u8 protocol; | 35 | u8 protocol; |
36 | u8 flags; | ||
33 | struct udp_port_cfg udp_config; | 37 | struct udp_port_cfg udp_config; |
34 | }; | 38 | }; |
35 | 39 | ||
@@ -64,7 +68,8 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb) | |||
64 | } | 68 | } |
65 | 69 | ||
66 | static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, | 70 | static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, |
67 | void *data, size_t hdrlen, u8 ipproto) | 71 | void *data, size_t hdrlen, u8 ipproto, |
72 | bool nopartial) | ||
68 | { | 73 | { |
69 | __be16 *pd = data; | 74 | __be16 *pd = data; |
70 | size_t start = ntohs(pd[0]); | 75 | size_t start = ntohs(pd[0]); |
@@ -75,7 +80,8 @@ static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, | |||
75 | return NULL; | 80 | return NULL; |
76 | guehdr = (struct guehdr *)&udp_hdr(skb)[1]; | 81 | guehdr = (struct guehdr *)&udp_hdr(skb)[1]; |
77 | 82 | ||
78 | skb_remcsum_process(skb, (void *)guehdr + hdrlen, start, offset, true); | 83 | skb_remcsum_process(skb, (void *)guehdr + hdrlen, |
84 | start, offset, nopartial); | ||
79 | 85 | ||
80 | return guehdr; | 86 | return guehdr; |
81 | } | 87 | } |
@@ -136,7 +142,9 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb) | |||
136 | 142 | ||
137 | if (flags & GUE_PFLAG_REMCSUM) { | 143 | if (flags & GUE_PFLAG_REMCSUM) { |
138 | guehdr = gue_remcsum(skb, guehdr, data + doffset, | 144 | guehdr = gue_remcsum(skb, guehdr, data + doffset, |
139 | hdrlen, guehdr->proto_ctype); | 145 | hdrlen, guehdr->proto_ctype, |
146 | !!(fou->flags & | ||
147 | FOU_F_REMCSUM_NOPARTIAL)); | ||
140 | if (!guehdr) | 148 | if (!guehdr) |
141 | goto drop; | 149 | goto drop; |
142 | 150 | ||
@@ -209,7 +217,7 @@ out_unlock: | |||
209 | static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, | 217 | static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, |
210 | struct guehdr *guehdr, void *data, | 218 | struct guehdr *guehdr, void *data, |
211 | size_t hdrlen, u8 ipproto, | 219 | size_t hdrlen, u8 ipproto, |
212 | struct gro_remcsum *grc) | 220 | struct gro_remcsum *grc, bool nopartial) |
213 | { | 221 | { |
214 | __be16 *pd = data; | 222 | __be16 *pd = data; |
215 | size_t start = ntohs(pd[0]); | 223 | size_t start = ntohs(pd[0]); |
@@ -230,7 +238,7 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, | |||
230 | } | 238 | } |
231 | 239 | ||
232 | skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen, | 240 | skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen, |
233 | start, offset, grc, true); | 241 | start, offset, grc, nopartial); |
234 | 242 | ||
235 | skb->remcsum_offload = 1; | 243 | skb->remcsum_offload = 1; |
236 | 244 | ||
@@ -250,6 +258,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, | |||
250 | void *data; | 258 | void *data; |
251 | u16 doffset = 0; | 259 | u16 doffset = 0; |
252 | int flush = 1; | 260 | int flush = 1; |
261 | struct fou *fou = container_of(uoff, struct fou, udp_offloads); | ||
253 | struct gro_remcsum grc; | 262 | struct gro_remcsum grc; |
254 | 263 | ||
255 | skb_gro_remcsum_init(&grc); | 264 | skb_gro_remcsum_init(&grc); |
@@ -294,7 +303,9 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, | |||
294 | if (flags & GUE_PFLAG_REMCSUM) { | 303 | if (flags & GUE_PFLAG_REMCSUM) { |
295 | guehdr = gue_gro_remcsum(skb, off, guehdr, | 304 | guehdr = gue_gro_remcsum(skb, off, guehdr, |
296 | data + doffset, hdrlen, | 305 | data + doffset, hdrlen, |
297 | guehdr->proto_ctype, &grc); | 306 | guehdr->proto_ctype, &grc, |
307 | !!(fou->flags & | ||
308 | FOU_F_REMCSUM_NOPARTIAL)); | ||
298 | if (!guehdr) | 309 | if (!guehdr) |
299 | goto out; | 310 | goto out; |
300 | 311 | ||
@@ -455,6 +466,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, | |||
455 | 466 | ||
456 | sk = sock->sk; | 467 | sk = sock->sk; |
457 | 468 | ||
469 | fou->flags = cfg->flags; | ||
458 | fou->port = cfg->udp_config.local_udp_port; | 470 | fou->port = cfg->udp_config.local_udp_port; |
459 | 471 | ||
460 | /* Initial for fou type */ | 472 | /* Initial for fou type */ |
@@ -541,6 +553,7 @@ static struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = { | |||
541 | [FOU_ATTR_AF] = { .type = NLA_U8, }, | 553 | [FOU_ATTR_AF] = { .type = NLA_U8, }, |
542 | [FOU_ATTR_IPPROTO] = { .type = NLA_U8, }, | 554 | [FOU_ATTR_IPPROTO] = { .type = NLA_U8, }, |
543 | [FOU_ATTR_TYPE] = { .type = NLA_U8, }, | 555 | [FOU_ATTR_TYPE] = { .type = NLA_U8, }, |
556 | [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, }, | ||
544 | }; | 557 | }; |
545 | 558 | ||
546 | static int parse_nl_config(struct genl_info *info, | 559 | static int parse_nl_config(struct genl_info *info, |
@@ -571,6 +584,9 @@ static int parse_nl_config(struct genl_info *info, | |||
571 | if (info->attrs[FOU_ATTR_TYPE]) | 584 | if (info->attrs[FOU_ATTR_TYPE]) |
572 | cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]); | 585 | cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]); |
573 | 586 | ||
587 | if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL]) | ||
588 | cfg->flags |= FOU_F_REMCSUM_NOPARTIAL; | ||
589 | |||
574 | return 0; | 590 | return 0; |
575 | } | 591 | } |
576 | 592 | ||