Skip to content

Commit 193e309

Browse files
Jarno Rajahalmedavem330
authored andcommitted
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: 182e304 ("openvswitch: Allow matching on conntrack mark") Fixes: c2ac667 ("openvswitch: Allow matching on conntrack label") Signed-off-by: Jarno Rajahalme <[email protected]> Acked-by: Joe Stringer <[email protected]> Acked-by: Pravin B Shelar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9ff464d commit 193e309

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

net/openvswitch/conntrack.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
245245
new_mark = ct_mark | (ct->mark & ~(mask));
246246
if (ct->mark != new_mark) {
247247
ct->mark = new_mark;
248-
nf_conntrack_event_cache(IPCT_MARK, ct);
248+
if (nf_ct_is_confirmed(ct))
249+
nf_conntrack_event_cache(IPCT_MARK, ct);
249250
key->ct.mark = new_mark;
250251
}
251252

@@ -262,7 +263,6 @@ static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
262263
enum ip_conntrack_info ctinfo;
263264
struct nf_conn_labels *cl;
264265
struct nf_conn *ct;
265-
int err;
266266

267267
/* The connection could be invalid, in which case set_label is no-op.*/
268268
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,
277277
if (!cl || sizeof(cl->bits) < OVS_CT_LABELS_LEN)
278278
return -ENOSPC;
279279

280-
err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
281-
OVS_CT_LABELS_LEN / sizeof(u32));
282-
if (err)
283-
return err;
280+
if (nf_ct_is_confirmed(ct)) {
281+
/* Triggers a change event, which makes sense only for
282+
* confirmed connections.
283+
*/
284+
int err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
285+
OVS_CT_LABELS_LEN / sizeof(u32));
286+
if (err)
287+
return err;
288+
} else {
289+
u32 *dst = (u32 *)cl->bits;
290+
const u32 *msk = (const u32 *)mask->ct_labels;
291+
const u32 *lbl = (const u32 *)labels->ct_labels;
292+
int i;
293+
294+
/* No-one else has access to the non-confirmed entry, copy
295+
* labels over, keeping any bits we are not explicitly setting.
296+
*/
297+
for (i = 0; i < OVS_CT_LABELS_LEN / sizeof(u32); i++)
298+
dst[i] = (dst[i] & ~msk[i]) | (lbl[i] & msk[i]);
299+
}
284300

285301
ovs_ct_get_labels(ct, &key->ct.labels);
286302
return 0;

0 commit comments

Comments
 (0)