coverage: Make the coverage counters catalog program-specific.
[sliver-openvswitch.git] / lib / dpif.c
index 315f11f..5402033 100644 (file)
@@ -30,6 +30,7 @@
 #include "netlink.h"
 #include "odp-util.h"
 #include "ofp-print.h"
+#include "ofp-util.h"
 #include "ofpbuf.h"
 #include "packets.h"
 #include "poll-loop.h"
 #include "svec.h"
 #include "util.h"
 #include "valgrind.h"
-
 #include "vlog.h"
-#define THIS_MODULE VLM_dpif
+
+VLOG_DEFINE_THIS_MODULE(dpif);
+
+COVERAGE_DEFINE(dpif_destroy);
+COVERAGE_DEFINE(dpif_port_add);
+COVERAGE_DEFINE(dpif_port_del);
+COVERAGE_DEFINE(dpif_flow_flush);
+COVERAGE_DEFINE(dpif_flow_get);
+COVERAGE_DEFINE(dpif_flow_put);
+COVERAGE_DEFINE(dpif_flow_del);
+COVERAGE_DEFINE(dpif_flow_query_list);
+COVERAGE_DEFINE(dpif_flow_query_list_n);
+COVERAGE_DEFINE(dpif_execute);
+COVERAGE_DEFINE(dpif_purge);
 
 static const struct dpif_class *base_dpif_classes[] = {
+#ifdef HAVE_NETLINK
     &dpif_linux_class,
+#endif
     &dpif_netdev_class,
 };
 
 struct registered_dpif_class {
-    struct dpif_class dpif_class;
+    const struct dpif_class *dpif_class;
     int refcount;
 };
 static struct shash dpif_classes = SHASH_INITIALIZER(&dpif_classes);
@@ -58,7 +73,7 @@ static struct shash dpif_classes = SHASH_INITIALIZER(&dpif_classes);
 static struct vlog_rate_limit dpmsg_rl = VLOG_RATE_LIMIT_INIT(600, 600);
 
 /* Not really much point in logging many dpif errors. */
-static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5);
+static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);
 
 static void log_operation(const struct dpif *, const char *operation,
                           int error);
@@ -94,8 +109,8 @@ dp_run(void)
     struct shash_node *node;
     SHASH_FOR_EACH(node, &dpif_classes) {
         const struct registered_dpif_class *registered_class = node->data;
-        if (registered_class->dpif_class.run) {
-            registered_class->dpif_class.run();
+        if (registered_class->dpif_class->run) {
+            registered_class->dpif_class->run();
         }
     }
 }
@@ -110,8 +125,8 @@ dp_wait(void)
     struct shash_node *node;
     SHASH_FOR_EACH(node, &dpif_classes) {
         const struct registered_dpif_class *registered_class = node->data;
-        if (registered_class->dpif_class.wait) {
-            registered_class->dpif_class.wait();
+        if (registered_class->dpif_class->wait) {
+            registered_class->dpif_class->wait();
         }
     }
 }
@@ -130,8 +145,7 @@ dp_register_provider(const struct dpif_class *new_class)
     }
 
     registered_class = xmalloc(sizeof *registered_class);
-    memcpy(&registered_class->dpif_class, new_class,
-           sizeof registered_class->dpif_class);
+    registered_class->dpif_class = new_class;
     registered_class->refcount = 0;
 
     shash_add(&dpif_classes, new_class->type, registered_class);
@@ -179,7 +193,7 @@ dp_enumerate_types(struct svec *types)
 
     SHASH_FOR_EACH(node, &dpif_classes) {
         const struct registered_dpif_class *registered_class = node->data;
-        svec_add(types, registered_class->dpif_class.type);
+        svec_add(types, registered_class->dpif_class->type);
     }
 }
 
@@ -205,7 +219,7 @@ dp_enumerate_names(const char *type, struct svec *names)
         return EAFNOSUPPORT;
     }
 
-    dpif_class = &registered_class->dpif_class;
+    dpif_class = registered_class->dpif_class;
     error = dpif_class->enumerate ? dpif_class->enumerate(names) : 0;
 
     if (error) {
@@ -256,8 +270,10 @@ do_open(const char *name, const char *type, bool create, struct dpif **dpifp)
         goto exit;
     }
 
