From patchwork Mon Jun 26 17:25:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 780809 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wxGGy59W5z9s9Y for ; Tue, 27 Jun 2017 03:28:10 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="XkuOi8/S"; dkim-atps=neutral Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 84314C26; Mon, 26 Jun 2017 17:25:43 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id D1260C23 for ; Mon, 26 Jun 2017 17:25:42 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f196.google.com (mail-pf0-f196.google.com [209.85.192.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 65514FB for ; Mon, 26 Jun 2017 17:25:41 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id s66so1004858pfs.2 for ; Mon, 26 Jun 2017 10:25:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fH4OU3C6A8hrawS0d9Qn+3gQGm9OwcCV3tg2K/hAyG4=; b=XkuOi8/S2iLm2R7EQ53ok1nqYhnDATmTxJTsmX76eDwJMs3aVx9X3EG3Q8WvIqVvkK hq9PD047zsmEOt3GKz6mmoUDHqYK/Q/gCTLYQIF5S5b/f+G/jG8L/gVzlZCVxy6HKpFY E/mM6LAYunUV7EjGUaKyEYQyvptO6i498R5NeVFQMYeSGXKhxdJbIOfs01ONFWEwbdCW MVgfsV405+ttPVqQASYsJZhIVvd9hi+MFG8PZ10BcVdPRxkrgZxQa34jtJLVFLiP0KKN k+y9iR3hc7OPDmxMp3/JmVfFuJ6mlWT1FMgJci2uliVDAtyualdCycCka1OnfsH+wiC1 KkqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fH4OU3C6A8hrawS0d9Qn+3gQGm9OwcCV3tg2K/hAyG4=; b=DFNlQKc9kZulHxWrZmUh5egGvSCblfqnnvIi14iWvEgvbSwC0VPa1QW02+HiSIbOrl EqmaeW0zCNMnhniNVYzmsSpmSL5mb7D+YvacdUMiKTBZwY3RjjmCzBZfpDOJj9r6Fj9l er9oGHxFtUx/UtyRUmpKixD1VrHTqwFNX/FppIb6QdFTslUBpL9niVgAa7Fk7sIL/RpG aYysbAHjv0m6uf9qe9eV+/d/pvNjpugN9TOqoGKSeyCb2dqlbgT757Lpi+VZ23HaGiWj GBdOWFGVXJesMn875RfcQ+pXxGNHPhDZ52pYcSawvihGHaLD6lDxsiBJdIiVoyw2IsqC lUUA== X-Gm-Message-State: AKS2vOyRMTbvRlTEyA7Kot2xjLRGXEhdSWwY+puVqk+KtBmXXllqrh3p NDGEtxXVacO/Qndvz+w= X-Received: by 10.84.215.220 with SMTP id g28mr1228346plj.281.1498497940572; Mon, 26 Jun 2017 10:25:40 -0700 (PDT) Received: from sc9-mailhost1.vmware.com ([208.91.1.34]) by smtp.gmail.com with ESMTPSA id z86sm1243592pfl.40.2017.06.26.10.25.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Jun 2017 10:25:40 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Mon, 26 Jun 2017 10:25:24 -0700 Message-Id: <1498497924-48674-4-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1498497924-48674-1-git-send-email-yihung.wei@gmail.com> References: <1498497924-48674-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 3/3] ofproto/trace: Add --ct-next option to ofproto/trace X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Previous patch enables ofproto/trace to automatically trace a flow that involves multiple recirculation on conntrack. However, it always sets the ct_state to trk|est when it processes recirculated conntrack flows. With this patch, users can customize the expected next ct_state in the aforementioned use case. Signed-off-by: Yi-Hung Wei --- NEWS | 2 + ofproto/ofproto-dpif-trace.c | 124 +++++++++++++++++++++++++++++++++++++------ ofproto/ofproto-dpif-trace.h | 6 +++ ofproto/ofproto-unixctl.man | 54 +++++++++++++++++-- tests/completion.at | 8 +-- tests/ofproto-dpif.at | 33 ++++++++---- 6 files changed, 195 insertions(+), 32 deletions(-) diff --git a/NEWS b/NEWS index 4ea7e628e1fc..ff8bc590e64a 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,8 @@ Post-v2.7.0 - Fedora Packaging: * OVN services are no longer restarted automatically after upgrade. - Add --cleanup option to command 'ovs-appctl exit' (see ovs-vswitchd(8)). + - Add --ct-next option to command 'ovs-appctl ofproto/trace' (see + ovs-vswitchd(8)). - L3 tunneling: * Add "layer3" options for tunnel ports that support non-Ethernet (L3) payload (GRE, VXLAN-GPE). diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c index 1e4290e8fe0b..99a57c2f56f3 100644 --- a/ofproto/ofproto-dpif-trace.c +++ b/ofproto/ofproto-dpif-trace.c @@ -18,6 +18,7 @@ #include "ofproto-dpif-trace.h" +#include "conntrack.h" #include "dpif.h" #include "ofproto-dpif-xlate.h" #include "openvswitch/ofp-parse.h" @@ -26,7 +27,7 @@ static void ofproto_trace(struct ofproto_dpif *, struct flow *, const struct dp_packet *packet, const struct ofpact[], size_t ofpacts_len, - struct ds *); + struct ds *, struct ovs_list *next_ct_states); static void oftrace_node_destroy(struct oftrace_node *); /* Creates a new oftrace_node, populates it with the given 'type' and a copy of @@ -119,6 +120,28 @@ oftrace_recirc_node_destroy(struct oftrace_recirc_node *node) } static void +oftrace_push_ct_state(struct ovs_list *next_ct_states, uint32_t ct_state) +{ + struct oftrace_next_ct_state *next_ct_state = + xmalloc(sizeof *next_ct_state); + next_ct_state->state = ct_state; + ovs_list_push_back(next_ct_states, &next_ct_state->node); +} + +static uint32_t +oftrace_pop_ct_state(struct ovs_list *next_ct_states) +{ + struct ovs_list *list_node = ovs_list_pop_front(next_ct_states); + struct oftrace_next_ct_state *next_ct_state; + + ASSIGN_CONTAINER(next_ct_state, list_node, node); + uint32_t ct_state = next_ct_state->state; + free(next_ct_state); + + return ct_state; +} + +static void oftrace_node_print_details(struct ds *output, const struct ovs_list *nodes, int level) { @@ -159,18 +182,49 @@ oftrace_node_print_details(struct ds *output, } } +static char * OVS_WARN_UNUSED_RESULT +parse_oftrace_options(int argc, const char *argv[], + struct ovs_list *next_ct_states) +{ + int k; + struct ds ds = DS_EMPTY_INITIALIZER; + + for (k = 0; k < argc; k++) { + if (!strncmp(argv[k], "--ct-next", 9)) { + if (k + 1 > argc) { + return xasprintf("Missing argument for option %s", argv[k]); + } + + uint32_t ct_state; + if (!parse_ct_state(argv[++k], 0, &ct_state, &ds)) { + return ds_steal_cstr(&ds); + } + if (!validate_ct_state(ct_state, &ds)) { + return ds_steal_cstr(&ds); + } + oftrace_push_ct_state(next_ct_states, ct_state); + } else { + return xasprintf("Invalid option %s", argv[k]); + } + } + + ds_destroy(&ds); + return NULL; +} + /* Parses the 'argc' elements of 'argv', ignoring argv[0]. The following * forms are supported: * - * - [dpname] odp_flow [-generate | packet] - * - bridge br_flow [-generate | packet] + * - [dpname] odp_flow [OPTIONS] [-generate | packet] + * - bridge br_flow [OPTIONS] [-generate | packet] * * On success, initializes '*ofprotop' and 'flow' and returns NULL. On failure * returns a nonnull malloced error message. */ static char * OVS_WARN_UNUSED_RESULT parse_flow_and_packet(int argc, const char *argv[], struct ofproto_dpif **ofprotop, struct flow *flow, - struct dp_packet **packetp) + struct dp_packet **packetp, + struct ovs_list *next_ct_states) { const struct dpif_backer *backer = NULL; const char *error = NULL; @@ -179,6 +233,7 @@ parse_flow_and_packet(int argc, const char *argv[], struct dp_packet *packet; struct ofpbuf odp_key; struct ofpbuf odp_mask; + int first_option; ofpbuf_init(&odp_key, 0); ofpbuf_init(&odp_mask, 0); @@ -198,6 +253,25 @@ parse_flow_and_packet(int argc, const char *argv[], error = NULL; } + /* Parse options. */ + if (argc >= 4) { + if (!strncmp(argv[2], "--", 2)) { + first_option = 2; + } else if (!strncmp(argv[3], "--", 2)) { + first_option = 3; + } else { + error = "Syntax error: invalid option"; + goto exit; + } + + m_err = parse_oftrace_options(argc - first_option, argv + first_option, + next_ct_states); + if (m_err) { + goto exit; + } + argc = first_option; + } + /* odp_flow can have its in_port specified as a name instead of port no. * We do not yet know whether a given flow is a odp_flow or a br_flow. * But, to know whether a flow is odp_flow through odp_flow_from_string(), @@ -337,13 +411,16 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], struct dp_packet *packet; char *error; struct flow flow; + struct ovs_list next_ct_states = OVS_LIST_INITIALIZER(&next_ct_states); - error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet); + error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet, + &next_ct_states); if (!error) { struct ds result; ds_init(&result); - ofproto_trace(ofproto, &flow, packet, NULL, 0, &result); + ofproto_trace(ofproto, &flow, packet, NULL, 0, &result, + &next_ct_states); unixctl_command_reply(conn, ds_cstr(&result)); ds_destroy(&result); dp_packet_delete(packet); @@ -365,6 +442,7 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc, struct ds result; struct match match; uint16_t in_port; + struct ovs_list next_ct_states = OVS_LIST_INITIALIZER(&next_ct_states); /* Three kinds of error return values! */ enum ofperr retval; @@ -394,7 +472,8 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc, enforce_consistency = false; } - error = parse_flow_and_packet(argc, argv, &ofproto, &match.flow, &packet); + error = parse_flow_and_packet(argc, argv, &ofproto, &match.flow, &packet, + &next_ct_states); if (error) { unixctl_command_reply_error(conn, error); free(error); @@ -442,7 +521,7 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc, } ofproto_trace(ofproto, &match.flow, packet, - ofpacts.data, ofpacts.size, &result); + ofpacts.data, ofpacts.size, &result, &next_ct_states); unixctl_command_reply(conn, ds_cstr(&result)); exit: @@ -540,7 +619,7 @@ static void ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, const struct dp_packet *packet, const struct ofpact ofpacts[], size_t ofpacts_len, - struct ds *output) + struct ds *output, struct ovs_list *next_ct_states) { struct ovs_list recirc_queue = OVS_LIST_INITIALIZER(&recirc_queue); oftrace_add_recirc_node(&recirc_queue, OFT_RECIRC_INIT, flow, @@ -553,9 +632,21 @@ ofproto_trace(struct ofproto_dpif *ofproto, struct flow *flow, ASSIGN_CONTAINER(recirc_node, node, node); if (recirc_node->type == OFT_RECIRC_CONNTRACK) { - recirc_node->flow->ct_state = CS_ESTABLISHED | CS_TRACKED; - ds_put_cstr(output, "\n\nResume conntrack prcessing with " - "default ct_state=trk|est.\n"); + if (ovs_list_is_empty(next_ct_states)) { + recirc_node->flow->ct_state = CS_TRACKED | CS_ESTABLISHED; + ds_put_cstr(output, "\n\nResume conntrack prcessing with " + "default ct_state=trk|est. Use --ct-next " + "to customize\n"); + } else { + recirc_node->flow->ct_state = + oftrace_pop_ct_state(next_ct_states); + struct ds s = DS_EMPTY_INITIALIZER; + format_flags(&s, ct_state_to_string, + recirc_node->flow->ct_state, '|'); + ds_put_format(output, "\n\nResume conntrack prcessing with " + "ct_state=%s\n", ds_cstr(&s)); + ds_destroy(&s); + } ds_put_char_multiple(output, '-', 79); ds_put_char(output, '\n'); } @@ -576,10 +667,11 @@ ofproto_dpif_trace_init(void) unixctl_command_register( "ofproto/trace", - "{[dp_name] odp_flow | bridge br_flow} [-generate|packet]", - 1, 3, ofproto_unixctl_trace, NULL); + "{[dp_name] odp_flow | bridge br_flow} [OPTIONS...] " + "[-generate|packet]", 1, INT_MAX, ofproto_unixctl_trace, NULL); unixctl_command_register( "ofproto/trace-packet-out", - "[-consistent] {[dp_name] odp_flow | bridge br_flow} [-generate|packet] actions", - 2, 6, ofproto_unixctl_trace_actions, NULL); + "[-consistent] {[dp_name] odp_flow | bridge br_flow} [OPTIONS...] " + "[-generate|packet] actions", + 2, INT_MAX, ofproto_unixctl_trace_actions, NULL); } diff --git a/ofproto/ofproto-dpif-trace.h b/ofproto/ofproto-dpif-trace.h index db3be290e477..8bcc7caf1a57 100644 --- a/ofproto/ofproto-dpif-trace.h +++ b/ofproto/ofproto-dpif-trace.h @@ -73,6 +73,12 @@ struct oftrace_recirc_node { struct flow *flow; }; +/* A node within a next_ct_states list. */ +struct oftrace_next_ct_state { + struct ovs_list node; /* In next_ct_states. */ + uint32_t state; +}; + void ofproto_dpif_trace_init(void); struct oftrace_node *oftrace_report(struct ovs_list *, enum oftrace_node_type, diff --git a/ofproto/ofproto-unixctl.man b/ofproto/ofproto-unixctl.man index 423837351910..e6c37894e980 100644 --- a/ofproto/ofproto-unixctl.man +++ b/ofproto/ofproto-unixctl.man @@ -6,10 +6,10 @@ These commands manage the core OpenFlow switch implementation (called Lists the names of the running ofproto instances. These are the names that may be used on \fBofproto/trace\fR. . -.IP "\fBofproto/trace\fR [\fIdpname\fR] \fIodp_flow\fR [\fB\-generate \fR| \fIpacket\fR]" -.IQ "\fBofproto/trace\fR \fIbridge\fR \fIbr_flow\fR [\fB\-generate \fR| \fIpacket\fR]" -.IQ "\fBofproto/trace\-packet\-out\fR [\fB\-consistent\fR] [\fIdpname\fR] \fIodp_flow\fR [\fB\-generate \fR| \fIpacket\fR] \fIactions\fR" -.IQ "\fBofproto/trace\-packet\-out\fR [\fB\-consistent\fR] \fIbridge\fR \fIbr_flow\fR [\fB\-generate \fR| \fIpacket\fR] \fIactions\fR" +.IP "\fBofproto/trace\fR [\fIdpname\fR] \fIodp_flow\fR [\fIOPTIONS\fR] [\fB\-generate \fR| \fIpacket\fR]" +.IQ "\fBofproto/trace\fR \fIbridge\fR \fIbr_flow\fR [\fIOPTIONS\fR] [\fB\-generate \fR| \fIpacket\fR]" +.IQ "\fBofproto/trace\-packet\-out\fR [\fB\-consistent\fR] [\fIdpname\fR] \fIodp_flow\fR [\fIOPTIONS\fR] [\fB\-generate \fR| \fIpacket\fR] \fIactions\fR" +.IQ "\fBofproto/trace\-packet\-out\fR [\fB\-consistent\fR] \fIbridge\fR \fIbr_flow\fR [\fIOPTIONS\fR] [\fB\-generate \fR| \fIpacket\fR] \fIactions\fR" Traces the path of an imaginary packet through \fIswitch\fR and reports the path that it took. The initial treatment of the packet varies based on the command: @@ -48,6 +48,52 @@ wildcards.) \fIbridge\fR names of the bridge through which .RE . .IP +.RS +\fBofproto/trace\fR supports the following options: +. +.IP "--ct-next \fIflags\fR" +When the traced flow triggers conntrack actions, \fBofproto/trace\fR +will automatically trace the forked packet processing pipeline with +user specified ct_state. This option sets the ct_state flags that the +conntrack module will report. The \fIflags\fR must be a comma- or +space-separated list of the following connection tracking flags: +. +.RS +.IP \(bu +\fBtrk\fR: Include to indicate connection tracking has taken place. +. +.IP \(bu +\fBnew\fR: Include to indicate a new flow. +. +.IP \(bu +\fBest\fR: Include to indicate an established flow. +. +.IP \(bu +\fBrel\fR: Include to indicate a related flow. +. +.IP \(bu +\fBrpl\fR: Include to indicate a reply flow. +. +.IP \(bu +\fBinv\fR: Include to indicate a connection entry in a bad state. +. +.IP \(bu +\fBdnat\fR: Include to indicate a packet whose destination IP address has been +changed. +. +.IP \(bu +\fBsnat\fR: Include to indicate a packet whose source IP address has been +changed. +. +.RE +. +.IP +When --ct-next is unspecified, or when there are fewer --ct-next options that +ct actions, the \fIflags\fR default to trk,est. +. +.RE +. +.IP Most commonly, one specifies only a flow, using one of the forms above, but sometimes one might need to specify an actual packet instead of just a flow: diff --git a/tests/completion.at b/tests/completion.at index e28c75239227..00e3a46b8bfa 100644 --- a/tests/completion.at +++ b/tests/completion.at @@ -171,7 +171,7 @@ AT_CLEANUP # complex completion check - ofproto/trace -# ofproto/trace {[dp_name] odp_flow | bridge br_flow} [-generate|packet] +# ofproto/trace {[dp_name] odp_flow | bridge br_flow} [OPTIONS] [-generate|packet] # test expansion on 'dp|dp_name' and 'bridge' AT_SETUP([appctl-bashcomp - complex completion check 3]) AT_SKIP_IF([test -z ${BASH_VERSION+x}]) @@ -209,7 +209,8 @@ AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})], [0]) # set odp_flow to some random string, should go to the next level. INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace ovs-dummy "in_port(123),mac(),ip,tcp" TAB 2>&1)" MATCH="$(GET_COMP_STR([-generate], [-generate]) -GET_COMP_STR([packet], []))" +GET_COMP_STR([packet], []) +GET_COMP_STR([OPTIONS...], []))" AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})], [0], [dnl ${MATCH} @@ -242,7 +243,8 @@ AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})], [0]) # set argument to some random string, should go to the odp_flow path. INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace "in_port(123),mac(),ip,tcp" TAB 2>&1)" MATCH="$(GET_COMP_STR([-generate], [-generate]) -GET_COMP_STR([packet], []))" +GET_COMP_STR([packet], []) +GET_COMP_STR([OPTIONS...], []))" AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})], [0], [dnl ${MATCH} diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index c51c689b9f46..142322afd777 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -5208,14 +5208,6 @@ Trailing garbage in packet data ovs-appctl: ovs-vswitchd: server returned an error ]) -# Test incorrect command: ofproto/trace with 4 arguments -AT_CHECK([ovs-appctl ofproto/trace \ - arg1, arg2, arg3, arg4], [2], [stdout],[stderr]) -AT_CHECK([tail -2 stderr], [0], [dnl -"ofproto/trace" command takes at most 3 arguments -ovs-appctl: ovs-vswitchd: server returned an error -]) - # Test incorrect command: ofproto/trace with 0 argument AT_CHECK([ovs-appctl ofproto/trace ], [2], [stdout],[stderr]) AT_CHECK([tail -2 stderr], [0], [dnl @@ -9713,13 +9705,14 @@ AT_CLEANUP AT_SETUP([ofproto-dpif - conntrack - ofproto/trace]) OVS_VSWITCHD_START -add_of_ports br0 1 2 +add_of_ports br0 1 2 3 4 AT_DATA([flows.txt], [dnl dnl Table 0 dnl table=0,priority=100,arp,action=normal table=0,priority=10,udp,action=ct(table=1,zone=0) +table=0,priority=10,tcp,action=ct(table=2,zone=1) table=0,priority=1,action=drop dnl dnl Table 1 @@ -9728,6 +9721,18 @@ table=1,priority=10,in_port=1,ct_state=+trk+new,udp,action=ct(commit,zone=0),2 table=1,priority=10,in_port=1,ct_state=+trk+est,udp,action=2 table=1,priority=10,in_port=2,ct_state=+trk+est,udp,action=1 table=1,priority=1,action=drop +dnl +dnl Table 2 +dnl +table=2,priority=10,in_port=1,tcp,ct_state=+trk+new,tcp,action=ct(commit,zone=1),ct(table=3,zone=2) +table=2,priority=10,in_port=1,tcp,ct_state=+trk+est,tcp,action=ct(table=3,zone=2) +table=2,priority=1,action=drop +dnl +dnl Table 3 +dnl +table=3,priority=10,in_port=1,tcp,ct_state=+trk+new,tcp,action=ct(commit,zone=2),4 +table=3,priority=10,in_port=1,tcp,ct_state=+trk+est,tcp,action=3 +table=2,priority=1,action=drop ]) AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) @@ -9742,6 +9747,16 @@ AT_CHECK([tail -1 stdout], [0], [Datapath actions: 2 ]) +AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,tcp'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: 3 +]) + +AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,tcp' --ct-next 'trk,new' --ct-next 'trk,new' ], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: ct(commit,zone=2),4 +]) + OVS_VSWITCHD_STOP AT_CLEANUP