datapath: Get rid of query operations for single flows.
authorBen Pfaff <blp@nicira.com>
Wed, 17 Jun 2009 19:41:30 +0000 (12:41 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 6 Jul 2009 16:07:24 +0000 (09:07 -0700)
datapath/datapath.c
include/openvswitch/datapath-protocol.h
lib/dpif.c

index 27bc5ce47e429183056695c11624ebf06b6a3f94..f76b51f998d975e6fa337d7b87539d45819257dc 100644 (file)
@@ -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:
index beaba32d8bd174aa28d1750568d1c189ad9f94b8..9b601a3cf091564273c2e6d9399d657f6ae43802 100644 (file)
@@ -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 {
index 5558631ec14509a2a1cb7b8cb410944e0559921b..e0e5f36425529163626066ea44ae90964e22d65a 100644 (file)
@@ -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);
 }