-    error = registered_class->dpif_class.open(name, type, create, &dpif);
+    error = registered_class->dpif_class->open(registered_class->dpif_class,
+                                               name, create, &dpif);
     if (!error) {
+        assert(dpif->dpif_class == registered_class->dpif_class);
         registered_class->refcount++;
     }
 
@@ -319,7 +335,7 @@ dpif_close(struct dpif *dpif)
     if (dpif) {
         struct registered_dpif_class *registered_class;
 
-        registered_class = shash_find_data(&dpif_classes, 
+        registered_class = shash_find_data(&dpif_classes,
                 dpif->dpif_class->type);
         assert(registered_class);
         assert(registered_class->refcount);
@@ -371,6 +387,7 @@ dpif_get_all_names(const struct dpif *dpif, struct svec *all_names)
     }
 }
 
+
 /* Destroys the datapath that 'dpif' is connected to, first removing all of its
  * ports.  After calling this function, it does not make sense to pass 'dpif'
  * to any functions other than dpif_name() or dpif_close(). */
@@ -623,68 +640,6 @@ dpif_port_poll_wait(const struct dpif *dpif)
     dpif->dpif_class->port_poll_wait(dpif);
 }
 
-/* Retrieves a list of the port numbers in port group 'group' in 'dpif'.
- *
- * On success, returns 0 and points '*ports' to a newly allocated array of
- * integers, each of which is a 'dpif' port number for a port in
- * 'group'.  Stores the number of elements in the array in '*n_ports'.  The
- * caller is responsible for freeing '*ports' by calling free().
- *
- * On failure, returns a positive errno value and sets '*ports' to NULL and
- * '*n_ports' to 0. */
-int
-dpif_port_group_get(const struct dpif *dpif, uint16_t group,
-                    uint16_t **ports, size_t *n_ports)
-{
-    int error;
-
-    *ports = NULL;
-    *n_ports = 0;
-    for (;;) {
-        int retval = dpif->dpif_class->port_group_get(dpif, group,
-                                                      *ports, *n_ports);
-        if (retval < 0) {
-            /* Hard error. */
-            error = -retval;
-            free(*ports);
-            *ports = NULL;
-            *n_ports = 0;
-            break;
-        } else if (retval <= *n_ports) {
-            /* Success. */
-            error = 0;
-            *n_ports = retval;
-            break;
-        } else {
-            /* Soft error: there were more ports than we expected in the
-             * group.  Try again. */
-            free(*ports);
-            *ports = xcalloc(retval, sizeof **ports);
-            *n_ports = retval;
-        }
-    }
-    log_operation(dpif, "port_group_get", error);
-    return error;
-}
-
-/* Updates port group 'group' in 'dpif', making it contain the 'n_ports' ports
- * whose 'dpif' port numbers are given in 'n_ports'.  Returns 0 if
- * successful, otherwise a positive errno value.
- *
- * Behavior is undefined if the values in ports[] are not unique. */
-int
-dpif_port_group_set(struct dpif *dpif, uint16_t group,
-                    const uint16_t ports[], size_t n_ports)
-{
-    int error;
-
-    COVERAGE_INC(dpif_port_group_set);
-
-    error = dpif->dpif_class->port_group_set(dpif, group, ports, n_ports);
-    log_operation(dpif, "port_group_set", error);
-    return error;
-}
-
 /* Deletes all flows from 'dpif'.  Returns 0 if successful, otherwise a
  * positive errno value.  */
 int
@@ -724,6 +679,11 @@ dpif_flow_get(const struct dpif *dpif, struct odp_flow *flow)
     if (!error) {
         error = flow->stats.error;
     }
+    if (error) {
+        /* Make the results predictable on error. */
+        memset(&flow->stats, 0, sizeof flow->stats);
+        flow->n_actions = 0;
+    }
     if (should_log_flow_message(error)) {
         log_flow_operation(dpif, "flow_get", error, flow);
     }
