Deal with the IPCB() area away from the fragment transformer. The bridge codebase has its own control buffer layout, move specific IP control buffer into function. Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- net/ipv4/ip_output.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index bf02c7d37acd..92ad57638b2f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -632,6 +632,25 @@ void ip_frag_init(struct sk_buff *skb, unsigned int hlen, } EXPORT_SYMBOL(ip_frag_init); +static void ip_frag_ipcb(struct sk_buff *from, struct sk_buff *to, + bool first_frag, struct ip_frag_state *state) +{ + /* Copy the flags to each fragment. */ + IPCB(to)->flags = IPCB(from)->flags; + + if (IPCB(from)->flags & IPSKB_FRAG_PMTU) + state->iph->frag_off |= htons(IP_DF); + + /* ANK: dirty, but effective trick. Upgrade options only if + * the segment to be fragmented was THE FIRST (otherwise, + * options are already fixed) and make it ONCE + * on the initial skb, so that all the following fragments + * will inherit fixed options. + */ + if (first_frag) + ip_options_fragment(from); +} + struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state) { unsigned int len = state->left; @@ -690,18 +709,6 @@ struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state) iph = ip_hdr(skb2); iph->frag_off = htons((state->offset >> 3)); - if (IPCB(skb)->flags & IPSKB_FRAG_PMTU) - iph->frag_off |= htons(IP_DF); - - /* ANK: dirty, but effective trick. Upgrade options only if - * the segment to be fragmented was THE FIRST (otherwise, - * options are already fixed) and make it ONCE - * on the initial skb, so that all the following fragments - * will inherit fixed options. - */ - if (state->offset == 0) - ip_options_fragment(skb); - /* * Added AC : If we are fragmenting a fragment that's not the * last fragment then keep MF on each bit @@ -851,11 +858,14 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, */ while (state.left > 0) { + bool first_frag = (state.offset == 0); + skb2 = ip_frag_next(skb, &state); if (IS_ERR(skb2)) { err = PTR_ERR(skb2); goto fail; } + ip_frag_ipcb(skb, skb2, first_frag, &state); /* * Put this fragment into the sending queue. -- 2.11.0