aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-03-27 15:35:23 -0400
committerJesse Gross <jesse@nicira.com>2014-05-16 16:40:29 -0400
commit23dabf88abb48a866fdb19ee08ebcf1ddd9b1840 (patch)
treecc835b9d88c36d7b3b0c296fb2617f9971c5bd7e
parent8c63ff09bddf944ab0033fea97aacfadfffa76de (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.c11
-rw-r--r--net/openvswitch/flow.c32
-rw-r--r--net/openvswitch/flow.h10
-rw-r--r--net/openvswitch/flow_netlink.c58
-rw-r--r--net/openvswitch/flow_netlink.h1
-rw-r--r--net/openvswitch/flow_table.c31
-rw-r--r--net/openvswitch/flow_table.h2
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
158struct sw_flow_stats {
159 bool is_percpu;
160 union {
161 struct flow_stats *stat;
162 struct flow_stats __percpu *cpu_stats;
163 };
164};
165
166struct sw_flow { 158struct 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
178struct arp_eth_header { 170struct 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
271static 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
285static int __parse_flow_nlattrs(const struct nlattr *attr, 271static 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
506static int ovs_key_from_nlattrs(struct sw_flow_match *match, bool *exact_5tuple, 492static 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 */
806int ovs_nla_get_match(struct sw_flow_match *match, 760int 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 *,
45int ovs_nla_get_flow_metadata(struct sw_flow *flow, 45int ovs_nla_get_flow_metadata(struct sw_flow *flow,
46 const struct nlattr *attr); 46 const struct nlattr *attr);
47int ovs_nla_get_match(struct sw_flow_match *match, 47int 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
75struct sw_flow *ovs_flow_alloc(bool percpu_stats) 75struct 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;
108err: 98err:
@@ -141,10 +131,7 @@ static struct flex_array *alloc_buckets(unsigned int n_buckets)
141static void flow_free(struct sw_flow *flow) 131static 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 {
55int ovs_flow_init(void); 55int ovs_flow_init(void);
56void ovs_flow_exit(void); 56void ovs_flow_exit(void);
57 57
58struct sw_flow *ovs_flow_alloc(bool percpu_stats); 58struct sw_flow *ovs_flow_alloc(void);
59void ovs_flow_free(struct sw_flow *, bool deferred); 59void ovs_flow_free(struct sw_flow *, bool deferred);
60 60
61int ovs_flow_tbl_init(struct flow_table *); 61int ovs_flow_tbl_init(struct flow_table *);