@@ -611,6 +611,28 @@ ovs_be128_is_zero(const ovs_be128 *val)
return !(val->be64.hi || val->be64.lo);
}
+static inline ovs_u128
+ovs_u128_xor(const ovs_u128 a, const ovs_u128 b)
+{
+ ovs_u128 dst;
+
+ dst.u64.hi = a.u64.hi ^ b.u64.hi;
+ dst.u64.lo = a.u64.lo ^ b.u64.lo;
+
+ return dst;
+}
+
+static inline ovs_u128
+ovs_u128_and(const ovs_u128 a, const ovs_u128 b)
+{
+ ovs_u128 dst;
+
+ dst.u64.hi = a.u64.hi & b.u64.hi;
+ dst.u64.lo = a.u64.lo & b.u64.lo;
+
+ return dst;
+}
+
void xsleep(unsigned int seconds);
bool is_stdout_a_tty(void);
@@ -4301,10 +4301,9 @@ put_ct_mark(const struct flow *flow, struct flow *base_flow,
static void
put_ct_label(const struct flow *flow, struct flow *base_flow,
- struct ofpbuf *odp_actions, struct flow_wildcards *wc)
+ struct ofpbuf *odp_actions)
{
- if (!ovs_u128_is_zero(&wc->masks.ct_label)
- && !ovs_u128_equals(&flow->ct_label, &base_flow->ct_label)) {
+ if (!ovs_u128_equals(&flow->ct_label, &base_flow->ct_label)) {
struct {
ovs_u128 key;
ovs_u128 mask;
@@ -4313,8 +4312,8 @@ put_ct_label(const struct flow *flow, struct flow *base_flow,
odp_ct_label = nl_msg_put_unspec_uninit(odp_actions,
OVS_CT_ATTR_LABELS,
sizeof(*odp_ct_label));
- odp_ct_label->key = flow->ct_label;
- odp_ct_label->mask = wc->masks.ct_label;
+ odp_ct_label->mask = ovs_u128_xor(base_flow->ct_label, flow->ct_label);
+ odp_ct_label->key = ovs_u128_and(flow->ct_label, odp_ct_label->mask);
}
}
@@ -4414,7 +4413,7 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc)
}
nl_msg_put_u16(ctx->odp_actions, OVS_CT_ATTR_ZONE, zone);
put_ct_mark(&ctx->xin->flow, &ctx->base_flow, ctx->odp_actions);
- put_ct_label(&ctx->xin->flow, &ctx->base_flow, ctx->odp_actions, ctx->wc);
+ put_ct_label(&ctx->xin->flow, &ctx->base_flow, ctx->odp_actions);
put_ct_helper(ctx->odp_actions, ofc);
put_ct_nat(ctx);
ctx->ct_nat_action = NULL;
@@ -889,6 +889,40 @@ NS_CHECK_EXEC([at_ns2], [wget 10.1.1.4 -t 3 -T 1 -v -o wget1.log], [4])
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([conntrack - ct_label bit-fiddling])
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1, at_ns2, at_ns3)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+dnl Allow traffic between ns0<->ns1 using the ct_labels. Return traffic should
+dnl cause an additional bit to be set in the connection labels (and be allowed)
+AT_DATA([flows.txt], [dnl
+priority=1,action=drop
+priority=10,arp,action=normal
+priority=10,icmp,action=normal
+priority=100,in_port=1,tcp,action=ct(commit,exec(set_field:0x1/0x1->ct_label)),2
+priority=100,in_port=2,ct_state=-trk,tcp,action=ct(table=0,commit,exec(set_field:0x200000000/0x200000000->ct_label))
+priority=100,in_port=2,ct_state=+trk,ct_label=0x1,tcp,action=1
+priority=100,in_port=2,ct_state=+trk,ct_label=0x200000001,tcp,action=1
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl HTTP requests from p0->p1 should work fine.
+NETNS_DAEMONIZE([at_ns1], [[$PYTHON $srcdir/test-l7.py]], [http0.pid])
+NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | grep TIME], [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>),labels=0x200000001,protoinfo=(state=TIME_WAIT)
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([conntrack - ICMP related])
CHECK_CONNTRACK()
OVS_TRAFFIC_VSWITCHD_START()
@@ -1730,7 +1730,7 @@ Store a 32-bit metadata value with the connection. If the connection is
committed, then subsequent lookups for packets in this connection will
populate the \fBct_mark\fR flow field when the packet is sent to the
connection tracker with the \fBtable\fR specified.
-.IP \fBset_field:\fIvalue\fR->ct_label\fR
+.IP \fBset_field:\fIvalue\fR[\fB/\fImask\fR]->ct_label\fR
Store a 128-bit metadata value with the connection. If the connection is
committed, then subsequent lookups for packets in this connection will
populate the \fBct_label\fR flow field when the packet is sent to the
Using the action ct(commit,set_field:0x1/0x1->ct_label), ie, specifying a mask, would previously overwrite the entire ct_labels field rather than modifying only the specified bits. Fix the issue. Fixes: 9daf23484fb1 ("Add connection tracking label support.") Signed-off-by: Joe Stringer <joe@ovn.org> --- v2: Remove wildcards from put_ct_label(). --- lib/util.h | 22 ++++++++++++++++++++++ ofproto/ofproto-dpif-xlate.c | 11 +++++------ tests/system-traffic.at | 34 ++++++++++++++++++++++++++++++++++ utilities/ovs-ofctl.8.in | 2 +- 4 files changed, 62 insertions(+), 7 deletions(-)