@@ -911,14 +871,9 @@ dpif_flow_list_all(const struct dpif *dpif,
 /* Causes 'dpif' to perform the 'n_actions' actions in 'actions' on the
  * Ethernet frame specified in 'packet'.
  *
- * Pretends that the frame was originally received on the port numbered
- * 'in_port'.  This affects only ODPAT_OUTPUT_GROUP actions, which will not
- * send a packet out their input port.  Specify the number of an unused port
- * (e.g. UINT16_MAX is currently always unused) to avoid this behavior.
- *
  * Returns 0 if successful, otherwise a positive errno value. */
 int
-dpif_execute(struct dpif *dpif, uint16_t in_port,
+dpif_execute(struct dpif *dpif,
              const union odp_action actions[], size_t n_actions,
              const struct ofpbuf *buf)
 {
@@ -926,8 +881,7 @@ dpif_execute(struct dpif *dpif, uint16_t in_port,
 
     COVERAGE_INC(dpif_execute);
     if (n_actions > 0) {
-        error = dpif->dpif_class->execute(dpif, in_port, actions,
-                                          n_actions, buf);
+        error = dpif->dpif_class->execute(dpif, actions, n_actions, buf);
     } else {
         error = 0;
     }
@@ -1010,7 +964,8 @@ dpif_set_sflow_probability(struct dpif *dpif, uint32_t probability)
 
 /* Attempts to receive a message from 'dpif'.  If successful, stores the
  * message into '*packetp'.  The message, if one is received, will begin with
- * 'struct odp_msg' as a header.  Only messages of the types selected with
+ * 'struct odp_msg' as a header, and will have at least DPIF_RECV_MSG_PADDING
+ * bytes of headroom.  Only messages of the types selected with
  * dpif_set_listen_mask() will ordinarily be received (but if a message type is
  * enabled and then later disabled, some stragglers might pop up).
  *
@@ -1021,8 +976,10 @@ dpif_recv(struct dpif *dpif, struct ofpbuf **packetp)
 {
     int error = dpif->dpif_class->recv(dpif, packetp);
     if (!error) {
+        struct ofpbuf *buf = *packetp;
+
+        assert(ofpbuf_headroom(buf) >= DPIF_RECV_MSG_PADDING);
         if (VLOG_IS_DBG_ENABLED()) {
-            struct ofpbuf *buf = *packetp;
             struct odp_msg *msg = buf->data;
             void *payload = msg + 1;
             size_t payload_len = buf->size - sizeof *msg;
@@ -1086,6 +1043,25 @@ dpif_get_netflow_ids(const struct dpif *dpif,
     *engine_type = dpif->netflow_engine_type;
     *engine_id = dpif->netflow_engine_id;
 }
+
+/* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a priority
+ * value for use in the ODPAT_SET_PRIORITY action.  On success, returns 0 and
+ * stores the priority into '*priority'.  On failure, returns a positive errno
+ * value and stores 0 into '*priority'. */
+int
+dpif_queue_to_priority(const struct dpif *dpif, uint32_t queue_id,
+                       uint32_t *priority)
+{
+    int error = (dpif->dpif_class->queue_to_priority
+                 ? dpif->dpif_class->queue_to_priority(dpif, queue_id,
+                                                       priority)
+                 : EOPNOTSUPP);
+    if (error) {
+        *priority = 0;
+    }
+    log_operation(dpif, "queue_to_priority", error);
+    return error;
+}
 \f
 void
 dpif_init(struct dpif *dpif, const struct dpif_class *dpif_class,
@@ -1124,9 +1100,13 @@ log_operation(const struct dpif *dpif, const char *operation, int error)
 {
     if (!error) {
         VLOG_DBG_RL(&dpmsg_rl, "%s: %s success", dpif_name(dpif), operation);
-    } else {
+    } else if (is_errno(error)) {
         VLOG_WARN_RL(&error_rl, "%s: %s failed (%s)",
                      dpif_name(dpif), operation, strerror(error));
+    } else {
+        VLOG_WARN_RL(&error_rl, "%s: %s failed (%d/%d)",
+                     dpif_name(dpif), operation,
+                     get_ofp_err_type(error), get_ofp_err_code(error));
     }
 }
 
@@ -1145,7 +1125,8 @@ should_log_flow_message(int error)
 
 static void
 log_flow_message(const struct dpif *dpif, int error, const char *operation,
-                 const flow_t *flow, const struct odp_flow_stats *stats,
+                 const struct odp_flow_key *flow,
+                 const struct odp_flow_stats *stats,
                  const union odp_action *actions, size_t n_actions)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
@@ -1157,7 +1138,7 @@ log_flow_message(const struct dpif *dpif, int error, const char *operation,
     if (error) {
         ds_put_format(&ds, "(%s) ", strerror(error));
     }
-    flow_format(&ds, flow);
+    format_odp_flow_key(&ds, flow);
     if (stats) {
         ds_put_cstr(&ds, ", ");
         format_odp_flow_stats(&ds, stats);