[ovs-dev] [PATCH 6/9] netlink-conntrack: Add support for querying conntrack exp
Greg Rose
gvrose8192 at gmail.com
Fri Sep 1 17:53:25 UTC 2017
On 08/25/2017 03:51 PM, Yi-Hung Wei wrote:
> The ct_state of an uncommmited new flow is marked as related if the flow
> is in the conntrack expectation table. In order for ofproto/trace to
> identify the ct_state of a new related flow, this patch utilizes
> NFNL_SUBSYS_CTNETLINK_EXP netlink subsystem to query the conntrack
> expectation table, therefore, we can mark the ct_state of a related flow
> correctly.
>
> Signed-off-by: Yi-Hung Wei <yihung.wei at gmail.com>
> ---
> lib/ct-dpif.h | 13 ++++
> lib/netlink-conntrack.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++
> lib/netlink-conntrack.h | 2 +
> tests/atlocal.in | 3 +
> tests/system-traffic.at | 137 ++++++++++++++++++++++++++++++++
> 5 files changed, 358 insertions(+)
>
> diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
> index f4ca07b5e776..9122e8cd752b 100644
> --- a/lib/ct-dpif.h
> +++ b/lib/ct-dpif.h
> @@ -177,6 +177,19 @@ struct ct_dpif_info {
> uint32_t ct_state;
> };
>
> +struct ct_dpif_exp_entry {
> + struct ct_dpif_tuple tuple;
> + struct ct_dpif_tuple tuple_mask;
> + struct ct_dpif_tuple tuple_master;
> + struct ct_dpif_tuple tuple_nat;
> + struct ct_dpif_helper helper;
> + uint32_t timeout;
> + uint32_t id;
> + uint32_t nat_dir;
> + uint32_t exp_flags;
> + uint32_t exp_class;
> +};
> +
> enum {
> CT_STATS_UDP,
> CT_STATS_TCP,
> diff --git a/lib/netlink-conntrack.c b/lib/netlink-conntrack.c
> index 93cd0ac2c34f..de1e467dc61a 100644
> --- a/lib/netlink-conntrack.c
> +++ b/lib/netlink-conntrack.c
> @@ -70,6 +70,15 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> #define CTA_TIMESTAMP_START 1
> #define CTA_TIMESTAMP_STOP 2
>
> +#define CTA_EXPECT_ZONE (CTA_EXPECT_HELP_NAME + 1)
> +#define CTA_EXPECT_FLAGS (CTA_EXPECT_HELP_NAME + 2)
> +#define CTA_EXPECT_CLASS (CTA_EXPECT_HELP_NAME + 3)
> +#define CTA_EXPECT_NAT (CTA_EXPECT_HELP_NAME + 4)
> +#define CTA_EXPECT_FN (CTA_EXPECT_HELP_NAME + 5)
These are duplicates of enums from /usr/include/linux/netfilter/nfnetlink_conntrack.h:
-----
enum ctattr_expect {
CTA_EXPECT_UNSPEC,
CTA_EXPECT_MASTER,
CTA_EXPECT_TUPLE,
CTA_EXPECT_MASK,
CTA_EXPECT_TIMEOUT,
CTA_EXPECT_ID,
CTA_EXPECT_HELP_NAME,
CTA_EXPECT_ZONE,
CTA_EXPECT_FLAGS,
CTA_EXPECT_CLASS,
CTA_EXPECT_NAT,
CTA_EXPECT_FN,
__CTA_EXPECT_MAX
};
#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
> +
> +#define CTA_EXPECT_NAT_DIR 1
> +#define CTA_EXPECT_NAT_TUPLE 2
> +
These are also duplicates from /usr/include/linux/netfilter/nfnetlink_conntrack.h.
> #define IPS_TEMPLATE_BIT 11
> #define IPS_TEMPLATE (1 << IPS_TEMPLATE_BIT)
>
> @@ -99,6 +108,20 @@ static const struct nl_policy nfnlgrp_conntrack_policy[] = {
> * CTA_LABELS_MASK are not received from kernel. */
> };
>
> +static const struct nl_policy nfnlgrp_conntrack_exp_policy[] = {
> + [CTA_EXPECT_MASTER] = { .type = NL_A_NESTED, .optional = false },
> + [CTA_EXPECT_TUPLE] = { .type = NL_A_NESTED, .optional = false },
> + [CTA_EXPECT_MASK] = { .type = NL_A_NESTED, .optional = false },
> + [CTA_EXPECT_TIMEOUT] = { .type = NL_A_U32, .optional = false },
> + [CTA_EXPECT_ID] = { .type = NL_A_U32, .optional = false },
> + [CTA_EXPECT_HELP_NAME] = { .type = NL_A_STRING, .optional = true },
> + [CTA_EXPECT_ZONE] = { .type = NL_A_U16, .optional = true },
> + [CTA_EXPECT_FLAGS] = { .type = NL_A_U32, .optional = false },
> + [CTA_EXPECT_CLASS] = { .type = NL_A_U32, .optional = false },
> + [CTA_EXPECT_NAT] = { .type = NL_A_NESTED, .optional = true },
> + [CTA_EXPECT_FN] = { .type = NL_A_STRING, .optional = true },
> +};
> +
> /* Declarations for conntrack netlink dumping. */
> static void nl_msg_put_nfgenmsg(struct ofpbuf *msg, size_t expected_payload,
> int family, uint8_t subsystem, uint8_t cmd,
> @@ -108,13 +131,22 @@ static bool nl_ct_parse_header_policy(struct ofpbuf *buf,
> enum nl_ct_event_type *event_type,
> uint8_t *nfgen_family,
> struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_policy)]);
> +static bool nl_ct_parse_ct_exp_policy(struct ofpbuf *buf,
> + uint8_t *nfgen_family,
> + struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_exp_policy)]);
>
> static bool nl_ct_attrs_to_ct_dpif_entry(struct ct_dpif_entry *entry,
> struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_policy)],
> uint8_t nfgen_family);
> +static bool nl_ct_exp_attrs_to_ct_dpif_exp_entry(
> + struct ct_dpif_exp_entry *entry,
> + struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_exp_policy)],
> + uint8_t nfgen_family);
>
> static bool nl_ct_put_ct_tuple(struct ofpbuf *, struct ct_dpif_tuple *,
> enum ctattr_type);
> +static bool nl_ct_put_ct_exp_tuple(struct ofpbuf *, struct ct_dpif_tuple *,
> + enum ctattr_expect);
>
> struct nl_ct_dump_state {
> struct nl_dump dump;
> @@ -385,6 +417,51 @@ nl_ct_get_ct_state(struct ct_dpif_tuple *tuple, struct ct_dpif_entry *entry,
> }
> }
>
> +/* Searches nf_conntrack's expectation table for 'tuple' in 'zone'.
> + * Sets 'exp' and returns 0 if we successfully find a match. Otherwise,
> + * returns non-zero errno. */
> +int
> +nl_ct_get_expect(struct ct_dpif_tuple *tuple, uint16_t zone,
> + struct ct_dpif_exp_entry *exp)
> +{
> + struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_exp_policy)];
> + struct ofpbuf request, *reply;
> + uint8_t nfgen_family;
> + int err;
> +
> + ofpbuf_init(&request, NL_DUMP_BUFSIZE);
> +
> + nl_msg_put_nfgenmsg(&request, 0, tuple->l3_type, NFNL_SUBSYS_CTNETLINK_EXP,
> + IPCTNL_MSG_EXP_GET, NLM_F_REQUEST);
> + nl_msg_put_be16(&request, CTA_EXPECT_ZONE, htons(zone));
> + if (!nl_ct_put_ct_exp_tuple(&request, tuple, CTA_EXPECT_TUPLE)) {
> + ofpbuf_uninit(&request);
> + return EOPNOTSUPP;
> + }
> +
> + err = nl_transact(NETLINK_NETFILTER, &request, &reply);
> + ofpbuf_uninit(&request);
> + if (err) {
> + return err;
> + }
> +
> + if (!nl_ct_parse_ct_exp_policy(reply, &nfgen_family, attrs)) {
> + goto out;
> + }
> +
> + memset(exp, 0, sizeof(*exp));
> + if (!nl_ct_exp_attrs_to_ct_dpif_exp_entry(exp, attrs, nfgen_family)) {
> + goto out;
> + }
> +
> + ofpbuf_delete(reply);
> + return 0;
> +
> +out:
> + ofpbuf_delete(reply);
> + return EOPNOTSUPP;
> +}
> +
> int
> nl_ct_get_info(struct ct_dpif_tuple *tuple, uint16_t zone,
> struct ct_dpif_info *info)
> @@ -392,10 +469,17 @@ nl_ct_get_info(struct ct_dpif_tuple *tuple, uint16_t zone,
> struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_policy)];
> struct ofpbuf request, *reply;
> struct ct_dpif_entry entry;
> + struct ct_dpif_exp_entry exp;
> enum nl_ct_event_type type;
> uint8_t nfgen_family;
> int err;
>
> + if (nl_ct_get_expect(tuple, zone, &exp) == 0) {
> + info->ct_state = CS_TRACKED | CS_NEW | CS_RELATED;
> + free(exp.helper.name);
I feel like nl_ct_get_expect() should clean up after itself and not expect the caller to free this.
> + return 0;
> + }
> +
> ofpbuf_init(&request, NL_DUMP_BUFSIZE);
> nl_msg_put_nfgenmsg(&request, 0, tuple->l3_type, NFNL_SUBSYS_CTNETLINK,
> IPCTNL_MSG_CT_GET, NLM_F_REQUEST);
> @@ -721,6 +805,23 @@ nl_ct_put_ct_tuple(struct ofpbuf *buf, struct ct_dpif_tuple *tuple,
> return true;
> }
>
> +static bool
> +nl_ct_put_ct_exp_tuple(struct ofpbuf *buf, struct ct_dpif_tuple *tuple,
> + enum ctattr_expect type)
> +{
> + size_t offset = nl_msg_start_nested(buf, type);
> +
> + if (type != CTA_EXPECT_TUPLE && type != CTA_EXPECT_MASTER) {
> + return false;
> + }
I would not call nl_msg_start_nested() until after the check above.
> + if (!nl_ct_put_tuple(buf, tuple)) {
> + return false;
> + }
> +
> + nl_msg_end_nested(buf, offset);
> + return true;
> +}
> +
> /* Translate netlink TCP state to CT_DPIF_TCP state. */
> static uint8_t
> nl_ct_tcp_state_to_dpif(uint8_t state)
> @@ -945,6 +1046,42 @@ nl_ct_parse_header_policy(struct ofpbuf *buf,
> }
>
> static bool
> +nl_ct_parse_ct_exp_policy(struct ofpbuf *buf, uint8_t *nfgen_family,
> + struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_exp_policy)])
> +{
> + struct nlmsghdr *nlh;
> + struct nfgenmsg *nfm;
> +
> + nlh = ofpbuf_at(buf, 0, NLMSG_HDRLEN);
> + nfm = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *nfm);
> + if (!nfm) {
> + VLOG_ERR_RL(&rl, "Received bad nfnl message (no nfgenmsg).");
> + return false;
> + }
> + if (NFNL_SUBSYS_ID(nlh->nlmsg_type) != NFNL_SUBSYS_CTNETLINK_EXP) {
> + VLOG_ERR_RL(&rl, "Received non-conntrack message (subsystem: %u).",
> + NFNL_SUBSYS_ID(nlh->nlmsg_type));
> + return false;
> + }
> + if (nfm->version != NFNETLINK_V0) {
> + VLOG_ERR_RL(&rl, "Received unsupported nfnetlink version (%u).",
> + NFNL_MSG_TYPE(nfm->version));
> + return false;
> + }
> +
> + if (!nl_policy_parse(buf, NLMSG_HDRLEN + sizeof *nfm,
> + nfnlgrp_conntrack_exp_policy, attrs,
> + ARRAY_SIZE(nfnlgrp_conntrack_exp_policy))) {
> + VLOG_ERR_RL(&rl, "Received bad nfnl message (policy).");
> + return false;
> + }
> +
> + *nfgen_family = nfm->nfgen_family;
> +
> + return true;
> +}
> +
> +static bool
> nl_ct_attrs_to_ct_dpif_entry(struct ct_dpif_entry *entry,
> struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_policy)],
> uint8_t nfgen_family)
> @@ -1008,6 +1145,72 @@ nl_ct_attrs_to_ct_dpif_entry(struct ct_dpif_entry *entry,
> return true;
> }
>
> +static bool
> +nl_ct_parse_exp_nat(struct nlattr *nla, struct ct_dpif_exp_entry *entry,
> + uint16_t l3_type)
> +{
> + static const struct nl_policy policy[] = {
> + [CTA_EXPECT_NAT_DIR] = { .type = NL_A_BE32, .optional = false },
> + [CTA_EXPECT_NAT_TUPLE] = { .type = NL_A_NESTED, .optional = false },
> + };
> + struct nlattr *attrs[ARRAY_SIZE(policy)];
> + bool parsed;
> +
> + parsed = nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy));
> +
> + if (parsed) {
> + entry->nat_dir = ntohl(nl_attr_get_be32(attrs[CTA_EXPECT_NAT_DIR]));
> + if (!nl_ct_parse_tuple(attrs[CTA_EXPECT_NAT_TUPLE], &entry->tuple_nat,
> + l3_type)) {
> + return false;
> + }
> + } else {
> + VLOG_ERR_RL(&rl, "Could not parse nested expect NAT options. "
> + "Possibly incompatible Linux kernel version.");
> + }
> + return parsed;
> +}
> +
> +static bool
> +nl_ct_exp_attrs_to_ct_dpif_exp_entry(struct ct_dpif_exp_entry *entry,
> + struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_exp_policy)],
> + uint8_t nfgen_family)
> +{
> + if (!nl_ct_parse_tuple(attrs[CTA_EXPECT_TUPLE], &entry->tuple,
> + nfgen_family)) {
> + return false;
> + }
> + if (!nl_ct_parse_tuple(attrs[CTA_EXPECT_MASK], &entry->tuple_mask,
> + nfgen_family)) {
> + return false;
> + }
> + if (!nl_ct_parse_tuple(attrs[CTA_EXPECT_MASTER], &entry->tuple_master,
> + nfgen_family)) {
> + return false;
> + }
> + if (attrs[CTA_EXPECT_NAT] &&
> + !nl_ct_parse_exp_nat(attrs[CTA_EXPECT_NAT], entry, nfgen_family)) {
> + return false;
> + }
> + if (attrs[CTA_EXPECT_TIMEOUT]) {
> + entry->timeout = ntohl(nl_attr_get_be32(attrs[CTA_EXPECT_TIMEOUT]));
> + }
> + if (attrs[CTA_EXPECT_ID]) {
> + entry->id = ntohl(nl_attr_get_be32(attrs[CTA_EXPECT_ID]));
> + }
> + if (attrs[CTA_EXPECT_FLAGS]) {
> + entry->exp_flags = ntohl(nl_attr_get_be32(attrs[CTA_EXPECT_FLAGS]));
> + }
> + if (attrs[CTA_EXPECT_CLASS]) {
> + entry->exp_class = ntohl(nl_attr_get_be32(attrs[CTA_EXPECT_CLASS]));
> + }
> + if (attrs[CTA_EXPECT_HELP_NAME]) {
> + entry->helper.name = xstrdup(nl_attr_get_string(
> + attrs[CTA_EXPECT_HELP_NAME]));
> + }
> + return true;
> +}
> +
I think in general you need to provide more comments for your new functions
and struct declarations.
http://docs.openvswitch.org/en/latest/internals/contributing/coding-style/#functions
Thanks,
- Greg
> bool
> nl_ct_parse_entry(struct ofpbuf *buf, struct ct_dpif_entry *entry,
> enum nl_ct_event_type *event_type)
> diff --git a/lib/netlink-conntrack.h b/lib/netlink-conntrack.h
> index 86d3adab0403..4c5798bdefc8 100644
> --- a/lib/netlink-conntrack.h
> +++ b/lib/netlink-conntrack.h
> @@ -45,6 +45,8 @@ int nl_ct_flush_zone(uint16_t zone);
>
> int nl_ct_get_info(struct ct_dpif_tuple *, uint16_t zone,
> struct ct_dpif_info *info);
> +int nl_ct_get_expect(struct ct_dpif_tuple *, uint16_t zone,
> + struct ct_dpif_exp_entry *);
>
> bool nl_ct_parse_entry(struct ofpbuf *, struct ct_dpif_entry *,
> enum nl_ct_event_type *);
> diff --git a/tests/atlocal.in b/tests/atlocal.in
> index 7c5e9e3357e5..35a1c7ebc7d0 100644
> --- a/tests/atlocal.in
> +++ b/tests/atlocal.in
> @@ -162,6 +162,9 @@ fi
> # Set HAVE_TCPDUMP
> find_command tcpdump
>
> +# Set HAVE_CONNTRACK
> +find_command conntrack
> +
> CURL_OPT="-g -v --max-time 1 --retry 2 --retry-delay 1 --connect-timeout 1"
>
> # Turn off proxies.
> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> index ccad3fab0ca4..727f97f7a7dd 100644
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -4113,6 +4113,143 @@ AT_CHECK([grep -c 'ct_state=est|rpl|trk' stdout], [0], [2
> OVS_TRAFFIC_VSWITCHD_STOP
> AT_CLEANUP
>
> +AT_SETUP([conntrack - ofproto/trace FTP])
> +AT_SKIP_IF([test $HAVE_FTP = no])
> +AT_SKIP_IF([test $HAVE_CONNTRACK = no])
> +CHECK_CONNTRACK()
> +CHECK_CONNTRACK_ALG()
> +CHECK_CT_DPIF_GET_INFO()
> +OVS_TRAFFIC_VSWITCHD_START()
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> +
> +dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
> +AT_DATA([flows1.txt], [dnl
> +table=0,priority=1,action=drop
> +table=0,priority=10,arp,action=normal
> +table=0,priority=10,icmp,action=normal
> +table=0,priority=100,in_port=1,tcp,action=ct(alg=ftp,commit),2
> +table=0,priority=100,in_port=2,tcp,action=ct(table=1)
> +table=1,in_port=2,tcp,ct_state=+trk+est,action=1
> +table=1,in_port=2,tcp,ct_state=+trk+rel,action=1
> +])
> +
> +dnl Similar policy but without allowing all traffic from ns0->ns1.
> +AT_DATA([flows2.txt], [dnl
> +table=0,priority=1,action=drop
> +table=0,priority=10,arp,action=normal
> +table=0,priority=10,icmp,action=normal
> +
> +dnl Allow outgoing TCP connections, and treat them as FTP
> +table=0,priority=100,in_port=1,tcp,action=ct(table=1)
> +table=1,in_port=1,tcp,ct_state=+trk+new,action=ct(commit,alg=ftp),2
> +table=1,in_port=1,tcp,ct_state=+trk+est,action=2
> +
> +dnl Allow incoming FTP data connections and responses to existing connections
> +table=0,priority=100,in_port=2,tcp,action=ct(table=1)
> +table=1,in_port=2,tcp,ct_state=+trk+new+rel,action=ct(commit),1
> +table=1,in_port=2,tcp,ct_state=+trk+est,action=1
> +table=1,in_port=2,tcp,ct_state=+trk-new+rel,action=1
> +])
> +
> +AT_CHECK([ovs-ofctl --bundle replace-flows br0 flows1.txt])
> +
> +OVS_START_L7([at_ns0], [ftp])
> +OVS_START_L7([at_ns1], [ftp])
> +
> +dnl FTP requests from p1->p0 should fail due to network failure.
> +dnl Try 3 times, in 1 second intervals.
> +NS_CHECK_EXEC([at_ns1], [wget ftp://10.1.1.1 --no-passive-ftp -t 3 -T 1 -v -o wget1.log], [4])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.1)], [0], [dnl
> +])
> +
> +dnl FTP requests from p0->p1 should work fine.
> +NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 --no-passive-ftp -t 3 -T 1 --retry-connrefused -v -o wget0.log])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
> +tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>),helper=ftp
> +])
> +
> +dnl Test ofproto/trace
> +DPORT=$(conntrack -L expect | grep 'src=10.1.1.2' | cut -d ' ' -f6 | cut -d '=' -f2)
> +
> +AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=2,dl_type=0x800,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_proto=6,tcp_src=12345,tcp_dst=$DPORT"], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> + [Datapath actions: 2
> +])
> +AT_CHECK([grep -c 'ct_state=new|rel|trk' stdout], [0], [2
> +])
> +
> +dnl Try the second set of flows.
> +AT_CHECK([ovs-ofctl --bundle replace-flows br0 flows2.txt])
> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> +
> +dnl FTP requests from p1->p0 should fail due to network failure.
> +dnl Try 3 times, in 1 second intervals.
> +NS_CHECK_EXEC([at_ns1], [wget ftp://10.1.1.1 --no-passive-ftp -t 3 -T 1 -v -o wget1.log], [4])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.1)], [0], [dnl
> +])
> +
> +dnl Active FTP requests from p0->p1 should work fine.
> +NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 --no-passive-ftp -t 3 -T 1 --retry-connrefused -v -o wget0-1.log])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
> +tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>),helper=ftp
> +tcp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>)
> +])
> +
> +dnl Test ofproto/trace
> +ovs-appctl dpctl/dump-conntrack
> +CONNTRACK_INFO=$(ovs-appctl dpctl/dump-conntrack | grep -v 'dport=21)' | grep '(src=10.1.1.2,dst=10.1.1.1,')
> +SPORT=$(echo $CONNTRACK_INFO | cut -d ',' -f4 | cut -d '=' -f2)
> +DPORT=$(echo $CONNTRACK_INFO | cut -d ',' -f5 | cut -d ')' -f1 | cut -d '=' -f2)
> +
> +AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=2,dl_type=0x800,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_proto=6,tcp_src=$SPORT,tcp_dst=$DPORT"], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> + [Datapath actions: 2
> +])
> +AT_CHECK([grep -c 'ct_state=est|rel|trk' stdout], [0], [2
> +])
> +
> +AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=1,dl_type=0x800,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_proto=6,tcp_src=$DPORT,tcp_dst=$SPORT"], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> + [Datapath actions: 3
> +])
> +AT_CHECK([grep -c 'ct_state=est|rel|rpl|trk' stdout], [0], [2
> +])
> +
> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> +
> +dnl Passive FTP requests from p0->p1 should work fine.
> +NS_CHECK_EXEC([at_ns0], [wget ftp://10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0-2.log])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
> +tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),protoinfo=(state=<cleared>),helper=ftp
> +])
> +
> +dnl Test ofproto/trace
> +ovs-appctl dpctl/dump-conntrack
> +CONNTRACK_INFO=$(ovs-appctl dpctl/dump-conntrack | grep -v 'dport=21)' | grep '(src=10.1.1.1,dst=10.1.1.2,')
> +SPORT=$(echo $CONNTRACK_INFO | cut -d ',' -f4 | cut -d '=' -f2)
> +DPORT=$(echo $CONNTRACK_INFO | cut -d ',' -f5 | cut -d ')' -f1 | cut -d '=' -f2)
> +
> +AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=2,dl_type=0x800,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_proto=6,tcp_src=$DPORT,tcp_dst=$SPORT"], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> + [Datapath actions: 2
> +])
> +AT_CHECK([grep -c 'ct_state=est|rel|rpl|trk' stdout], [0], [2
> +])
> +
> +AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=1,dl_type=0x800,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_proto=6,tcp_src=$SPORT,tcp_dst=$DPORT"], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> + [Datapath actions: 3
> +])
> +AT_CHECK([grep -c 'ct_state=est|rel|trk' stdout], [0], [2
> +])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> +
> AT_SETUP([conntrack - ofproto/trace SNAT])
> AT_SKIP_IF([test $HAVE_NC = no])
> CHECK_CONNTRACK()
>
More information about the dev
mailing list