Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
68493d8
ionic: clean interrupt before enabling queue to avoid credit race
gvrose8192 Oct 28, 2024
70b1b0a
ionic: fix use after netif_napi_del()
gvrose8192 Oct 7, 2024
8a1d1bd
netfilter: nftables: add catch-all set element support
gvrose8192 Oct 17, 2024
1f7885f
netfilter: nf_tables: Remove spurious code
gvrose8192 Oct 27, 2024
fab4dfd
netfilter: nf_tables: honor NLM_F_CREATE and NLM_F_EXCL in event noti…
gvrose8192 Oct 18, 2024
8ec9ab0
netfilter: nf_tables: integrate pipapo into commit protocol
gvrose8192 Oct 21, 2024
e147d6a
netfilter: nf_tables: disallow element updates of bound anonymous sets
gvrose8192 Oct 21, 2024
d42d3d6
netfilter: nf_tables: disallow updates of anonymous sets
gvrose8192 Oct 21, 2024
0891f13
netfilter: nf_tables: disallow timeout for anonymous sets
gvrose8192 Oct 21, 2024
b318769
netfilter: nf_tables: add nft_chain_add()
gvrose8192 Oct 21, 2024
76baffa
netfilter: nf_tables: report use refcount overflow
gvrose8192 Oct 22, 2024
7221a94
netfilter: nf_tables: fix spurious set element insertion failure
gvrose8192 Oct 22, 2024
a32ff5b
netfilter: nf_tables: don't skip expired elements during walk
gvrose8192 Oct 22, 2024
d6cf9a9
netfilter: nftables: rename set element data activation/deactivation …
gvrose8192 Oct 22, 2024
c720248
netfilter: nftables: add nft_pernet() helper function
gvrose8192 Oct 22, 2024
b6ecc9d
netfilter: nf_tables: GC transaction API to avoid race with control p…
gvrose8192 Oct 22, 2024
a3c9441
netfilter: nf_tables: adapt set backend to use GC transaction API
gvrose8192 Oct 23, 2024
3ca5985
netfilter: nf_tables: remove busy mark and gc batch API
gvrose8192 Oct 23, 2024
2dbe733
netfilter: nf_tables: fix false-positive lockdep splat
gvrose8192 Oct 23, 2024
ae0997d
netfilter: nf_tables: fix kdoc warnings after gc rework
gvrose8192 Oct 23, 2024
ef98a42
netfilter: nf_tables: don't fail inserts if duplicate has expired
gvrose8192 Oct 23, 2024
9ea9c18
netfilter: nf_tables: fix GC transaction races with netns and netlink…
gvrose8192 Oct 23, 2024
c84dcb7
netfilter: nf_tables: GC transaction race with netns dismantle
gvrose8192 Oct 23, 2024
9e3b392
netfilter: nf_tables: GC transaction race with abort path
gvrose8192 Oct 29, 2024
8cfad08
netfilter: nf_tables: use correct lock to protect gc_list
gvrose8192 Oct 23, 2024
7ca4ba0
netfilter: nf_tables: fix out of memory error handling
gvrose8192 Oct 23, 2024
dc9592f
netfilter: nf_tables: defer gc run if previous batch is still pending
gvrose8192 Oct 23, 2024
f2de13a
netfilter: nf_tables: fix nft_trans type confusion
gvrose8192 Oct 24, 2024
9d0955c
netfilter: nf_tables: disallow element removal on anonymous sets
gvrose8192 Oct 24, 2024
10c7204
netfilter: nftables: update table flags from the commit phase
gvrose8192 Oct 24, 2024
ca03502
netfilter: nf_tables: fix table flag updates
gvrose8192 Oct 24, 2024
0bbef03
netfilter: nf_tables: disable toggling dormant table state more than …
gvrose8192 Oct 24, 2024
92adac9
netfilter: nf_tables: fix memleak when more than 255 elements expired
gvrose8192 Oct 24, 2024
2d7983e
netfilter: nf_tables: mark set as dead when unbinding anonymous set w…
gvrose8192 Oct 26, 2024
4227fa3
netfilter: nf_tables: set backend .flush always succeeds
gvrose8192 Oct 31, 2024
24e2355
netfilter: nf_tables: bail out on mismatching dynset and set expressions
gvrose8192 Nov 4, 2024
224cc99
netfilter: nf_tables: disallow anonymous set with timeout flag
gvrose8192 Nov 4, 2024
c80ea03
netfilter: nf_tables: use timestamp to check for set element timeout
gvrose8192 Nov 5, 2024
e37bce7
netfilter: nf_tables: honor table dormant flag from netdev release ev…
gvrose8192 Nov 8, 2024
032cc7d
netfilter: nf_tables: release batch on table validation from abort path
gvrose8192 Nov 8, 2024
c792aca
netfilter: nf_tables: release mutex after nft_gc_seq_end from abort path
gvrose8192 Nov 8, 2024
2e6ba1c
netfilter: nf_tables: __nft_expr_type_get() selects specific family type
gvrose8192 Nov 8, 2024
3d347ad
netfilter: nf_tables: Fix potential data-race in __nft_expr_type_get()
gvrose8192 Nov 8, 2024
004ecc1
netfilter: nf_tables: Fix potential data-race in __nft_obj_type_get()
gvrose8192 Nov 8, 2024
e788218
netfilter: nf_tables: do not compare internal table flags on updates
gvrose8192 Nov 8, 2024
f8d9f6b
netfilter: nf_tables: flush pending destroy work before exit_net release
gvrose8192 Nov 8, 2024
3bd9bb3
netfilter: nf_tables: reject new basechain after table flag update
gvrose8192 Nov 8, 2024
3d7f9ca
netfilter: nf_tables: reject table flag and netdev basechain updates
gvrose8192 Nov 14, 2024
7100e30
netfilter: nf_tables: discard table flag update with pending basechai…
gvrose8192 Nov 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions drivers/net/ethernet/pensando/ionic/ionic_lif.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,23 +267,34 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)
.oper = IONIC_Q_ENABLE,
},
};
int ret;

