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 <[email protected]> --- 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 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
