hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/net/netfilter/nft_set_pipapo.c
....@@ -566,8 +566,9 @@
566566 goto out;
567567
568568 if (last) {
569
- if (nft_set_elem_expired(&f->mt[b].e->ext) ||
570
- (genmask &&
569
+ if (nft_set_elem_expired(&f->mt[b].e->ext))
570
+ goto next_match;
571
+ if ((genmask &&
571572 !nft_set_elem_active(&f->mt[b].e->ext, genmask)))
572573 goto next_match;
573574
....@@ -901,11 +902,13 @@
901902 static int pipapo_insert(struct nft_pipapo_field *f, const uint8_t *k,
902903 int mask_bits)
903904 {
904
- int rule = f->rules++, group, ret, bit_offset = 0;
905
+ int rule = f->rules, group, ret, bit_offset = 0;
905906
906
- ret = pipapo_resize(f, f->rules - 1, f->rules);
907
+ ret = pipapo_resize(f, f->rules, f->rules + 1);
907908 if (ret)
908909 return ret;
910
+
911
+ f->rules++;
909912
910913 for (group = 0; group < f->groups; group++) {
911914 int i, v;
....@@ -1051,7 +1054,9 @@
10511054 step++;
10521055 if (step >= len) {
10531056 if (!masks) {
1054
- pipapo_insert(f, base, 0);
1057
+ err = pipapo_insert(f, base, 0);
1058
+ if (err < 0)
1059
+ return err;
10551060 masks = 1;
10561061 }
10571062 goto out;
....@@ -1233,6 +1238,9 @@
12331238 ret = pipapo_insert(f, start, f->groups * f->bb);
12341239 else
12351240 ret = pipapo_expand(f, start, end, f->groups * f->bb);
1241
+
1242
+ if (ret < 0)
1243
+ return ret;
12361244
12371245 if (f->bsize > bsize_max)
12381246 bsize_max = f->bsize;
....@@ -1529,15 +1537,32 @@
15291537 }
15301538 }
15311539
1540
+static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set,
1541
+ struct nft_pipapo_elem *e)
1542
+{
1543
+ struct nft_set_elem elem = {
1544
+ .priv = e,
1545
+ };
1546
+
1547
+ nft_setelem_data_deactivate(net, set, &elem);
1548
+}
1549
+
15321550 /**
15331551 * pipapo_gc() - Drop expired entries from set, destroy start and end elements
1534
- * @set: nftables API set representation
1552
+ * @_set: nftables API set representation
15351553 * @m: Matching data
15361554 */
1537
-static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
1555
+static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
15381556 {
1557
+ struct nft_set *set = (struct nft_set *) _set;
15391558 struct nft_pipapo *priv = nft_set_priv(set);
1559
+ struct net *net = read_pnet(&set->net);
15401560 int rules_f0, first_rule = 0;
1561
+ struct nft_trans_gc *gc;
1562
+
1563
+ gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);
1564
+ if (!gc)
1565
+ return;
15411566
15421567 while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
15431568 union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
....@@ -1562,13 +1587,19 @@
15621587 f--;
15631588 i--;
15641589 e = f->mt[rulemap[i].to].e;
1565
- if (nft_set_elem_expired(&e->ext) &&
1566
- !nft_set_elem_mark_busy(&e->ext)) {
1590
+ /* synchronous gc never fails, there is no need to set on
1591
+ * NFT_SET_ELEM_DEAD_BIT.
1592
+ */
1593
+ if (nft_set_elem_expired(&e->ext)) {
15671594 priv->dirty = true;
1568
- pipapo_drop(m, rulemap);
15691595
1570
- rcu_barrier();
1571
- nft_set_elem_destroy(set, e, true);
1596
+ gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
1597
+ if (!gc)
1598
+ return;
1599
+
1600
+ nft_pipapo_gc_deactivate(net, set, e);
1601
+ pipapo_drop(m, rulemap);
1602
+ nft_trans_gc_elem_add(gc, e);
15721603
15731604 /* And check again current first rule, which is now the
15741605 * first we haven't checked.
....@@ -1578,7 +1609,10 @@
15781609 }
15791610 }
15801611
1581
- priv->last_gc = jiffies;
1612
+ if (gc) {
1613
+ nft_trans_gc_queue_sync_done(gc);
1614
+ priv->last_gc = jiffies;
1615
+ }
15821616 }
15831617
15841618 /**
....@@ -1596,16 +1630,9 @@
15961630 }
15971631 }
15981632
1599
-/**
1600
- * pipapo_reclaim_match - RCU callback to free fields from old matching data
1601
- * @rcu: RCU head
1602
- */
1603
-static void pipapo_reclaim_match(struct rcu_head *rcu)
1633
+static void pipapo_free_match(struct nft_pipapo_match *m)
16041634 {
1605
- struct nft_pipapo_match *m;
16061635 int i;
1607
-
1608
- m = container_of(rcu, struct nft_pipapo_match, rcu);
16091636
16101637 for_each_possible_cpu(i)
16111638 kfree(*per_cpu_ptr(m->scratch, i));
....@@ -1621,7 +1648,19 @@
16211648 }
16221649
16231650 /**
1624
- * pipapo_commit() - Replace lookup data with current working copy
1651
+ * pipapo_reclaim_match - RCU callback to free fields from old matching data
1652
+ * @rcu: RCU head
1653
+ */
1654
+static void pipapo_reclaim_match(struct rcu_head *rcu)
1655
+{
1656
+ struct nft_pipapo_match *m;
1657
+
1658
+ m = container_of(rcu, struct nft_pipapo_match, rcu);
1659
+ pipapo_free_match(m);
1660
+}
1661
+
1662
+/**
1663
+ * nft_pipapo_commit() - Replace lookup data with current working copy
16251664 * @set: nftables API set representation
16261665 *
16271666 * While at it, check if we should perform garbage collection on the working
....@@ -1631,7 +1670,7 @@
16311670 * We also need to create a new working copy for subsequent insertions and
16321671 * deletions.
16331672 */
1634
-static void pipapo_commit(const struct nft_set *set)
1673
+static void nft_pipapo_commit(const struct nft_set *set)
16351674 {
16361675 struct nft_pipapo *priv = nft_set_priv(set);
16371676 struct nft_pipapo_match *new_clone, *old;
....@@ -1656,6 +1695,26 @@
16561695 priv->clone = new_clone;
16571696 }
16581697
1698
+static void nft_pipapo_abort(const struct nft_set *set)
1699
+{
1700
+ struct nft_pipapo *priv = nft_set_priv(set);
1701
+ struct nft_pipapo_match *new_clone, *m;
1702
+
1703
+ if (!priv->dirty)
1704
+ return;
1705
+
1706
+ m = rcu_dereference(priv->match);
1707
+
1708
+ new_clone = pipapo_clone(m);
1709
+ if (IS_ERR(new_clone))
1710
+ return;
1711
+
1712
+ priv->dirty = false;
1713
+
1714
+ pipapo_free_match(priv->clone);
1715
+ priv->clone = new_clone;
1716
+}
1717
+
16591718 /**
16601719 * nft_pipapo_activate() - Mark element reference as active given key, commit
16611720 * @net: Network namespace
....@@ -1663,8 +1722,7 @@
16631722 * @elem: nftables API element representation containing key data
16641723 *
16651724 * On insertion, elements are added to a copy of the matching data currently
1666
- * in use for lookups, and not directly inserted into current lookup data, so
1667
- * we'll take care of that by calling pipapo_commit() here. Both
1725
+ * in use for lookups, and not directly inserted into current lookup data. Both
16681726 * nft_pipapo_insert() and nft_pipapo_activate() are called once for each
16691727 * element, hence we can't purpose either one as a real commit operation.
16701728 */
....@@ -1672,16 +1730,9 @@
16721730 const struct nft_set *set,
16731731 const struct nft_set_elem *elem)
16741732 {
1675
- struct nft_pipapo_elem *e;
1676
-
1677
- e = pipapo_get(net, set, (const u8 *)elem->key.val.data, 0);
1678
- if (IS_ERR(e))
1679
- return;
1733
+ struct nft_pipapo_elem *e = elem->priv;
16801734
16811735 nft_set_elem_change_active(net, set, &e->ext);
1682
- nft_set_elem_clear_busy(&e->ext);
1683
-
1684
- pipapo_commit(set);
16851736 }
16861737
16871738 /**
....@@ -1893,10 +1944,6 @@
18931944
18941945 data = (const u8 *)nft_set_ext_key(&e->ext);
18951946
1896
- e = pipapo_get(net, set, data, 0);
1897
- if (IS_ERR(e))
1898
- return;
1899
-
19001947 while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
19011948 union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
19021949 const u8 *match_start, *match_end;
....@@ -1904,7 +1951,11 @@
19041951 int i, start, rules_fx;
19051952
19061953 match_start = data;
1907
- match_end = (const u8 *)nft_set_ext_key_end(&e->ext)->data;
1954
+
1955
+ if (nft_set_ext_exists(&e->ext, NFT_SET_EXT_KEY_END))
1956
+ match_end = (const u8 *)nft_set_ext_key_end(&e->ext)->data;
1957
+ else
1958
+ match_end = data;
19081959
19091960 start = first_rule;
19101961 rules_fx = rules_f0;
....@@ -1927,7 +1978,6 @@
19271978 if (i == m->field_count) {
19281979 priv->dirty = true;
19291980 pipapo_drop(m, rulemap);
1930
- pipapo_commit(set);
19311981 return;
19321982 }
19331983
....@@ -1949,12 +1999,16 @@
19491999 struct nft_set_iter *iter)
19502000 {
19512001 struct nft_pipapo *priv = nft_set_priv(set);
2002
+ struct net *net = read_pnet(&set->net);
19522003 struct nft_pipapo_match *m;
19532004 struct nft_pipapo_field *f;
19542005 int i, r;
19552006
19562007 rcu_read_lock();
1957
- m = rcu_dereference(priv->match);
2008
+ if (iter->genmask == nft_genmask_cur(net))
2009
+ m = rcu_dereference(priv->match);
2010
+ else
2011
+ m = priv->clone;
19582012
19592013 if (unlikely(!m))
19602014 goto out;
....@@ -1973,8 +2027,6 @@
19732027 goto cont;
19742028
19752029 e = f->mt[r].e;
1976
- if (nft_set_elem_expired(&e->ext))
1977
- goto cont;
19782030
19792031 elem.priv = e;
19802032
....@@ -2123,10 +2175,12 @@
21232175
21242176 /**
21252177 * nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
2178
+ * @ctx: context
21262179 * @set: nftables API set representation
21272180 * @m: matching data pointing to key mapping array
21282181 */
2129
-static void nft_set_pipapo_match_destroy(const struct nft_set *set,
2182
+static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
2183
+ const struct nft_set *set,
21302184 struct nft_pipapo_match *m)
21312185 {
21322186 struct nft_pipapo_field *f;
....@@ -2143,15 +2197,17 @@
21432197
21442198 e = f->mt[r].e;
21452199
2146
- nft_set_elem_destroy(set, e, true);
2200
+ nf_tables_set_elem_destroy(ctx, set, e);
21472201 }
21482202 }
21492203
21502204 /**
21512205 * nft_pipapo_destroy() - Free private data for set and all committed elements
2206
+ * @ctx: context
21522207 * @set: nftables API set representation
21532208 */
2154
-static void nft_pipapo_destroy(const struct nft_set *set)
2209
+static void nft_pipapo_destroy(const struct nft_ctx *ctx,
2210
+ const struct nft_set *set)
21552211 {
21562212 struct nft_pipapo *priv = nft_set_priv(set);
21572213 struct nft_pipapo_match *m;
....@@ -2161,7 +2217,7 @@
21612217 if (m) {
21622218 rcu_barrier();
21632219
2164
- nft_set_pipapo_match_destroy(set, m);
2220
+ nft_set_pipapo_match_destroy(ctx, set, m);
21652221
21662222 #ifdef NFT_PIPAPO_ALIGN
21672223 free_percpu(m->scratch_aligned);
....@@ -2178,7 +2234,7 @@
21782234 m = priv->clone;
21792235
21802236 if (priv->dirty)
2181
- nft_set_pipapo_match_destroy(set, m);
2237
+ nft_set_pipapo_match_destroy(ctx, set, m);
21822238
21832239 #ifdef NFT_PIPAPO_ALIGN
21842240 free_percpu(priv->clone->scratch_aligned);
....@@ -2226,6 +2282,8 @@
22262282 .init = nft_pipapo_init,
22272283 .destroy = nft_pipapo_destroy,
22282284 .gc_init = nft_pipapo_gc_init,
2285
+ .commit = nft_pipapo_commit,
2286
+ .abort = nft_pipapo_abort,
22292287 .elemsize = offsetof(struct nft_pipapo_elem, ext),
22302288 },
22312289 };
....@@ -2248,6 +2306,8 @@
22482306 .init = nft_pipapo_init,
22492307 .destroy = nft_pipapo_destroy,
22502308 .gc_init = nft_pipapo_gc_init,
2309
+ .commit = nft_pipapo_commit,
2310
+ .abort = nft_pipapo_abort,
22512311 .elemsize = offsetof(struct nft_pipapo_elem, ext),
22522312 },
22532313 };