idev = &lif->ionic->idev;
dev = lif->ionic->dev;

dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n",
ctx.cmd.q_control.index, ctx.cmd.q_control.type);

if (qcq->flags & IONIC_QCQ_F_INTR)
ionic_intr_clean(idev->intr_ctrl, qcq->intr.index);

ret = ionic_adminq_post_wait(lif, &ctx);
if (ret)
return ret;

if (qcq->napi.poll)
napi_enable(&qcq->napi);

if (qcq->flags & IONIC_QCQ_F_INTR) {
napi_enable(&qcq->napi);
irq_set_affinity_hint(qcq->intr.vector,
&qcq->intr.affinity_mask);
napi_enable(&qcq->napi);
ionic_intr_clean(idev->intr_ctrl, qcq->intr.index);
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
IONIC_INTR_MASK_CLEAR);
}

return ionic_adminq_post_wait(lif, &ctx);
return 0;
}

static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int fw_err)
Expand Down
193 changes: 107 additions & 86 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <net/netfilter/nf_flow_table.h>
#include <net/netlink.h>
#include <net/flow_offload.h>
#include <net/netns/generic.h>

struct module;

Expand Down Expand Up @@ -374,7 +375,7 @@ struct nft_set_ops {
void * (*deactivate)(const struct net *net,
const struct nft_set *set,
const struct nft_set_elem *elem);
bool (*flush)(const struct net *net,
void (*flush)(const struct net *net,
const struct nft_set *set,
void *priv);
void (*remove)(const struct net *net,
Expand All @@ -388,6 +389,8 @@ struct nft_set_ops {
const struct nft_set_elem *elem,
unsigned int flags);

void (*commit)(const struct nft_set *set);
void (*abort)(const struct nft_set *set);
u64 (*privsize)(const struct nlattr * const nla[],
const struct nft_set_desc *desc);
bool (*estimate)(const struct nft_set_desc *desc,
Expand Down Expand Up @@ -442,6 +445,7 @@ struct nft_set_elem_expr {
*
* @list: table set list node
* @bindings: list of set bindings
* @refs: internal refcounting for async set destruction
* @table: table this set belongs to
* @net: netnamespace this set belongs to
* @name: name of the set
Expand All @@ -463,6 +467,7 @@ struct nft_set_elem_expr {
* @expr: stateful expression
* @ops: set ops
* @flags: set flags
* @dead: set will be freed, never cleared
* @genmask: generation mask
* @klen: key length
* @dlen: data length
Expand All @@ -471,6 +476,7 @@ struct nft_set_elem_expr {
struct nft_set {
struct list_head list;
struct list_head bindings;
refcount_t refs;
struct nft_table *table;
possible_net_t net;
char *name;
Expand All @@ -489,9 +495,11 @@ struct nft_set {
u16 policy;
u16 udlen;
unsigned char *udata;
struct list_head pending_update;
/* runtime data below here */
const struct nft_set_ops *ops ____cacheline_aligned;
u16 flags:14,
u16 flags:13,
dead:1,
genmask:2;
u8 klen;
u8 dlen;
Expand All @@ -511,6 +519,11 @@ static inline void *nft_set_priv(const struct nft_set *set)
return (void *)set->data;
}

static inline bool nft_set_gc_is_pending(const struct nft_set *s)
{
return refcount_read(&s->refs) != 1;
}

static inline struct nft_set *nft_set_container_of(const void *priv)
{
return (void *)priv - offsetof(struct nft_set, data);
Expand Down Expand Up @@ -703,10 +716,16 @@ static inline struct nft_set_elem_expr *nft_set_ext_expr(const struct nft_set_ex
return nft_set_ext(ext, NFT_SET_EXT_EXPRESSIONS);
}

static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext,
u64 tstamp)
{
return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
time_is_before_eq_jiffies64(*nft_set_ext_expiration(ext));
time_after_eq64(tstamp, *nft_set_ext_expiration(ext));
}

static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
{
return __nft_set_elem_expired(ext, get_jiffies_64());
}

static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
Expand All @@ -733,62 +752,6 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
bool destroy_expr);

/**
* struct nft_set_gc_batch_head - nf_tables set garbage collection batch
*
* @rcu: rcu head
* @set: set the elements belong to
* @cnt: count of elements
*/
struct nft_set_gc_batch_head {
struct rcu_head rcu;
const struct nft_set *set;
unsigned int cnt;
};

#define NFT_SET_GC_BATCH_SIZE ((PAGE_SIZE - \
sizeof(struct nft_set_gc_batch_head)) / \
sizeof(void *))

/**
* struct nft_set_gc_batch - nf_tables set garbage collection batch
*
* @head: GC batch head
* @elems: garbage collection elements
*/
struct nft_set_gc_batch {
struct nft_set_gc_batch_head head;
void *elems[NFT_SET_GC_BATCH_SIZE];
};

struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
gfp_t gfp);
void nft_set_gc_batch_release(struct rcu_head *rcu);

static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
{
if (gcb != NULL)
call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
}

static inline struct nft_set_gc_batch *
nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
gfp_t gfp)
{
if (gcb != NULL) {
if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
return gcb;
nft_set_gc_batch_complete(gcb);
}
return nft_set_gc_batch_alloc(set, gfp);
}

static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
void *elem)
{
gcb->elems[gcb->head.cnt++] = elem;
}

struct nft_expr_ops;
/**
* struct nft_expr_type - nf_tables expression type
Expand Down Expand Up @@ -1076,6 +1039,29 @@ int __nft_release_basechain(struct nft_ctx *ctx);

unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv);

static inline bool nft_use_inc(u32 *use)
{
if (*use == UINT_MAX)
return false;

(*use)++;

return true;
}

static inline void nft_use_dec(u32 *use)
{
WARN_ON_ONCE((*use)-- == 0);
}

/* For error and abort path: restore use counter to previous state. */
static inline void nft_use_inc_restore(u32 *use)
{
WARN_ON_ONCE(!nft_use_inc(use));
}

#define nft_use_dec_restore nft_use_dec

/**
* struct nft_table - nf_tables table
*
Expand Down Expand Up @@ -1145,8 +1131,8 @@ struct nft_object {
struct list_head list;
struct rhlist_head rhlhead;
struct nft_object_hash_key key;
u32 genmask:2,
use:30;
u32 genmask:2;
u32 use;
u64 handle;
/* runtime data below here */
const struct nft_object_ops *ops ____cacheline_aligned;
Expand All @@ -1167,8 +1153,8 @@ struct nft_object *nft_obj_lookup(const struct net *net,
u8 genmask);

void nft_obj_notify(struct net *net, const struct nft_table *table,
struct nft_object *obj, u32 portid, u32 seq,
int event, int family, int report, gfp_t gfp);
struct nft_object *obj, u32 portid, u32 seq, int event,
u16 flags, int family, int report, gfp_t gfp);

/**
* struct nft_object_type - stateful object type
Expand Down Expand Up @@ -1246,8 +1232,8 @@ struct nft_flowtable {
char *name;
int hooknum;
int ops_len;
u32 genmask:2,
use:30;
u32 genmask:2;
u32 use;
u64 handle;
/* runtime data below here */
struct list_head hook_list ____cacheline_aligned;
Expand Down Expand Up @@ -1382,39 +1368,30 @@ static inline void nft_set_elem_change_active(const struct net *net,
ext->genmask ^= nft_genmask_next(net);
}

/*
* We use a free bit in the genmask field to indicate the element
* is busy, meaning it is currently being processed either by
* the netlink API or GC.
*
* Even though the genmask is only a single byte wide, this works
* because the extension structure if fully constant once initialized,
* so there are no non-atomic write accesses unless it is already
* marked busy.
*/
#define NFT_SET_ELEM_BUSY_MASK (1 << 2)
#define NFT_SET_ELEM_DEAD_MASK (1 << 2)

#if defined(__LITTLE_ENDIAN_BITFIELD)
#define NFT_SET_ELEM_BUSY_BIT 2
#define NFT_SET_ELEM_DEAD_BIT 2
#elif defined(__BIG_ENDIAN_BITFIELD)
#define NFT_SET_ELEM_BUSY_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
#else
#error
#endif

static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
static inline void nft_set_elem_dead(struct nft_set_ext *ext)
{
unsigned long *word = (unsigned long *)ext;

BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
set_bit(NFT_SET_ELEM_DEAD_BIT, word);
}

static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext)
{
unsigned long *word = (unsigned long *)ext;

clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
return test_bit(NFT_SET_ELEM_DEAD_BIT, word);
}

