Add support for connection tracking.
[cascardo/ovs.git] / lib / dpif.c
index 499def9..c03aa1d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
 #include "coverage.h"
 #include "dpctl.h"
 #include "dp-packet.h"
+#include "dpif-netdev.h"
 #include "dynamic-string.h"
 #include "flow.h"
 #include "netdev.h"
@@ -46,6 +47,7 @@
 #include "tnl-arp-cache.h"
 #include "tnl-ports.h"
 #include "util.h"
+#include "uuid.h"
 #include "valgrind.h"
 #include "openvswitch/vlog.h"
 
@@ -135,6 +137,7 @@ static int
 dp_register_provider__(const struct dpif_class *new_class)
 {
     struct registered_dpif_class *registered_class;
+    int error;
 
     if (sset_contains(&dpif_blacklist, new_class->type)) {
         VLOG_DBG("attempted to register blacklisted provider: %s",
@@ -148,6 +151,13 @@ dp_register_provider__(const struct dpif_class *new_class)
         return EEXIST;
     }
 
+    error = new_class->init ? new_class->init() : 0;
+    if (error) {
+        VLOG_WARN("failed to initialize %s datapath class: %s",
+                  new_class->type, ovs_strerror(error));
+        return error;
+    }
+
     registered_class = xmalloc(sizeof *registered_class);
     registered_class->dpif_class = new_class;
     registered_class->refcount = 0;
@@ -844,6 +854,7 @@ dpif_flow_hash(const struct dpif *dpif OVS_UNUSED,
         ovsthread_once_done(&once);
     }
     hash_bytes128(key, key_len, secret, hash);
+    uuid_set_bits_v4((struct uuid *)hash);
 }
 
 /* Deletes all flows from 'dpif'.  Returns 0 if successful, otherwise a
@@ -877,7 +888,7 @@ dpif_probe_feature(struct dpif *dpif, const char *name,
      * restarted) at just the right time such that feature probes from the
      * previous run are still present in the datapath. */
     error = dpif_flow_put(dpif, DPIF_FP_CREATE | DPIF_FP_MODIFY | DPIF_FP_PROBE,
-                          ofpbuf_data(key), ofpbuf_size(key), NULL, 0, NULL, 0,
+                          key->data, key->size, NULL, 0, NULL, 0,
                           ufid, PMD_ID_NULL, NULL);
     if (error) {
         if (error != EINVAL) {
@@ -888,14 +899,15 @@ dpif_probe_feature(struct dpif *dpif, const char *name,
     }
 
     ofpbuf_use_stack(&reply, &stub, sizeof stub);
-    error = dpif_flow_get(dpif, ofpbuf_data(key), ofpbuf_size(key), ufid,
+    error = dpif_flow_get(dpif, key->data, key->size, ufid,
                           PMD_ID_NULL, &reply, &flow);
     if (!error
-        && (!ufid || (flow.ufid_present && ovs_u128_equal(ufid, &flow.ufid)))) {
+        && (!ufid || (flow.ufid_present
+                      && ovs_u128_equals(ufid, &flow.ufid)))) {
         enable_feature = true;
     }
 
-    error = dpif_flow_del(dpif, ofpbuf_data(key), ofpbuf_size(key), ufid,
+    error = dpif_flow_del(dpif, key->data, key->size, ufid,
                           PMD_ID_NULL, NULL);
     if (error) {
         VLOG_WARN("%s: failed to delete %s feature probe flow",
@@ -909,7 +921,7 @@ dpif_probe_feature(struct dpif *dpif, const char *name,
 int
 dpif_flow_get(struct dpif *dpif,
               const struct nlattr *key, size_t key_len, const ovs_u128 *ufid,
-              const int pmd_id, struct ofpbuf *buf, struct dpif_flow *flow)
+              const unsigned pmd_id, struct ofpbuf *buf, struct dpif_flow *flow)
 {
     struct dpif_op *opp;
     struct dpif_op op;
@@ -938,7 +950,7 @@ dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
               const struct nlattr *key, size_t key_len,
               const struct nlattr *mask, size_t mask_len,
               const struct nlattr *actions, size_t actions_len,
-              const ovs_u128 *ufid, const int pmd_id,
+              const ovs_u128 *ufid, const unsigned pmd_id,
               struct dpif_flow_stats *stats)
 {
     struct dpif_op *opp;
@@ -966,7 +978,7 @@ dpif_flow_put(struct dpif *dpif, enum dpif_flow_put_flags flags,
 int
 dpif_flow_del(struct dpif *dpif,
               const struct nlattr *key, size_t key_len, const ovs_u128 *ufid,
-              const int pmd_id, struct dpif_flow_stats *stats)
+              const unsigned pmd_id, struct dpif_flow_stats *stats)
 {
     struct dpif_op *opp;
     struct dpif_op op;
@@ -1085,6 +1097,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet **packets, int cnt,
     ovs_assert(cnt == 1);
 
     switch ((enum ovs_action_attr)type) {
+    case OVS_ACTION_ATTR_CT:
     case OVS_ACTION_ATTR_OUTPUT:
     case OVS_ACTION_ATTR_TUNNEL_PUSH:
     case OVS_ACTION_ATTR_TUNNEL_POP:
@@ -1103,8 +1116,8 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet **packets, int cnt,
             odp_put_tunnel_action(&md->tunnel, &execute_actions);
             ofpbuf_put(&execute_actions, action, NLA_ALIGN(action->nla_len));
 
-            execute.actions = ofpbuf_data(&execute_actions);
-            execute.actions_len = ofpbuf_size(&execute_actions);
+            execute.actions = execute_actions.data;
+            execute.actions_len = execute_actions.size;
         } else {
             execute.actions = action;
             execute.actions_len = NLA_ALIGN(action->nla_len);
@@ -1333,6 +1346,14 @@ dpif_handlers_set(struct dpif *dpif, uint32_t n_handlers)
     return error;
 }
 
+void
+dpif_register_dp_purge_cb(struct dpif *dpif, dp_purge_callback *cb, void *aux)
+{
+    if (dpif->dpif_class->register_dp_purge_cb) {
+        dpif->dpif_class->register_dp_purge_cb(dpif, cb, aux);
+    }
+}
+
 void
 dpif_register_upcall_cb(struct dpif *dpif, upcall_callback *cb, void *aux)
 {
@@ -1694,6 +1715,5 @@ log_flow_get_message(const struct dpif *dpif, const struct dpif_flow_get *get,
 bool
 dpif_supports_tnl_push_pop(const struct dpif *dpif)
 {
-   return !strcmp(dpif->dpif_class->type, "netdev") ||
-          !strcmp(dpif->dpif_class->type, "dummy");
+    return dpif_is_netdev(dpif);
 }