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:
@@ -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
|
||||
|
@@ -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]);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
16
tests/odp.at
16
tests/odp.at
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user