Commit 86ec8dba authored by Jarno Rajahalme's avatar Jarno Rajahalme Committed by Pravin B Shelar

openvswitch: Fix ovs_flow_stats_get/clear RCU dereference.

For ovs_flow_stats_get() using ovsl_dereference() was wrong, since
flow dumps call this with RCU read lock.

ovs_flow_stats_clear() is always called with ovs_mutex, so can use
ovsl_dereference().

Also, make the ovs_flow_stats_get() 'flow' argument const to make
later patches cleaner.
Signed-off-by: default avatarJarno Rajahalme <jrajahalme@nicira.com>
Signed-off-by: default avatarPravin B Shelar <pshelar@nicira.com>
parent eb072659
...@@ -122,8 +122,9 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb) ...@@ -122,8 +122,9 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
spin_unlock(&stats->lock); spin_unlock(&stats->lock);
} }
/* Called with ovs_mutex. */ /* Must be called with rcu_read_lock or ovs_mutex. */
void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, void ovs_flow_stats_get(const struct sw_flow *flow,
struct ovs_flow_stats *ovs_stats,
unsigned long *used, __be16 *tcp_flags) unsigned long *used, __be16 *tcp_flags)
{ {
int node; int node;
...@@ -133,7 +134,7 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, ...@@ -133,7 +134,7 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
memset(ovs_stats, 0, sizeof(*ovs_stats)); memset(ovs_stats, 0, sizeof(*ovs_stats));
for_each_node(node) { for_each_node(node) {
struct flow_stats *stats = ovsl_dereference(flow->stats[node]); struct flow_stats *stats = rcu_dereference_ovsl(flow->stats[node]);
if (stats) { if (stats) {
/* Local CPU may write on non-local stats, so we must /* Local CPU may write on non-local stats, so we must
...@@ -150,12 +151,13 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, ...@@ -150,12 +151,13 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
} }
} }
/* Called with ovs_mutex. */
void ovs_flow_stats_clear(struct sw_flow *flow) void ovs_flow_stats_clear(struct sw_flow *flow)
{ {
int node; int node;
for_each_node(node) { for_each_node(node) {
struct flow_stats *stats = rcu_dereference(flow->stats[node]); struct flow_stats *stats = ovsl_dereference(flow->stats[node]);
if (stats) { if (stats) {
spin_lock_bh(&stats->lock); spin_lock_bh(&stats->lock);
......
...@@ -180,10 +180,10 @@ struct arp_eth_header { ...@@ -180,10 +180,10 @@ struct arp_eth_header {
unsigned char ar_tip[4]; /* target IP address */ unsigned char ar_tip[4]; /* target IP address */
} __packed; } __packed;
void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb); void ovs_flow_stats_update(struct sw_flow *, struct sk_buff *);
void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *stats, void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
unsigned long *used, __be16 *tcp_flags); unsigned long *used, __be16 *tcp_flags);
void ovs_flow_stats_clear(struct sw_flow *flow); void ovs_flow_stats_clear(struct sw_flow *);
u64 ovs_flow_used_time(unsigned long flow_jiffies); u64 ovs_flow_used_time(unsigned long flow_jiffies);
int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *); int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment