[ovs-dev] [PATCH 4/9] ofproto/trace: Query ct_state for conntrack recirc from DP

Yi-Hung Wei yihung.wei at gmail.com
Fri Aug 25 22:51:14 UTC 2017


Instead of using fixed default conntrack state 'trk|new' in
ofproto/trace for conntrack recirculation, this patch queries the
conntrack state from datapath using ct_dpif_get_info().

Signed-off-by: Yi-Hung Wei <yihung.wei at gmail.com>
---
 lib/ct-dpif.c                | 42 ++++++++++++++++++++++++++++++++++++++
 lib/ct-dpif.h                |  2 ++
 ofproto/ofproto-dpif-trace.c | 48 ++++++++++++++++++++++++++++++++++----------
 3 files changed, 81 insertions(+), 11 deletions(-)

diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c
index 3e6f4cbe9be2..91388dd6681b 100644
--- a/lib/ct-dpif.c
+++ b/lib/ct-dpif.c
@@ -442,3 +442,45 @@ ct_dpif_format_tcp_stat(struct ds * ds, int tcp_state, int conn_per_state)
     ds_put_cstr(ds, "]");
     ds_put_format(ds, "=%u", conn_per_state);
 }
+
+/* Converts a given 'flow' to conntrack 'tuple'. Returns true if the
+ * conversion is valid. Returns false and reports error in 'ds', if
+ * the type of the connection is not supported. */
+bool
+ct_dpif_flow_to_tuple(struct flow *flow, struct ct_dpif_tuple *tuple,
+                      struct ds *ds)
+{
+    memset(tuple, 0, sizeof *tuple);
+
+    if (flow->dl_type == htons(ETH_TYPE_IP)) {
+        tuple->l3_type = AF_INET;
+        memcpy(&tuple->src.in, &flow->nw_src, sizeof tuple->src.in);
+        memcpy(&tuple->dst.in, &flow->nw_dst, sizeof tuple->dst.in);
+    } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
+        tuple->l3_type = AF_INET6;
+        memcpy(&tuple->src.in6, &flow->ipv6_src, sizeof tuple->src.in6);
+        memcpy(&tuple->dst.in6, &flow->ipv6_dst, sizeof tuple->dst.in6);
+    } else {
+        ds_put_format(ds,
+                      "Failed to convert flow to conntrack tuple "
+                      "(Unsupported dl_type: %"PRIu16").",
+                      ntohs(flow->dl_type));
+        return false;
+    }
+
+    tuple->ip_proto = flow->nw_proto;
+
+    /* Conntrack does support ICMP, however, we can not get ICMP id
+     * from 'flow'. */
+    if (flow->nw_proto == IPPROTO_TCP || flow->nw_proto == IPPROTO_UDP) {
+        tuple->src_port = flow->tp_src;
+        tuple->dst_port = flow->tp_dst;
+    } else {
+        ds_put_format(ds,
+                      "Failed to convert flow to conntrack tuple "
+                      "(Unsupported ip_proto: %"PRIu8").", flow->nw_proto);
+        return false;
+    }
+
+    return true;
+}
diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
index 0c82fb022f2b..f4ca07b5e776 100644
--- a/lib/ct-dpif.h
+++ b/lib/ct-dpif.h
@@ -17,6 +17,7 @@
 #ifndef CT_DPIF_H
 #define CT_DPIF_H
 
+#include "flow.h"
 #include "openvswitch/types.h"
 #include "packets.h"
 
@@ -209,5 +210,6 @@ void ct_dpif_format_entry(const struct ct_dpif_entry *, struct ds *,
 void ct_dpif_format_tuple(struct ds *, const struct ct_dpif_tuple *);
 uint8_t ct_dpif_coalesce_tcp_state(uint8_t state);
 void ct_dpif_format_tcp_stat(struct ds *, int, int);
+bool ct_dpif_flow_to_tuple(struct flow *, struct ct_dpif_tuple *, struct ds *);
 
 #endif /* CT_DPIF_H */
diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c
index c3c929520a2d..a86cf211803e 100644
--- a/ofproto/ofproto-dpif-trace.c
+++ b/ofproto/ofproto-dpif-trace.c
@@ -18,7 +18,9 @@
 
 #include "ofproto-dpif-trace.h"
 
+#include <errno.h>
 #include "conntrack.h"
+#include "ct-dpif.h"
 #include "dpif.h"
 #include "ofproto-dpif-xlate.h"
 #include "openvswitch/ofp-parse.h"
@@ -645,20 +647,44 @@ ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow,
                       recirc_node->recirc_id);
 
         if (recirc_node->type == OFT_RECIRC_CONNTRACK) {
-            uint32_t ct_state;
+            struct ct_dpif_info ct_info;
+            memset(&ct_info, 0, sizeof(ct_info));
+
             if (ovs_list_is_empty(next_ct_states)) {
-                ct_state = CS_TRACKED | CS_NEW;
-                ds_put_cstr(output, " - resume conntrack with default "
-                            "ct_state=trk|new (use --ct-next to customize)");
+                struct ds errs = DS_EMPTY_INITIALIZER;
+                struct ct_dpif_tuple tuple;
+                int err, indent_size;
+
+                indent_size = 14 + recirc_node->recirc_id / 16;
+                ds_put_cstr(output, " - resume conntrack with conntrack info"
+                            "from datapath\n");
+                ds_put_char_multiple(output, ' ', indent_size);
+
+                if (ct_dpif_flow_to_tuple(&recirc_node->flow, &tuple, &errs)) {
+                    err = ct_dpif_get_info(ofproto->backer->dpif, &tuple,
+                                            recirc_node->flow.ct_zone,
+                                            &ct_info);
+                    if (err) {
+                        ds_put_format(&errs, "%s", ovs_strerror(err));
+                    }
+                }
+
+                if (errs.length) {
+                    ct_info.ct_state = CS_TRACKED | CS_NEW;
+                    ds_put_format(output, "Failed to query ct_state from "
+                                  "datapath (%s).\n", ds_cstr(&errs));
+                    ds_put_char_multiple(output, ' ', indent_size);
+                    ds_put_format(output, "Use default ct_state = trk|new.");
+                } else {
+                    ct_dpif_format_info(&ct_info, output);
+                }
+                ds_put_format(output, " (use --ct-next to customize)");
+                ds_destroy(&errs);
             } else {
-                oftrace_pop_ct_state(next_ct_states, &ct_state);
-                struct ds s = DS_EMPTY_INITIALIZER;
-                format_flags(&s, ct_state_to_string, ct_state, '|');
-                ds_put_format(output, " - resume conntrack with ct_state=%s",
-                              ds_cstr(&s));
-                ds_destroy(&s);
+                oftrace_pop_ct_state(next_ct_states, &ct_info.ct_state);
+                ct_dpif_format_info(&ct_info, output);
             }
-            recirc_node->flow.ct_state = ct_state;
+            recirc_node->flow.ct_state = ct_info.ct_state;
         }
         ds_put_char(output, '\n');
         ds_put_char_multiple(output, '=', 79);
-- 
2.7.4



More information about the dev mailing list