|
|
|
@ -853,61 +853,6 @@ csum_page(struct page *page, int offset, int copy) |
|
|
|
|
return csum; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline int ip_ufo_append_data(struct sock *sk, |
|
|
|
|
struct sk_buff_head *queue, |
|
|
|
|
int getfrag(void *from, char *to, int offset, int len, |
|
|
|
|
int odd, struct sk_buff *skb), |
|
|
|
|
void *from, int length, int hh_len, int fragheaderlen, |
|
|
|
|
int transhdrlen, int maxfraglen, unsigned int flags) |
|
|
|
|
{ |
|
|
|
|
struct sk_buff *skb; |
|
|
|
|
int err; |
|
|
|
|
|
|
|
|
|
/* There is support for UDP fragmentation offload by network
|
|
|
|
|
* device, so create one single skb packet containing complete |
|
|
|
|
* udp datagram |
|
|
|
|
*/ |
|
|
|
|
skb = skb_peek_tail(queue); |
|
|
|
|
if (!skb) { |
|
|
|
|
skb = sock_alloc_send_skb(sk, |
|
|
|
|
hh_len + fragheaderlen + transhdrlen + 20, |
|
|
|
|
(flags & MSG_DONTWAIT), &err); |
|
|
|
|
|
|
|
|
|
if (!skb) |
|
|
|
|
return err; |
|
|
|
|
|
|
|
|
|
/* reserve space for Hardware header */ |
|
|
|
|
skb_reserve(skb, hh_len); |
|
|
|
|
|
|
|
|
|
/* create space for UDP/IP header */ |
|
|
|
|
skb_put(skb, fragheaderlen + transhdrlen); |
|
|
|
|
|
|
|
|
|
/* initialize network header pointer */ |
|
|
|
|
skb_reset_network_header(skb); |
|
|
|
|
|
|
|
|
|
/* initialize protocol header pointer */ |
|
|
|
|
skb->transport_header = skb->network_header + fragheaderlen; |
|
|
|
|
|
|
|
|
|
skb->csum = 0; |
|
|
|
|
|
|
|
|
|
if (flags & MSG_CONFIRM) |
|
|
|
|
skb_set_dst_pending_confirm(skb, 1); |
|
|
|
|
|
|
|
|
|
__skb_queue_tail(queue, skb); |
|
|
|
|
} else if (skb_is_gso(skb)) { |
|
|
|
|
goto append; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
skb->ip_summed = CHECKSUM_PARTIAL; |
|
|
|
|
/* specify the length of each IP datagram fragment */ |
|
|
|
|
skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen; |
|
|
|
|
skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
|
|
|
|
|
|
|
|
|
append: |
|
|
|
|
return skb_append_datato_frags(sk, skb, getfrag, from, |
|
|
|
|
(length - transhdrlen)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int __ip_append_data(struct sock *sk, |
|
|
|
|
struct flowi4 *fl4, |
|
|
|
|
struct sk_buff_head *queue, |
|
|
|
@ -965,18 +910,6 @@ static int __ip_append_data(struct sock *sk, |
|
|
|
|
csummode = CHECKSUM_PARTIAL; |
|
|
|
|
|
|
|
|
|
cork->length += length; |
|
|
|
|
if ((((length + (skb ? skb->len : fragheaderlen)) > mtu) || |
|
|
|
|
(skb && skb_is_gso(skb))) && |
|
|
|
|
(sk->sk_protocol == IPPROTO_UDP) && |
|
|
|
|
(rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) && |
|
|
|
|
(sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) { |
|
|
|
|
err = ip_ufo_append_data(sk, queue, getfrag, from, length, |
|
|
|
|
hh_len, fragheaderlen, transhdrlen, |
|
|
|
|
maxfraglen, flags); |
|
|
|
|
if (err) |
|
|
|
|
goto error; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* So, what's going on in the loop below?
|
|
|
|
|
* |
|
|
|
@ -1287,15 +1220,6 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, |
|
|
|
|
if (!skb) |
|
|
|
|
return -EINVAL; |
|
|
|
|
|
|
|
|
|
if ((size + skb->len > mtu) && |
|
|
|
|
(sk->sk_protocol == IPPROTO_UDP) && |
|
|
|
|
(rt->dst.dev->features & NETIF_F_UFO)) { |
|
|
|
|
if (skb->ip_summed != CHECKSUM_PARTIAL) |
|
|
|
|
return -EOPNOTSUPP; |
|
|
|
|
|
|
|
|
|
skb_shinfo(skb)->gso_size = mtu - fragheaderlen; |
|
|
|
|
skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
|
|
|
|
} |
|
|
|
|
cork->length += size; |
|
|
|
|
|
|
|
|
|
while (size > 0) { |
|
|
|
|