ofpbuf: New functions ofpbuf_use_stub() and ofpbuf_get_uninit_pointer().
[sliver-openvswitch.git] / lib / dpif.c
index febe8b0..e000e13 100644 (file)
@@ -89,6 +89,8 @@ static void log_operation(const struct dpif *, const char *operation,
 static bool should_log_flow_message(int error);
 static void log_flow_put_message(struct dpif *, const struct dpif_flow_put *,
                                  int error);
+static void log_flow_del_message(struct dpif *, const struct dpif_flow_del *,
+                                 int error);
 static void log_execute_message(struct dpif *, const struct dpif_execute *,
                                 int error);
 
@@ -678,10 +680,10 @@ void
 dpif_flow_stats_extract(const struct flow *flow, const struct ofpbuf *packet,
                         struct dpif_flow_stats *stats)
 {
-    memset(stats, 0, sizeof(*stats));
     stats->tcp_flags = packet_get_tcp_flags(packet, flow);
     stats->n_bytes = packet->size;
     stats->n_packets = 1;
+    stats->used = time_msec();
 }
 
 /* Appends a human-readable representation of 'stats' to 's'. */
@@ -695,7 +697,10 @@ dpif_flow_stats_format(const struct dpif_flow_stats *stats, struct ds *s)
     } else {
         ds_put_format(s, "never");
     }
-    /* XXX tcp_flags? */
+    if (stats->tcp_flags) {
+        ds_put_cstr(s, ", flags:");
+        packet_format_tcp_flags(s, stats->tcp_flags);
+    }
 }
 
 /* Deletes all flows from 'dpif'.  Returns 0 if successful, otherwise a
@@ -815,6 +820,21 @@ dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
     return dpif_flow_put__(dpif, &put);
 }
 
+static int
+dpif_flow_del__(struct dpif *dpif, struct dpif_flow_del *del)
+{
+    int error;
+
+    COVERAGE_INC(dpif_flow_del);
+
+    error = dpif->dpif_class->flow_del(dpif, del);
+    if (error && del->stats) {
+        memset(del->stats, 0, sizeof *del->stats);
+    }
+    log_flow_del_message(dpif, del, error);
+    return error;
+}
+
 /* Deletes a flow from 'dpif' and returns 0, or returns ENOENT if 'dpif' does
  * not contain such a flow.  The flow is specified by the Netlink attributes
  * with types OVS_KEY_ATTR_* in the 'key_len' bytes starting at 'key'.
@@ -826,19 +846,12 @@ dpif_flow_del(struct dpif *dpif,
               const struct nlattr *key, size_t key_len,
               struct dpif_flow_stats *stats)
 {
-    int error;
-
-    COVERAGE_INC(dpif_flow_del);
+    struct dpif_flow_del del;
 
-    error = dpif->dpif_class->flow_del(dpif, key, key_len, stats);
-    if (error && stats) {
-        memset(stats, 0, sizeof *stats);
-    }
-    if (should_log_flow_message(error)) {
-        log_flow_message(dpif, error, "flow_del", key, key_len,
-                         !error ? stats : NULL, NULL, 0);
-    }
-    return error;
+    del.key = key;
+    del.key_len = key_len;
+    del.stats = stats;
+    return dpif_flow_del__(dpif, &del);
 }
 
 /* Initializes 'dump' to begin dumping the flows in a dpif.
@@ -994,6 +1007,10 @@ dpif_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops)
                 log_flow_put_message(dpif, &op->u.flow_put, op->error);
                 break;
 
+            case DPIF_OP_FLOW_DEL:
+                log_flow_del_message(dpif, &op->u.flow_del, op->error);
+                break;
+
             case DPIF_OP_EXECUTE:
                 log_execute_message(dpif, &op->u.execute, op->error);
                 break;
@@ -1010,6 +1027,10 @@ dpif_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops)
             op->error = dpif_flow_put__(dpif, &op->u.flow_put);
             break;
 
+        case DPIF_OP_FLOW_DEL:
+            op->error = dpif_flow_del__(dpif, &op->u.flow_del);
+            break;
+
         case DPIF_OP_EXECUTE:
             op->error = dpif_execute__(dpif, &op->u.execute);
             break;
@@ -1245,6 +1266,16 @@ log_flow_put_message(struct dpif *dpif, const struct dpif_flow_put *put,
     }
 }
 
+static void
+log_flow_del_message(struct dpif *dpif, const struct dpif_flow_del *del,
+                     int error)
+{
+    if (should_log_flow_message(error)) {
+        log_flow_message(dpif, error, "flow_del", del->key, del->key_len,
+                         !error ? del->stats : NULL, NULL, 0);
+    }
+}
+
 static void
 log_execute_message(struct dpif *dpif, const struct dpif_execute *execute,
                     int error)