aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/flow.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch/flow.c')
-rw-r--r--net/openvswitch/flow.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 2b78789ea7c5..90a21010fc8f 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -32,6 +32,7 @@
32#include <linux/if_arp.h> 32#include <linux/if_arp.h>
33#include <linux/ip.h> 33#include <linux/ip.h>
34#include <linux/ipv6.h> 34#include <linux/ipv6.h>
35#include <linux/mpls.h>
35#include <linux/sctp.h> 36#include <linux/sctp.h>
36#include <linux/smp.h> 37#include <linux/smp.h>
37#include <linux/tcp.h> 38#include <linux/tcp.h>
@@ -42,6 +43,7 @@
42#include <net/ip.h> 43#include <net/ip.h>
43#include <net/ip_tunnels.h> 44#include <net/ip_tunnels.h>
44#include <net/ipv6.h> 45#include <net/ipv6.h>
46#include <net/mpls.h>
45#include <net/ndisc.h> 47#include <net/ndisc.h>
46 48
47#include "datapath.h" 49#include "datapath.h"
@@ -480,6 +482,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
480 return -ENOMEM; 482 return -ENOMEM;
481 483
482 skb_reset_network_header(skb); 484 skb_reset_network_header(skb);
485 skb_reset_mac_len(skb);
483 __skb_push(skb, skb->data - skb_mac_header(skb)); 486 __skb_push(skb, skb->data - skb_mac_header(skb));
484 487
485 /* Network layer. */ 488 /* Network layer. */
@@ -584,6 +587,33 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
584 memset(&key->ip, 0, sizeof(key->ip)); 587 memset(&key->ip, 0, sizeof(key->ip));
585 memset(&key->ipv4, 0, sizeof(key->ipv4)); 588 memset(&key->ipv4, 0, sizeof(key->ipv4));
586 } 589 }
590 } else if (eth_p_mpls(key->eth.type)) {
591 size_t stack_len = MPLS_HLEN;
592
593 /* In the presence of an MPLS label stack the end of the L2
594 * header and the beginning of the L3 header differ.
595 *
596 * Advance network_header to the beginning of the L3
597 * header. mac_len corresponds to the end of the L2 header.
598 */
599 while (1) {
600 __be32 lse;
601
602 error = check_header(skb, skb->mac_len + stack_len);
603 if (unlikely(error))
604 return 0;
605
606 memcpy(&lse, skb_network_header(skb), MPLS_HLEN);
607
608 if (stack_len == MPLS_HLEN)
609 memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN);
610
611 skb_set_network_header(skb, skb->mac_len + stack_len);
612 if (lse & htonl(MPLS_LS_S_MASK))
613 break;
614
615 stack_len += MPLS_HLEN;
616 }
587 } else if (key->eth.type == htons(ETH_P_IPV6)) { 617 } else if (key->eth.type == htons(ETH_P_IPV6)) {
588 int nh_len; /* IPv6 Header + Extensions */ 618 int nh_len; /* IPv6 Header + Extensions */
589 619