Skip to content

Commit

Permalink
Merge branch 'ovs-mpls'
Browse files Browse the repository at this point in the history
Jiri Benc says:

====================
openvswitch: mpls fix and clean up

Convert to the new mpls skb layout the last remaining place in openvswitch,
forgotten on the mpls GSO rework. The GSO rework also allows for some
cleanup in the third patch.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Oct 3, 2016
2 parents ab58070 + 85de4a2 commit 32986b5
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 38 deletions.
15 changes: 6 additions & 9 deletions include/net/mpls.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,18 @@

#define MPLS_HLEN 4

struct mpls_shim_hdr {
__be32 label_stack_entry;
};

static inline bool eth_p_mpls(__be16 eth_type)
{
return eth_type == htons(ETH_P_MPLS_UC) ||
eth_type == htons(ETH_P_MPLS_MC);
}

/*
* For non-MPLS skbs this will correspond to the network header.
* For MPLS skbs it will be before the network_header as the MPLS
* label stack lies between the end of the mac header and the network
* header. That is, for MPLS skbs the end of the mac header
* is the top of the MPLS label stack.
*/
static inline unsigned char *skb_mpls_header(struct sk_buff *skb)
static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb)
{
return skb_mac_header(skb) + skb->mac_len;
return (struct mpls_shim_hdr *)skb_network_header(skb);
}
#endif
10 changes: 1 addition & 9 deletions net/mpls/internal.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#ifndef MPLS_INTERNAL_H
#define MPLS_INTERNAL_H

struct mpls_shim_hdr {
__be32 label_stack_entry;
};
#include <net/mpls.h>

struct mpls_entry_decoded {
u32 label;
Expand Down Expand Up @@ -93,11 +90,6 @@ struct mpls_route { /* next hop label forwarding entry */

#define endfor_nexthops(rt) }

static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb)
{
return (struct mpls_shim_hdr *)skb_network_header(skb);
}

static inline struct mpls_shim_hdr mpls_entry_encode(u32 label, unsigned ttl, unsigned tc, bool bos)
{
struct mpls_shim_hdr result;
Expand Down
24 changes: 12 additions & 12 deletions net/openvswitch/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
const struct ovs_action_push_mpls *mpls)
{
__be32 *new_mpls_lse;
struct mpls_shim_hdr *new_mpls_lse;

/* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */
if (skb->encapsulation)
Expand All @@ -180,8 +180,8 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
skb_reset_mac_header(skb);
skb_set_network_header(skb, skb->mac_len);

new_mpls_lse = (__be32 *)skb_mpls_header(skb);
*new_mpls_lse = mpls->mpls_lse;
new_mpls_lse = mpls_hdr(skb);
new_mpls_lse->label_stack_entry = mpls->mpls_lse;

skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);

Expand All @@ -202,7 +202,7 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
if (unlikely(err))
return err;

skb_postpull_rcsum(skb, skb_mpls_header(skb), MPLS_HLEN);
skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN);

memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb),
skb->mac_len);
Expand All @@ -211,10 +211,10 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
skb_reset_mac_header(skb);
skb_set_network_header(skb, skb->mac_len);

/* skb_mpls_header() is used to locate the ethertype
* field correctly in the presence of VLAN tags.
/* mpls_hdr() is used to locate the ethertype field correctly in the
* presence of VLAN tags.
*/
hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN);
hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN);
update_ethertype(skb, hdr, ethertype);
if (eth_p_mpls(skb->protocol))
skb->protocol = ethertype;
Expand All @@ -226,24 +226,24 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
static int set_mpls(struct sk_buff *skb, struct sw_flow_key *flow_key,
const __be32 *mpls_lse, const __be32 *mask)
{
__be32 *stack;
struct mpls_shim_hdr *stack;
__be32 lse;
int err;

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

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

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

*stack = lse;
stack->label_stack_entry = lse;
flow_key->mpls.top_lse = lse;
return 0;
}
Expand Down
11 changes: 3 additions & 8 deletions net/openvswitch/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,25 +633,20 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
} else if (eth_p_mpls(key->eth.type)) {
size_t stack_len = MPLS_HLEN;

/* In the presence of an MPLS label stack the end of the L2
* header and the beginning of the L3 header differ.
*
* Advance network_header to the beginning of the L3
* header. mac_len corresponds to the end of the L2 header.
*/
skb_set_inner_network_header(skb, skb->mac_len);
while (1) {
__be32 lse;

error = check_header(skb, skb->mac_len + stack_len);
if (unlikely(error))
return 0;

memcpy(&lse, skb_network_header(skb), MPLS_HLEN);
memcpy(&lse, skb_inner_network_header(skb), MPLS_HLEN);

if (stack_len == MPLS_HLEN)
memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN);

skb_set_network_header(skb, skb->mac_len + stack_len);
skb_set_inner_network_header(skb, skb->mac_len + stack_len);
if (lse & htonl(MPLS_LS_S_MASK))
break;

Expand Down

0 comments on commit 32986b5

Please sign in to comment.