diff options
author | Jarno Rajahalme <jrajahalme@nicira.com> | 2014-03-27 15:35:23 -0400 |
---|---|---|
committer | Jesse Gross <jesse@nicira.com> | 2014-05-16 16:40:29 -0400 |
commit | 23dabf88abb48a866fdb19ee08ebcf1ddd9b1840 (patch) | |
tree | cc835b9d88c36d7b3b0c296fb2617f9971c5bd7e | |
parent | 8c63ff09bddf944ab0033fea97aacfadfffa76de (diff) |
openvswitch: Remove 5-tuple optimization.
The 5-tuple optimization becomes unnecessary with a later per-NUMA
node stats patch. Remove it first to make the changes easier to
grasp.
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
-rw-r--r-- | net/openvswitch/datapath.c | 11 | ||||
-rw-r--r-- | net/openvswitch/flow.c | 32 | ||||
-rw-r--r-- | net/openvswitch/flow.h | 10 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.c | 58 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.h | 1 | ||||
-rw-r--r-- | net/openvswitch/flow_table.c | 31 | ||||
-rw-r--r-- | net/openvswitch/flow_table.h | 2 |
7 files changed, 32 insertions, 113 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index a3276e3c4feb..8867d7e2d65b 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -524,7 +524,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) | |||
524 | packet->protocol = htons(ETH_P_802_2); | 524 | packet->protocol = htons(ETH_P_802_2); |
525 | 525 | ||
526 | /* Build an sw_flow for sending this packet. */ | 526 | /* Build an sw_flow for sending this packet. */ |
527 | flow = ovs_flow_alloc(false); | 527 | flow = ovs_flow_alloc(); |
528 | err = PTR_ERR(flow); | 528 | err = PTR_ERR(flow); |
529 | if (IS_ERR(flow)) | 529 | if (IS_ERR(flow)) |
530 | goto err_kfree_skb; | 530 | goto err_kfree_skb; |
@@ -782,7 +782,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
782 | struct datapath *dp; | 782 | struct datapath *dp; |
783 | struct sw_flow_actions *acts = NULL; | 783 | struct sw_flow_actions *acts = NULL; |
784 | struct sw_flow_match match; | 784 | struct sw_flow_match match; |
785 | bool exact_5tuple; | ||
786 | int error; | 785 | int error; |
787 | 786 | ||
788 | /* Extract key. */ | 787 | /* Extract key. */ |
@@ -791,7 +790,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
791 | goto error; | 790 | goto error; |
792 | 791 | ||
793 | ovs_match_init(&match, &key, &mask); | 792 | ovs_match_init(&match, &key, &mask); |
794 | error = ovs_nla_get_match(&match, &exact_5tuple, | 793 | error = ovs_nla_get_match(&match, |
795 | a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]); | 794 | a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]); |
796 | if (error) | 795 | if (error) |
797 | goto error; | 796 | goto error; |
@@ -830,7 +829,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
830 | goto err_unlock_ovs; | 829 | goto err_unlock_ovs; |
831 | 830 | ||
832 | /* Allocate flow. */ | 831 | /* Allocate flow. */ |
833 | flow = ovs_flow_alloc(!exact_5tuple); | 832 | flow = ovs_flow_alloc(); |
834 | if (IS_ERR(flow)) { | 833 | if (IS_ERR(flow)) { |
835 | error = PTR_ERR(flow); | 834 | error = PTR_ERR(flow); |
836 | goto err_unlock_ovs; | 835 | goto err_unlock_ovs; |
@@ -914,7 +913,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
914 | } | 913 | } |
915 | 914 | ||
916 | ovs_match_init(&match, &key, NULL); | 915 | ovs_match_init(&match, &key, NULL); |
917 | err = ovs_nla_get_match(&match, NULL, a[OVS_FLOW_ATTR_KEY], NULL); | 916 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL); |
918 | if (err) | 917 | if (err) |
919 | return err; | 918 | return err; |
920 | 919 | ||
@@ -968,7 +967,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
968 | } | 967 | } |
969 | 968 | ||
970 | ovs_match_init(&match, &key, NULL); | 969 | ovs_match_init(&match, &key, NULL); |
971 | err = ovs_nla_get_match(&match, NULL, a[OVS_FLOW_ATTR_KEY], NULL); | 970 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL); |
972 | if (err) | 971 | if (err) |
973 | goto unlock; | 972 | goto unlock; |
974 | 973 | ||
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 332aa01492f1..aad7a8da70b1 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -66,10 +66,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb) | |||
66 | struct flow_stats *stats; | 66 | struct flow_stats *stats; |
67 | __be16 tcp_flags = 0; | 67 | __be16 tcp_flags = 0; |
68 | 68 | ||
69 | if (!flow->stats.is_percpu) | 69 | stats = this_cpu_ptr(flow->stats); |
70 | stats = flow->stats.stat; | ||
71 | else | ||
72 | stats = this_cpu_ptr(flow->stats.cpu_stats); | ||
73 | 70 | ||
74 | if ((flow->key.eth.type == htons(ETH_P_IP) || | 71 | if ((flow->key.eth.type == htons(ETH_P_IP) || |
75 | flow->key.eth.type == htons(ETH_P_IPV6)) && | 72 | flow->key.eth.type == htons(ETH_P_IPV6)) && |
@@ -110,16 +107,14 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, | |||
110 | memset(ovs_stats, 0, sizeof(*ovs_stats)); | 107 | memset(ovs_stats, 0, sizeof(*ovs_stats)); |
111 | 108 | ||
112 | local_bh_disable(); | 109 | local_bh_disable(); |
113 | if (!flow->stats.is_percpu) { | 110 | |
114 | stats_read(flow->stats.stat, ovs_stats, used, tcp_flags); | 111 | for_each_possible_cpu(cpu) { |
115 | } else { | 112 | struct flow_stats *stats; |
116 | for_each_possible_cpu(cpu) { | 113 | |
117 | struct flow_stats *stats; | 114 | stats = per_cpu_ptr(flow->stats.cpu_stats, cpu); |
118 | 115 | stats_read(stats, ovs_stats, used, tcp_flags); | |
119 | stats = per_cpu_ptr(flow->stats.cpu_stats, cpu); | ||
120 | stats_read(stats, ovs_stats, used, tcp_flags); | ||
121 | } | ||
122 | } | 116 | } |
117 | |||
123 | local_bh_enable(); | 118 | local_bh_enable(); |
124 | } | 119 | } |
125 | 120 | ||
@@ -138,13 +133,10 @@ void ovs_flow_stats_clear(struct sw_flow *flow) | |||
138 | int cpu; | 133 | int cpu; |
139 | 134 | ||
140 | local_bh_disable(); | 135 | local_bh_disable(); |
141 | if (!flow->stats.is_percpu) { | 136 | |
142 | stats_reset(flow->stats.stat); | 137 | for_each_possible_cpu(cpu) |
143 | } else { | 138 | stats_reset(per_cpu_ptr(flow->stats, cpu)); |
144 | for_each_possible_cpu(cpu) { | 139 | |
145 | stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu)); | ||
146 | } | ||
147 | } | ||
148 | local_bh_enable(); | 140 | local_bh_enable(); |
149 | } | 141 | } |
150 | 142 | ||
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 2d770e28a3a3..9c0dd8aa3117 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h | |||
@@ -155,14 +155,6 @@ struct flow_stats { | |||
155 | __be16 tcp_flags; /* Union of seen TCP flags. */ | 155 | __be16 tcp_flags; /* Union of seen TCP flags. */ |
156 | }; | 156 | }; |
157 | 157 | ||
158 | struct sw_flow_stats { | ||
159 | bool is_percpu; | ||
160 | union { | ||
161 | struct flow_stats *stat; | ||
162 | struct flow_stats __percpu *cpu_stats; | ||
163 | }; | ||
164 | }; | ||
165 | |||
166 | struct sw_flow { | 158 | struct sw_flow { |
167 | struct rcu_head rcu; | 159 | struct rcu_head rcu; |
168 | struct hlist_node hash_node[2]; | 160 | struct hlist_node hash_node[2]; |
@@ -172,7 +164,7 @@ struct sw_flow { | |||
172 | struct sw_flow_key unmasked_key; | 164 | struct sw_flow_key unmasked_key; |
173 | struct sw_flow_mask *mask; | 165 | struct sw_flow_mask *mask; |
174 | struct sw_flow_actions __rcu *sf_acts; | 166 | struct sw_flow_actions __rcu *sf_acts; |
175 | struct sw_flow_stats stats; | 167 | struct flow_stats __percpu *stats; |
176 | }; | 168 | }; |
177 | 169 | ||
178 | struct arp_eth_header { | 170 | struct arp_eth_header { |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 5511ad18be51..84caa99b3769 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -268,20 +268,6 @@ static bool is_all_zero(const u8 *fp, size_t size) | |||
268 | return true; | 268 | return true; |
269 | } | 269 | } |
270 | 270 | ||
271 | static bool is_all_set(const u8 *fp, size_t size) | ||
272 | { | ||
273 | int i; | ||
274 | |||
275 | if (!fp) | ||
276 | return false; | ||
277 | |||
278 | for (i = 0; i < size; i++) | ||
279 | if (fp[i] != 0xff) | ||
280 | return false; | ||
281 | |||
282 | return true; | ||
283 | } | ||
284 | |||
285 | static int __parse_flow_nlattrs(const struct nlattr *attr, | 271 | static int __parse_flow_nlattrs(const struct nlattr *attr, |
286 | const struct nlattr *a[], | 272 | const struct nlattr *a[], |
287 | u64 *attrsp, bool nz) | 273 | u64 *attrsp, bool nz) |
@@ -503,9 +489,8 @@ static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs, | |||
503 | return 0; | 489 | return 0; |
504 | } | 490 | } |
505 | 491 | ||
506 | static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple, | 492 | static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs, |
507 | u64 attrs, const struct nlattr **a, | 493 | const struct nlattr **a, bool is_mask) |
508 | bool is_mask) | ||
509 | { | 494 | { |
510 | int err; | 495 | int err; |
511 | u64 orig_attrs = attrs; | 496 | u64 orig_attrs = attrs; |
@@ -562,11 +547,6 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple | |||
562 | SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask); | 547 | SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask); |
563 | } | 548 | } |
564 | 549 | ||
565 | if (is_mask && exact_5tuple) { | ||
566 | if (match->mask->key.eth.type != htons(0xffff)) | ||
567 | *exact_5tuple = false; | ||
568 | } | ||
569 | |||
570 | if (attrs & (1 << OVS_KEY_ATTR_IPV4)) { | 550 | if (attrs & (1 << OVS_KEY_ATTR_IPV4)) { |
571 | const struct ovs_key_ipv4 *ipv4_key; | 551 | const struct ovs_key_ipv4 *ipv4_key; |
572 | 552 | ||
@@ -589,13 +569,6 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple | |||
589 | SW_FLOW_KEY_PUT(match, ipv4.addr.dst, | 569 | SW_FLOW_KEY_PUT(match, ipv4.addr.dst, |
590 | ipv4_key->ipv4_dst, is_mask); | 570 | ipv4_key->ipv4_dst, is_mask); |
591 | attrs &= ~(1 << OVS_KEY_ATTR_IPV4); | 571 | attrs &= ~(1 << OVS_KEY_ATTR_IPV4); |
592 | |||
593 | if (is_mask && exact_5tuple && *exact_5tuple) { | ||
594 | if (ipv4_key->ipv4_proto != 0xff || | ||
595 | ipv4_key->ipv4_src != htonl(0xffffffff) || | ||
596 | ipv4_key->ipv4_dst != htonl(0xffffffff)) | ||
597 | *exact_5tuple = false; | ||
598 | } | ||
599 | } | 572 | } |
600 | 573 | ||
601 | if (attrs & (1 << OVS_KEY_ATTR_IPV6)) { | 574 | if (attrs & (1 << OVS_KEY_ATTR_IPV6)) { |
@@ -627,15 +600,6 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple | |||
627 | is_mask); | 600 | is_mask); |
628 | 601 | ||
629 | attrs &= ~(1 << OVS_KEY_ATTR_IPV6); | 602 | attrs &= ~(1 << OVS_KEY_ATTR_IPV6); |
630 | |||
631 | if (is_mask && exact_5tuple && *exact_5tuple) { | ||
632 | if (ipv6_key->ipv6_proto != 0xff || | ||
633 | !is_all_set((const u8 *)ipv6_key->ipv6_src, | ||
634 | sizeof(match->key->ipv6.addr.src)) || | ||
635 | !is_all_set((const u8 *)ipv6_key->ipv6_dst, | ||
636 | sizeof(match->key->ipv6.addr.dst))) | ||
637 | *exact_5tuple = false; | ||
638 | } | ||
639 | } | 603 | } |
640 | 604 | ||
641 | if (attrs & (1 << OVS_KEY_ATTR_ARP)) { | 605 | if (attrs & (1 << OVS_KEY_ATTR_ARP)) { |
@@ -678,11 +642,6 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple | |||
678 | tcp_key->tcp_dst, is_mask); | 642 | tcp_key->tcp_dst, is_mask); |
679 | } | 643 | } |
680 | attrs &= ~(1 << OVS_KEY_ATTR_TCP); | 644 | attrs &= ~(1 << OVS_KEY_ATTR_TCP); |
681 | |||
682 | if (is_mask && exact_5tuple && *exact_5tuple && | ||
683 | (tcp_key->tcp_src != htons(0xffff) || | ||
684 | tcp_key->tcp_dst != htons(0xffff))) | ||
685 | *exact_5tuple = false; | ||
686 | } | 645 | } |
687 | 646 | ||
688 | if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) { | 647 | if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) { |
@@ -714,11 +673,6 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple | |||
714 | udp_key->udp_dst, is_mask); | 673 | udp_key->udp_dst, is_mask); |
715 | } | 674 | } |
716 | attrs &= ~(1 << OVS_KEY_ATTR_UDP); | 675 | attrs &= ~(1 << OVS_KEY_ATTR_UDP); |
717 | |||
718 | if (is_mask && exact_5tuple && *exact_5tuple && | ||
719 | (udp_key->udp_src != htons(0xffff) || | ||
720 | udp_key->udp_dst != htons(0xffff))) | ||
721 | *exact_5tuple = false; | ||
722 | } | 676 | } |
723 | 677 | ||
724 | if (attrs & (1 << OVS_KEY_ATTR_SCTP)) { | 678 | if (attrs & (1 << OVS_KEY_ATTR_SCTP)) { |
@@ -804,7 +758,6 @@ static void sw_flow_mask_set(struct sw_flow_mask *mask, | |||
804 | * attribute specifies the mask field of the wildcarded flow. | 758 | * attribute specifies the mask field of the wildcarded flow. |
805 | */ | 759 | */ |
806 | int ovs_nla_get_match(struct sw_flow_match *match, | 760 | int ovs_nla_get_match(struct sw_flow_match *match, |
807 | bool *exact_5tuple, | ||
808 | const struct nlattr *key, | 761 | const struct nlattr *key, |
809 | const struct nlattr *mask) | 762 | const struct nlattr *mask) |
810 | { | 763 | { |
@@ -852,13 +805,10 @@ int ovs_nla_get_match(struct sw_flow_match *match, | |||
852 | } | 805 | } |
853 | } | 806 | } |
854 | 807 | ||
855 | err = ovs_key_from_nlattrs(match, NULL, key_attrs, a, false); | 808 | err = ovs_key_from_nlattrs(match, key_attrs, a, false); |
856 | if (err) | 809 | if (err) |
857 | return err; | 810 | return err; |
858 | 811 | ||
859 | if (exact_5tuple) | ||
860 | *exact_5tuple = true; | ||
861 | |||
862 | if (mask) { | 812 | if (mask) { |
863 | err = parse_flow_mask_nlattrs(mask, a, &mask_attrs); | 813 | err = parse_flow_mask_nlattrs(mask, a, &mask_attrs); |
864 | if (err) | 814 | if (err) |
@@ -896,7 +846,7 @@ int ovs_nla_get_match(struct sw_flow_match *match, | |||
896 | } | 846 | } |
897 | } | 847 | } |
898 | 848 | ||
899 | err = ovs_key_from_nlattrs(match, exact_5tuple, mask_attrs, a, true); | 849 | err = ovs_key_from_nlattrs(match, mask_attrs, a, true); |
900 | if (err) | 850 | if (err) |
901 | return err; | 851 | return err; |
902 | } else { | 852 | } else { |
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h index b31fbe28bc7a..440151045d39 100644 --- a/net/openvswitch/flow_netlink.h +++ b/net/openvswitch/flow_netlink.h | |||
@@ -45,7 +45,6 @@ int ovs_nla_put_flow(const struct sw_flow_key *, | |||
45 | int ovs_nla_get_flow_metadata(struct sw_flow *flow, | 45 | int ovs_nla_get_flow_metadata(struct sw_flow *flow, |
46 | const struct nlattr *attr); | 46 | const struct nlattr *attr); |
47 | int ovs_nla_get_match(struct sw_flow_match *match, | 47 | int ovs_nla_get_match(struct sw_flow_match *match, |
48 | bool *exact_5tuple, | ||
49 | const struct nlattr *, | 48 | const struct nlattr *, |
50 | const struct nlattr *); | 49 | const struct nlattr *); |
51 | 50 | ||
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index 1ba1e0b8ade5..aa92da23053d 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c | |||
@@ -72,7 +72,7 @@ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, | |||
72 | *d++ = *s++ & *m++; | 72 | *d++ = *s++ & *m++; |
73 | } | 73 | } |
74 | 74 | ||
75 | struct sw_flow *ovs_flow_alloc(bool percpu_stats) | 75 | struct sw_flow *ovs_flow_alloc(void) |
76 | { | 76 | { |
77 | struct sw_flow *flow; | 77 | struct sw_flow *flow; |
78 | int cpu; | 78 | int cpu; |
@@ -84,25 +84,15 @@ struct sw_flow *ovs_flow_alloc(bool percpu_stats) | |||
84 | flow->sf_acts = NULL; | 84 | flow->sf_acts = NULL; |
85 | flow->mask = NULL; | 85 | flow->mask = NULL; |
86 | 86 | ||
87 | flow->stats.is_percpu = percpu_stats; | 87 | flow->stats = alloc_percpu(struct flow_stats); |
88 | if (!flow->stats) | ||
89 | goto err; | ||
88 | 90 | ||
89 | if (!percpu_stats) { | 91 | for_each_possible_cpu(cpu) { |
90 | flow->stats.stat = kzalloc(sizeof(*flow->stats.stat), GFP_KERNEL); | 92 | struct flow_stats *cpu_stats; |
91 | if (!flow->stats.stat) | ||
92 | goto err; | ||
93 | 93 | ||
94 | spin_lock_init(&flow->stats.stat->lock); | 94 | cpu_stats = per_cpu_ptr(flow->stats, cpu); |
95 | } else { | 95 | spin_lock_init(&cpu_stats->lock); |
96 | flow->stats.cpu_stats = alloc_percpu(struct flow_stats); | ||
97 | if (!flow->stats.cpu_stats) | ||
98 | goto err; | ||
99 | |||
100 | for_each_possible_cpu(cpu) { | ||
101 | struct flow_stats *cpu_stats; | ||
102 | |||
103 | cpu_stats = per_cpu_ptr(flow->stats.cpu_stats, cpu); | ||
104 | spin_lock_init(&cpu_stats->lock); | ||
105 | } | ||
106 | } | 96 | } |
107 | return flow; | 97 | return flow; |
108 | err: | 98 | err: |
@@ -141,10 +131,7 @@ static struct flex_array *alloc_buckets(unsigned int n_buckets) | |||
141 | static void flow_free(struct sw_flow *flow) | 131 | static void flow_free(struct sw_flow *flow) |
142 | { | 132 | { |
143 | kfree((struct sf_flow_acts __force *)flow->sf_acts); | 133 | kfree((struct sf_flow_acts __force *)flow->sf_acts); |
144 | if (flow->stats.is_percpu) | 134 | free_percpu(flow->stats); |
145 | free_percpu(flow->stats.cpu_stats); | ||
146 | else | ||
147 | kfree(flow->stats.stat); | ||
148 | kmem_cache_free(flow_cache, flow); | 135 | kmem_cache_free(flow_cache, flow); |
149 | } | 136 | } |
150 | 137 | ||
diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h index baaeb101924d..c26c59a7ab57 100644 --- a/net/openvswitch/flow_table.h +++ b/net/openvswitch/flow_table.h | |||
@@ -55,7 +55,7 @@ struct flow_table { | |||
55 | int ovs_flow_init(void); | 55 | int ovs_flow_init(void); |
56 | void ovs_flow_exit(void); | 56 | void ovs_flow_exit(void); |
57 | 57 | ||
58 | struct sw_flow *ovs_flow_alloc(bool percpu_stats); | 58 | struct sw_flow *ovs_flow_alloc(void); |
59 | void ovs_flow_free(struct sw_flow *, bool deferred); | 59 | void ovs_flow_free(struct sw_flow *, bool deferred); |
60 | 60 | ||
61 | int ovs_flow_tbl_init(struct flow_table *); | 61 | int ovs_flow_tbl_init(struct flow_table *); |