2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 14:55:18 +00:00

conntrack: Force commit.

Userspace support for force commit.

Signed-off-by: Jarno Rajahalme <jarno@ovn.org>
Acked-by: Joe Stringer <joe@ovn.org>
This commit is contained in:
Jarno Rajahalme
2017-03-08 17:18:23 -08:00
parent b80e259f8e
commit a76a37efec
13 changed files with 253 additions and 19 deletions

View File

@@ -557,9 +557,14 @@ ofpact_nest_get_action_len(const struct ofpact_nest *on)
/* Bits for 'flags' in struct nx_action_conntrack.
*
* If NX_CT_F_COMMIT is set, then the connection entry is moved from the
* unconfirmed to confirmed list in the tracker. */
* unconfirmed to confirmed list in the tracker.
* If NX_CT_F_FORCE is set, in addition to NX_CT_F_COMMIT, then the conntrack
* entry is replaced with a new one in case the original direction of the
* existing entry is opposite of the current packet direction.
*/
enum nx_conntrack_flags {
NX_CT_F_COMMIT = 1 << 0,
NX_CT_F_FORCE = 1 << 1,
};
/* Magic value for struct nx_action_conntrack 'recirc_table' field, to specify

View File

@@ -239,12 +239,21 @@ conn_not_found(struct conntrack *ct, struct dp_packet *pkt,
static struct conn *
process_one(struct conntrack *ct, struct dp_packet *pkt,
struct conn_lookup_ctx *ctx, uint16_t zone,
bool commit, long long now)
bool force, bool commit, long long now)
{
unsigned bucket = hash_to_bucket(ctx->hash);
struct conn *conn = ctx->conn;
uint16_t state = 0;
/* Delete found entry if in wrong direction. 'force' implies commit. */
if (conn && force && ctx->reply) {
ovs_list_remove(&conn->exp_node);
hmap_remove(&ct->buckets[bucket].connections, &conn->node);
atomic_count_dec(&ct->n_conn);
delete_conn(conn);
conn = NULL;
}
if (conn) {
if (ctx->related) {
state |= CS_RELATED;
@@ -301,7 +310,7 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
* 'setlabel' behaves similarly for the connection label.*/
int
conntrack_execute(struct conntrack *ct, struct dp_packet_batch *pkt_batch,
ovs_be16 dl_type, bool commit, uint16_t zone,
ovs_be16 dl_type, bool force, bool commit, uint16_t zone,
const uint32_t *setmark,
const struct ovs_key_ct_labels *setlabel,
const char *helper)
@@ -364,7 +373,8 @@ conntrack_execute(struct conntrack *ct, struct dp_packet_batch *pkt_batch,
conn_key_lookup(ctb, &ctxs[j], now);
conn = process_one(ct, pkts[j], &ctxs[j], zone, commit, now);
conn = process_one(ct, pkts[j], &ctxs[j], zone, force, commit,
now);
if (conn && setmark) {
set_mark(pkts[j], conn, setmark[0], setmark[1]);

View File

@@ -65,7 +65,7 @@ void conntrack_init(struct conntrack *);
void conntrack_destroy(struct conntrack *);
int conntrack_execute(struct conntrack *, struct dp_packet_batch *,
ovs_be16 dl_type, bool commit,
ovs_be16 dl_type, bool force, bool commit,
uint16_t zone, const uint32_t *setmark,
const struct ovs_key_ct_labels *setlabel,
const char *helper);

View File

@@ -5114,6 +5114,7 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
case OVS_ACTION_ATTR_CT: {
const struct nlattr *b;
bool force = false;
bool commit = false;
unsigned int left;
uint16_t zone = 0;
@@ -5127,7 +5128,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
switch(sub_type) {
case OVS_CT_ATTR_FORCE_COMMIT:
/* Not implemented yet. */
force = true;
/* fall through. */
case OVS_CT_ATTR_COMMIT:
commit = true;
break;
@@ -5150,8 +5152,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
}
}
conntrack_execute(&dp->conntrack, packets_, aux->flow->dl_type, commit,
zone, setmark, setlabel, helper);
conntrack_execute(&dp->conntrack, packets_, aux->flow->dl_type, force,
commit, zone, setmark, setlabel, helper);
break;
}

View File

@@ -723,6 +723,7 @@ format_odp_ct_nat(struct ds *ds, const struct nlattr *attr)
static const struct nl_policy ovs_conntrack_policy[] = {
[OVS_CT_ATTR_COMMIT] = { .type = NL_A_FLAG, .optional = true, },
[OVS_CT_ATTR_FORCE_COMMIT] = { .type = NL_A_FLAG, .optional = true, },
[OVS_CT_ATTR_ZONE] = { .type = NL_A_U16, .optional = true, },
[OVS_CT_ATTR_MARK] = { .type = NL_A_UNSPEC, .optional = true,
.min_len = sizeof(uint32_t) * 2 },
@@ -741,7 +742,7 @@ format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr)
const uint32_t *mark;
const char *helper;
uint16_t zone;
bool commit;
bool commit, force;
const struct nlattr *nat;
if (!nl_parse_nested(attr, ovs_conntrack_policy, a, ARRAY_SIZE(a))) {
@@ -750,6 +751,7 @@ format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr)
}
commit = a[OVS_CT_ATTR_COMMIT] ? true : false;
force = a[OVS_CT_ATTR_FORCE_COMMIT] ? true : false;
zone = a[OVS_CT_ATTR_ZONE] ? nl_attr_get_u16(a[OVS_CT_ATTR_ZONE]) : 0;
mark = a[OVS_CT_ATTR_MARK] ? nl_attr_get(a[OVS_CT_ATTR_MARK]) : NULL;
label = a[OVS_CT_ATTR_LABELS] ? nl_attr_get(a[OVS_CT_ATTR_LABELS]): NULL;
@@ -757,11 +759,14 @@ format_odp_conntrack_action(struct ds *ds, const struct nlattr *attr)
nat = a[OVS_CT_ATTR_NAT];
ds_put_format(ds, "ct");
if (commit || zone || mark || label || helper || nat) {
if (commit || force || zone || mark || label || helper || nat) {
ds_put_cstr(ds, "(");
if (commit) {
ds_put_format(ds, "commit,");
}
if (force) {
ds_put_format(ds, "force_commit,");
}
if (zone) {
ds_put_format(ds, "zone=%"PRIu16",", zone);
}
@@ -1468,6 +1473,7 @@ parse_conntrack_action(const char *s_, struct ofpbuf *actions)
const char *helper = NULL;
size_t helper_len = 0;
bool commit = false;
bool force_commit = false;
uint16_t zone = 0;
struct {
uint32_t value;
@@ -1502,6 +1508,11 @@ find_end:
s += n;
continue;
}
if (ovs_scan(s, "force_commit%n", &n)) {
force_commit = true;
s += n;
continue;
}
if (ovs_scan(s, "zone=%"SCNu16"%n", &zone, &n)) {
s += n;
continue;
@@ -1552,10 +1563,15 @@ find_end:
}
s++;
}
if (commit && force_commit) {
return -EINVAL;
}
start = nl_msg_start_nested(actions, OVS_ACTION_ATTR_CT);
if (commit) {
nl_msg_put_flag(actions, OVS_CT_ATTR_COMMIT);
} else if (force_commit) {
nl_msg_put_flag(actions, OVS_CT_ATTR_FORCE_COMMIT);
}
if (zone) {
nl_msg_put_u16(actions, OVS_CT_ATTR_ZONE, zone);

View File

@@ -5267,6 +5267,15 @@ format_DEBUG_RECIRC(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
* tracker, and the state of the connection will be stored beyond the
* lifetime of packet processing.
*
* A committed connection always has the directionality of the packet that
* caused the connection to be committed in the first place. This is the
* "original direction" of the connection, and the opposite direction is
* the "reply direction". If a connection is already committed, but it is
* then decided that the original direction should be the opposite of the
* existing connection, NX_CT_F_FORCE flag may be used in addition to
* NX_CT_F_COMMIT flag to in effect terminate the existing connection and
* start a new one in the current direction.
*
* Connections may transition back into the uncommitted state due to
* external timers, or due to the contents of packets that are sent to the
* connection tracker. This behaviour is outside of the scope of the
@@ -5328,7 +5337,7 @@ format_DEBUG_RECIRC(const struct ofpact_null *a OVS_UNUSED, struct ds *s)
*
* Zero or more actions may immediately follow this action. These actions will
* be executed within the context of the connection tracker, and they require
* the NX_CT_F_COMMIT flag to be set.
* NX_CT_F_COMMIT flag be set.
*/
struct nx_action_conntrack {
ovs_be16 type; /* OFPAT_VENDOR. */
@@ -5393,9 +5402,16 @@ decode_NXAST_RAW_CT(const struct nx_action_conntrack *nac,
{
const size_t ct_offset = ofpacts_pull(out);
struct ofpact_conntrack *conntrack = ofpact_put_CT(out);
conntrack->flags = ntohs(nac->flags);
int error;
int error = decode_ct_zone(nac, conntrack, vl_mff_map);
conntrack->flags = ntohs(nac->flags);
if (conntrack->flags & NX_CT_F_FORCE &&
!(conntrack->flags & NX_CT_F_COMMIT)) {
error = OFPERR_OFPBAC_BAD_ARGUMENT;
goto out;
}
error = decode_ct_zone(nac, conntrack, vl_mff_map);
if (error) {
goto out;
}
@@ -5491,6 +5507,8 @@ parse_CT(char *arg, struct ofpbuf *ofpacts,
while (ofputil_parse_key_value(&arg, &key, &value)) {
if (!strcmp(key, "commit")) {
oc->flags |= NX_CT_F_COMMIT;
} else if (!strcmp(key, "force")) {
oc->flags |= NX_CT_F_FORCE;
} else if (!strcmp(key, "table")) {
error = str_to_u8(value, "recirc_table", &oc->recirc_table);
if (!error && oc->recirc_table == NX_CT_RECIRC_NONE) {
@@ -5536,7 +5554,9 @@ parse_CT(char *arg, struct ofpbuf *ofpacts,
break;
}
}
if (oc->flags & NX_CT_F_FORCE && !(oc->flags & NX_CT_F_COMMIT)) {
error = xasprintf("\"force\" flag requires \"commit\" flag.");
}
ofpact_finish_CT(ofpacts, &oc);
ofpbuf_push_uninit(ofpacts, ct_offset);
return error;
@@ -5570,6 +5590,9 @@ format_CT(const struct ofpact_conntrack *a, struct ds *s)
if (a->flags & NX_CT_F_COMMIT) {
ds_put_format(s, "%scommit%s,", colors.value, colors.end);
}
if (a->flags & NX_CT_F_FORCE) {
ds_put_format(s, "%sforce%s,", colors.value, colors.end);
}
if (a->recirc_table != NX_CT_RECIRC_NONE) {
ds_put_format(s, "%stable=%s%"PRIu8",",
colors.special, colors.end, a->recirc_table);

View File

@@ -5148,7 +5148,8 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc)
ct_offset = nl_msg_start_nested(ctx->odp_actions, OVS_ACTION_ATTR_CT);
if (ofc->flags & NX_CT_F_COMMIT) {
nl_msg_put_flag(ctx->odp_actions, OVS_CT_ATTR_COMMIT);
nl_msg_put_flag(ctx->odp_actions, ofc->flags & NX_CT_F_FORCE ?
OVS_CT_ATTR_FORCE_COMMIT : OVS_CT_ATTR_COMMIT);
}
nl_msg_put_u16(ctx->odp_actions, OVS_CT_ATTR_ZONE, zone);
put_ct_mark(&ctx->xin->flow, ctx->odp_actions, ctx->wc);

View File

@@ -332,6 +332,22 @@ ct(commit,nat(src=fe80::20c:29ff:fe88:a18b,random))
ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random))
ct(commit,nat(src=[[fe80::20c:29ff:fe88:1]]-[[fe80::20c:29ff:fe88:a18b]]:255-4096,random))
ct(commit,helper=ftp,nat(src=10.1.1.240-10.1.1.255))
ct(force_commit)
ct(force_commit,zone=5)
ct(force_commit,mark=0xa0a0a0a0/0xfefefefe)
ct(force_commit,label=0x1234567890abcdef1234567890abcdef/0xf1f2f3f4f5f6f7f8f9f0fafbfcfdfeff)
ct(force_commit,helper=ftp)
ct(nat)
ct(force_commit,nat(src))
ct(force_commit,nat(dst))
ct(force_commit,nat(src=10.0.0.240,random))
ct(force_commit,nat(src=10.0.0.240:32768-65535,random))
ct(force_commit,nat(dst=10.0.0.128-10.0.0.254,hash))
ct(force_commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent))
ct(force_commit,nat(src=fe80::20c:29ff:fe88:a18b,random))
ct(force_commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random))
ct(force_commit,nat(src=[[fe80::20c:29ff:fe88:1]]-[[fe80::20c:29ff:fe88:a18b]]:255-4096,random))
ct(force_commit,helper=ftp,nat(src=10.1.1.240-10.1.1.255))
trunc(100)
clone(1)
clone(clone(push_vlan(vid=12,pcp=0),2),1)

View File

@@ -161,6 +161,12 @@ ffff 0018 00002320 0023 0000 00000000 0000 FF 000000 0000
# actions=ct(commit)
ffff 0018 00002320 0023 0001 00000000 0000 FF 000000 0000
# actions=ct(commit,force)
ffff 0018 00002320 0023 0003 00000000 0000 FF 000000 0000
# bad OpenFlow10 actions: OFPBAC_BAD_ARGUMENT
ffff 0018 00002320 0023 0002 00000000 0000 FF 000000 0000
# actions=ct(table=10)
ffff 0018 00002320 0023 0000 00000000 0000 0A 000000 0000
@@ -182,6 +188,10 @@ ffff 0018 00002320 0023 0000 00010004 001F FF 000000 0000
ffff 0030 00002320 0023 0001 00000000 0000 FF 000000 0000 dnl
ffff 0018 00002320 0007 001f 0001d604 000000000000f009
# actions=ct(commit,force,exec(load:0xf009->NXM_NX_CT_MARK[]))
ffff 0030 00002320 0023 0003 00000000 0000 FF 000000 0000 dnl
ffff 0018 00002320 0007 001f 0001d604 000000000000f009
# bad OpenFlow10 actions: OFPBAC_BAD_SET_ARGUMENT
& ofp_actions|WARN|cannot set CT fields outside of ct action
ffff 0018 00002320 0007 001f 0001d604 000000000000f009

View File

@@ -8528,6 +8528,88 @@ udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.
OVS_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([ofproto-dpif - conntrack - force commit])
OVS_VSWITCHD_START
add_of_ports br0 1 2
AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])
dnl Allow new connections on p1->p2, but not on p2->p1.
AT_DATA([flows.txt], [dnl
dnl Table 0
dnl
table=0,priority=100,arp,action=normal
table=0,priority=10,in_port=1,udp,action=ct(commit),controller
table=0,priority=10,in_port=2,udp,action=ct(table=1)
table=0,priority=1,action=drop
dnl
dnl Table 1
dnl
table=1,priority=10,in_port=2,ct_state=+est,udp,action=ct(force,commit),controller
table=1,priority=1,action=drop
])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
dnl Check this output. We only see the latter two packets, not the first.
dnl Note that the first packet doesn't have the ct_state bits set. This
dnl happens because the ct_state field is available only after recirc.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=1,tp_dst=2 udp_csum:e9d6
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=42 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,in_port=2 (via action) data_len=42 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:e9d6
])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
dnl OK, now start a second connection from port 1
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=3,dst=4)'])
dnl Now try a reply from port 2.
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=4,dst=3)'])
OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 4])
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
dnl Check this output. We should see both packets
dnl Note that the first packet doesn't have the ct_state bits set. This
dnl happens because the ct_state field is available only after recirc.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=3,tp_dst=4 udp_csum:e9d2
dnl
NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=42 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=3,ct_tp_dst=4,in_port=2 (via action) data_len=42 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4,tp_dst=3 udp_csum:e9d2
])
dnl
dnl Check that the directionality has been changed by force commit.
dnl
AT_CHECK([ovs-appctl dpctl/dump-conntrack | sort], [], [dnl
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2)
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=4,dport=3),reply=(src=10.1.1.1,dst=10.1.1.2,sport=3,dport=4)
])
OVS_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([ofproto-dpif - conntrack - ipv6])
OVS_VSWITCHD_START
@@ -9033,6 +9115,9 @@ AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
# Give time for logs to appear.
ovs-appctl revalidator/wait
AT_CHECK([cat ovs-vswitchd.log | strip_ufid | filter_flow_install], [0], [dnl
ct_state(+rpl+trk),ct_label(0x1),recirc_id(0x1),in_port(2),eth_type(0x0800),ipv4(frag=no), actions:1
recirc_id(0),in_port(1),eth_type(0x0800),ipv4(proto=17,frag=no),udp(src=1), actions:ct(commit,label=0x1),2

View File

@@ -653,6 +653,59 @@ udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([conntrack - force commit])
CHECK_CONNTRACK()
OVS_TRAFFIC_VSWITCHD_START()
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg ofproto_dpif_upcall:dbg])
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")
AT_DATA([flows.txt], [dnl
priority=1,action=drop
priority=10,arp,action=normal
priority=100,in_port=1,udp,action=ct(commit),controller
priority=100,in_port=2,ct_state=-trk,udp,action=ct(table=0)
priority=100,in_port=2,ct_state=+trk+est,udp,action=ct(force,commit,table=1)
table=1,in_port=2,ct_state=+trk,udp,action=controller
])
AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
AT_CAPTURE_FILE([ofctl_monitor.log])
AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl --detach --no-chdir --pidfile 2> ofctl_monitor.log])
dnl Send an unsolicited reply from port 2. This should be dropped.
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 actions=resubmit(,0)"])
dnl OK, now start a new connection from port 1.
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000200080000 actions=resubmit(,0)"])
dnl Now try a reply from port 2.
AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=2 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101020a0101010002000100080000 actions=resubmit(,0)"])
AT_CHECK([ovs-appctl revalidator/purge], [0])
dnl Check this output. We only see the latter two packets, not the first.
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
NXT_PACKET_IN2 (xid=0x0): cookie=0x0 total_len=42 in_port=1 (via action) data_len=42 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.1,nw_dst=10.1.1.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1,tp_dst=2 udp_csum:0
NXT_PACKET_IN2 (xid=0x0): table_id=1 cookie=0x0 total_len=42 ct_state=new|trk,ct_nw_src=10.1.1.2,ct_nw_dst=10.1.1.1,ct_nw_proto=17,ct_tp_src=2,ct_tp_dst=1,in_port=2 (via action) data_len=42 (unbuffered)
udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=2,tp_dst=1 udp_csum:0
])
dnl
dnl Check that the directionality has been changed by force commit.
dnl
AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.2,"], [], [dnl
udp,orig=(src=10.1.1.2,dst=10.1.1.1,sport=2,dport=1),reply=(src=10.1.1.1,dst=10.1.1.2,sport=1,dport=2)
])
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([conntrack - IPv4 ping])
CHECK_CONNTRACK()
OVS_TRAFFIC_VSWITCHD_START()

View File

@@ -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, false, true, 0, NULL, NULL,
NULL);
}
ovs_barrier_block(&barrier);
destroy_packets(pkt_batch);
@@ -170,15 +171,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);
conntrack_execute(ct, &new_batch, dl_type, false, true, 0, 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, false, true, 0, NULL, NULL, NULL);
}
}

View File

@@ -1037,6 +1037,18 @@ Commit the connection to the connection tracking module. Information about the
connection will be stored beyond the lifetime of the packet in the pipeline.
Some \fBct_state\fR flags are only available for committed connections.
.RE
.IP \fBforce\fR
.RS
A committed connection always has the directionality of the packet
that caused the connection to be committed in the first place. This
is the ``original direction'' of the connection, and the opposite
direction is the ``reply direction''. If a connection is already
committed, but it is in the wrong direction, \fBforce\fR flag may be
used in addition to \fBcommit\fR flag to effectively terminate the
existing connection and start a new one in the current direction.
This flag has no effect if the original direction of the connection is
already the same as that of the current packet.
.RE
.IP \fBtable=\fInumber\fR
Fork pipeline processing in two. The original instance of the packet will
continue processing the current actions list as an untracked packet. An