[ovs-dev] [DPDK:patch_v5 2/8] Parse NAT netlink for userspace datapath.

Darrell Ball dlu998 at gmail.com
Wed Feb 8 08:17:55 UTC 2017


Signed-off-by: Darrell Ball <dlu998 at gmail.com>
---
 lib/conntrack-private.h |  9 ------
 lib/conntrack.c         |  3 +-
 lib/conntrack.h         | 29 ++++++++++++++++-
 lib/dpif-netdev.c       | 82 ++++++++++++++++++++++++++++++++++++++++++++++---
 tests/test-conntrack.c  |  8 +++--
 5 files changed, 113 insertions(+), 18 deletions(-)

diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h
index 013f19f..493865f 100644
--- a/lib/conntrack-private.h
+++ b/lib/conntrack-private.h
@@ -29,15 +29,6 @@
 #include "packets.h"
 #include "unaligned.h"
 
-struct ct_addr {
-    union {
-        ovs_16aligned_be32 ipv4;
-        union ovs_16aligned_in6_addr ipv6;
-        ovs_be32 ipv4_aligned;
-        struct in6_addr ipv6_aligned;
-    };
-};
-
 struct ct_endpoint {
     struct ct_addr addr;
     union {
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 9bea3d9..0a611a2 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -273,7 +273,8 @@ conntrack_execute(struct conntrack *ct, struct dp_packet_batch *pkt_batch,
                   ovs_be16 dl_type, bool commit, uint16_t zone,
                   const uint32_t *setmark,
                   const struct ovs_key_ct_labels *setlabel,
-                  const char *helper)
+                  const char *helper,
+                  const struct nat_action_info_t *nat_action_info OVS_UNUSED)
 {
     struct dp_packet **pkts = pkt_batch->packets;
     size_t cnt = pkt_batch->count;
diff --git a/lib/conntrack.h b/lib/conntrack.h
index 254f61c..288808b 100644
--- a/lib/conntrack.h
+++ b/lib/conntrack.h
@@ -26,6 +26,8 @@
 #include "openvswitch/thread.h"
 #include "openvswitch/types.h"
 #include "ovs-atomic.h"
+#include "ovs-thread.h"
+#include "packets.h"
 
 /* Userspace connection tracker
  * ============================
@@ -61,6 +63,30 @@ struct dp_packet_batch;
 
 struct conntrack;
 
+struct ct_addr {
+    union {
+        ovs_16aligned_be32 ipv4;
+        union ovs_16aligned_in6_addr ipv6;
+        ovs_be32 ipv4_aligned;
+        struct in6_addr ipv6_aligned;
+    };
+};
+
+enum nat_action_e {
+    NAT_ACTION_SRC = 1 << 0,
+    NAT_ACTION_SRC_PORT = 1 << 1,
+    NAT_ACTION_DST = 1 << 2,
+    NAT_ACTION_DST_PORT = 1 << 3,
+};
+
+struct nat_action_info_t {
+    struct ct_addr min_addr;
+    struct ct_addr max_addr;
+    uint16_t min_port;
+    uint16_t max_port;
+    uint16_t nat_action;
+};
+
 void conntrack_init(struct conntrack *);
 void conntrack_destroy(struct conntrack *);
 
@@ -68,7 +94,8 @@ int conntrack_execute(struct conntrack *, struct dp_packet_batch *,
                       ovs_be16 dl_type, bool commit,
                       uint16_t zone, const uint32_t *setmark,
                       const struct ovs_key_ct_labels *setlabel,
-                      const char *helper);
+                      const char *helper,
+                      const struct nat_action_info_t *nat_action_info);
 
 struct conntrack_dump {
     struct conntrack *ct;
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 0be5db5..81d5f52 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -97,7 +97,8 @@ static struct shash dp_netdevs OVS_GUARDED_BY(dp_netdev_mutex)
 static struct vlog_rate_limit upcall_rl = VLOG_RATE_LIMIT_INIT(600, 600);
 
 #define DP_NETDEV_CS_SUPPORTED_MASK (CS_NEW | CS_ESTABLISHED | CS_RELATED \
-                                     | CS_INVALID | CS_REPLY_DIR | CS_TRACKED)
+                                     | CS_INVALID | CS_REPLY_DIR | CS_TRACKED \
+                                     | CS_SRC_NAT | CS_DST_NAT)
 #define DP_NETDEV_CS_UNSUPPORTED_MASK (~(uint32_t)DP_NETDEV_CS_SUPPORTED_MASK)
 
 static struct odp_support dp_netdev_support = {
@@ -4689,7 +4690,9 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
         const char *helper = NULL;
         const uint32_t *setmark = NULL;
         const struct ovs_key_ct_labels *setlabel = NULL;
-
+        struct nat_action_info_t nat_action_info;
+        struct nat_action_info_t *nat_action_info_ref = NULL;
+        bool nat_config = false;
         NL_ATTR_FOR_EACH_UNSAFE (b, left, nl_attr_get(a),
                                  nl_attr_get_size(a)) {
             enum ovs_ct_attr sub_type = nl_attr_type(b);
@@ -4710,15 +4713,86 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
             case OVS_CT_ATTR_LABELS:
                 setlabel = nl_attr_get(b);
                 break;
-            case OVS_CT_ATTR_NAT:
+            case OVS_CT_ATTR_NAT: {
+                const struct nlattr *b_nest;
+                unsigned int left_nest;
+                bool ip_min_specified = false;
+                bool proto_num_min_specified = false;
+                bool ip_max_specified = false;
+                bool proto_num_max_specified = false;
+                memset(&nat_action_info, 0, sizeof nat_action_info);
+                nat_action_info_ref = &nat_action_info;
+
+                NL_NESTED_FOR_EACH_UNSAFE (b_nest, left_nest, b) {
+                    enum ovs_nat_attr sub_type_nest = nl_attr_type(b_nest);
+
+                    switch(sub_type_nest) {
+                    case OVS_NAT_ATTR_SRC:
+                    case OVS_NAT_ATTR_DST:
+                        nat_config = true;
+                        nat_action_info.nat_action |=
+                            ((sub_type_nest == OVS_NAT_ATTR_SRC)
+                                ? NAT_ACTION_SRC : NAT_ACTION_DST);
+                        break;
+                    case OVS_NAT_ATTR_IP_MIN:
+                        memcpy(&nat_action_info.min_addr,
+                           (char *) b_nest + NLA_HDRLEN, b_nest->nla_len);
+                        ip_min_specified = true;
+                        break;
+                    case OVS_NAT_ATTR_IP_MAX:
+                        memcpy(&nat_action_info.max_addr,
+                            (char *) b_nest + NLA_HDRLEN, b_nest->nla_len);
+                        ip_max_specified = true;
+                        break;
+                    case OVS_NAT_ATTR_PROTO_MIN:
+                        nat_action_info.min_port = nl_attr_get_u16(b_nest);
+                        proto_num_min_specified = true;
+                        break;
+                    case OVS_NAT_ATTR_PROTO_MAX:
+                        nat_action_info.max_port = nl_attr_get_u16(b_nest);
+                        proto_num_max_specified = true;
+                        break;
+                    case OVS_NAT_ATTR_PERSISTENT:
+                    case OVS_NAT_ATTR_PROTO_HASH:
+                    case OVS_NAT_ATTR_PROTO_RANDOM:
+                        break;
+                    case OVS_NAT_ATTR_UNSPEC:
+                    case __OVS_NAT_ATTR_MAX:
+                        OVS_NOT_REACHED();
+                    }
+                }
+
+                if (ip_min_specified && !ip_max_specified) {
+                    memcpy(&nat_action_info.max_addr,
+                           &nat_action_info.min_addr,
+                           sizeof(nat_action_info.max_addr));
+                }
+                if (proto_num_min_specified && !proto_num_max_specified) {
+                    nat_action_info.max_port = nat_action_info.min_port;
+                }
+                if (proto_num_min_specified || proto_num_max_specified) {
+                    if (nat_action_info.nat_action & NAT_ACTION_SRC) {
+                        nat_action_info.nat_action |= NAT_ACTION_SRC_PORT;
+                    } else if (nat_action_info.nat_action & NAT_ACTION_DST) {
+                        nat_action_info.nat_action |= NAT_ACTION_DST_PORT;
+                    }
+                }
+                break;
+            }
+
             case OVS_CT_ATTR_UNSPEC:
             case __OVS_CT_ATTR_MAX:
                 OVS_NOT_REACHED();
             }
         }
 
+        if (nat_config && !commit) {
+            VLOG_WARN("NAT specified without commit.");
+        }
+
         conntrack_execute(&dp->conntrack, packets_, aux->flow->dl_type, commit,
-                          zone, setmark, setlabel, helper);
+                          zone, setmark, setlabel, helper,
+                          nat_action_info_ref);
         break;
     }
 
diff --git a/tests/test-conntrack.c b/tests/test-conntrack.c
index d259325..b091ceb 100644
--- a/tests/test-conntrack.c
+++ b/tests/test-conntrack.c
@@ -88,7 +88,8 @@ ct_thread_main(void *aux_)
     pkt_batch = prepare_packets(batch_size, change_conn, aux->tid, &dl_type);
     ovs_barrier_block(&barrier);
     for (i = 0; i < n_pkts; i += batch_size) {
-        conntrack_execute(&ct, pkt_batch, dl_type, true, 0, NULL, NULL, NULL);
+        conntrack_execute(&ct, pkt_batch, dl_type, true, 0, NULL, NULL,
+                          NULL, NULL);
     }
     ovs_barrier_block(&barrier);
     destroy_packets(pkt_batch);
@@ -171,14 +172,15 @@ pcap_batch_execute_conntrack(struct conntrack *ct,
 
         if (flow.dl_type != dl_type) {
             conntrack_execute(ct, &new_batch, dl_type, true, 0, NULL, NULL,
-                              NULL);
+                              NULL, NULL);
             dp_packet_batch_init(&new_batch);
         }
         new_batch.packets[new_batch.count++] = packet;;
     }
 
     if (!dp_packet_batch_is_empty(&new_batch)) {
-        conntrack_execute(ct, &new_batch, dl_type, true, 0, NULL, NULL, NULL);
+        conntrack_execute(ct, &new_batch, dl_type, true, 0, NULL, NULL,
+                          NULL, NULL);
     }
 
 }
-- 
1.9.1



More information about the dev mailing list