On Mon, Jul 1, 2019 at 8:31 AM John Hurley <john.hur...@netronome.com> wrote: > > Open vSwitch allows the updating of an existing MPLS header on a packet. > In preparation for supporting similar functionality in TC, move this to a > common skb helper function. > > Signed-off-by: John Hurley <john.hur...@netronome.com> > Reviewed-by: Jakub Kicinski <jakub.kicin...@netronome.com> > Reviewed-by: Simon Horman <simon.hor...@netronome.com> > --- > /** > + * skb_mpls_update_lse() - modify outermost MPLS header and update csum > + * > + * @skb: buffer > + * @mpls_lse: new MPLS label stack entry to update to > + * > + * Expects skb->data at mac header. > + * > + * Returns 0 on success, -errno otherwise. > + */ > +int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse) > +{ > + struct mpls_shim_hdr *old_lse = mpls_hdr(skb); > + int err; > + > + if (unlikely(!eth_p_mpls(skb->protocol))) > + return -EINVAL; > + > + err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN); > + if (unlikely(err)) > + return err; > + > + if (skb->ip_summed == CHECKSUM_COMPLETE) { > + __be32 diff[] = { ~old_lse->label_stack_entry, mpls_lse }; > + > + skb->csum = csum_partial((char *)diff, sizeof(diff), > skb->csum); > + } > + > + old_lse->label_stack_entry = mpls_lse;
skb_ensure_writable may have reallocated the skb linear. old_lse needs to be loaded after. Or, safer: mpls_hdr(skb)->label_stack_entry = mpls_lse;