/**
Expand Down Expand Up @@ -1478,13 +1455,10 @@ struct nft_trans_chain {

struct nft_trans_table {
bool update;
bool enable;
};

#define nft_trans_table_update(trans) \
(((struct nft_trans_table *)trans->data)->update)
#define nft_trans_table_enable(trans) \
(((struct nft_trans_table *)trans->data)->enable)

struct nft_trans_elem {
struct nft_set *set;
Expand Down Expand Up @@ -1519,6 +1493,35 @@ struct nft_trans_flowtable {
#define nft_trans_flowtable(trans) \
(((struct nft_trans_flowtable *)trans->data)->flowtable)

#define NFT_TRANS_GC_BATCHCOUNT 256

struct nft_trans_gc {
struct list_head list;
struct net *net;
struct nft_set *set;
u32 seq;
u16 count;
void *priv[NFT_TRANS_GC_BATCHCOUNT];
struct rcu_head rcu;
};

struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
unsigned int gc_seq, gfp_t gfp);
void nft_trans_gc_destroy(struct nft_trans_gc *trans);

struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
unsigned int gc_seq, gfp_t gfp);
void nft_trans_gc_queue_async_done(struct nft_trans_gc *gc);

struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp);
void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans);

void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv);

void nft_setelem_data_deactivate(const struct net *net,
const struct nft_set *set,
struct nft_set_elem *elem);

int __init nft_chain_filter_init(void);
void nft_chain_filter_fini(void);

Expand All @@ -1535,4 +1538,22 @@ __printf(2, 3) int nft_request_module(struct net *net, const char *fmt, ...);
#else
static inline int nft_request_module(struct net *net, const char *fmt, ...) { return -ENOENT; }
#endif

struct nftables_pernet {
u64 tstamp;
unsigned int gc_seq;
};

extern unsigned int nf_tables_net_id;

static inline struct nftables_pernet *nft_pernet(const struct net *net)
{
return net_generic(net, nf_tables_net_id);
}

static inline u64 nft_net_tstamp(const struct net *net)
{
return nft_pernet(net)->tstamp;
}

#endif /* _NET_NF_TABLES_H */
1 change: 1 addition & 0 deletions include/uapi/linux/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ enum nft_hook_attributes {
enum nft_table_flags {
NFT_TABLE_F_DORMANT = 0x1,
};
#define NFT_TABLE_F_MASK (NFT_TABLE_F_DORMANT)

/**
* enum nft_table_attributes - nf_tables table netlink attributes
Expand Down
Loading