aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/nf_conntrack_labels.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c
index 3a30900891c1..bd7f26b97ac6 100644
--- a/net/netfilter/nf_conntrack_labels.c
+++ b/net/netfilter/nf_conntrack_labels.c
@@ -33,14 +33,18 @@ int nf_connlabel_set(struct nf_conn *ct, u16 bit)
33} 33}
34EXPORT_SYMBOL_GPL(nf_connlabel_set); 34EXPORT_SYMBOL_GPL(nf_connlabel_set);
35 35
36static void replace_u32(u32 *address, u32 mask, u32 new) 36static int replace_u32(u32 *address, u32 mask, u32 new)
37{ 37{
38 u32 old, tmp; 38 u32 old, tmp;
39 39
40 do { 40 do {
41 old = *address; 41 old = *address;
42 tmp = (old & mask) ^ new; 42 tmp = (old & mask) ^ new;
43 if (old == tmp)
44 return 0;
43 } while (cmpxchg(address, old, tmp) != old); 45 } while (cmpxchg(address, old, tmp) != old);
46
47 return 1;
44} 48}
45 49
46int nf_connlabels_replace(struct nf_conn *ct, 50int nf_connlabels_replace(struct nf_conn *ct,
@@ -49,6 +53,7 @@ int nf_connlabels_replace(struct nf_conn *ct,
49{ 53{
50 struct nf_conn_labels *labels; 54 struct nf_conn_labels *labels;
51 unsigned int size, i; 55 unsigned int size, i;
56 int changed = 0;
52 u32 *dst; 57 u32 *dst;
53 58
54 labels = nf_ct_labels_find(ct); 59 labels = nf_ct_labels_find(ct);
@@ -60,16 +65,15 @@ int nf_connlabels_replace(struct nf_conn *ct,
60 words32 = size / sizeof(u32); 65 words32 = size / sizeof(u32);
61 66
62 dst = (u32 *) labels->bits; 67 dst = (u32 *) labels->bits;
63 if (words32) { 68 for (i = 0; i < words32; i++)
64 for (i = 0; i < words32; i++) 69 changed |= replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]);
65 replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]);
66 }
67 70
68 size /= sizeof(u32); 71 size /= sizeof(u32);
69 for (i = words32; i < size; i++) /* pad */ 72 for (i = words32; i < size; i++) /* pad */
70 replace_u32(&dst[i], 0, 0); 73 replace_u32(&dst[i], 0, 0);
71 74
72 nf_conntrack_event_cache(IPCT_LABEL, ct); 75 if (changed)
76 nf_conntrack_event_cache(IPCT_LABEL, ct);
73 return 0; 77 return 0;
74} 78}
75EXPORT_SYMBOL_GPL(nf_connlabels_replace); 79EXPORT_SYMBOL_GPL(nf_connlabels_replace);