Commit 193e3096 authored by Jarno Rajahalme's avatar Jarno Rajahalme Committed by David S. Miller

openvswitch: Do not trigger events for unconfirmed connections.

Receiving change events before the 'new' event for the connection has
been received can be confusing.  Avoid triggering change events for
setting conntrack mark or labels before the conntrack entry has been
confirmed.

Fixes: 182e3042 ("openvswitch: Allow matching on conntrack mark")
Fixes: c2ac6673 ("openvswitch: Allow matching on conntrack label")
Signed-off-by: default avatarJarno Rajahalme <jarno@ovn.org>
Acked-by: default avatarJoe Stringer <joe@ovn.org>
Acked-by: default avatarPravin B Shelar <pshelar@ovn.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9ff464db
...@@ -245,6 +245,7 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key, ...@@ -245,6 +245,7 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
new_mark = ct_mark | (ct->mark & ~(mask)); new_mark = ct_mark | (ct->mark & ~(mask));
if (ct->mark != new_mark) { if (ct->mark != new_mark) {
ct->mark = new_mark; ct->mark = new_mark;
if (nf_ct_is_confirmed(ct))
nf_conntrack_event_cache(IPCT_MARK, ct); nf_conntrack_event_cache(IPCT_MARK, ct);
key->ct.mark = new_mark; key->ct.mark = new_mark;
} }
...@@ -262,7 +263,6 @@ static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key, ...@@ -262,7 +263,6 @@ static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn_labels *cl; struct nf_conn_labels *cl;
struct nf_conn *ct; struct nf_conn *ct;
int err;
/* The connection could be invalid, in which case set_label is no-op.*/ /* The connection could be invalid, in which case set_label is no-op.*/
ct = nf_ct_get(skb, &ctinfo); ct = nf_ct_get(skb, &ctinfo);
...@@ -277,10 +277,26 @@ static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key, ...@@ -277,10 +277,26 @@ static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
if (!cl || sizeof(cl->bits) < OVS_CT_LABELS_LEN) if (!cl || sizeof(cl->bits) < OVS_CT_LABELS_LEN)
return -ENOSPC; return -ENOSPC;
err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask, if (nf_ct_is_confirmed(ct)) {
/* Triggers a change event, which makes sense only for
* confirmed connections.
*/
int err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
OVS_CT_LABELS_LEN / sizeof(u32)); OVS_CT_LABELS_LEN / sizeof(u32));
if (err) if (err)
return err; return err;
} else {
u32 *dst = (u32 *)cl->bits;
const u32 *msk = (const u32 *)mask->ct_labels;
const u32 *lbl = (const u32 *)labels->ct_labels;
int i;
/* No-one else has access to the non-confirmed entry, copy
* labels over, keeping any bits we are not explicitly setting.
*/
for (i = 0; i < OVS_CT_LABELS_LEN / sizeof(u32); i++)
dst[i] = (dst[i] & ~msk[i]) | (lbl[i] & msk[i]);
}
ovs_ct_get_labels(ct, &key->ct.labels); ovs_ct_get_labels(ct, &key->ct.labels);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment