From f1aa2072c80dc8d4fb7a776801537172a656dbdd Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 17 Jun 2009 12:41:30 -0700 Subject: [PATCH] datapath: Get rid of query operations for single flows. --- datapath/datapath.c | 44 ++++++++++--------------- include/openvswitch/datapath-protocol.h | 3 +- lib/dpif.c | 21 +++++++++--- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 27bc5ce4..f76b51f9 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -831,6 +831,7 @@ static void get_stats(struct sw_flow *flow, struct odp_flow_stats *stats) stats->n_bytes = flow->byte_count; stats->ip_tos = flow->ip_tos; stats->tcp_flags = flow->tcp_flags; + stats->error = 0; } static void clear_stats(struct sw_flow *flow) @@ -984,9 +985,7 @@ static int answer_query(struct sw_flow *flow, struct odp_flow __user *ufp) return put_actions(flow, ufp); } -static int del_or_query_flow(struct datapath *dp, - struct odp_flow __user *ufp, - unsigned int cmd) +static int del_flow(struct datapath *dp, struct odp_flow __user *ufp) { struct dp_table *table = rcu_dereference(dp->table); struct odp_flow uf; @@ -1003,29 +1002,24 @@ static int del_or_query_flow(struct datapath *dp, if (!flow) goto error; - if (cmd == ODP_FLOW_DEL) { - /* XXX redundant lookup */ - error = dp_table_delete(table, flow); - if (error) - goto error; + /* XXX redundant lookup */ + error = dp_table_delete(table, flow); + if (error) + goto error; - /* XXX These statistics might lose a few packets, since other - * CPUs can be using this flow. We used to synchronize_rcu() - * to make sure that we get completely accurate stats, but that - * blows our performance, badly. */ - dp->n_flows--; - error = answer_query(flow, ufp); - flow_deferred_free(flow); - } else { - error = answer_query(flow, ufp); - } + /* XXX These statistics might lose a few packets, since other CPUs can + * be using this flow. We used to synchronize_rcu() to make sure that + * we get completely accurate stats, but that blows our performance, + * badly. */ + dp->n_flows--; + error = answer_query(flow, ufp); + flow_deferred_free(flow); error: return error; } -static int query_multiple_flows(struct datapath *dp, - const struct odp_flowvec *flowvec) +static int query_flows(struct datapath *dp, const struct odp_flowvec *flowvec) { struct dp_table *table = rcu_dereference(dp->table); int i; @@ -1041,7 +1035,7 @@ static int query_multiple_flows(struct datapath *dp, flow = dp_table_lookup(table, &uf.key); if (!flow) - error = __clear_user(&ufp->stats, sizeof ufp->stats); + error = __put_user(ENOENT, &ufp->stats.error); else error = answer_query(flow, ufp); if (error) @@ -1430,13 +1424,11 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, break; case ODP_FLOW_DEL: - case ODP_FLOW_GET: - err = del_or_query_flow(dp, (struct odp_flow __user *)argp, - cmd); + err = del_flow(dp, (struct odp_flow __user *)argp); break; - case ODP_FLOW_GET_MULTIPLE: - err = do_flowvec_ioctl(dp, argp, query_multiple_flows); + case ODP_FLOW_GET: + err = do_flowvec_ioctl(dp, argp, query_flows); break; case ODP_FLOW_LIST: diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h index beaba32d..9b601a3c 100644 --- a/include/openvswitch/datapath-protocol.h +++ b/include/openvswitch/datapath-protocol.h @@ -70,7 +70,6 @@ #define ODP_PORT_GROUP_GET _IOWR('O', 12, struct odp_port_group) #define ODP_FLOW_GET _IOWR('O', 13, struct odp_flow) -#define ODP_FLOW_GET_MULTIPLE _IOWR('O', 14, struct odp_flowvec) #define ODP_FLOW_LIST _IOWR('O', 15, struct odp_flowvec) #define ODP_FLOW_FLUSH _IO('O', 16) @@ -149,7 +148,7 @@ struct odp_flow_stats { __u32 used_nsec; __u8 tcp_flags; __u8 ip_tos; - __u16 reserved; + __u16 error; /* Used by ODP_FLOW_GET. */ }; struct odp_flow_key { diff --git a/lib/dpif.c b/lib/dpif.c index 5558631e..e0e5f364 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -522,10 +522,23 @@ dpif_flow_del(struct dpif *dpif, struct odp_flow *flow) int dpif_flow_get(const struct dpif *dpif, struct odp_flow *flow) { - COVERAGE_INC(dpif_flow_query); + struct odp_flowvec fv; + int error; + + COVERAGE_INC(dpif_flow_get); + check_rw_odp_flow(flow); - memset(&flow->stats, 0, sizeof flow->stats); - return do_flow_ioctl(dpif, ODP_FLOW_GET, flow, "get flow", true); + fv.flows = flow; + fv.n_flows = 1; + error = do_ioctl(dpif, ODP_FLOW_GET, "ODP_FLOW_GET", &fv); + if (!error) { + error = flow->stats.error; + if (error) { + VLOG_WARN_RL(&error_rl, "%s: ioctl(ODP_FLOW_GET) failed (%s)", + dpif_name(dpif), strerror(error)); + } + } + return error; } int @@ -541,7 +554,7 @@ dpif_flow_get_multiple(const struct dpif *dpif, for (i = 0; i < n; i++) { check_rw_odp_flow(&flows[i]); } - return do_ioctl(dpif, ODP_FLOW_GET_MULTIPLE, "ODP_FLOW_GET_MULTIPLE", + return do_ioctl(dpif, ODP_FLOW_GET, "ODP_FLOW_GET", &fv); } -- 2.30.2