.. | .. |
---|
28 | 28 | struct xt_action_param xt; |
---|
29 | 29 | }; |
---|
30 | 30 | |
---|
| 31 | +static inline struct sock *nft_sk(const struct nft_pktinfo *pkt) |
---|
| 32 | +{ |
---|
| 33 | + return pkt->xt.state->sk; |
---|
| 34 | +} |
---|
| 35 | + |
---|
| 36 | +static inline unsigned int nft_thoff(const struct nft_pktinfo *pkt) |
---|
| 37 | +{ |
---|
| 38 | + return pkt->xt.thoff; |
---|
| 39 | +} |
---|
| 40 | + |
---|
31 | 41 | static inline struct net *nft_net(const struct nft_pktinfo *pkt) |
---|
32 | 42 | { |
---|
33 | 43 | return pkt->xt.state->net; |
---|
.. | .. |
---|
205 | 215 | } |
---|
206 | 216 | |
---|
207 | 217 | int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest); |
---|
208 | | -unsigned int nft_parse_register(const struct nlattr *attr); |
---|
209 | 218 | int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); |
---|
210 | 219 | |
---|
211 | 220 | int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len); |
---|
.. | .. |
---|
374 | 383 | const struct nft_set *set, |
---|
375 | 384 | const struct nft_set_elem *elem, |
---|
376 | 385 | unsigned int flags); |
---|
377 | | - |
---|
| 386 | + void (*commit)(const struct nft_set *set); |
---|
| 387 | + void (*abort)(const struct nft_set *set); |
---|
378 | 388 | u64 (*privsize)(const struct nlattr * const nla[], |
---|
379 | 389 | const struct nft_set_desc *desc); |
---|
380 | 390 | bool (*estimate)(const struct nft_set_desc *desc, |
---|
.. | .. |
---|
383 | 393 | int (*init)(const struct nft_set *set, |
---|
384 | 394 | const struct nft_set_desc *desc, |
---|
385 | 395 | const struct nlattr * const nla[]); |
---|
386 | | - void (*destroy)(const struct nft_set *set); |
---|
| 396 | + void (*destroy)(const struct nft_ctx *ctx, |
---|
| 397 | + const struct nft_set *set); |
---|
387 | 398 | void (*gc_init)(const struct nft_set *set); |
---|
388 | 399 | |
---|
389 | 400 | unsigned int elemsize; |
---|
.. | .. |
---|
406 | 417 | * |
---|
407 | 418 | * @list: table set list node |
---|
408 | 419 | * @bindings: list of set bindings |
---|
| 420 | + * @refs: internal refcounting for async set destruction |
---|
409 | 421 | * @table: table this set belongs to |
---|
410 | 422 | * @net: netnamespace this set belongs to |
---|
411 | 423 | * @name: name of the set |
---|
.. | .. |
---|
427 | 439 | * @expr: stateful expression |
---|
428 | 440 | * @ops: set ops |
---|
429 | 441 | * @flags: set flags |
---|
| 442 | + * @dead: set will be freed, never cleared |
---|
430 | 443 | * @genmask: generation mask |
---|
431 | 444 | * @klen: key length |
---|
432 | 445 | * @dlen: data length |
---|
.. | .. |
---|
435 | 448 | struct nft_set { |
---|
436 | 449 | struct list_head list; |
---|
437 | 450 | struct list_head bindings; |
---|
| 451 | + refcount_t refs; |
---|
438 | 452 | struct nft_table *table; |
---|
439 | 453 | possible_net_t net; |
---|
440 | 454 | char *name; |
---|
.. | .. |
---|
454 | 468 | u16 udlen; |
---|
455 | 469 | unsigned char *udata; |
---|
456 | 470 | struct nft_expr *expr; |
---|
| 471 | + struct list_head pending_update; |
---|
457 | 472 | /* runtime data below here */ |
---|
458 | 473 | const struct nft_set_ops *ops ____cacheline_aligned; |
---|
459 | | - u16 flags:14, |
---|
| 474 | + u16 flags:13, |
---|
| 475 | + dead:1, |
---|
460 | 476 | genmask:2; |
---|
461 | 477 | u8 klen; |
---|
462 | 478 | u8 dlen; |
---|
.. | .. |
---|
472 | 488 | static inline void *nft_set_priv(const struct nft_set *set) |
---|
473 | 489 | { |
---|
474 | 490 | return (void *)set->data; |
---|
| 491 | +} |
---|
| 492 | + |
---|
| 493 | +static inline bool nft_set_gc_is_pending(const struct nft_set *s) |
---|
| 494 | +{ |
---|
| 495 | + return refcount_read(&s->refs) != 1; |
---|
475 | 496 | } |
---|
476 | 497 | |
---|
477 | 498 | static inline struct nft_set *nft_set_container_of(const void *priv) |
---|
.. | .. |
---|
507 | 528 | }; |
---|
508 | 529 | |
---|
509 | 530 | enum nft_trans_phase; |
---|
| 531 | +void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set); |
---|
510 | 532 | void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set, |
---|
511 | 533 | struct nft_set_binding *binding, |
---|
512 | 534 | enum nft_trans_phase phase); |
---|
.. | .. |
---|
686 | 708 | u64 timeout, u64 expiration, gfp_t gfp); |
---|
687 | 709 | void nft_set_elem_destroy(const struct nft_set *set, void *elem, |
---|
688 | 710 | bool destroy_expr); |
---|
689 | | - |
---|
690 | | -/** |
---|
691 | | - * struct nft_set_gc_batch_head - nf_tables set garbage collection batch |
---|
692 | | - * |
---|
693 | | - * @rcu: rcu head |
---|
694 | | - * @set: set the elements belong to |
---|
695 | | - * @cnt: count of elements |
---|
696 | | - */ |
---|
697 | | -struct nft_set_gc_batch_head { |
---|
698 | | - struct rcu_head rcu; |
---|
699 | | - const struct nft_set *set; |
---|
700 | | - unsigned int cnt; |
---|
701 | | -}; |
---|
702 | | - |
---|
703 | | -#define NFT_SET_GC_BATCH_SIZE ((PAGE_SIZE - \ |
---|
704 | | - sizeof(struct nft_set_gc_batch_head)) / \ |
---|
705 | | - sizeof(void *)) |
---|
706 | | - |
---|
707 | | -/** |
---|
708 | | - * struct nft_set_gc_batch - nf_tables set garbage collection batch |
---|
709 | | - * |
---|
710 | | - * @head: GC batch head |
---|
711 | | - * @elems: garbage collection elements |
---|
712 | | - */ |
---|
713 | | -struct nft_set_gc_batch { |
---|
714 | | - struct nft_set_gc_batch_head head; |
---|
715 | | - void *elems[NFT_SET_GC_BATCH_SIZE]; |
---|
716 | | -}; |
---|
717 | | - |
---|
718 | | -struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set, |
---|
719 | | - gfp_t gfp); |
---|
720 | | -void nft_set_gc_batch_release(struct rcu_head *rcu); |
---|
721 | | - |
---|
722 | | -static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb) |
---|
723 | | -{ |
---|
724 | | - if (gcb != NULL) |
---|
725 | | - call_rcu(&gcb->head.rcu, nft_set_gc_batch_release); |
---|
726 | | -} |
---|
727 | | - |
---|
728 | | -static inline struct nft_set_gc_batch * |
---|
729 | | -nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb, |
---|
730 | | - gfp_t gfp) |
---|
731 | | -{ |
---|
732 | | - if (gcb != NULL) { |
---|
733 | | - if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems)) |
---|
734 | | - return gcb; |
---|
735 | | - nft_set_gc_batch_complete(gcb); |
---|
736 | | - } |
---|
737 | | - return nft_set_gc_batch_alloc(set, gfp); |
---|
738 | | -} |
---|
739 | | - |
---|
740 | | -static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb, |
---|
741 | | - void *elem) |
---|
742 | | -{ |
---|
743 | | - gcb->elems[gcb->head.cnt++] = elem; |
---|
744 | | -} |
---|
| 711 | +void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, |
---|
| 712 | + const struct nft_set *set, void *elem); |
---|
745 | 713 | |
---|
746 | 714 | struct nft_expr_ops; |
---|
747 | 715 | /** |
---|
.. | .. |
---|
777 | 745 | |
---|
778 | 746 | enum nft_trans_phase { |
---|
779 | 747 | NFT_TRANS_PREPARE, |
---|
| 748 | + NFT_TRANS_PREPARE_ERROR, |
---|
780 | 749 | NFT_TRANS_ABORT, |
---|
781 | 750 | NFT_TRANS_COMMIT, |
---|
782 | 751 | NFT_TRANS_RELEASE |
---|
.. | .. |
---|
907 | 876 | return (void *)&rule->data[rule->dlen]; |
---|
908 | 877 | } |
---|
909 | 878 | |
---|
910 | | -void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule); |
---|
| 879 | +void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule); |
---|
| 880 | +void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule, |
---|
| 881 | + enum nft_trans_phase phase); |
---|
| 882 | +void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule); |
---|
911 | 883 | |
---|
912 | 884 | static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext, |
---|
913 | 885 | struct nft_regs *regs, |
---|
.. | .. |
---|
966 | 938 | }; |
---|
967 | 939 | |
---|
968 | 940 | int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain); |
---|
| 941 | +int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain); |
---|
| 942 | +void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain); |
---|
969 | 943 | |
---|
970 | 944 | enum nft_chain_types { |
---|
971 | 945 | NFT_CHAIN_T_DEFAULT = 0, |
---|
.. | .. |
---|
1002 | 976 | int nft_chain_validate_hooks(const struct nft_chain *chain, |
---|
1003 | 977 | unsigned int hook_flags); |
---|
1004 | 978 | |
---|
| 979 | +static inline bool nft_chain_binding(const struct nft_chain *chain) |
---|
| 980 | +{ |
---|
| 981 | + return chain->flags & NFT_CHAIN_BINDING; |
---|
| 982 | +} |
---|
| 983 | + |
---|
1005 | 984 | static inline bool nft_chain_is_bound(struct nft_chain *chain) |
---|
1006 | 985 | { |
---|
1007 | 986 | return (chain->flags & NFT_CHAIN_BINDING) && chain->bound; |
---|
1008 | 987 | } |
---|
1009 | 988 | |
---|
| 989 | +int nft_chain_add(struct nft_table *table, struct nft_chain *chain); |
---|
1010 | 990 | void nft_chain_del(struct nft_chain *chain); |
---|
1011 | 991 | void nf_tables_chain_destroy(struct nft_ctx *ctx); |
---|
1012 | 992 | |
---|
.. | .. |
---|
1057 | 1037 | int __nft_release_basechain(struct nft_ctx *ctx); |
---|
1058 | 1038 | |
---|
1059 | 1039 | unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv); |
---|
| 1040 | + |
---|
| 1041 | +static inline bool nft_use_inc(u32 *use) |
---|
| 1042 | +{ |
---|
| 1043 | + if (*use == UINT_MAX) |
---|
| 1044 | + return false; |
---|
| 1045 | + |
---|
| 1046 | + (*use)++; |
---|
| 1047 | + |
---|
| 1048 | + return true; |
---|
| 1049 | +} |
---|
| 1050 | + |
---|
| 1051 | +static inline void nft_use_dec(u32 *use) |
---|
| 1052 | +{ |
---|
| 1053 | + WARN_ON_ONCE((*use)-- == 0); |
---|
| 1054 | +} |
---|
| 1055 | + |
---|
| 1056 | +/* For error and abort path: restore use counter to previous state. */ |
---|
| 1057 | +static inline void nft_use_inc_restore(u32 *use) |
---|
| 1058 | +{ |
---|
| 1059 | + WARN_ON_ONCE(!nft_use_inc(use)); |
---|
| 1060 | +} |
---|
| 1061 | + |
---|
| 1062 | +#define nft_use_dec_restore nft_use_dec |
---|
1060 | 1063 | |
---|
1061 | 1064 | /** |
---|
1062 | 1065 | * struct nft_table - nf_tables table |
---|
.. | .. |
---|
1135 | 1138 | struct list_head list; |
---|
1136 | 1139 | struct rhlist_head rhlhead; |
---|
1137 | 1140 | struct nft_object_hash_key key; |
---|
1138 | | - u32 genmask:2, |
---|
1139 | | - use:30; |
---|
| 1141 | + u32 genmask:2; |
---|
| 1142 | + u32 use; |
---|
1140 | 1143 | u64 handle; |
---|
1141 | 1144 | u16 udlen; |
---|
1142 | 1145 | u8 *udata; |
---|
.. | .. |
---|
1238 | 1241 | char *name; |
---|
1239 | 1242 | int hooknum; |
---|
1240 | 1243 | int ops_len; |
---|
1241 | | - u32 genmask:2, |
---|
1242 | | - use:30; |
---|
| 1244 | + u32 genmask:2; |
---|
| 1245 | + u32 use; |
---|
1243 | 1246 | u64 handle; |
---|
1244 | 1247 | /* runtime data below here */ |
---|
1245 | 1248 | struct list_head hook_list ____cacheline_aligned; |
---|
.. | .. |
---|
1375 | 1378 | |
---|
1376 | 1379 | #endif /* IS_ENABLED(CONFIG_NF_TABLES) */ |
---|
1377 | 1380 | |
---|
1378 | | -/* |
---|
1379 | | - * We use a free bit in the genmask field to indicate the element |
---|
1380 | | - * is busy, meaning it is currently being processed either by |
---|
1381 | | - * the netlink API or GC. |
---|
1382 | | - * |
---|
1383 | | - * Even though the genmask is only a single byte wide, this works |
---|
1384 | | - * because the extension structure if fully constant once initialized, |
---|
1385 | | - * so there are no non-atomic write accesses unless it is already |
---|
1386 | | - * marked busy. |
---|
1387 | | - */ |
---|
1388 | | -#define NFT_SET_ELEM_BUSY_MASK (1 << 2) |
---|
| 1381 | +#define NFT_SET_ELEM_DEAD_MASK (1 << 2) |
---|
1389 | 1382 | |
---|
1390 | 1383 | #if defined(__LITTLE_ENDIAN_BITFIELD) |
---|
1391 | | -#define NFT_SET_ELEM_BUSY_BIT 2 |
---|
| 1384 | +#define NFT_SET_ELEM_DEAD_BIT 2 |
---|
1392 | 1385 | #elif defined(__BIG_ENDIAN_BITFIELD) |
---|
1393 | | -#define NFT_SET_ELEM_BUSY_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2) |
---|
| 1386 | +#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2) |
---|
1394 | 1387 | #else |
---|
1395 | 1388 | #error |
---|
1396 | 1389 | #endif |
---|
1397 | 1390 | |
---|
1398 | | -static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext) |
---|
| 1391 | +static inline void nft_set_elem_dead(struct nft_set_ext *ext) |
---|
1399 | 1392 | { |
---|
1400 | 1393 | unsigned long *word = (unsigned long *)ext; |
---|
1401 | 1394 | |
---|
1402 | 1395 | BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0); |
---|
1403 | | - return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word); |
---|
| 1396 | + set_bit(NFT_SET_ELEM_DEAD_BIT, word); |
---|
1404 | 1397 | } |
---|
1405 | 1398 | |
---|
1406 | | -static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext) |
---|
| 1399 | +static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext) |
---|
1407 | 1400 | { |
---|
1408 | 1401 | unsigned long *word = (unsigned long *)ext; |
---|
1409 | 1402 | |
---|
1410 | | - clear_bit(NFT_SET_ELEM_BUSY_BIT, word); |
---|
| 1403 | + BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0); |
---|
| 1404 | + return test_bit(NFT_SET_ELEM_DEAD_BIT, word); |
---|
1411 | 1405 | } |
---|
1412 | 1406 | |
---|
1413 | 1407 | /** |
---|
1414 | 1408 | * struct nft_trans - nf_tables object update in transaction |
---|
1415 | 1409 | * |
---|
1416 | 1410 | * @list: used internally |
---|
| 1411 | + * @binding_list: list of objects with possible bindings |
---|
1417 | 1412 | * @msg_type: message type |
---|
1418 | 1413 | * @put_net: ctx->net needs to be put |
---|
1419 | 1414 | * @ctx: transaction context |
---|
.. | .. |
---|
1421 | 1416 | */ |
---|
1422 | 1417 | struct nft_trans { |
---|
1423 | 1418 | struct list_head list; |
---|
| 1419 | + struct list_head binding_list; |
---|
1424 | 1420 | int msg_type; |
---|
1425 | 1421 | bool put_net; |
---|
1426 | 1422 | struct nft_ctx ctx; |
---|
.. | .. |
---|
1431 | 1427 | struct nft_rule *rule; |
---|
1432 | 1428 | struct nft_flow_rule *flow; |
---|
1433 | 1429 | u32 rule_id; |
---|
| 1430 | + bool bound; |
---|
1434 | 1431 | }; |
---|
1435 | 1432 | |
---|
1436 | 1433 | #define nft_trans_rule(trans) \ |
---|
.. | .. |
---|
1439 | 1436 | (((struct nft_trans_rule *)trans->data)->flow) |
---|
1440 | 1437 | #define nft_trans_rule_id(trans) \ |
---|
1441 | 1438 | (((struct nft_trans_rule *)trans->data)->rule_id) |
---|
| 1439 | +#define nft_trans_rule_bound(trans) \ |
---|
| 1440 | + (((struct nft_trans_rule *)trans->data)->bound) |
---|
1442 | 1441 | |
---|
1443 | 1442 | struct nft_trans_set { |
---|
1444 | 1443 | struct nft_set *set; |
---|
.. | .. |
---|
1454 | 1453 | (((struct nft_trans_set *)trans->data)->bound) |
---|
1455 | 1454 | |
---|
1456 | 1455 | struct nft_trans_chain { |
---|
| 1456 | + struct nft_chain *chain; |
---|
1457 | 1457 | bool update; |
---|
1458 | 1458 | char *name; |
---|
1459 | 1459 | struct nft_stats __percpu *stats; |
---|
1460 | 1460 | u8 policy; |
---|
| 1461 | + bool bound; |
---|
1461 | 1462 | u32 chain_id; |
---|
1462 | 1463 | }; |
---|
1463 | 1464 | |
---|
| 1465 | +#define nft_trans_chain(trans) \ |
---|
| 1466 | + (((struct nft_trans_chain *)trans->data)->chain) |
---|
1464 | 1467 | #define nft_trans_chain_update(trans) \ |
---|
1465 | 1468 | (((struct nft_trans_chain *)trans->data)->update) |
---|
1466 | 1469 | #define nft_trans_chain_name(trans) \ |
---|
.. | .. |
---|
1469 | 1472 | (((struct nft_trans_chain *)trans->data)->stats) |
---|
1470 | 1473 | #define nft_trans_chain_policy(trans) \ |
---|
1471 | 1474 | (((struct nft_trans_chain *)trans->data)->policy) |
---|
| 1475 | +#define nft_trans_chain_bound(trans) \ |
---|
| 1476 | + (((struct nft_trans_chain *)trans->data)->bound) |
---|
1472 | 1477 | #define nft_trans_chain_id(trans) \ |
---|
1473 | 1478 | (((struct nft_trans_chain *)trans->data)->chain_id) |
---|
1474 | 1479 | |
---|
.. | .. |
---|
1524 | 1529 | #define nft_trans_flowtable_flags(trans) \ |
---|
1525 | 1530 | (((struct nft_trans_flowtable *)trans->data)->flags) |
---|
1526 | 1531 | |
---|
| 1532 | +#define NFT_TRANS_GC_BATCHCOUNT 256 |
---|
| 1533 | + |
---|
| 1534 | +struct nft_trans_gc { |
---|
| 1535 | + struct list_head list; |
---|
| 1536 | + struct net *net; |
---|
| 1537 | + struct nft_set *set; |
---|
| 1538 | + u32 seq; |
---|
| 1539 | + u16 count; |
---|
| 1540 | + void *priv[NFT_TRANS_GC_BATCHCOUNT]; |
---|
| 1541 | + struct rcu_head rcu; |
---|
| 1542 | +}; |
---|
| 1543 | + |
---|
| 1544 | +struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set, |
---|
| 1545 | + unsigned int gc_seq, gfp_t gfp); |
---|
| 1546 | +void nft_trans_gc_destroy(struct nft_trans_gc *trans); |
---|
| 1547 | + |
---|
| 1548 | +struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc, |
---|
| 1549 | + unsigned int gc_seq, gfp_t gfp); |
---|
| 1550 | +void nft_trans_gc_queue_async_done(struct nft_trans_gc *gc); |
---|
| 1551 | + |
---|
| 1552 | +struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp); |
---|
| 1553 | +void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans); |
---|
| 1554 | + |
---|
| 1555 | +void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv); |
---|
| 1556 | + |
---|
| 1557 | +void nft_setelem_data_deactivate(const struct net *net, |
---|
| 1558 | + const struct nft_set *set, |
---|
| 1559 | + struct nft_set_elem *elem); |
---|
| 1560 | + |
---|
1527 | 1561 | int __init nft_chain_filter_init(void); |
---|
1528 | 1562 | void nft_chain_filter_fini(void); |
---|
1529 | 1563 | |
---|
.. | .. |
---|
1535 | 1569 | int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result); |
---|
1536 | 1570 | __be64 nf_jiffies64_to_msecs(u64 input); |
---|
1537 | 1571 | |
---|
| 1572 | +struct nftables_pernet { |
---|
| 1573 | + struct list_head tables; |
---|
| 1574 | + struct list_head commit_list; |
---|
| 1575 | + struct list_head binding_list; |
---|
| 1576 | + struct list_head module_list; |
---|
| 1577 | + struct list_head notify_list; |
---|
| 1578 | + struct mutex commit_mutex; |
---|
| 1579 | + unsigned int base_seq; |
---|
| 1580 | + u8 validate_state; |
---|
| 1581 | + unsigned int gc_seq; |
---|
| 1582 | +}; |
---|
| 1583 | + |
---|
1538 | 1584 | #endif /* _NET_NF_TABLES_H */ |
---|