.. | .. |
---|
566 | 566 | goto out; |
---|
567 | 567 | |
---|
568 | 568 | 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 && |
---|
571 | 572 | !nft_set_elem_active(&f->mt[b].e->ext, genmask))) |
---|
572 | 573 | goto next_match; |
---|
573 | 574 | |
---|
.. | .. |
---|
901 | 902 | static int pipapo_insert(struct nft_pipapo_field *f, const uint8_t *k, |
---|
902 | 903 | int mask_bits) |
---|
903 | 904 | { |
---|
904 | | - int rule = f->rules++, group, ret, bit_offset = 0; |
---|
| 905 | + int rule = f->rules, group, ret, bit_offset = 0; |
---|
905 | 906 | |
---|
906 | | - ret = pipapo_resize(f, f->rules - 1, f->rules); |
---|
| 907 | + ret = pipapo_resize(f, f->rules, f->rules + 1); |
---|
907 | 908 | if (ret) |
---|
908 | 909 | return ret; |
---|
| 910 | + |
---|
| 911 | + f->rules++; |
---|
909 | 912 | |
---|
910 | 913 | for (group = 0; group < f->groups; group++) { |
---|
911 | 914 | int i, v; |
---|
.. | .. |
---|
1051 | 1054 | step++; |
---|
1052 | 1055 | if (step >= len) { |
---|
1053 | 1056 | if (!masks) { |
---|
1054 | | - pipapo_insert(f, base, 0); |
---|
| 1057 | + err = pipapo_insert(f, base, 0); |
---|
| 1058 | + if (err < 0) |
---|
| 1059 | + return err; |
---|
1055 | 1060 | masks = 1; |
---|
1056 | 1061 | } |
---|
1057 | 1062 | goto out; |
---|
.. | .. |
---|
1233 | 1238 | ret = pipapo_insert(f, start, f->groups * f->bb); |
---|
1234 | 1239 | else |
---|
1235 | 1240 | ret = pipapo_expand(f, start, end, f->groups * f->bb); |
---|
| 1241 | + |
---|
| 1242 | + if (ret < 0) |
---|
| 1243 | + return ret; |
---|
1236 | 1244 | |
---|
1237 | 1245 | if (f->bsize > bsize_max) |
---|
1238 | 1246 | bsize_max = f->bsize; |
---|
.. | .. |
---|
1529 | 1537 | } |
---|
1530 | 1538 | } |
---|
1531 | 1539 | |
---|
| 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 | + |
---|
1532 | 1550 | /** |
---|
1533 | 1551 | * pipapo_gc() - Drop expired entries from set, destroy start and end elements |
---|
1534 | | - * @set: nftables API set representation |
---|
| 1552 | + * @_set: nftables API set representation |
---|
1535 | 1553 | * @m: Matching data |
---|
1536 | 1554 | */ |
---|
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) |
---|
1538 | 1556 | { |
---|
| 1557 | + struct nft_set *set = (struct nft_set *) _set; |
---|
1539 | 1558 | struct nft_pipapo *priv = nft_set_priv(set); |
---|
| 1559 | + struct net *net = read_pnet(&set->net); |
---|
1540 | 1560 | 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; |
---|
1541 | 1566 | |
---|
1542 | 1567 | while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) { |
---|
1543 | 1568 | union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS]; |
---|
.. | .. |
---|
1562 | 1587 | f--; |
---|
1563 | 1588 | i--; |
---|
1564 | 1589 | 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)) { |
---|
1567 | 1594 | priv->dirty = true; |
---|
1568 | | - pipapo_drop(m, rulemap); |
---|
1569 | 1595 | |
---|
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); |
---|
1572 | 1603 | |
---|
1573 | 1604 | /* And check again current first rule, which is now the |
---|
1574 | 1605 | * first we haven't checked. |
---|
.. | .. |
---|
1578 | 1609 | } |
---|
1579 | 1610 | } |
---|
1580 | 1611 | |
---|
1581 | | - priv->last_gc = jiffies; |
---|
| 1612 | + if (gc) { |
---|
| 1613 | + nft_trans_gc_queue_sync_done(gc); |
---|
| 1614 | + priv->last_gc = jiffies; |
---|
| 1615 | + } |
---|
1582 | 1616 | } |
---|
1583 | 1617 | |
---|
1584 | 1618 | /** |
---|
.. | .. |
---|
1596 | 1630 | } |
---|
1597 | 1631 | } |
---|
1598 | 1632 | |
---|
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) |
---|
1604 | 1634 | { |
---|
1605 | | - struct nft_pipapo_match *m; |
---|
1606 | 1635 | int i; |
---|
1607 | | - |
---|
1608 | | - m = container_of(rcu, struct nft_pipapo_match, rcu); |
---|
1609 | 1636 | |
---|
1610 | 1637 | for_each_possible_cpu(i) |
---|
1611 | 1638 | kfree(*per_cpu_ptr(m->scratch, i)); |
---|
.. | .. |
---|
1621 | 1648 | } |
---|
1622 | 1649 | |
---|
1623 | 1650 | /** |
---|
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 |
---|
1625 | 1664 | * @set: nftables API set representation |
---|
1626 | 1665 | * |
---|
1627 | 1666 | * While at it, check if we should perform garbage collection on the working |
---|
.. | .. |
---|
1631 | 1670 | * We also need to create a new working copy for subsequent insertions and |
---|
1632 | 1671 | * deletions. |
---|
1633 | 1672 | */ |
---|
1634 | | -static void pipapo_commit(const struct nft_set *set) |
---|
| 1673 | +static void nft_pipapo_commit(const struct nft_set *set) |
---|
1635 | 1674 | { |
---|
1636 | 1675 | struct nft_pipapo *priv = nft_set_priv(set); |
---|
1637 | 1676 | struct nft_pipapo_match *new_clone, *old; |
---|
.. | .. |
---|
1656 | 1695 | priv->clone = new_clone; |
---|
1657 | 1696 | } |
---|
1658 | 1697 | |
---|
| 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 | + |
---|
1659 | 1718 | /** |
---|
1660 | 1719 | * nft_pipapo_activate() - Mark element reference as active given key, commit |
---|
1661 | 1720 | * @net: Network namespace |
---|
.. | .. |
---|
1663 | 1722 | * @elem: nftables API element representation containing key data |
---|
1664 | 1723 | * |
---|
1665 | 1724 | * 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 |
---|
1668 | 1726 | * nft_pipapo_insert() and nft_pipapo_activate() are called once for each |
---|
1669 | 1727 | * element, hence we can't purpose either one as a real commit operation. |
---|
1670 | 1728 | */ |
---|
.. | .. |
---|
1672 | 1730 | const struct nft_set *set, |
---|
1673 | 1731 | const struct nft_set_elem *elem) |
---|
1674 | 1732 | { |
---|
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; |
---|
1680 | 1734 | |
---|
1681 | 1735 | nft_set_elem_change_active(net, set, &e->ext); |
---|
1682 | | - nft_set_elem_clear_busy(&e->ext); |
---|
1683 | | - |
---|
1684 | | - pipapo_commit(set); |
---|
1685 | 1736 | } |
---|
1686 | 1737 | |
---|
1687 | 1738 | /** |
---|
.. | .. |
---|
1893 | 1944 | |
---|
1894 | 1945 | data = (const u8 *)nft_set_ext_key(&e->ext); |
---|
1895 | 1946 | |
---|
1896 | | - e = pipapo_get(net, set, data, 0); |
---|
1897 | | - if (IS_ERR(e)) |
---|
1898 | | - return; |
---|
1899 | | - |
---|
1900 | 1947 | while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) { |
---|
1901 | 1948 | union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS]; |
---|
1902 | 1949 | const u8 *match_start, *match_end; |
---|
.. | .. |
---|
1904 | 1951 | int i, start, rules_fx; |
---|
1905 | 1952 | |
---|
1906 | 1953 | 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; |
---|
1908 | 1959 | |
---|
1909 | 1960 | start = first_rule; |
---|
1910 | 1961 | rules_fx = rules_f0; |
---|
.. | .. |
---|
1927 | 1978 | if (i == m->field_count) { |
---|
1928 | 1979 | priv->dirty = true; |
---|
1929 | 1980 | pipapo_drop(m, rulemap); |
---|
1930 | | - pipapo_commit(set); |
---|
1931 | 1981 | return; |
---|
1932 | 1982 | } |
---|
1933 | 1983 | |
---|
.. | .. |
---|
1949 | 1999 | struct nft_set_iter *iter) |
---|
1950 | 2000 | { |
---|
1951 | 2001 | struct nft_pipapo *priv = nft_set_priv(set); |
---|
| 2002 | + struct net *net = read_pnet(&set->net); |
---|
1952 | 2003 | struct nft_pipapo_match *m; |
---|
1953 | 2004 | struct nft_pipapo_field *f; |
---|
1954 | 2005 | int i, r; |
---|
1955 | 2006 | |
---|
1956 | 2007 | 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; |
---|
1958 | 2012 | |
---|
1959 | 2013 | if (unlikely(!m)) |
---|
1960 | 2014 | goto out; |
---|
.. | .. |
---|
1973 | 2027 | goto cont; |
---|
1974 | 2028 | |
---|
1975 | 2029 | e = f->mt[r].e; |
---|
1976 | | - if (nft_set_elem_expired(&e->ext)) |
---|
1977 | | - goto cont; |
---|
1978 | 2030 | |
---|
1979 | 2031 | elem.priv = e; |
---|
1980 | 2032 | |
---|
.. | .. |
---|
2123 | 2175 | |
---|
2124 | 2176 | /** |
---|
2125 | 2177 | * nft_set_pipapo_match_destroy() - Destroy elements from key mapping array |
---|
| 2178 | + * @ctx: context |
---|
2126 | 2179 | * @set: nftables API set representation |
---|
2127 | 2180 | * @m: matching data pointing to key mapping array |
---|
2128 | 2181 | */ |
---|
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, |
---|
2130 | 2184 | struct nft_pipapo_match *m) |
---|
2131 | 2185 | { |
---|
2132 | 2186 | struct nft_pipapo_field *f; |
---|
.. | .. |
---|
2143 | 2197 | |
---|
2144 | 2198 | e = f->mt[r].e; |
---|
2145 | 2199 | |
---|
2146 | | - nft_set_elem_destroy(set, e, true); |
---|
| 2200 | + nf_tables_set_elem_destroy(ctx, set, e); |
---|
2147 | 2201 | } |
---|
2148 | 2202 | } |
---|
2149 | 2203 | |
---|
2150 | 2204 | /** |
---|
2151 | 2205 | * nft_pipapo_destroy() - Free private data for set and all committed elements |
---|
| 2206 | + * @ctx: context |
---|
2152 | 2207 | * @set: nftables API set representation |
---|
2153 | 2208 | */ |
---|
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) |
---|
2155 | 2211 | { |
---|
2156 | 2212 | struct nft_pipapo *priv = nft_set_priv(set); |
---|
2157 | 2213 | struct nft_pipapo_match *m; |
---|
.. | .. |
---|
2161 | 2217 | if (m) { |
---|
2162 | 2218 | rcu_barrier(); |
---|
2163 | 2219 | |
---|
2164 | | - nft_set_pipapo_match_destroy(set, m); |
---|
| 2220 | + nft_set_pipapo_match_destroy(ctx, set, m); |
---|
2165 | 2221 | |
---|
2166 | 2222 | #ifdef NFT_PIPAPO_ALIGN |
---|
2167 | 2223 | free_percpu(m->scratch_aligned); |
---|
.. | .. |
---|
2178 | 2234 | m = priv->clone; |
---|
2179 | 2235 | |
---|
2180 | 2236 | if (priv->dirty) |
---|
2181 | | - nft_set_pipapo_match_destroy(set, m); |
---|
| 2237 | + nft_set_pipapo_match_destroy(ctx, set, m); |
---|
2182 | 2238 | |
---|
2183 | 2239 | #ifdef NFT_PIPAPO_ALIGN |
---|
2184 | 2240 | free_percpu(priv->clone->scratch_aligned); |
---|
.. | .. |
---|
2226 | 2282 | .init = nft_pipapo_init, |
---|
2227 | 2283 | .destroy = nft_pipapo_destroy, |
---|
2228 | 2284 | .gc_init = nft_pipapo_gc_init, |
---|
| 2285 | + .commit = nft_pipapo_commit, |
---|
| 2286 | + .abort = nft_pipapo_abort, |
---|
2229 | 2287 | .elemsize = offsetof(struct nft_pipapo_elem, ext), |
---|
2230 | 2288 | }, |
---|
2231 | 2289 | }; |
---|
.. | .. |
---|
2248 | 2306 | .init = nft_pipapo_init, |
---|
2249 | 2307 | .destroy = nft_pipapo_destroy, |
---|
2250 | 2308 | .gc_init = nft_pipapo_gc_init, |
---|
| 2309 | + .commit = nft_pipapo_commit, |
---|
| 2310 | + .abort = nft_pipapo_abort, |
---|
2251 | 2311 | .elemsize = offsetof(struct nft_pipapo_elem, ext), |
---|
2252 | 2312 | }, |
---|
2253 | 2313 | }; |
---|