Skip to content

Commit 19c3401

Browse files
ummakynesdavem330
authored andcommitted
net: ipv4: place control buffer handling away from fragmentation iterators
Deal with the IPCB() area away from the iterators. The bridge codebase has its own control buffer layout, move specific IP control buffer handling into the IPv4 codepath. Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8a6a1f1 commit 19c3401

File tree

1 file changed

+37
-18
lines changed

1 file changed

+37
-18
lines changed

net/ipv4/ip_output.c

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -525,9 +525,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
525525

526526
skb_copy_hash(to, from);
527527

528-
/* Copy the flags to each fragment. */
529-
IPCB(to)->flags = IPCB(from)->flags;
530-
531528
#ifdef CONFIG_NET_SCHED
532529
to->tc_index = from->tc_index;
533530
#endif
@@ -582,6 +579,18 @@ void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph,
582579
}
583580
EXPORT_SYMBOL(ip_fraglist_init);
584581

582+
static void ip_fraglist_ipcb_prepare(struct sk_buff *skb,
583+
struct ip_fraglist_iter *iter)
584+
{
585+
struct sk_buff *to = iter->frag;
586+
587+
/* Copy the flags to each fragment. */
588+
IPCB(to)->flags = IPCB(skb)->flags;
589+
590+
if (iter->offset == 0)
591+
ip_options_fragment(to);
592+
}
593+
585594
void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
586595
{
587596
unsigned int hlen = iter->hlen;
@@ -598,8 +607,6 @@ void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
598607
iph = iter->iph;
599608
iph->tot_len = htons(frag->len);
600609
ip_copy_metadata(frag, skb);
601-
if (iter->offset == 0)
602-
ip_options_fragment(frag);
603610
iter->offset += skb->len - hlen;
604611
iph->frag_off = htons(iter->offset >> 3);
605612
if (frag->next)
@@ -627,6 +634,25 @@ void ip_frag_init(struct sk_buff *skb, unsigned int hlen,
627634
}
628635
EXPORT_SYMBOL(ip_frag_init);
629636

637+
static void ip_frag_ipcb(struct sk_buff *from, struct sk_buff *to,
638+
bool first_frag, struct ip_frag_state *state)
639+
{
640+
/* Copy the flags to each fragment. */
641+
IPCB(to)->flags = IPCB(from)->flags;
642+
643+
if (IPCB(from)->flags & IPSKB_FRAG_PMTU)
644+
state->iph->frag_off |= htons(IP_DF);
645+
646+
/* ANK: dirty, but effective trick. Upgrade options only if
647+
* the segment to be fragmented was THE FIRST (otherwise,
648+
* options are already fixed) and make it ONCE
649+
* on the initial skb, so that all the following fragments
650+
* will inherit fixed options.
651+
*/
652+
if (first_frag)
653+
ip_options_fragment(from);
654+
}
655+
630656
struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state)
631657
{
632658
unsigned int len = state->left;
@@ -685,18 +711,6 @@ struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state)
685711
iph = ip_hdr(skb2);
686712
iph->frag_off = htons((state->offset >> 3));
687713

688-
if (IPCB(skb)->flags & IPSKB_FRAG_PMTU)
689-
iph->frag_off |= htons(IP_DF);
690-
691-
/* ANK: dirty, but effective trick. Upgrade options only if
692-
* the segment to be fragmented was THE FIRST (otherwise,
693-
* options are already fixed) and make it ONCE
694-
* on the initial skb, so that all the following fragments
695-
* will inherit fixed options.
696-
*/
697-
if (state->offset == 0)
698-
ip_options_fragment(skb);
699-
700714
/*
701715
* Added AC : If we are fragmenting a fragment that's not the
702716
* last fragment then keep MF on each bit
@@ -799,8 +813,10 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
799813
for (;;) {
800814
/* Prepare header of the next frame,
801815
* before previous one went down. */
802-
if (iter.frag)
816+
if (iter.frag) {
817+
ip_fraglist_ipcb_prepare(skb, &iter);
803818
ip_fraglist_prepare(skb, &iter);
819+
}
804820

805821
err = output(net, sk, skb);
806822

@@ -844,11 +860,14 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
844860
*/
845861

846862
while (state.left > 0) {
863+
bool first_frag = (state.offset == 0);
864+
847865
skb2 = ip_frag_next(skb, &state);
848866
if (IS_ERR(skb2)) {
849867
err = PTR_ERR(skb2);
850868
goto fail;
851869
}
870+
ip_frag_ipcb(skb, skb2, first_frag, &state);
852871

853872
/*
854873
* Put this fragment into the sending queue.

0 commit comments

Comments
 (0)