mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
openvswitch: Add basic MPLS support to kernel
Allow datapath to recognize and extract MPLS labels into flow keys and execute actions which push, pop, and set labels on packets. Based heavily on work by Leo Alterman, Ravi K, Isaku Yamahata and Joe Stringer. Cc: Ravi K <rkerur@gmail.com> Cc: Leo Alterman <lalterman@nicira.com> Cc: Isaku Yamahata <yamahata@valinux.co.jp> Cc: Joe Stringer <joe@wand.net.nz> Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
This commit is contained in:
parent
59b93b41e7
commit
25cd9ba0ab
10 changed files with 345 additions and 30 deletions
|
@ -32,6 +32,7 @@
|
|||
#include <linux/if_arp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/mpls.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/tcp.h>
|
||||
|
@ -42,6 +43,7 @@
|
|||
#include <net/ip.h>
|
||||
#include <net/ip_tunnels.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/mpls.h>
|
||||
#include <net/ndisc.h>
|
||||
|
||||
#include "datapath.h"
|
||||
|
@ -480,6 +482,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
|||
return -ENOMEM;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_mac_len(skb);
|
||||
__skb_push(skb, skb->data - skb_mac_header(skb));
|
||||
|
||||
/* Network layer. */
|
||||
|
@ -584,6 +587,33 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
|||
memset(&key->ip, 0, sizeof(key->ip));
|
||||
memset(&key->ipv4, 0, sizeof(key->ipv4));
|
||||
}
|
||||
} 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.
|
||||
*/
|
||||
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);
|
||||
|
||||
if (stack_len == MPLS_HLEN)
|
||||
memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN);
|
||||
|
||||
skb_set_network_header(skb, skb->mac_len + stack_len);
|
||||
if (lse & htonl(MPLS_LS_S_MASK))
|
||||
break;
|
||||
|
||||
stack_len += MPLS_HLEN;
|
||||
}
|
||||
} else if (key->eth.type == htons(ETH_P_IPV6)) {
|
||||
int nh_len; /* IPv6 Header + Extensions */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue