Eliminate ODPL_* from userspace-facing interface.
[openvswitch] / ofproto / ofproto.c
index ea869f1ec781295915fbcdf5f057d3d6478d688f..5c7a497ecd72a5cd05e5c2d1c8fb3f5ffda8973f 100644 (file)
@@ -206,7 +206,8 @@ struct facet {
      *
      *   - Do include packets and bytes that were obtained from the datapath
      *     when a flow was deleted (e.g. dpif_flow_del()) or when its
-     *     statistics were reset (e.g. dpif_flow_put() with ODPPF_ZERO_STATS).
+     *     statistics were reset (e.g. dpif_flow_put() with
+     *     DPIF_FP_ZERO_STATS).
      *
      *   - Do not include any packets or bytes that can currently be obtained
      *     from the datapath by, e.g., dpif_flow_get().
@@ -248,7 +249,7 @@ static void facet_flush_stats(struct ofproto *, struct facet *);
 static void facet_make_actions(struct ofproto *, struct facet *,
                                const struct ofpbuf *packet);
 static void facet_update_stats(struct ofproto *, struct facet *,
-                               const struct odp_flow_stats *);
+                               const struct dpif_flow_stats *);
 
 /* ofproto supports two kinds of OpenFlow connections:
  *
@@ -300,7 +301,8 @@ struct ofconn {
 
     /* OFPT_PACKET_IN related data. */
     struct rconn_packet_counter *packet_in_counter; /* # queued on 'rconn'. */
-    struct pinsched *schedulers[2]; /* Indexed by reason code; see below. */
+#define N_SCHEDULERS 2
+    struct pinsched *schedulers[N_SCHEDULERS];
     struct pktbuf *pktbuf;         /* OpenFlow packet buffers. */
     int miss_send_len;             /* Bytes to send of buffered packets. */
 
@@ -318,15 +320,6 @@ struct ofconn {
     enum ofproto_band band;      /* In-band or out-of-band? */
 };
 
-/* We use OFPR_NO_MATCH and OFPR_ACTION as indexes into struct ofconn's
- * "schedulers" array.  Their values are 0 and 1, and their meanings and values
- * coincide with _ODPL_MISS_NR and _ODPL_ACTION_NR, so this is convenient.  In
- * case anything ever changes, check their values here.  */
-#define N_SCHEDULERS 2
-BUILD_ASSERT_DECL(OFPR_NO_MATCH == 0);
-BUILD_ASSERT_DECL(OFPR_NO_MATCH == _ODPL_MISS_NR);
-BUILD_ASSERT_DECL(OFPR_ACTION == 1);
-BUILD_ASSERT_DECL(OFPR_ACTION == _ODPL_ACTION_NR);
 
 static struct ofconn *ofconn_create(struct ofproto *, struct rconn *,
                                     enum ofconn_type);
@@ -443,7 +436,10 @@ ofproto_create(const char *datapath, const char *datapath_type,
         VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error));
         return error;
     }
-    error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION | ODPL_SFLOW);
+    error = dpif_recv_set_mask(dpif,
+                               ((1u << DPIF_UC_MISS) |
+                                (1u << DPIF_UC_ACTION) |
+                                (1u << DPIF_UC_SAMPLE)));
     if (error) {
         VLOG_ERR("failed to listen on datapath %s: %s",
                  datapath, strerror(error));
@@ -2098,7 +2094,7 @@ execute_odp_actions(struct ofproto *ofproto, const struct flow *flow,
          * buffers along the way. */
         struct dpif_upcall upcall;
 
-        upcall.type = _ODPL_ACTION_NR;
+        upcall.type = DPIF_UC_ACTION;
         upcall.packet = packet;
         upcall.key = NULL;
         upcall.key_len = 0;
@@ -2135,7 +2131,7 @@ static void
 facet_execute(struct ofproto *ofproto, struct facet *facet,
               struct ofpbuf *packet)
 {
-    struct odp_flow_stats stats;
+    struct dpif_flow_stats stats;
 
     assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in));
 
@@ -2306,24 +2302,25 @@ facet_make_actions(struct ofproto *p, struct facet *facet,
 }
 
 static int
-facet_put__(struct ofproto *ofproto, struct facet *facet, int flags,
-            struct odp_flow_put *put)
+facet_put__(struct ofproto *ofproto, struct facet *facet,
+            const struct nlattr *actions, size_t actions_len,
+            struct dpif_flow_stats *stats)
 {
     uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
+    enum dpif_flow_put_flags flags;
     struct ofpbuf key;
 
+    flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
+    if (stats) {
+        flags |= DPIF_FP_ZERO_STATS;
+    }
+
     ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
     odp_flow_key_from_flow(&key, &facet->flow);
     assert(key.base == keybuf);
 
-    memset(&put->flow.stats, 0, sizeof put->flow.stats);
-    put->flow.key = key.data;
-    put->flow.key_len = key.size;
-    put->flow.actions = facet->actions;
-    put->flow.actions_len = facet->actions_len;
-    put->flow.flags = 0;
-    put->flags = flags;
-    return dpif_flow_put(ofproto->dpif, put);
+    return dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
+                         actions, actions_len, stats);
 }
 
 /* If 'facet' is installable, inserts or re-inserts it into 'p''s datapath.  If
@@ -2332,17 +2329,12 @@ facet_put__(struct ofproto *ofproto, struct facet *facet, int flags,
 static void
 facet_install(struct ofproto *p, struct facet *facet, bool zero_stats)
 {
-    if (facet->may_install) {
-        struct odp_flow_put put;
-        int flags;
+    struct dpif_flow_stats stats;
 
-        flags = ODPPF_CREATE | ODPPF_MODIFY;
-        if (zero_stats) {
-            flags |= ODPPF_ZERO_STATS;
-        }
-        if (!facet_put__(p, facet, flags, &put)) {
-            facet->installed = true;
-        }
+    if (facet->may_install
+        && !facet_put__(p, facet, facet->actions, facet->actions_len,
+                        zero_stats ? &stats : NULL)) {
+        facet->installed = true;
     }
 }
 
@@ -2370,20 +2362,15 @@ facet_uninstall(struct ofproto *p, struct facet *facet)
 {
     if (facet->installed) {
         uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
-        struct odp_flow odp_flow;
+        struct dpif_flow_stats stats;
         struct ofpbuf key;
 
         ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
         odp_flow_key_from_flow(&key, &facet->flow);
         assert(key.base == keybuf);
 
-        odp_flow.key = key.data;
-        odp_flow.key_len = key.size;
-        odp_flow.actions = NULL;
-        odp_flow.actions_len = 0;
-        odp_flow.flags = 0;
-        if (!dpif_flow_del(p->dpif, &odp_flow)) {
-            facet_update_stats(p, facet, &odp_flow.stats);
+        if (!dpif_flow_del(p->dpif, key.data, key.size, &stats)) {
+            facet_update_stats(p, facet, &stats);
         }
         facet->installed = false;
     }
@@ -2512,25 +2499,13 @@ facet_revalidate(struct ofproto *ofproto, struct facet *facet)
 
     /* If the ODP actions changed or the installability changed, then we need
      * to talk to the datapath. */
-    if (actions_changed || facet->may_install != facet->installed) {
-        if (facet->may_install) {
-            uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
-            struct odp_flow_put put;
-            struct ofpbuf key;
-
-            ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
-            odp_flow_key_from_flow(&key, &facet->flow);
-
-            memset(&put.flow.stats, 0, sizeof put.flow.stats);
-            put.flow.key = key.data;
-            put.flow.key_len = key.size;
-            put.flow.actions = odp_actions->data;
-            put.flow.actions_len = odp_actions->size;
-            put.flow.flags = 0;
-            put.flags = ODPPF_CREATE | ODPPF_MODIFY | ODPPF_ZERO_STATS;
-            dpif_flow_put(ofproto->dpif, &put);
-
-            facet_update_stats(ofproto, facet, &put.flow.stats);
+    if (actions_changed || ctx.may_set_up_flow != facet->installed) {
+        if (ctx.may_set_up_flow) {
+            struct dpif_flow_stats stats;
+
+            facet_put__(ofproto, facet,
+                        odp_actions->data, odp_actions->size, &stats);
+            facet_update_stats(ofproto, facet, &stats);
         } else {
             facet_uninstall(ofproto, facet);
         }
@@ -3487,9 +3462,7 @@ query_stats(struct ofproto *p, struct rule *rule,
     packet_count = rule->packet_count;
     byte_count = rule->byte_count;
 
-    /* Ask the datapath for statistics on all of the rule's facets.  (We could
-     * batch up statistics requests using dpif_flow_get_multiple(), but that is
-     * not yet implemented.)
+    /* Ask the datapath for statistics on all of the rule's facets.
      *
      * Also, add any statistics that are not tracked by the datapath for each
      * facet.  This includes, for example, statistics for packets that were
@@ -3497,23 +3470,14 @@ query_stats(struct ofproto *p, struct rule *rule,
      * to a rule. */
     ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
     LIST_FOR_EACH (facet, list_node, &rule->facets) {
-        struct odp_flow odp_flow;
+        struct dpif_flow_stats stats;
 
         ofpbuf_clear(&key);
         odp_flow_key_from_flow(&key, &facet->flow);
+        dpif_flow_get(p->dpif, key.data, key.size, NULL, &stats);
 
-        odp_flow.key = key.data;
-        odp_flow.key_len = key.size;
-        odp_flow.actions = NULL;
-        odp_flow.actions_len = 0;
-        odp_flow.flags = 0;
-        if (!dpif_flow_get(p->dpif, &odp_flow)) {
-            packet_count += odp_flow.stats.n_packets;
-            byte_count += odp_flow.stats.n_bytes;
-        }
-
-        packet_count += facet->packet_count;
-        byte_count += facet->byte_count;
+        packet_count += stats.n_packets + facet->packet_count;
+        byte_count += stats.n_bytes + facet->byte_count;
     }
 
     /* Return the stats to the caller. */
@@ -3884,17 +3848,11 @@ handle_queue_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
     return 0;
 }
 
-static long long int
-msec_from_nsec(uint64_t sec, uint32_t nsec)
-{
-    return !sec ? 0 : sec * 1000 + nsec / 1000000;
-}
-
 static void
 facet_update_time(struct ofproto *ofproto, struct facet *facet,
-                  const struct odp_flow_stats *stats)
+                  const struct dpif_flow_stats *stats)
 {
-    long long int used = msec_from_nsec(stats->used_sec, stats->used_nsec);
+    long long int used = stats->used;
     if (used > facet->used) {
         facet->used = used;
         if (used > facet->rule->used) {
@@ -3912,7 +3870,7 @@ facet_update_time(struct ofproto *ofproto, struct facet *facet,
  * cleared out of the datapath. */
 static void
 facet_update_stats(struct ofproto *ofproto, struct facet *facet,
-                   const struct odp_flow_stats *stats)
+                   const struct dpif_flow_stats *stats)
 {
     if (stats->n_packets) {
         facet_update_time(ofproto, facet, stats);
@@ -4476,13 +4434,13 @@ handle_upcall(struct ofproto *p, struct dpif_upcall *upcall)
     struct flow flow;
 
     switch (upcall->type) {
-    case _ODPL_ACTION_NR:
+    case DPIF_UC_ACTION:
         COVERAGE_INC(ofproto_ctlr_action);
         odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
         send_packet_in(p, upcall, &flow, false);
         break;
 
-    case _ODPL_SFLOW_NR:
+    case DPIF_UC_SAMPLE:
         if (p->sflow) {
             odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
             ofproto_sflow_received(p->sflow, upcall, &flow);
@@ -4490,7 +4448,7 @@ handle_upcall(struct ofproto *p, struct dpif_upcall *upcall)
         ofpbuf_delete(upcall->packet);
         break;
 
-    case _ODPL_MISS_NR:
+    case DPIF_UC_MISS:
         handle_miss_upcall(p, upcall);
         break;
 
@@ -4548,31 +4506,21 @@ ofproto_expire(struct ofproto *ofproto)
 static void
 ofproto_update_used(struct ofproto *p)
 {
+    const struct dpif_flow_stats *stats;
     struct dpif_flow_dump dump;
+    const struct nlattr *key;
+    size_t key_len;
 
     dpif_flow_dump_start(&dump, p->dpif);
-    for (;;) {
-        uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
+    while (dpif_flow_dump_next(&dump, &key, &key_len, NULL, NULL, &stats)) {
         struct facet *facet;
-        struct odp_flow f;
         struct flow flow;
 
-        memset(&f, 0, sizeof f);
-        f.key = (struct nlattr *) keybuf;
-        f.key_len = sizeof keybuf;
-        if (!dpif_flow_dump_next(&dump, &f)) {
-            break;
-        }
-
-        if (f.key_len > sizeof keybuf) {
-            VLOG_WARN_RL(&rl, "ODP flow key overflowed buffer");
-            continue;
-        }
-        if (odp_flow_key_to_flow(f.key, f.key_len, &flow)) {
+        if (odp_flow_key_to_flow(key, key_len, &flow)) {
             struct ds s;
 
             ds_init(&s);
-            odp_flow_key_format(f.key, f.key_len, &s);
+            odp_flow_key_format(key, key_len, &s);
             VLOG_WARN_RL(&rl, "failed to convert ODP flow key to flow: %s",
                          ds_cstr(&s));
             ds_destroy(&s);
@@ -4582,13 +4530,13 @@ ofproto_update_used(struct ofproto *p)
         facet = facet_find(p, &flow);
 
         if (facet && facet->installed) {
-            facet_update_time(p, facet, &f.stats);
-            facet_account(p, facet, f.stats.n_bytes);
+            facet_update_time(p, facet, stats);
+            facet_account(p, facet, stats->n_bytes);
         } else {
             /* There's a flow in the datapath that we know nothing about.
              * Delete it. */
             COVERAGE_INC(ofproto_unexpected_rule);
-            dpif_flow_del(p->dpif, &f);
+            dpif_flow_del(p->dpif, key, key_len, NULL);
         }
     }
     dpif_flow_dump_done(&dump);
@@ -4690,39 +4638,19 @@ facet_active_timeout(struct ofproto *ofproto, struct facet *facet)
     if (ofproto->netflow && !facet_is_controller_flow(facet) &&
         netflow_active_timeout_expired(ofproto->netflow, &facet->nf_flow)) {
         struct ofexpired expired;
-        struct odp_flow odp_flow;
 
-        /* Get updated flow stats.
-         *
-         * XXX We could avoid this call entirely if (1) ofproto_update_used()
-         * updated TCP flags and (2) the dpif_flow_list_all() in
-         * ofproto_update_used() zeroed TCP flags. */
-        memset(&odp_flow, 0, sizeof odp_flow);
         if (facet->installed) {
-            uint32_t keybuf[ODPUTIL_FLOW_KEY_U32S];
-            struct ofpbuf key;
+            struct dpif_flow_stats stats;
 
-            ofpbuf_use_stack(&key, keybuf, sizeof keybuf);
-            odp_flow_key_from_flow(&key, &facet->flow);
-
-            odp_flow.key = key.data;
-            odp_flow.key_len = key.size;
-            odp_flow.flags = ODPFF_ZERO_TCP_FLAGS;
-            dpif_flow_get(ofproto->dpif, &odp_flow);
-
-            if (odp_flow.stats.n_packets) {
-                facet_update_time(ofproto, facet, &odp_flow.stats);
-                netflow_flow_update_flags(&facet->nf_flow,
-                                          odp_flow.stats.tcp_flags);
-            }
+            facet_put__(ofproto, facet, facet->actions, facet->actions_len,
+                        &stats);
+            facet_update_stats(ofproto, facet, &stats);
         }
 
         expired.flow = facet->flow;
-        expired.packet_count = facet->packet_count +
-                               odp_flow.stats.n_packets;
-        expired.byte_count = facet->byte_count + odp_flow.stats.n_bytes;
+        expired.packet_count = facet->packet_count;
+        expired.byte_count = facet->byte_count;
         expired.used = facet->used;
-
         netflow_expire(ofproto->netflow, &facet->nf_flow, &expired);
     }
 }
@@ -4876,9 +4804,10 @@ schedule_packet_in(struct ofconn *ofconn, struct dpif_upcall *upcall,
     int total_len, send_len;
     struct ofpbuf *packet;
     uint32_t buffer_id;
+    int idx;
 
     /* Get OpenFlow buffer_id. */
-    if (upcall->type == _ODPL_ACTION_NR) {
+    if (upcall->type == DPIF_UC_ACTION) {
         buffer_id = UINT32_MAX;
     } else if (ofproto->fail_open && fail_open_is_active(ofproto->fail_open)) {
         buffer_id = pktbuf_get_null();
@@ -4893,7 +4822,7 @@ schedule_packet_in(struct ofconn *ofconn, struct dpif_upcall *upcall,
     if (buffer_id != UINT32_MAX) {
         send_len = MIN(send_len, ofconn->miss_send_len);
     }
-    if (upcall->type == _ODPL_ACTION_NR) {
+    if (upcall->type == DPIF_UC_ACTION) {
         send_len = MIN(send_len, upcall->userdata);
     }
 
@@ -4912,18 +4841,19 @@ schedule_packet_in(struct ofconn *ofconn, struct dpif_upcall *upcall,
     opi->header.type = OFPT_PACKET_IN;
     opi->total_len = htons(total_len);
     opi->in_port = htons(odp_port_to_ofp_port(flow->in_port));
-    opi->reason = upcall->type == _ODPL_MISS_NR ? OFPR_NO_MATCH : OFPR_ACTION;
+    opi->reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION;
     opi->buffer_id = htonl(buffer_id);
     update_openflow_length(packet);
 
     /* Hand over to packet scheduler.  It might immediately call into
      * do_send_packet_in() or it might buffer it for a while (until a later
      * call to pinsched_run()). */
-    pinsched_send(ofconn->schedulers[opi->reason], flow->in_port,
+    idx = upcall->type == DPIF_UC_MISS ? 0 : 1;
+    pinsched_send(ofconn->schedulers[idx], flow->in_port,
                   packet, do_send_packet_in, ofconn);
 }
 
-/* Given 'upcall', of type _ODPL_ACTION_NR or _ODPL_MISS_NR, sends an
+/* Given 'upcall', of type DPIF_UC_ACTION or DPIF_UC_MISS, sends an
  * OFPT_PACKET_IN message to each OpenFlow controller as necessary according to
  * their individual configurations.
  *