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.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 2b78789ea7c5..da2fae0873a5 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"
@@ -64,10 +66,11 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
64#define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF)) 66#define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF))
65 67
66void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, 68void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
67 struct sk_buff *skb) 69 const struct sk_buff *skb)
68{ 70{
69 struct flow_stats *stats; 71 struct flow_stats *stats;
70 int node = numa_node_id(); 72 int node = numa_node_id();
73 int len = skb->len + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
71 74
72 stats = rcu_dereference(flow->stats[node]); 75 stats = rcu_dereference(flow->stats[node]);
73 76
@@ -103,7 +106,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
103 if (likely(new_stats)) { 106 if (likely(new_stats)) {
104 new_stats->used = jiffies; 107 new_stats->used = jiffies;
105 new_stats->packet_count = 1; 108 new_stats->packet_count = 1;
106 new_stats->byte_count = skb->len; 109 new_stats->byte_count = len;
107 new_stats->tcp_flags = tcp_flags; 110 new_stats->tcp_flags = tcp_flags;
108 spin_lock_init(&new_stats->lock); 111 spin_lock_init(&new_stats->lock);
109 112
@@ -118,7 +121,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
118 121
119 stats->used = jiffies; 122 stats->used = jiffies;
120 stats->packet_count++; 123 stats->packet_count++;
121 stats->byte_count += skb->len; 124 stats->byte_count += len;
122 stats->tcp_flags |= tcp_flags; 125 stats->tcp_flags |= tcp_flags;
123unlock: 126unlock:
124 spin_unlock(&stats->lock); 127 spin_unlock(&stats->lock);
@@ -480,6 +483,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
480 return -ENOMEM; 483 return -ENOMEM;
481 484
482 skb_reset_network_header(skb); 485 skb_reset_network_header(skb);
486 skb_reset_mac_len(skb);
483 __skb_push(skb, skb->data - skb_mac_header(skb)); 487 __skb_push(skb, skb->data - skb_mac_header(skb));
484 488
485 /* Network layer. */ 489 /* Network layer. */
@@ -584,6 +588,33 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
584 memset(&key->ip, 0, sizeof(key->ip)); 588 memset(&key->ip, 0, sizeof(key->ip));
585 memset(&key->ipv4, 0, sizeof(key->ipv4)); 589 memset(&key->ipv4, 0, sizeof(key->ipv4));
586 } 590 }
591 } else if (eth_p_mpls(key->eth.type)) {
592 size_t stack_len = MPLS_HLEN;
593
594 /* In the presence of an MPLS label stack the end of the L2
595 * header and the beginning of the L3 header differ.
596 *
597 * Advance network_header to the beginning of the L3
598 * header. mac_len corresponds to the end of the L2 header.
599 */
600 while (1) {
601 __be32 lse;
602
603 error = check_header(skb, skb->mac_len + stack_len);
604 if (unlikely(error))
605 return 0;
606
607 memcpy(&lse, skb_network_header(skb), MPLS_HLEN);
608
609 if (stack_len == MPLS_HLEN)
610 memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN);
611
612 skb_set_network_header(skb, skb->mac_len + stack_len);
613 if (lse & htonl(MPLS_LS_S_MASK))
614 break;
615
616 stack_len += MPLS_HLEN;
617 }
587 } else if (key->eth.type == htons(ETH_P_IPV6)) { 618 } else if (key->eth.type == htons(ETH_P_IPV6)) {
588 int nh_len; /* IPv6 Header + Extensions */ 619 int nh_len; /* IPv6 Header + Extensions */
589 620
@@ -649,7 +680,7 @@ int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
649 return key_extract(skb, key); 680 return key_extract(skb, key);
650} 681}
651 682
652int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info, 683int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
653 struct sk_buff *skb, struct sw_flow_key *key) 684 struct sk_buff *skb, struct sw_flow_key *key)
654{ 685{
655 /* Extract metadata from packet. */ 686 /* Extract metadata from packet. */
@@ -682,12 +713,12 @@ int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info,
682 713
683int ovs_flow_key_extract_userspace(const struct nlattr *attr, 714int ovs_flow_key_extract_userspace(const struct nlattr *attr,
684 struct sk_buff *skb, 715 struct sk_buff *skb,
685 struct sw_flow_key *key) 716 struct sw_flow_key *key, bool log)
686{ 717{
687 int err; 718 int err;
688 719
689 /* Extract metadata from netlink attributes. */ 720 /* Extract metadata from netlink attributes. */
690 err = ovs_nla_get_flow_metadata(attr, key); 721 err = ovs_nla_get_flow_metadata(attr, key, log);
691 if (err) 722 if (err)
692 return err; 723 return err;
693 724