diff options
author | Tom Herbert <therbert@google.com> | 2015-02-10 19:30:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-11 18:12:13 -0500 |
commit | 0ace2ca89cbd6bcdf2b9d2df1fa0fa24ea9d1653 (patch) | |
tree | 77d53c7e1f2c5b67b683cbb874f3587eddea81cf | |
parent | 15e2396d4e3ce23188852b74d924107982c63b42 (diff) |
vxlan: 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>
-rw-r--r-- | drivers/net/vxlan.c | 25 | ||||
-rw-r--r-- | include/net/vxlan.h | 4 | ||||
-rw-r--r-- | include/uapi/linux/if_link.h | 1 |
3 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 4f04443cfd33..1e0a775ea882 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -555,7 +555,8 @@ static int vxlan_fdb_append(struct vxlan_fdb *f, | |||
555 | static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, | 555 | static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, |
556 | unsigned int off, | 556 | unsigned int off, |
557 | struct vxlanhdr *vh, size_t hdrlen, | 557 | struct vxlanhdr *vh, size_t hdrlen, |
558 | u32 data, struct gro_remcsum *grc) | 558 | u32 data, struct gro_remcsum *grc, |
559 | bool nopartial) | ||
559 | { | 560 | { |
560 | size_t start, offset, plen; | 561 | size_t start, offset, plen; |
561 | 562 | ||
@@ -580,7 +581,7 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb, | |||
580 | } | 581 | } |
581 | 582 | ||
582 | skb_gro_remcsum_process(skb, (void *)vh + hdrlen, | 583 | skb_gro_remcsum_process(skb, (void *)vh + hdrlen, |
583 | start, offset, grc, true); | 584 | start, offset, grc, nopartial); |
584 | 585 | ||
585 | skb->remcsum_offload = 1; | 586 | skb->remcsum_offload = 1; |
586 | 587 | ||
@@ -618,7 +619,9 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, | |||
618 | 619 | ||
619 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { | 620 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { |
620 | vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), | 621 | vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), |
621 | ntohl(vh->vx_vni), &grc); | 622 | ntohl(vh->vx_vni), &grc, |
623 | !!(vs->flags & | ||
624 | VXLAN_F_REMCSUM_NOPARTIAL)); | ||
622 | 625 | ||
623 | if (!vh) | 626 | if (!vh) |
624 | goto out; | 627 | goto out; |
@@ -1155,7 +1158,7 @@ static void vxlan_igmp_leave(struct work_struct *work) | |||
1155 | } | 1158 | } |
1156 | 1159 | ||
1157 | static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, | 1160 | static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, |
1158 | size_t hdrlen, u32 data) | 1161 | size_t hdrlen, u32 data, bool nopartial) |
1159 | { | 1162 | { |
1160 | size_t start, offset, plen; | 1163 | size_t start, offset, plen; |
1161 | 1164 | ||
@@ -1171,7 +1174,8 @@ static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, | |||
1171 | 1174 | ||
1172 | vh = (struct vxlanhdr *)(udp_hdr(skb) + 1); | 1175 | vh = (struct vxlanhdr *)(udp_hdr(skb) + 1); |
1173 | 1176 | ||
1174 | skb_remcsum_process(skb, (void *)vh + hdrlen, start, offset, true); | 1177 | skb_remcsum_process(skb, (void *)vh + hdrlen, start, offset, |
1178 | nopartial); | ||
1175 | 1179 | ||
1176 | return vh; | 1180 | return vh; |
1177 | } | 1181 | } |
@@ -1208,7 +1212,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) | |||
1208 | goto drop; | 1212 | goto drop; |
1209 | 1213 | ||
1210 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { | 1214 | if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { |
1211 | vxh = vxlan_remcsum(skb, vxh, sizeof(struct vxlanhdr), vni); | 1215 | vxh = vxlan_remcsum(skb, vxh, sizeof(struct vxlanhdr), vni, |
1216 | !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); | ||
1212 | if (!vxh) | 1217 | if (!vxh) |
1213 | goto drop; | 1218 | goto drop; |
1214 | 1219 | ||
@@ -2437,6 +2442,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { | |||
2437 | [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 }, | 2442 | [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 }, |
2438 | [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 }, | 2443 | [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 }, |
2439 | [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, }, | 2444 | [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, }, |
2445 | [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, | ||
2440 | }; | 2446 | }; |
2441 | 2447 | ||
2442 | static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) | 2448 | static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) |
@@ -2760,6 +2766,9 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, | |||
2760 | if (data[IFLA_VXLAN_GBP]) | 2766 | if (data[IFLA_VXLAN_GBP]) |
2761 | vxlan->flags |= VXLAN_F_GBP; | 2767 | vxlan->flags |= VXLAN_F_GBP; |
2762 | 2768 | ||
2769 | if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) | ||
2770 | vxlan->flags |= VXLAN_F_REMCSUM_NOPARTIAL; | ||
2771 | |||
2763 | if (vxlan_find_vni(src_net, vni, use_ipv6 ? AF_INET6 : AF_INET, | 2772 | if (vxlan_find_vni(src_net, vni, use_ipv6 ? AF_INET6 : AF_INET, |
2764 | vxlan->dst_port, vxlan->flags)) { | 2773 | vxlan->dst_port, vxlan->flags)) { |
2765 | pr_info("duplicate VNI %u\n", vni); | 2774 | pr_info("duplicate VNI %u\n", vni); |
@@ -2909,6 +2918,10 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
2909 | nla_put_flag(skb, IFLA_VXLAN_GBP)) | 2918 | nla_put_flag(skb, IFLA_VXLAN_GBP)) |
2910 | goto nla_put_failure; | 2919 | goto nla_put_failure; |
2911 | 2920 | ||
2921 | if (vxlan->flags & VXLAN_F_REMCSUM_NOPARTIAL && | ||
2922 | nla_put_flag(skb, IFLA_VXLAN_REMCSUM_NOPARTIAL)) | ||
2923 | goto nla_put_failure; | ||
2924 | |||
2912 | return 0; | 2925 | return 0; |
2913 | 2926 | ||
2914 | nla_put_failure: | 2927 | nla_put_failure: |
diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 2927d6244481..eabd3a038674 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h | |||
@@ -128,13 +128,15 @@ struct vxlan_sock { | |||
128 | #define VXLAN_F_REMCSUM_TX 0x200 | 128 | #define VXLAN_F_REMCSUM_TX 0x200 |
129 | #define VXLAN_F_REMCSUM_RX 0x400 | 129 | #define VXLAN_F_REMCSUM_RX 0x400 |
130 | #define VXLAN_F_GBP 0x800 | 130 | #define VXLAN_F_GBP 0x800 |
131 | #define VXLAN_F_REMCSUM_NOPARTIAL 0x1000 | ||
131 | 132 | ||
132 | /* Flags that are used in the receive patch. These flags must match in | 133 | /* Flags that are used in the receive patch. These flags must match in |
133 | * order for a socket to be shareable | 134 | * order for a socket to be shareable |
134 | */ | 135 | */ |
135 | #define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \ | 136 | #define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \ |
136 | VXLAN_F_UDP_ZERO_CSUM6_RX | \ | 137 | VXLAN_F_UDP_ZERO_CSUM6_RX | \ |
137 | VXLAN_F_REMCSUM_RX) | 138 | VXLAN_F_REMCSUM_RX | \ |
139 | VXLAN_F_REMCSUM_NOPARTIAL) | ||
138 | 140 | ||
139 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, | 141 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, |
140 | vxlan_rcv_t *rcv, void *data, | 142 | vxlan_rcv_t *rcv, void *data, |
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 0deee3eeddbf..dfd0bb22e554 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h | |||
@@ -374,6 +374,7 @@ enum { | |||
374 | IFLA_VXLAN_REMCSUM_TX, | 374 | IFLA_VXLAN_REMCSUM_TX, |
375 | IFLA_VXLAN_REMCSUM_RX, | 375 | IFLA_VXLAN_REMCSUM_RX, |
376 | IFLA_VXLAN_GBP, | 376 | IFLA_VXLAN_GBP, |
377 | IFLA_VXLAN_REMCSUM_NOPARTIAL, | ||
377 | __IFLA_VXLAN_MAX | 378 | __IFLA_VXLAN_MAX |
378 | }; | 379 | }; |
379 | #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) | 380 | #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) |