On Mon, Jun 30, 2014 at 2:36 PM, Alex Wang <[email protected]> wrote:
> Due to the race condition in userspace, there is chance that two
> overlapping megaflows could be installed in datapath. And this
> causes userspace unable to delete the less inclusive megaflow flow
> even after it timeout, since the flow_del logic will stop at the
> first match of masked flow.
>
> This commit fixes the bug by making the kernel flow_del and flow_get
> logic check all masks in that case.
>
> Signed-off-by: Alex Wang <[email protected]>
> Acked-by: Andy Zhou <[email protected]>
>
> ---
> PATCH -> V2:
> - remove the 'key' as input argument, since 'match' has reference to 'key'.
> - use normal iterator for mask_list iteration.
> - use the exact-lookup for flow_get.
> ---
> datapath/datapath.c | 8 ++++----
> datapath/flow_table.c | 16 ++++++++++++++++
> datapath/flow_table.h | 2 ++
> 3 files changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/datapath/datapath.c b/datapath/datapath.c
> index c15ded9..6ba59fe 100644
> --- a/datapath/datapath.c
> +++ b/datapath/datapath.c
> @@ -927,8 +927,8 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct
> genl_info *info)
> goto unlock;
> }
>
> - flow = ovs_flow_tbl_lookup(&dp->table, &key);
> - if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
> + flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
> + if (!flow) {
> err = -ENOENT;
> goto unlock;
> }
> @@ -974,8 +974,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct
> genl_info *info)
> if (err)
> goto unlock;
>
> - flow = ovs_flow_tbl_lookup(&dp->table, &key);
> - if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
> + flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
> + if (!flow) {
> err = -ENOENT;
> goto unlock;
> }
We need to do exact lookup if ovs_flow_cmp_unmasked_key() fails in
ovs_flow_cmd_new_or_set().
> diff --git a/datapath/flow_table.c b/datapath/flow_table.c
> index fa7ad36..88af281 100644
> --- a/datapath/flow_table.c
> +++ b/datapath/flow_table.c
> @@ -482,6 +482,22 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table
> *tbl,
> return ovs_flow_tbl_lookup_stats(tbl, key, &n_mask_hit);
> }
>
> +struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
> + struct sw_flow_match *match)
> +{
> + struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
> + struct sw_flow_mask *mask;
> + struct sw_flow *flow;
> +
> + /* Always called under ovs-mutex. */
> + list_for_each_entry(mask, &tbl->mask_list, list) {
> + flow = masked_flow_lookup(ti, match->key, mask);
> + if (flow && ovs_flow_cmp_unmasked_key(flow, match)) /* Found
> */
> + return flow;
> + }
> + return NULL;
> +}
> +
> int ovs_flow_tbl_num_masks(const struct flow_table *table)
> {
> struct sw_flow_mask *mask;
> diff --git a/datapath/flow_table.h b/datapath/flow_table.h
> index baaeb10..0188c9b 100644
> --- a/datapath/flow_table.h
> +++ b/datapath/flow_table.h
> @@ -72,6 +72,8 @@ struct sw_flow *ovs_flow_tbl_dump_next(struct
> table_instance *table,
> struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *,
> const struct sw_flow_key *,
> u32 *n_mask_hit);
> +struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
> + struct sw_flow_match *match);
> struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
> const struct sw_flow_key *);
>
Otherwise looks good
Acked-by: Pravin B Shelar <[email protected]>
> --
> 1.7.9.5
>
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev