Skip to content

Commit

Permalink
net: core: add MPLS update core helper and use in OvS
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Jakub Kicinski <[email protected]>
Reviewed-by: Simon Horman <[email protected]>
Reviewed-by: Willem de Bruijn <[email protected]>
Acked-by: Cong Wang <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jahurley authored and davem330 committed Jul 9, 2019
1 parent ed246ce commit d27cf5c
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
1 change: 1 addition & 0 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -3449,6 +3449,7 @@ int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto);
int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto);
int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse);
struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
gfp_t gfp);

Expand Down
33 changes: 33 additions & 0 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -5531,6 +5531,39 @@ int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto)
}
EXPORT_SYMBOL_GPL(skb_mpls_pop);

/**
* 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)
{
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[] = { ~mpls_hdr(skb)->label_stack_entry, mpls_lse };

skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
}

mpls_hdr(skb)->label_stack_entry = mpls_lse;

return 0;
}
EXPORT_SYMBOL_GPL(skb_mpls_update_lse);

/**
* alloc_skb_with_frags - allocate skb with page frags
*
Expand Down
13 changes: 3 additions & 10 deletions net/openvswitch/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,12 @@ static int set_mpls(struct sk_buff *skb, struct sw_flow_key *flow_key,
__be32 lse;
int err;

err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
if (unlikely(err))
return err;

stack = mpls_hdr(skb);
lse = OVS_MASKED(stack->label_stack_entry, *mpls_lse, *mask);
if (skb->ip_summed == CHECKSUM_COMPLETE) {
__be32 diff[] = { ~(stack->label_stack_entry), lse };

skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
}
err = skb_mpls_update_lse(skb, lse);
if (err)
return err;

stack->label_stack_entry = lse;
flow_key->mpls.top_lse = lse;
return 0;
}
Expand Down

0 comments on commit d27cf5c

Please sign in to comment.