diff options
Diffstat (limited to 'net/openvswitch/flow.c')
-rw-r--r-- | net/openvswitch/flow.c | 43 |
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 | ||
66 | void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, | 68 | void 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; |
123 | unlock: | 126 | unlock: |
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 | ||
652 | int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info, | 683 | int 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 | ||
683 | int ovs_flow_key_extract_userspace(const struct nlattr *attr, | 714 | int 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 | ||