diff options
author | Willem de Bruijn <willemb@google.com> | 2018-04-26 13:42:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-26 15:08:15 -0400 |
commit | 15e36f5b8e982debe43e425d2e12d34e022d51e9 (patch) | |
tree | 94d0a83602d2fbd81784c53138d4bdd601695d19 /net/ipv4/ip_output.c | |
parent | ad405857b174ed31a97982bb129c320d03321cf5 (diff) |
udp: paged allocation with gso
When sending large datagrams that are later segmented, store data in
page frags to avoid copying from linear in skb_segment.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index da4abbee10f7..f2338e40c37d 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -878,11 +878,13 @@ static int __ip_append_data(struct sock *sk, | |||
878 | struct rtable *rt = (struct rtable *)cork->dst; | 878 | struct rtable *rt = (struct rtable *)cork->dst; |
879 | unsigned int wmem_alloc_delta = 0; | 879 | unsigned int wmem_alloc_delta = 0; |
880 | u32 tskey = 0; | 880 | u32 tskey = 0; |
881 | bool paged; | ||
881 | 882 | ||
882 | skb = skb_peek_tail(queue); | 883 | skb = skb_peek_tail(queue); |
883 | 884 | ||
884 | exthdrlen = !skb ? rt->dst.header_len : 0; | 885 | exthdrlen = !skb ? rt->dst.header_len : 0; |
885 | mtu = cork->gso_size ? IP_MAX_MTU : cork->fragsize; | 886 | mtu = cork->gso_size ? IP_MAX_MTU : cork->fragsize; |
887 | paged = !!cork->gso_size; | ||
886 | 888 | ||
887 | if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP && | 889 | if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP && |
888 | sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) | 890 | sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) |
@@ -934,6 +936,7 @@ static int __ip_append_data(struct sock *sk, | |||
934 | unsigned int fraglen; | 936 | unsigned int fraglen; |
935 | unsigned int fraggap; | 937 | unsigned int fraggap; |
936 | unsigned int alloclen; | 938 | unsigned int alloclen; |
939 | unsigned int pagedlen = 0; | ||
937 | struct sk_buff *skb_prev; | 940 | struct sk_buff *skb_prev; |
938 | alloc_new_skb: | 941 | alloc_new_skb: |
939 | skb_prev = skb; | 942 | skb_prev = skb; |
@@ -954,8 +957,12 @@ alloc_new_skb: | |||
954 | if ((flags & MSG_MORE) && | 957 | if ((flags & MSG_MORE) && |
955 | !(rt->dst.dev->features&NETIF_F_SG)) | 958 | !(rt->dst.dev->features&NETIF_F_SG)) |
956 | alloclen = mtu; | 959 | alloclen = mtu; |
957 | else | 960 | else if (!paged) |
958 | alloclen = fraglen; | 961 | alloclen = fraglen; |
962 | else { | ||
963 | alloclen = min_t(int, fraglen, MAX_HEADER); | ||
964 | pagedlen = fraglen - alloclen; | ||
965 | } | ||
959 | 966 | ||
960 | alloclen += exthdrlen; | 967 | alloclen += exthdrlen; |
961 | 968 | ||
@@ -999,7 +1006,7 @@ alloc_new_skb: | |||
999 | /* | 1006 | /* |
1000 | * Find where to start putting bytes. | 1007 | * Find where to start putting bytes. |
1001 | */ | 1008 | */ |
1002 | data = skb_put(skb, fraglen + exthdrlen); | 1009 | data = skb_put(skb, fraglen + exthdrlen - pagedlen); |
1003 | skb_set_network_header(skb, exthdrlen); | 1010 | skb_set_network_header(skb, exthdrlen); |
1004 | skb->transport_header = (skb->network_header + | 1011 | skb->transport_header = (skb->network_header + |
1005 | fragheaderlen); | 1012 | fragheaderlen); |
@@ -1015,7 +1022,7 @@ alloc_new_skb: | |||
1015 | pskb_trim_unique(skb_prev, maxfraglen); | 1022 | pskb_trim_unique(skb_prev, maxfraglen); |
1016 | } | 1023 | } |
1017 | 1024 | ||
1018 | copy = datalen - transhdrlen - fraggap; | 1025 | copy = datalen - transhdrlen - fraggap - pagedlen; |
1019 | if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { | 1026 | if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { |
1020 | err = -EFAULT; | 1027 | err = -EFAULT; |
1021 | kfree_skb(skb); | 1028 | kfree_skb(skb); |
@@ -1023,7 +1030,7 @@ alloc_new_skb: | |||
1023 | } | 1030 | } |
1024 | 1031 | ||
1025 | offset += copy; | 1032 | offset += copy; |
1026 | length -= datalen - fraggap; | 1033 | length -= copy + transhdrlen; |
1027 | transhdrlen = 0; | 1034 | transhdrlen = 0; |
1028 | exthdrlen = 0; | 1035 | exthdrlen = 0; |
1029 | csummode = CHECKSUM_NONE; | 1036 | csummode = CHECKSUM_NONE; |