diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c index 5a8c388ebf0e4d..b737fef1c4e810 100644 --- a/net/xfrm/xfrm_iptfs.c +++ b/net/xfrm/xfrm_iptfs.c @@ -1795,10 +1795,11 @@ static void iptfs_output_prepare_skb(struct sk_buff *skb, uint blkoff) } static int iptfs_first_skb(struct sk_buff **skbp, struct xfrm_iptfs_data *xtfs, - uint mtu, uint blkoff) + uint mtu) { struct sk_buff *skb = *skbp; struct sk_buff *nskb, *head_skb; + uint blkoff; int err; /* @@ -1814,7 +1815,6 @@ static int iptfs_first_skb(struct sk_buff **skbp, struct xfrm_iptfs_data *xtfs, /* The opportunity for HW offload has ended */ if (skb->ip_summed == CHECKSUM_PARTIAL) { - BUG_ON(blkoff); err = skb_checksum_help(skb); if (err) return err; @@ -1971,33 +1971,11 @@ static struct sk_buff **iptfs_rehome_fraglist(struct sk_buff **nextp, return nextp; } -/* - * Return if we should fragment skb using `remaining` octets. For now we just - * say yes as long as the length field of an IPv6 (thus IPv4 too) header will - * fit; however, we can do smarter things here. For example, see that the output - * queue is not growing over time then we could wait to send this skb in it's - * own packet avoiding fragmentation. - * - * TODO: add a short history of queue sizes when we unload the queue and use - * this to determine if we should fragment. - * - * We also do not try and fragment non-linerar skbs or create tiny fragments - * heads less than enough to container IP/IPv6 packet length field. - */ -static bool iptfs_should_fragment(struct sk_buff *skb, uint mtu, uint remaining) -{ - if (skb_is_nonlinear(skb)) - return false; - return remaining >= 6; // true; -} - static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list) { struct xfrm_iptfs_data *xtfs = x->mode_data; uint payload_mtu = xtfs->payload_mtu; - bool df = xtfs->cfg.dont_frag; - struct sk_buff *skb, *skb2, *nskb, **nextp; - uint blkoff; + struct sk_buff *skb, *skb2, **nextp; /* For now we are just outputting packets as fast as we can, so if we * are fragmenting we will do so until the last inner packet has been @@ -2053,11 +2031,6 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list) * */ - /* blkoff is the offset to the start of the next packet if a fragment - * is at the start - */ - blkoff = 0; - /* and send them on their way */ while ((skb = __skb_dequeue(list))) { @@ -2081,14 +2054,14 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list) XFRM_INC_STATS(dev_net(skb->dev), LINUX_MIB_XFRMOUTERROR); - trace_iptfs_first_toobig(skb, xtfs, mtu, blkoff); + trace_iptfs_first_toobig(skb, xtfs, mtu, 0); kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG); continue; } remaining = mtu; - if (iptfs_first_skb(&skb, xtfs, mtu, blkoff)) { + if (iptfs_first_skb(&skb, xtfs, mtu)) { kfree_skb(skb); continue; } @@ -2099,11 +2072,9 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list) */ remaining -= (skb->len - sizeof(struct ip_iptfs_hdr)); - /* - * we are starting over now, no fragmentation yet. + /* Rehome fragment lists so we don't have fragments lists of + * fragment lists. */ - blkoff = 0; - nextp = &skb_shinfo(skb)->frag_list; while (*nextp) { if (skb_has_frag_list(*nextp)) @@ -2137,9 +2108,7 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list) * happen as the list get's walked and freed but maybe * this is out leak? */ - // skb_ext_put(skb2); - - // skb_shinfo(skb)->frag_list = skb2; + // skb_ext_putskb_shinfo(skb)->frag_list = skb2; *nextp = skb2; nextp = &skb2->next; BUG_ON(*nextp != NULL); @@ -2157,94 +2126,12 @@ static void iptfs_output_queued(struct xfrm_state *x, struct sk_buff_head *list) } /* - * Check to see if we had a packet that didn't fit that we could - * fragment into the current iptfs skb. + * Consider fragmenting this skb2 that didn't fit. For demand + * driven variable sized IPTFS pkts, though this isn't buying + * a whole lot, especially if we are doing a copy which waiting + * to send in a new pkt would not. */ - if (!df && skb2 && !skb_has_frag_list(skb2) && - iptfs_should_fragment(skb2, mtu, remaining)) { - struct sk_buff *head_skb; - - /* TODO: remove this when we start sharing page frags */ - BUG_ON(skb_is_nonlinear(skb2)); - - /* The opportunity for HW offload has ended */ - /* XXX we are we doing anything with cksum here? */ - if (skb2->ip_summed == CHECKSUM_PARTIAL) { - if (skb_checksum_help(skb2)) { - BUG_ON(skb2 != __skb_dequeue(list)); - XFRM_INC_STATS( - dev_net(skb_dst(skb2)->dev), - LINUX_MIB_XFRMOUTERROR); - kfree_skb(skb2); - goto sendit; - } - } - - head_skb = iptfs_alloc_header_skb(); - if (!head_skb) - goto sendit; - - nskb = skb_clone(skb2, GFP_ATOMIC); - if (!nskb) { - consume_skb(head_skb); - XFRM_INC_STATS(dev_net(skb->dev), - LINUX_MIB_XFRMOUTERROR); - pr_err_ratelimited("failed to clone skb\n"); - goto sendit; - } - - /* Dequeue now that there's no chance of error */ - __skb_unlink(skb2, list); - - /* copy a couple selected items from skb2 into new head skb */ - head_skb->tstamp = skb2->tstamp; - head_skb->dev = skb2->dev; - memcpy(head_skb->cb, skb2->cb, sizeof(skb2->cb)); - skb_dst_copy(head_skb, skb2); - __skb_ext_copy(head_skb, skb2); - __nf_copy(head_skb, skb2, false); - - pr_devinf( - "appending skb as fragment: skb2->len %u skb2->data_len %u\n", - skb2->len, skb2->data_len); - - /* Set skb2 to remaining avail len, pull down remainning - * from the clone nskb. - */ - __skb_set_length(skb2, remaining); - __skb_pull(nskb, remaining); - - /* put leftovers into blank head skb */ - skb_shinfo(head_skb)->frag_list = nskb; - head_skb->len += nskb->len; - head_skb->data_len += nskb->len; - head_skb->truesize += nskb->truesize; - blkoff = head_skb->len; - - pr_devinf( - "append fragment len %u data_len %u proto %u seq %u\n" - "new head and leftover on queue with remaining len %u data_len %u\n", - skb2->len, skb2->data_len, _proto(skb2), - _seq(skb2), head_skb->len, head_skb->data_len); - - /* link skb2 into current packet */ - *nextp = skb2; - nextp = &skb2->next; - BUG_ON(*nextp != NULL); - skb->data_len += skb2->len; - skb->len += skb2->len; - skb->truesize += skb2->truesize; - - if (skb_has_frag_list(skb2)) - nextp = iptfs_rehome_fraglist(nextp, skb2); - remaining -= skb2->len; - BUG_ON(remaining != 0); - - /* put the new head skb back on the top of the queue */ - __skb_queue_head(list, head_skb); - } - sendit: iptfs_xfrm_output(skb, remaining); } }