Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter/IPVS updates for net-next,
more specifically:

* Updates for ipset:

1) Coding style fix for ipset comment extension, from Jeremy Sowden.

2) De-inline many functions in ipset, from Jeremy Sowden.

3) Move ipset function definition from header to source file.

4) Move ip_set_put_flags() to source, export it as a symbol, remove
inline.

5) Move range_to_mask() to the source file where this is used.

6) Move ip_set_get_ip_port() to the source file where this is used.

* IPVS selftests and netns improvements:

7) Two patches to speedup ipvs netns dismantle, from Haishuang Yan.

8) Three patches to add selftest script for ipvs, also from
Haishuang Yan.

* Conntrack updates and new nf_hook_slow_list() function:

9) Document ct ecache extension, from Florian Westphal.

10) Skip ct extensions from ctnetlink dump, from Florian.

11) Free ct extension immediately, from Florian.

12) Skip access to ecache extension from nf_ct_deliver_cached_events()
this is not correct as reported by Syzbot.

13) Add and use nf_hook_slow_list(), from Florian.

* Flowtable infrastructure updates:

14) Move priority to nf_flowtable definition.

15) Dynamic allocation of per-device hooks in flowtables.

16) Allow to include netdevice only once in flowtable definitions.

17) Rise maximum number of devices per flowtable.

* Netfilter hardware offload infrastructure updates:

18) Add nft_flow_block_chain() helper function.

19) Pass callback list to nft_setup_cb_call().

20) Add nft_flow_cls_offload_setup() helper function.

21) Remove rules for the unregistered device via netdevice event.

22) Support for multiple devices in a basechain definition at the
ingress hook.

22) Add nft_chain_offload_cmd() helper function.

23) Add nft_flow_block_offload_init() helper function.

24) Rewind in case of failing to bind multiple devices to hook.

25) Typo in IPv6 tproxy module description, from Norman Rasmussen.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+1343 -727
+30 -9
include/linux/netfilter.h
··· 199 199 int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, 200 200 const struct nf_hook_entries *e, unsigned int i); 201 201 202 + void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state, 203 + const struct nf_hook_entries *e); 202 204 /** 203 205 * nf_hook - call a netfilter hook 204 206 * ··· 313 311 struct list_head *head, struct net_device *in, struct net_device *out, 314 312 int (*okfn)(struct net *, struct sock *, struct sk_buff *)) 315 313 { 316 - struct sk_buff *skb, *next; 317 - struct list_head sublist; 314 + struct nf_hook_entries *hook_head = NULL; 318 315 319 - INIT_LIST_HEAD(&sublist); 320 - list_for_each_entry_safe(skb, next, head, list) { 321 - list_del(&skb->list); 322 - if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1) 323 - list_add_tail(&skb->list, &sublist); 316 + #ifdef CONFIG_JUMP_LABEL 317 + if (__builtin_constant_p(pf) && 318 + __builtin_constant_p(hook) && 319 + !static_key_false(&nf_hooks_needed[pf][hook])) 320 + return; 321 + #endif 322 + 323 + rcu_read_lock(); 324 + switch (pf) { 325 + case NFPROTO_IPV4: 326 + hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]); 327 + break; 328 + case NFPROTO_IPV6: 329 + hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]); 330 + break; 331 + default: 332 + WARN_ON_ONCE(1); 333 + break; 324 334 } 325 - /* Put passed packets back on main list */ 326 - list_splice(&sublist, head); 335 + 336 + if (hook_head) { 337 + struct nf_hook_state state; 338 + 339 + nf_hook_state_init(&state, hook, pf, in, out, sk, net, okfn); 340 + 341 + nf_hook_slow_list(head, &state, hook_head); 342 + } 343 + rcu_read_unlock(); 327 344 } 328 345 329 346 /* Call setsockopt() */
+8 -188
include/linux/netfilter/ipset/ip_set.h
··· 269 269 /* Check that the extension is enabled for the set and 270 270 * call it's destroy function for its extension part in data. 271 271 */ 272 - if (SET_WITH_COMMENT(set)) 273 - ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy( 274 - set, ext_comment(data, set)); 272 + if (SET_WITH_COMMENT(set)) { 273 + struct ip_set_comment *c = ext_comment(data, set); 274 + 275 + ip_set_extensions[IPSET_EXT_ID_COMMENT].destroy(set, c); 276 + } 275 277 } 276 278 277 - static inline int 278 - ip_set_put_flags(struct sk_buff *skb, struct ip_set *set) 279 - { 280 - u32 cadt_flags = 0; 281 - 282 - if (SET_WITH_TIMEOUT(set)) 283 - if (unlikely(nla_put_net32(skb, IPSET_ATTR_TIMEOUT, 284 - htonl(set->timeout)))) 285 - return -EMSGSIZE; 286 - if (SET_WITH_COUNTER(set)) 287 - cadt_flags |= IPSET_FLAG_WITH_COUNTERS; 288 - if (SET_WITH_COMMENT(set)) 289 - cadt_flags |= IPSET_FLAG_WITH_COMMENT; 290 - if (SET_WITH_SKBINFO(set)) 291 - cadt_flags |= IPSET_FLAG_WITH_SKBINFO; 292 - if (SET_WITH_FORCEADD(set)) 293 - cadt_flags |= IPSET_FLAG_WITH_FORCEADD; 294 - 295 - if (!cadt_flags) 296 - return 0; 297 - return nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(cadt_flags)); 298 - } 279 + int ip_set_put_flags(struct sk_buff *skb, struct ip_set *set); 299 280 300 281 /* Netlink CB args */ 301 282 enum { ··· 487 506 *timeout = t; 488 507 } 489 508 490 - static inline u32 491 - ip_set_timeout_get(const unsigned long *timeout) 492 - { 493 - u32 t; 494 - 495 - if (*timeout == IPSET_ELEM_PERMANENT) 496 - return 0; 497 - 498 - t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; 499 - /* Zero value in userspace means no timeout */ 500 - return t == 0 ? 1 : t; 501 - } 502 - 503 - static inline char* 504 - ip_set_comment_uget(struct nlattr *tb) 505 - { 506 - return nla_data(tb); 507 - } 508 - 509 - /* Called from uadd only, protected by the set spinlock. 510 - * The kadt functions don't use the comment extensions in any way. 511 - */ 512 - static inline void 513 - ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, 514 - const struct ip_set_ext *ext) 515 - { 516 - struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1); 517 - size_t len = ext->comment ? strlen(ext->comment) : 0; 518 - 519 - if (unlikely(c)) { 520 - set->ext_size -= sizeof(*c) + strlen(c->str) + 1; 521 - kfree_rcu(c, rcu); 522 - rcu_assign_pointer(comment->c, NULL); 523 - } 524 - if (!len) 525 - return; 526 - if (unlikely(len > IPSET_MAX_COMMENT_SIZE)) 527 - len = IPSET_MAX_COMMENT_SIZE; 528 - c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); 529 - if (unlikely(!c)) 530 - return; 531 - strlcpy(c->str, ext->comment, len + 1); 532 - set->ext_size += sizeof(*c) + strlen(c->str) + 1; 533 - rcu_assign_pointer(comment->c, c); 534 - } 535 - 536 - /* Used only when dumping a set, protected by rcu_read_lock() */ 537 - static inline int 538 - ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment) 539 - { 540 - struct ip_set_comment_rcu *c = rcu_dereference(comment->c); 541 - 542 - if (!c) 543 - return 0; 544 - return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str); 545 - } 546 - 547 - /* Called from uadd/udel, flush or the garbage collectors protected 548 - * by the set spinlock. 549 - * Called when the set is destroyed and when there can't be any user 550 - * of the set data anymore. 551 - */ 552 - static inline void 553 - ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment) 554 - { 555 - struct ip_set_comment_rcu *c; 556 - 557 - c = rcu_dereference_protected(comment->c, 1); 558 - if (unlikely(!c)) 559 - return; 560 - set->ext_size -= sizeof(*c) + strlen(c->str) + 1; 561 - kfree_rcu(c, rcu); 562 - rcu_assign_pointer(comment->c, NULL); 563 - } 564 - 565 - static inline void 566 - ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) 567 - { 568 - atomic64_add((long long)bytes, &(counter)->bytes); 569 - } 570 - 571 - static inline void 572 - ip_set_add_packets(u64 packets, struct ip_set_counter *counter) 573 - { 574 - atomic64_add((long long)packets, &(counter)->packets); 575 - } 576 - 577 - static inline u64 578 - ip_set_get_bytes(const struct ip_set_counter *counter) 579 - { 580 - return (u64)atomic64_read(&(counter)->bytes); 581 - } 582 - 583 - static inline u64 584 - ip_set_get_packets(const struct ip_set_counter *counter) 585 - { 586 - return (u64)atomic64_read(&(counter)->packets); 587 - } 588 - 589 - static inline bool 590 - ip_set_match_counter(u64 counter, u64 match, u8 op) 591 - { 592 - switch (op) { 593 - case IPSET_COUNTER_NONE: 594 - return true; 595 - case IPSET_COUNTER_EQ: 596 - return counter == match; 597 - case IPSET_COUNTER_NE: 598 - return counter != match; 599 - case IPSET_COUNTER_LT: 600 - return counter < match; 601 - case IPSET_COUNTER_GT: 602 - return counter > match; 603 - } 604 - return false; 605 - } 606 - 607 - static inline void 608 - ip_set_update_counter(struct ip_set_counter *counter, 609 - const struct ip_set_ext *ext, u32 flags) 610 - { 611 - if (ext->packets != ULLONG_MAX && 612 - !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) { 613 - ip_set_add_bytes(ext->bytes, counter); 614 - ip_set_add_packets(ext->packets, counter); 615 - } 616 - } 617 - 618 - static inline bool 619 - ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter) 620 - { 621 - return nla_put_net64(skb, IPSET_ATTR_BYTES, 622 - cpu_to_be64(ip_set_get_bytes(counter)), 623 - IPSET_ATTR_PAD) || 624 - nla_put_net64(skb, IPSET_ATTR_PACKETS, 625 - cpu_to_be64(ip_set_get_packets(counter)), 626 - IPSET_ATTR_PAD); 627 - } 509 + void ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, 510 + const struct ip_set_ext *ext); 628 511 629 512 static inline void 630 513 ip_set_init_counter(struct ip_set_counter *counter, ··· 498 653 atomic64_set(&(counter)->bytes, (long long)(ext->bytes)); 499 654 if (ext->packets != ULLONG_MAX) 500 655 atomic64_set(&(counter)->packets, (long long)(ext->packets)); 501 - } 502 - 503 - static inline void 504 - ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo, 505 - const struct ip_set_ext *ext, 506 - struct ip_set_ext *mext, u32 flags) 507 - { 508 - mext->skbinfo = *skbinfo; 509 - } 510 - 511 - static inline bool 512 - ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo) 513 - { 514 - /* Send nonzero parameters only */ 515 - return ((skbinfo->skbmark || skbinfo->skbmarkmask) && 516 - nla_put_net64(skb, IPSET_ATTR_SKBMARK, 517 - cpu_to_be64((u64)skbinfo->skbmark << 32 | 518 - skbinfo->skbmarkmask), 519 - IPSET_ATTR_PAD)) || 520 - (skbinfo->skbprio && 521 - nla_put_net32(skb, IPSET_ATTR_SKBPRIO, 522 - cpu_to_be32(skbinfo->skbprio))) || 523 - (skbinfo->skbqueue && 524 - nla_put_net16(skb, IPSET_ATTR_SKBQUEUE, 525 - cpu_to_be16(skbinfo->skbqueue))); 526 656 } 527 657 528 658 static inline void
-14
include/linux/netfilter/ipset/ip_set_bitmap.h
··· 12 12 IPSET_ADD_START_STORED_TIMEOUT, 13 13 }; 14 14 15 - /* Common functions */ 16 - 17 - static inline u32 18 - range_to_mask(u32 from, u32 to, u8 *bits) 19 - { 20 - u32 mask = 0xFFFFFFFE; 21 - 22 - *bits = 32; 23 - while (--(*bits) > 0 && mask && (to & mask) != from) 24 - mask <<= 1; 25 - 26 - return mask; 27 - } 28 - 29 15 #endif /* __IP_SET_BITMAP_H */
-3
include/linux/netfilter/ipset/ip_set_getport.h
··· 20 20 } 21 21 #endif 22 22 23 - extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, 24 - __be16 *port); 25 - 26 23 static inline bool ip_set_proto_with_ports(u8 proto) 27 24 { 28 25 switch (proto) {
+1 -1
include/net/ip_vs.h
··· 1324 1324 void ip_vs_control_net_cleanup(struct netns_ipvs *ipvs); 1325 1325 void ip_vs_estimator_net_cleanup(struct netns_ipvs *ipvs); 1326 1326 void ip_vs_sync_net_cleanup(struct netns_ipvs *ipvs); 1327 - void ip_vs_service_net_cleanup(struct netns_ipvs *ipvs); 1327 + void ip_vs_service_nets_cleanup(struct list_head *net_list); 1328 1328 1329 1329 /* IPVS application functions 1330 1330 * (from ip_vs_app.c)
-10
include/net/netfilter/nf_conntrack_extend.h
··· 43 43 44 44 /* Extensions: optional stuff which isn't permanently in struct. */ 45 45 struct nf_ct_ext { 46 - struct rcu_head rcu; 47 46 u8 offset[NF_CT_EXT_NUM]; 48 47 u8 len; 49 48 char data[0]; ··· 70 71 71 72 /* Destroy all relationships */ 72 73 void nf_ct_ext_destroy(struct nf_conn *ct); 73 - 74 - /* Free operation. If you want to free a object referred from private area, 75 - * please implement __nf_ct_ext_free() and call it. 76 - */ 77 - static inline void nf_ct_ext_free(struct nf_conn *ct) 78 - { 79 - if (ct->ext) 80 - kfree_rcu(ct->ext, rcu); 81 - } 82 74 83 75 /* Add this type, returns pointer to data or NULL. */ 84 76 void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
+1
include/net/netfilter/nf_flow_table.h
··· 24 24 struct nf_flowtable { 25 25 struct list_head list; 26 26 struct rhashtable rhashtable; 27 + int priority; 27 28 const struct nf_flowtable_type *type; 28 29 struct delayed_work gc_work; 29 30 };
+10 -6
include/net/netfilter/nf_tables.h
··· 963 963 struct u64_stats_sync syncp; 964 964 }; 965 965 966 + struct nft_hook { 967 + struct list_head list; 968 + struct nf_hook_ops ops; 969 + struct rcu_head rcu; 970 + }; 971 + 966 972 /** 967 973 * struct nft_base_chain - nf_tables base chain 968 974 * 969 975 * @ops: netfilter hook ops 976 + * @hook_list: list of netfilter hooks (for NFPROTO_NETDEV family) 970 977 * @type: chain type 971 978 * @policy: default policy 972 979 * @stats: per-cpu chain stats 973 980 * @chain: the chain 974 - * @dev_name: device name that this base chain is attached to (if any) 975 981 * @flow_block: flow block (for hardware offload) 976 982 */ 977 983 struct nft_base_chain { 978 984 struct nf_hook_ops ops; 985 + struct list_head hook_list; 979 986 const struct nft_chain_type *type; 980 987 u8 policy; 981 988 u8 flags; 982 989 struct nft_stats __percpu *stats; 983 990 struct nft_chain chain; 984 - char dev_name[IFNAMSIZ]; 985 991 struct flow_block flow_block; 986 992 }; 987 993 ··· 1152 1146 int nft_register_obj(struct nft_object_type *obj_type); 1153 1147 void nft_unregister_obj(struct nft_object_type *obj_type); 1154 1148 1155 - #define NFT_FLOWTABLE_DEVICE_MAX 8 1149 + #define NFT_NETDEVICE_MAX 256 1156 1150 1157 1151 /** 1158 1152 * struct nft_flowtable - nf_tables flow table ··· 1161 1155 * @table: the table the flow table is contained in 1162 1156 * @name: name of this flow table 1163 1157 * @hooknum: hook number 1164 - * @priority: hook priority 1165 1158 * @ops_len: number of hooks in array 1166 1159 * @genmask: generation mask 1167 1160 * @use: number of references to this flow table ··· 1174 1169 struct nft_table *table; 1175 1170 char *name; 1176 1171 int hooknum; 1177 - int priority; 1178 1172 int ops_len; 1179 1173 u32 genmask:2, 1180 1174 use:30; 1181 1175 u64 handle; 1182 1176 /* runtime data below here */ 1183 - struct nf_hook_ops *ops ____cacheline_aligned; 1177 + struct list_head hook_list ____cacheline_aligned; 1184 1178 struct nf_flowtable data; 1185 1179 }; 1186 1180
+2
include/uapi/linux/netfilter/nf_tables.h
··· 144 144 * @NFTA_HOOK_HOOKNUM: netfilter hook number (NLA_U32) 145 145 * @NFTA_HOOK_PRIORITY: netfilter hook priority (NLA_U32) 146 146 * @NFTA_HOOK_DEV: netdevice name (NLA_STRING) 147 + * @NFTA_HOOK_DEVS: list of netdevices (NLA_NESTED) 147 148 */ 148 149 enum nft_hook_attributes { 149 150 NFTA_HOOK_UNSPEC, 150 151 NFTA_HOOK_HOOKNUM, 151 152 NFTA_HOOK_PRIORITY, 152 153 NFTA_HOOK_DEV, 154 + NFTA_HOOK_DEVS, 153 155 __NFTA_HOOK_MAX 154 156 }; 155 157 #define NFTA_HOOK_MAX (__NFTA_HOOK_MAX - 1)
+1 -1
net/ipv6/netfilter/nf_tproxy_ipv6.c
··· 150 150 151 151 MODULE_LICENSE("GPL"); 152 152 MODULE_AUTHOR("Balazs Scheidler, Krisztian Kovacs"); 153 - MODULE_DESCRIPTION("Netfilter IPv4 transparent proxy support"); 153 + MODULE_DESCRIPTION("Netfilter IPv6 transparent proxy support");
+20
net/netfilter/core.c
··· 536 536 } 537 537 EXPORT_SYMBOL(nf_hook_slow); 538 538 539 + void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state, 540 + const struct nf_hook_entries *e) 541 + { 542 + struct sk_buff *skb, *next; 543 + struct list_head sublist; 544 + int ret; 545 + 546 + INIT_LIST_HEAD(&sublist); 547 + 548 + list_for_each_entry_safe(skb, next, head, list) { 549 + skb_list_del_init(skb); 550 + ret = nf_hook_slow(skb, state, e, 0); 551 + if (ret == 1) 552 + list_add_tail(&skb->list, &sublist); 553 + } 554 + /* Put passed packets back on main list */ 555 + list_splice(&sublist, head); 556 + } 557 + EXPORT_SYMBOL(nf_hook_slow_list); 558 + 539 559 /* This needs to be compiled in any case to avoid dependencies between the 540 560 * nfnetlink_queue code and nf_conntrack. 541 561 */
+1 -1
net/netfilter/ipset/ip_set_bitmap_gen.h
··· 192 192 } 193 193 194 194 #ifndef IP_SET_BITMAP_STORED_TIMEOUT 195 - static inline bool 195 + static bool 196 196 mtype_is_filled(const struct mtype_elem *x) 197 197 { 198 198 return true;
+19 -7
net/netfilter/ipset/ip_set_bitmap_ip.c
··· 55 55 u16 id; 56 56 }; 57 57 58 - static inline u32 58 + static u32 59 59 ip_to_id(const struct bitmap_ip *m, u32 ip) 60 60 { 61 61 return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip) / m->hosts; ··· 63 63 64 64 /* Common functions */ 65 65 66 - static inline int 66 + static int 67 67 bitmap_ip_do_test(const struct bitmap_ip_adt_elem *e, 68 68 struct bitmap_ip *map, size_t dsize) 69 69 { 70 70 return !!test_bit(e->id, map->members); 71 71 } 72 72 73 - static inline int 73 + static int 74 74 bitmap_ip_gc_test(u16 id, const struct bitmap_ip *map, size_t dsize) 75 75 { 76 76 return !!test_bit(id, map->members); 77 77 } 78 78 79 - static inline int 79 + static int 80 80 bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map, 81 81 u32 flags, size_t dsize) 82 82 { 83 83 return !!test_bit(e->id, map->members); 84 84 } 85 85 86 - static inline int 86 + static int 87 87 bitmap_ip_do_del(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map) 88 88 { 89 89 return !test_and_clear_bit(e->id, map->members); 90 90 } 91 91 92 - static inline int 92 + static int 93 93 bitmap_ip_do_list(struct sk_buff *skb, const struct bitmap_ip *map, u32 id, 94 94 size_t dsize) 95 95 { ··· 97 97 htonl(map->first_ip + id * map->hosts)); 98 98 } 99 99 100 - static inline int 100 + static int 101 101 bitmap_ip_do_head(struct sk_buff *skb, const struct bitmap_ip *map) 102 102 { 103 103 return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) || ··· 235 235 set->family = NFPROTO_IPV4; 236 236 237 237 return true; 238 + } 239 + 240 + static u32 241 + range_to_mask(u32 from, u32 to, u8 *bits) 242 + { 243 + u32 mask = 0xFFFFFFFE; 244 + 245 + *bits = 32; 246 + while (--(*bits) > 0 && mask && (to & mask) != from) 247 + mask <<= 1; 248 + 249 + return mask; 238 250 } 239 251 240 252 static int
+9 -9
net/netfilter/ipset/ip_set_bitmap_ipmac.c
··· 65 65 unsigned char filled; 66 66 } __aligned(__alignof__(u64)); 67 67 68 - static inline u32 68 + static u32 69 69 ip_to_id(const struct bitmap_ipmac *m, u32 ip) 70 70 { 71 71 return ip - m->first_ip; ··· 79 79 80 80 /* Common functions */ 81 81 82 - static inline int 82 + static int 83 83 bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e, 84 84 const struct bitmap_ipmac *map, size_t dsize) 85 85 { ··· 94 94 return -EAGAIN; 95 95 } 96 96 97 - static inline int 97 + static int 98 98 bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize) 99 99 { 100 100 const struct bitmap_ipmac_elem *elem; ··· 106 106 return elem->filled == MAC_FILLED; 107 107 } 108 108 109 - static inline int 109 + static int 110 110 bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem) 111 111 { 112 112 return elem->filled == MAC_FILLED; 113 113 } 114 114 115 - static inline int 115 + static int 116 116 bitmap_ipmac_add_timeout(unsigned long *timeout, 117 117 const struct bitmap_ipmac_adt_elem *e, 118 118 const struct ip_set_ext *ext, struct ip_set *set, ··· 139 139 return 0; 140 140 } 141 141 142 - static inline int 142 + static int 143 143 bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e, 144 144 struct bitmap_ipmac *map, u32 flags, size_t dsize) 145 145 { ··· 177 177 return IPSET_ADD_STORE_PLAIN_TIMEOUT; 178 178 } 179 179 180 - static inline int 180 + static int 181 181 bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem *e, 182 182 struct bitmap_ipmac *map) 183 183 { 184 184 return !test_and_clear_bit(e->id, map->members); 185 185 } 186 186 187 - static inline int 187 + static int 188 188 bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map, 189 189 u32 id, size_t dsize) 190 190 { ··· 197 197 nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, elem->ether)); 198 198 } 199 199 200 - static inline int 200 + static int 201 201 bitmap_ipmac_do_head(struct sk_buff *skb, const struct bitmap_ipmac *map) 202 202 { 203 203 return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
+34 -7
net/netfilter/ipset/ip_set_bitmap_port.c
··· 46 46 u16 id; 47 47 }; 48 48 49 - static inline u16 49 + static u16 50 50 port_to_id(const struct bitmap_port *m, u16 port) 51 51 { 52 52 return port - m->first_port; ··· 54 54 55 55 /* Common functions */ 56 56 57 - static inline int 57 + static int 58 58 bitmap_port_do_test(const struct bitmap_port_adt_elem *e, 59 59 const struct bitmap_port *map, size_t dsize) 60 60 { 61 61 return !!test_bit(e->id, map->members); 62 62 } 63 63 64 - static inline int 64 + static int 65 65 bitmap_port_gc_test(u16 id, const struct bitmap_port *map, size_t dsize) 66 66 { 67 67 return !!test_bit(id, map->members); 68 68 } 69 69 70 - static inline int 70 + static int 71 71 bitmap_port_do_add(const struct bitmap_port_adt_elem *e, 72 72 struct bitmap_port *map, u32 flags, size_t dsize) 73 73 { 74 74 return !!test_bit(e->id, map->members); 75 75 } 76 76 77 - static inline int 77 + static int 78 78 bitmap_port_do_del(const struct bitmap_port_adt_elem *e, 79 79 struct bitmap_port *map) 80 80 { 81 81 return !test_and_clear_bit(e->id, map->members); 82 82 } 83 83 84 - static inline int 84 + static int 85 85 bitmap_port_do_list(struct sk_buff *skb, const struct bitmap_port *map, u32 id, 86 86 size_t dsize) 87 87 { ··· 89 89 htons(map->first_port + id)); 90 90 } 91 91 92 - static inline int 92 + static int 93 93 bitmap_port_do_head(struct sk_buff *skb, const struct bitmap_port *map) 94 94 { 95 95 return nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) || 96 96 nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); 97 + } 98 + 99 + static bool 100 + ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port) 101 + { 102 + bool ret; 103 + u8 proto; 104 + 105 + switch (pf) { 106 + case NFPROTO_IPV4: 107 + ret = ip_set_get_ip4_port(skb, src, port, &proto); 108 + break; 109 + case NFPROTO_IPV6: 110 + ret = ip_set_get_ip6_port(skb, src, port, &proto); 111 + break; 112 + default: 113 + return false; 114 + } 115 + if (!ret) 116 + return ret; 117 + switch (proto) { 118 + case IPPROTO_TCP: 119 + case IPPROTO_UDP: 120 + return true; 121 + default: 122 + return false; 123 + } 97 124 } 98 125 99 126 static int
+201 -11
net/netfilter/ipset/ip_set_core.c
··· 35 35 36 36 static unsigned int ip_set_net_id __read_mostly; 37 37 38 - static inline struct ip_set_net *ip_set_pernet(struct net *net) 38 + static struct ip_set_net *ip_set_pernet(struct net *net) 39 39 { 40 40 return net_generic(net, ip_set_net_id); 41 41 } ··· 67 67 * serialized by ip_set_type_mutex. 68 68 */ 69 69 70 - static inline void 70 + static void 71 71 ip_set_type_lock(void) 72 72 { 73 73 mutex_lock(&ip_set_type_mutex); 74 74 } 75 75 76 - static inline void 76 + static void 77 77 ip_set_type_unlock(void) 78 78 { 79 79 mutex_unlock(&ip_set_type_mutex); ··· 277 277 } 278 278 EXPORT_SYMBOL_GPL(ip_set_free); 279 279 280 - static inline bool 280 + static bool 281 281 flag_nested(const struct nlattr *nla) 282 282 { 283 283 return nla->nla_type & NLA_F_NESTED; ··· 325 325 } 326 326 EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6); 327 327 328 + static u32 329 + ip_set_timeout_get(const unsigned long *timeout) 330 + { 331 + u32 t; 332 + 333 + if (*timeout == IPSET_ELEM_PERMANENT) 334 + return 0; 335 + 336 + t = jiffies_to_msecs(*timeout - jiffies) / MSEC_PER_SEC; 337 + /* Zero value in userspace means no timeout */ 338 + return t == 0 ? 1 : t; 339 + } 340 + 341 + static char * 342 + ip_set_comment_uget(struct nlattr *tb) 343 + { 344 + return nla_data(tb); 345 + } 346 + 347 + /* Called from uadd only, protected by the set spinlock. 348 + * The kadt functions don't use the comment extensions in any way. 349 + */ 350 + void 351 + ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, 352 + const struct ip_set_ext *ext) 353 + { 354 + struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1); 355 + size_t len = ext->comment ? strlen(ext->comment) : 0; 356 + 357 + if (unlikely(c)) { 358 + set->ext_size -= sizeof(*c) + strlen(c->str) + 1; 359 + kfree_rcu(c, rcu); 360 + rcu_assign_pointer(comment->c, NULL); 361 + } 362 + if (!len) 363 + return; 364 + if (unlikely(len > IPSET_MAX_COMMENT_SIZE)) 365 + len = IPSET_MAX_COMMENT_SIZE; 366 + c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); 367 + if (unlikely(!c)) 368 + return; 369 + strlcpy(c->str, ext->comment, len + 1); 370 + set->ext_size += sizeof(*c) + strlen(c->str) + 1; 371 + rcu_assign_pointer(comment->c, c); 372 + } 373 + EXPORT_SYMBOL_GPL(ip_set_init_comment); 374 + 375 + /* Used only when dumping a set, protected by rcu_read_lock() */ 376 + static int 377 + ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment) 378 + { 379 + struct ip_set_comment_rcu *c = rcu_dereference(comment->c); 380 + 381 + if (!c) 382 + return 0; 383 + return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str); 384 + } 385 + 386 + /* Called from uadd/udel, flush or the garbage collectors protected 387 + * by the set spinlock. 388 + * Called when the set is destroyed and when there can't be any user 389 + * of the set data anymore. 390 + */ 391 + static void 392 + ip_set_comment_free(struct ip_set *set, void *ptr) 393 + { 394 + struct ip_set_comment *comment = ptr; 395 + struct ip_set_comment_rcu *c; 396 + 397 + c = rcu_dereference_protected(comment->c, 1); 398 + if (unlikely(!c)) 399 + return; 400 + set->ext_size -= sizeof(*c) + strlen(c->str) + 1; 401 + kfree_rcu(c, rcu); 402 + rcu_assign_pointer(comment->c, NULL); 403 + } 404 + 328 405 typedef void (*destroyer)(struct ip_set *, void *); 329 406 /* ipset data extension types, in size order */ 330 407 ··· 428 351 .flag = IPSET_FLAG_WITH_COMMENT, 429 352 .len = sizeof(struct ip_set_comment), 430 353 .align = __alignof__(struct ip_set_comment), 431 - .destroy = (destroyer) ip_set_comment_free, 354 + .destroy = ip_set_comment_free, 432 355 }, 433 356 }; 434 357 EXPORT_SYMBOL_GPL(ip_set_extensions); 435 358 436 - static inline bool 359 + static bool 437 360 add_extension(enum ip_set_ext_id id, u32 flags, struct nlattr *tb[]) 438 361 { 439 362 return ip_set_extensions[id].flag ? ··· 523 446 } 524 447 EXPORT_SYMBOL_GPL(ip_set_get_extensions); 525 448 449 + static u64 450 + ip_set_get_bytes(const struct ip_set_counter *counter) 451 + { 452 + return (u64)atomic64_read(&(counter)->bytes); 453 + } 454 + 455 + static u64 456 + ip_set_get_packets(const struct ip_set_counter *counter) 457 + { 458 + return (u64)atomic64_read(&(counter)->packets); 459 + } 460 + 461 + static bool 462 + ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter) 463 + { 464 + return nla_put_net64(skb, IPSET_ATTR_BYTES, 465 + cpu_to_be64(ip_set_get_bytes(counter)), 466 + IPSET_ATTR_PAD) || 467 + nla_put_net64(skb, IPSET_ATTR_PACKETS, 468 + cpu_to_be64(ip_set_get_packets(counter)), 469 + IPSET_ATTR_PAD); 470 + } 471 + 472 + static bool 473 + ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo) 474 + { 475 + /* Send nonzero parameters only */ 476 + return ((skbinfo->skbmark || skbinfo->skbmarkmask) && 477 + nla_put_net64(skb, IPSET_ATTR_SKBMARK, 478 + cpu_to_be64((u64)skbinfo->skbmark << 32 | 479 + skbinfo->skbmarkmask), 480 + IPSET_ATTR_PAD)) || 481 + (skbinfo->skbprio && 482 + nla_put_net32(skb, IPSET_ATTR_SKBPRIO, 483 + cpu_to_be32(skbinfo->skbprio))) || 484 + (skbinfo->skbqueue && 485 + nla_put_net16(skb, IPSET_ATTR_SKBQUEUE, 486 + cpu_to_be16(skbinfo->skbqueue))); 487 + } 488 + 526 489 int 527 490 ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set, 528 491 const void *e, bool active) ··· 587 470 return 0; 588 471 } 589 472 EXPORT_SYMBOL_GPL(ip_set_put_extensions); 473 + 474 + static bool 475 + ip_set_match_counter(u64 counter, u64 match, u8 op) 476 + { 477 + switch (op) { 478 + case IPSET_COUNTER_NONE: 479 + return true; 480 + case IPSET_COUNTER_EQ: 481 + return counter == match; 482 + case IPSET_COUNTER_NE: 483 + return counter != match; 484 + case IPSET_COUNTER_LT: 485 + return counter < match; 486 + case IPSET_COUNTER_GT: 487 + return counter > match; 488 + } 489 + return false; 490 + } 491 + 492 + static void 493 + ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) 494 + { 495 + atomic64_add((long long)bytes, &(counter)->bytes); 496 + } 497 + 498 + static void 499 + ip_set_add_packets(u64 packets, struct ip_set_counter *counter) 500 + { 501 + atomic64_add((long long)packets, &(counter)->packets); 502 + } 503 + 504 + static void 505 + ip_set_update_counter(struct ip_set_counter *counter, 506 + const struct ip_set_ext *ext, u32 flags) 507 + { 508 + if (ext->packets != ULLONG_MAX && 509 + !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) { 510 + ip_set_add_bytes(ext->bytes, counter); 511 + ip_set_add_packets(ext->packets, counter); 512 + } 513 + } 514 + 515 + static void 516 + ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo, 517 + const struct ip_set_ext *ext, 518 + struct ip_set_ext *mext, u32 flags) 519 + { 520 + mext->skbinfo = *skbinfo; 521 + } 590 522 591 523 bool 592 524 ip_set_match_extensions(struct ip_set *set, const struct ip_set_ext *ext, ··· 672 506 * The set behind an index may change by swapping only, from userspace. 673 507 */ 674 508 675 - static inline void 509 + static void 676 510 __ip_set_get(struct ip_set *set) 677 511 { 678 512 write_lock_bh(&ip_set_ref_lock); ··· 680 514 write_unlock_bh(&ip_set_ref_lock); 681 515 } 682 516 683 - static inline void 517 + static void 684 518 __ip_set_put(struct ip_set *set) 685 519 { 686 520 write_lock_bh(&ip_set_ref_lock); ··· 692 526 /* set->ref can be swapped out by ip_set_swap, netlink events (like dump) need 693 527 * a separate reference counter 694 528 */ 695 - static inline void 529 + static void 696 530 __ip_set_put_netlink(struct ip_set *set) 697 531 { 698 532 write_lock_bh(&ip_set_ref_lock); ··· 707 541 * so it can't be destroyed (or changed) under our foot. 708 542 */ 709 543 710 - static inline struct ip_set * 544 + static struct ip_set * 711 545 ip_set_rcu_get(struct net *net, ip_set_id_t index) 712 546 { 713 547 struct ip_set *set; ··· 836 670 * 837 671 */ 838 672 839 - static inline void 673 + static void 840 674 __ip_set_put_byindex(struct ip_set_net *inst, ip_set_id_t index) 841 675 { 842 676 struct ip_set *set; ··· 1417 1251 1418 1252 #define DUMP_TYPE(arg) (((u32)(arg)) & 0x0000FFFF) 1419 1253 #define DUMP_FLAGS(arg) (((u32)(arg)) >> 16) 1254 + 1255 + int 1256 + ip_set_put_flags(struct sk_buff *skb, struct ip_set *set) 1257 + { 1258 + u32 cadt_flags = 0; 1259 + 1260 + if (SET_WITH_TIMEOUT(set)) 1261 + if (unlikely(nla_put_net32(skb, IPSET_ATTR_TIMEOUT, 1262 + htonl(set->timeout)))) 1263 + return -EMSGSIZE; 1264 + if (SET_WITH_COUNTER(set)) 1265 + cadt_flags |= IPSET_FLAG_WITH_COUNTERS; 1266 + if (SET_WITH_COMMENT(set)) 1267 + cadt_flags |= IPSET_FLAG_WITH_COMMENT; 1268 + if (SET_WITH_SKBINFO(set)) 1269 + cadt_flags |= IPSET_FLAG_WITH_SKBINFO; 1270 + if (SET_WITH_FORCEADD(set)) 1271 + cadt_flags |= IPSET_FLAG_WITH_FORCEADD; 1272 + 1273 + if (!cadt_flags) 1274 + return 0; 1275 + return nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(cadt_flags)); 1276 + } 1277 + EXPORT_SYMBOL_GPL(ip_set_put_flags); 1420 1278 1421 1279 static int 1422 1280 ip_set_dump_done(struct netlink_callback *cb)
-28
net/netfilter/ipset/ip_set_getport.c
··· 148 148 } 149 149 EXPORT_SYMBOL_GPL(ip_set_get_ip6_port); 150 150 #endif 151 - 152 - bool 153 - ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port) 154 - { 155 - bool ret; 156 - u8 proto; 157 - 158 - switch (pf) { 159 - case NFPROTO_IPV4: 160 - ret = ip_set_get_ip4_port(skb, src, port, &proto); 161 - break; 162 - case NFPROTO_IPV6: 163 - ret = ip_set_get_ip6_port(skb, src, port, &proto); 164 - break; 165 - default: 166 - return false; 167 - } 168 - if (!ret) 169 - return ret; 170 - switch (proto) { 171 - case IPPROTO_TCP: 172 - case IPPROTO_UDP: 173 - return true; 174 - default: 175 - return false; 176 - } 177 - } 178 - EXPORT_SYMBOL_GPL(ip_set_get_ip_port);
+2 -2
net/netfilter/ipset/ip_set_hash_gen.h
··· 39 39 #ifdef IP_SET_HASH_WITH_MULTI 40 40 #define AHASH_MAX(h) ((h)->ahash_max) 41 41 42 - static inline u8 42 + static u8 43 43 tune_ahash_max(u8 curr, u32 multi) 44 44 { 45 45 u32 n; ··· 909 909 return ret; 910 910 } 911 911 912 - static inline int 912 + static int 913 913 mtype_data_match(struct mtype_elem *data, const struct ip_set_ext *ext, 914 914 struct ip_set_ext *mext, struct ip_set *set, u32 flags) 915 915 {
+5 -5
net/netfilter/ipset/ip_set_hash_ip.c
··· 44 44 45 45 /* Common functions */ 46 46 47 - static inline bool 47 + static bool 48 48 hash_ip4_data_equal(const struct hash_ip4_elem *e1, 49 49 const struct hash_ip4_elem *e2, 50 50 u32 *multi) ··· 63 63 return true; 64 64 } 65 65 66 - static inline void 66 + static void 67 67 hash_ip4_data_next(struct hash_ip4_elem *next, const struct hash_ip4_elem *e) 68 68 { 69 69 next->ip = e->ip; ··· 171 171 172 172 /* Common functions */ 173 173 174 - static inline bool 174 + static bool 175 175 hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 176 176 const struct hash_ip6_elem *ip2, 177 177 u32 *multi) ··· 179 179 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6); 180 180 } 181 181 182 - static inline void 182 + static void 183 183 hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix) 184 184 { 185 185 ip6_netmask(ip, prefix); ··· 196 196 return true; 197 197 } 198 198 199 - static inline void 199 + static void 200 200 hash_ip6_data_next(struct hash_ip6_elem *next, const struct hash_ip6_elem *e) 201 201 { 202 202 }
+4 -4
net/netfilter/ipset/ip_set_hash_ipmac.c
··· 47 47 48 48 /* Common functions */ 49 49 50 - static inline bool 50 + static bool 51 51 hash_ipmac4_data_equal(const struct hash_ipmac4_elem *e1, 52 52 const struct hash_ipmac4_elem *e2, 53 53 u32 *multi) ··· 67 67 return true; 68 68 } 69 69 70 - static inline void 70 + static void 71 71 hash_ipmac4_data_next(struct hash_ipmac4_elem *next, 72 72 const struct hash_ipmac4_elem *e) 73 73 { ··· 154 154 155 155 /* Common functions */ 156 156 157 - static inline bool 157 + static bool 158 158 hash_ipmac6_data_equal(const struct hash_ipmac6_elem *e1, 159 159 const struct hash_ipmac6_elem *e2, 160 160 u32 *multi) ··· 175 175 return true; 176 176 } 177 177 178 - static inline void 178 + static void 179 179 hash_ipmac6_data_next(struct hash_ipmac6_elem *next, 180 180 const struct hash_ipmac6_elem *e) 181 181 {
+4 -4
net/netfilter/ipset/ip_set_hash_ipmark.c
··· 42 42 43 43 /* Common functions */ 44 44 45 - static inline bool 45 + static bool 46 46 hash_ipmark4_data_equal(const struct hash_ipmark4_elem *ip1, 47 47 const struct hash_ipmark4_elem *ip2, 48 48 u32 *multi) ··· 64 64 return true; 65 65 } 66 66 67 - static inline void 67 + static void 68 68 hash_ipmark4_data_next(struct hash_ipmark4_elem *next, 69 69 const struct hash_ipmark4_elem *d) 70 70 { ··· 165 165 166 166 /* Common functions */ 167 167 168 - static inline bool 168 + static bool 169 169 hash_ipmark6_data_equal(const struct hash_ipmark6_elem *ip1, 170 170 const struct hash_ipmark6_elem *ip2, 171 171 u32 *multi) ··· 187 187 return true; 188 188 } 189 189 190 - static inline void 190 + static void 191 191 hash_ipmark6_data_next(struct hash_ipmark6_elem *next, 192 192 const struct hash_ipmark6_elem *d) 193 193 {
+4 -4
net/netfilter/ipset/ip_set_hash_ipport.c
··· 47 47 48 48 /* Common functions */ 49 49 50 - static inline bool 50 + static bool 51 51 hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1, 52 52 const struct hash_ipport4_elem *ip2, 53 53 u32 *multi) ··· 71 71 return true; 72 72 } 73 73 74 - static inline void 74 + static void 75 75 hash_ipport4_data_next(struct hash_ipport4_elem *next, 76 76 const struct hash_ipport4_elem *d) 77 77 { ··· 202 202 203 203 /* Common functions */ 204 204 205 - static inline bool 205 + static bool 206 206 hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, 207 207 const struct hash_ipport6_elem *ip2, 208 208 u32 *multi) ··· 226 226 return true; 227 227 } 228 228 229 - static inline void 229 + static void 230 230 hash_ipport6_data_next(struct hash_ipport6_elem *next, 231 231 const struct hash_ipport6_elem *d) 232 232 {
+4 -4
net/netfilter/ipset/ip_set_hash_ipportip.c
··· 46 46 u8 padding; 47 47 }; 48 48 49 - static inline bool 49 + static bool 50 50 hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1, 51 51 const struct hash_ipportip4_elem *ip2, 52 52 u32 *multi) ··· 72 72 return true; 73 73 } 74 74 75 - static inline void 75 + static void 76 76 hash_ipportip4_data_next(struct hash_ipportip4_elem *next, 77 77 const struct hash_ipportip4_elem *d) 78 78 { ··· 210 210 211 211 /* Common functions */ 212 212 213 - static inline bool 213 + static bool 214 214 hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, 215 215 const struct hash_ipportip6_elem *ip2, 216 216 u32 *multi) ··· 236 236 return true; 237 237 } 238 238 239 - static inline void 239 + static void 240 240 hash_ipportip6_data_next(struct hash_ipportip6_elem *next, 241 241 const struct hash_ipportip6_elem *d) 242 242 {
+12 -12
net/netfilter/ipset/ip_set_hash_ipportnet.c
··· 59 59 60 60 /* Common functions */ 61 61 62 - static inline bool 62 + static bool 63 63 hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, 64 64 const struct hash_ipportnet4_elem *ip2, 65 65 u32 *multi) ··· 71 71 ip1->proto == ip2->proto; 72 72 } 73 73 74 - static inline int 74 + static int 75 75 hash_ipportnet4_do_data_match(const struct hash_ipportnet4_elem *elem) 76 76 { 77 77 return elem->nomatch ? -ENOTEMPTY : 1; 78 78 } 79 79 80 - static inline void 80 + static void 81 81 hash_ipportnet4_data_set_flags(struct hash_ipportnet4_elem *elem, u32 flags) 82 82 { 83 83 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 84 84 } 85 85 86 - static inline void 86 + static void 87 87 hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *elem, u8 *flags) 88 88 { 89 89 swap(*flags, elem->nomatch); 90 90 } 91 91 92 - static inline void 92 + static void 93 93 hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr) 94 94 { 95 95 elem->ip2 &= ip_set_netmask(cidr); ··· 116 116 return true; 117 117 } 118 118 119 - static inline void 119 + static void 120 120 hash_ipportnet4_data_next(struct hash_ipportnet4_elem *next, 121 121 const struct hash_ipportnet4_elem *d) 122 122 { ··· 308 308 309 309 /* Common functions */ 310 310 311 - static inline bool 311 + static bool 312 312 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, 313 313 const struct hash_ipportnet6_elem *ip2, 314 314 u32 *multi) ··· 320 320 ip1->proto == ip2->proto; 321 321 } 322 322 323 - static inline int 323 + static int 324 324 hash_ipportnet6_do_data_match(const struct hash_ipportnet6_elem *elem) 325 325 { 326 326 return elem->nomatch ? -ENOTEMPTY : 1; 327 327 } 328 328 329 - static inline void 329 + static void 330 330 hash_ipportnet6_data_set_flags(struct hash_ipportnet6_elem *elem, u32 flags) 331 331 { 332 332 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 333 333 } 334 334 335 - static inline void 335 + static void 336 336 hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *elem, u8 *flags) 337 337 { 338 338 swap(*flags, elem->nomatch); 339 339 } 340 340 341 - static inline void 341 + static void 342 342 hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr) 343 343 { 344 344 ip6_netmask(&elem->ip2, cidr); ··· 365 365 return true; 366 366 } 367 367 368 - static inline void 368 + static void 369 369 hash_ipportnet6_data_next(struct hash_ipportnet6_elem *next, 370 370 const struct hash_ipportnet6_elem *d) 371 371 {
+3 -3
net/netfilter/ipset/ip_set_hash_mac.c
··· 37 37 38 38 /* Common functions */ 39 39 40 - static inline bool 40 + static bool 41 41 hash_mac4_data_equal(const struct hash_mac4_elem *e1, 42 42 const struct hash_mac4_elem *e2, 43 43 u32 *multi) ··· 45 45 return ether_addr_equal(e1->ether, e2->ether); 46 46 } 47 47 48 - static inline bool 48 + static bool 49 49 hash_mac4_data_list(struct sk_buff *skb, const struct hash_mac4_elem *e) 50 50 { 51 51 if (nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, e->ether)) ··· 56 56 return true; 57 57 } 58 58 59 - static inline void 59 + static void 60 60 hash_mac4_data_next(struct hash_mac4_elem *next, 61 61 const struct hash_mac4_elem *e) 62 62 {
+12 -12
net/netfilter/ipset/ip_set_hash_net.c
··· 47 47 48 48 /* Common functions */ 49 49 50 - static inline bool 50 + static bool 51 51 hash_net4_data_equal(const struct hash_net4_elem *ip1, 52 52 const struct hash_net4_elem *ip2, 53 53 u32 *multi) ··· 56 56 ip1->cidr == ip2->cidr; 57 57 } 58 58 59 - static inline int 59 + static int 60 60 hash_net4_do_data_match(const struct hash_net4_elem *elem) 61 61 { 62 62 return elem->nomatch ? -ENOTEMPTY : 1; 63 63 } 64 64 65 - static inline void 65 + static void 66 66 hash_net4_data_set_flags(struct hash_net4_elem *elem, u32 flags) 67 67 { 68 68 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 69 69 } 70 70 71 - static inline void 71 + static void 72 72 hash_net4_data_reset_flags(struct hash_net4_elem *elem, u8 *flags) 73 73 { 74 74 swap(*flags, elem->nomatch); 75 75 } 76 76 77 - static inline void 77 + static void 78 78 hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr) 79 79 { 80 80 elem->ip &= ip_set_netmask(cidr); ··· 97 97 return true; 98 98 } 99 99 100 - static inline void 100 + static void 101 101 hash_net4_data_next(struct hash_net4_elem *next, 102 102 const struct hash_net4_elem *d) 103 103 { ··· 212 212 213 213 /* Common functions */ 214 214 215 - static inline bool 215 + static bool 216 216 hash_net6_data_equal(const struct hash_net6_elem *ip1, 217 217 const struct hash_net6_elem *ip2, 218 218 u32 *multi) ··· 221 221 ip1->cidr == ip2->cidr; 222 222 } 223 223 224 - static inline int 224 + static int 225 225 hash_net6_do_data_match(const struct hash_net6_elem *elem) 226 226 { 227 227 return elem->nomatch ? -ENOTEMPTY : 1; 228 228 } 229 229 230 - static inline void 230 + static void 231 231 hash_net6_data_set_flags(struct hash_net6_elem *elem, u32 flags) 232 232 { 233 233 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 234 234 } 235 235 236 - static inline void 236 + static void 237 237 hash_net6_data_reset_flags(struct hash_net6_elem *elem, u8 *flags) 238 238 { 239 239 swap(*flags, elem->nomatch); 240 240 } 241 241 242 - static inline void 242 + static void 243 243 hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr) 244 244 { 245 245 ip6_netmask(&elem->ip, cidr); ··· 262 262 return true; 263 263 } 264 264 265 - static inline void 265 + static void 266 266 hash_net6_data_next(struct hash_net6_elem *next, 267 267 const struct hash_net6_elem *d) 268 268 {
+12 -12
net/netfilter/ipset/ip_set_hash_netiface.c
··· 62 62 63 63 /* Common functions */ 64 64 65 - static inline bool 65 + static bool 66 66 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, 67 67 const struct hash_netiface4_elem *ip2, 68 68 u32 *multi) ··· 74 74 strcmp(ip1->iface, ip2->iface) == 0; 75 75 } 76 76 77 - static inline int 77 + static int 78 78 hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem) 79 79 { 80 80 return elem->nomatch ? -ENOTEMPTY : 1; 81 81 } 82 82 83 - static inline void 83 + static void 84 84 hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags) 85 85 { 86 86 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 87 87 } 88 88 89 - static inline void 89 + static void 90 90 hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags) 91 91 { 92 92 swap(*flags, elem->nomatch); 93 93 } 94 94 95 - static inline void 95 + static void 96 96 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr) 97 97 { 98 98 elem->ip &= ip_set_netmask(cidr); ··· 119 119 return true; 120 120 } 121 121 122 - static inline void 122 + static void 123 123 hash_netiface4_data_next(struct hash_netiface4_elem *next, 124 124 const struct hash_netiface4_elem *d) 125 125 { ··· 285 285 286 286 /* Common functions */ 287 287 288 - static inline bool 288 + static bool 289 289 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, 290 290 const struct hash_netiface6_elem *ip2, 291 291 u32 *multi) ··· 297 297 strcmp(ip1->iface, ip2->iface) == 0; 298 298 } 299 299 300 - static inline int 300 + static int 301 301 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem) 302 302 { 303 303 return elem->nomatch ? -ENOTEMPTY : 1; 304 304 } 305 305 306 - static inline void 306 + static void 307 307 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags) 308 308 { 309 309 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 310 310 } 311 311 312 - static inline void 312 + static void 313 313 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags) 314 314 { 315 315 swap(*flags, elem->nomatch); 316 316 } 317 317 318 - static inline void 318 + static void 319 319 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr) 320 320 { 321 321 ip6_netmask(&elem->ip, cidr); ··· 342 342 return true; 343 343 } 344 344 345 - static inline void 345 + static void 346 346 hash_netiface6_data_next(struct hash_netiface6_elem *next, 347 347 const struct hash_netiface6_elem *d) 348 348 {
+14 -14
net/netfilter/ipset/ip_set_hash_netnet.c
··· 52 52 53 53 /* Common functions */ 54 54 55 - static inline bool 55 + static bool 56 56 hash_netnet4_data_equal(const struct hash_netnet4_elem *ip1, 57 57 const struct hash_netnet4_elem *ip2, 58 58 u32 *multi) ··· 61 61 ip1->ccmp == ip2->ccmp; 62 62 } 63 63 64 - static inline int 64 + static int 65 65 hash_netnet4_do_data_match(const struct hash_netnet4_elem *elem) 66 66 { 67 67 return elem->nomatch ? -ENOTEMPTY : 1; 68 68 } 69 69 70 - static inline void 70 + static void 71 71 hash_netnet4_data_set_flags(struct hash_netnet4_elem *elem, u32 flags) 72 72 { 73 73 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 74 74 } 75 75 76 - static inline void 76 + static void 77 77 hash_netnet4_data_reset_flags(struct hash_netnet4_elem *elem, u8 *flags) 78 78 { 79 79 swap(*flags, elem->nomatch); 80 80 } 81 81 82 - static inline void 82 + static void 83 83 hash_netnet4_data_reset_elem(struct hash_netnet4_elem *elem, 84 84 struct hash_netnet4_elem *orig) 85 85 { 86 86 elem->ip[1] = orig->ip[1]; 87 87 } 88 88 89 - static inline void 89 + static void 90 90 hash_netnet4_data_netmask(struct hash_netnet4_elem *elem, u8 cidr, bool inner) 91 91 { 92 92 if (inner) { ··· 117 117 return true; 118 118 } 119 119 120 - static inline void 120 + static void 121 121 hash_netnet4_data_next(struct hash_netnet4_elem *next, 122 122 const struct hash_netnet4_elem *d) 123 123 { ··· 282 282 283 283 /* Common functions */ 284 284 285 - static inline bool 285 + static bool 286 286 hash_netnet6_data_equal(const struct hash_netnet6_elem *ip1, 287 287 const struct hash_netnet6_elem *ip2, 288 288 u32 *multi) ··· 292 292 ip1->ccmp == ip2->ccmp; 293 293 } 294 294 295 - static inline int 295 + static int 296 296 hash_netnet6_do_data_match(const struct hash_netnet6_elem *elem) 297 297 { 298 298 return elem->nomatch ? -ENOTEMPTY : 1; 299 299 } 300 300 301 - static inline void 301 + static void 302 302 hash_netnet6_data_set_flags(struct hash_netnet6_elem *elem, u32 flags) 303 303 { 304 304 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 305 305 } 306 306 307 - static inline void 307 + static void 308 308 hash_netnet6_data_reset_flags(struct hash_netnet6_elem *elem, u8 *flags) 309 309 { 310 310 swap(*flags, elem->nomatch); 311 311 } 312 312 313 - static inline void 313 + static void 314 314 hash_netnet6_data_reset_elem(struct hash_netnet6_elem *elem, 315 315 struct hash_netnet6_elem *orig) 316 316 { 317 317 elem->ip[1] = orig->ip[1]; 318 318 } 319 319 320 - static inline void 320 + static void 321 321 hash_netnet6_data_netmask(struct hash_netnet6_elem *elem, u8 cidr, bool inner) 322 322 { 323 323 if (inner) { ··· 348 348 return true; 349 349 } 350 350 351 - static inline void 351 + static void 352 352 hash_netnet6_data_next(struct hash_netnet6_elem *next, 353 353 const struct hash_netnet6_elem *d) 354 354 {
+12 -12
net/netfilter/ipset/ip_set_hash_netport.c
··· 57 57 58 58 /* Common functions */ 59 59 60 - static inline bool 60 + static bool 61 61 hash_netport4_data_equal(const struct hash_netport4_elem *ip1, 62 62 const struct hash_netport4_elem *ip2, 63 63 u32 *multi) ··· 68 68 ip1->cidr == ip2->cidr; 69 69 } 70 70 71 - static inline int 71 + static int 72 72 hash_netport4_do_data_match(const struct hash_netport4_elem *elem) 73 73 { 74 74 return elem->nomatch ? -ENOTEMPTY : 1; 75 75 } 76 76 77 - static inline void 77 + static void 78 78 hash_netport4_data_set_flags(struct hash_netport4_elem *elem, u32 flags) 79 79 { 80 80 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 81 81 } 82 82 83 - static inline void 83 + static void 84 84 hash_netport4_data_reset_flags(struct hash_netport4_elem *elem, u8 *flags) 85 85 { 86 86 swap(*flags, elem->nomatch); 87 87 } 88 88 89 - static inline void 89 + static void 90 90 hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr) 91 91 { 92 92 elem->ip &= ip_set_netmask(cidr); ··· 112 112 return true; 113 113 } 114 114 115 - static inline void 115 + static void 116 116 hash_netport4_data_next(struct hash_netport4_elem *next, 117 117 const struct hash_netport4_elem *d) 118 118 { ··· 270 270 271 271 /* Common functions */ 272 272 273 - static inline bool 273 + static bool 274 274 hash_netport6_data_equal(const struct hash_netport6_elem *ip1, 275 275 const struct hash_netport6_elem *ip2, 276 276 u32 *multi) ··· 281 281 ip1->cidr == ip2->cidr; 282 282 } 283 283 284 - static inline int 284 + static int 285 285 hash_netport6_do_data_match(const struct hash_netport6_elem *elem) 286 286 { 287 287 return elem->nomatch ? -ENOTEMPTY : 1; 288 288 } 289 289 290 - static inline void 290 + static void 291 291 hash_netport6_data_set_flags(struct hash_netport6_elem *elem, u32 flags) 292 292 { 293 293 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 294 294 } 295 295 296 - static inline void 296 + static void 297 297 hash_netport6_data_reset_flags(struct hash_netport6_elem *elem, u8 *flags) 298 298 { 299 299 swap(*flags, elem->nomatch); 300 300 } 301 301 302 - static inline void 302 + static void 303 303 hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr) 304 304 { 305 305 ip6_netmask(&elem->ip, cidr); ··· 325 325 return true; 326 326 } 327 327 328 - static inline void 328 + static void 329 329 hash_netport6_data_next(struct hash_netport6_elem *next, 330 330 const struct hash_netport6_elem *d) 331 331 {
+14 -14
net/netfilter/ipset/ip_set_hash_netportnet.c
··· 56 56 57 57 /* Common functions */ 58 58 59 - static inline bool 59 + static bool 60 60 hash_netportnet4_data_equal(const struct hash_netportnet4_elem *ip1, 61 61 const struct hash_netportnet4_elem *ip2, 62 62 u32 *multi) ··· 67 67 ip1->proto == ip2->proto; 68 68 } 69 69 70 - static inline int 70 + static int 71 71 hash_netportnet4_do_data_match(const struct hash_netportnet4_elem *elem) 72 72 { 73 73 return elem->nomatch ? -ENOTEMPTY : 1; 74 74 } 75 75 76 - static inline void 76 + static void 77 77 hash_netportnet4_data_set_flags(struct hash_netportnet4_elem *elem, u32 flags) 78 78 { 79 79 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 80 80 } 81 81 82 - static inline void 82 + static void 83 83 hash_netportnet4_data_reset_flags(struct hash_netportnet4_elem *elem, u8 *flags) 84 84 { 85 85 swap(*flags, elem->nomatch); 86 86 } 87 87 88 - static inline void 88 + static void 89 89 hash_netportnet4_data_reset_elem(struct hash_netportnet4_elem *elem, 90 90 struct hash_netportnet4_elem *orig) 91 91 { 92 92 elem->ip[1] = orig->ip[1]; 93 93 } 94 94 95 - static inline void 95 + static void 96 96 hash_netportnet4_data_netmask(struct hash_netportnet4_elem *elem, 97 97 u8 cidr, bool inner) 98 98 { ··· 126 126 return true; 127 127 } 128 128 129 - static inline void 129 + static void 130 130 hash_netportnet4_data_next(struct hash_netportnet4_elem *next, 131 131 const struct hash_netportnet4_elem *d) 132 132 { ··· 331 331 332 332 /* Common functions */ 333 333 334 - static inline bool 334 + static bool 335 335 hash_netportnet6_data_equal(const struct hash_netportnet6_elem *ip1, 336 336 const struct hash_netportnet6_elem *ip2, 337 337 u32 *multi) ··· 343 343 ip1->proto == ip2->proto; 344 344 } 345 345 346 - static inline int 346 + static int 347 347 hash_netportnet6_do_data_match(const struct hash_netportnet6_elem *elem) 348 348 { 349 349 return elem->nomatch ? -ENOTEMPTY : 1; 350 350 } 351 351 352 - static inline void 352 + static void 353 353 hash_netportnet6_data_set_flags(struct hash_netportnet6_elem *elem, u32 flags) 354 354 { 355 355 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 356 356 } 357 357 358 - static inline void 358 + static void 359 359 hash_netportnet6_data_reset_flags(struct hash_netportnet6_elem *elem, u8 *flags) 360 360 { 361 361 swap(*flags, elem->nomatch); 362 362 } 363 363 364 - static inline void 364 + static void 365 365 hash_netportnet6_data_reset_elem(struct hash_netportnet6_elem *elem, 366 366 struct hash_netportnet6_elem *orig) 367 367 { 368 368 elem->ip[1] = orig->ip[1]; 369 369 } 370 370 371 - static inline void 371 + static void 372 372 hash_netportnet6_data_netmask(struct hash_netportnet6_elem *elem, 373 373 u8 cidr, bool inner) 374 374 { ··· 402 402 return true; 403 403 } 404 404 405 - static inline void 405 + static void 406 406 hash_netportnet6_data_next(struct hash_netportnet6_elem *next, 407 407 const struct hash_netportnet6_elem *d) 408 408 {
+2 -2
net/netfilter/ipset/ip_set_list_set.c
··· 149 149 kfree(e); 150 150 } 151 151 152 - static inline void 152 + static void 153 153 list_set_del(struct ip_set *set, struct set_elem *e) 154 154 { 155 155 struct list_set *map = set->data; ··· 160 160 call_rcu(&e->rcu, __list_set_del_rcu); 161 161 } 162 162 163 - static inline void 163 + static void 164 164 list_set_replace(struct ip_set *set, struct set_elem *e, struct set_elem *old) 165 165 { 166 166 struct list_set *map = set->data;
+27 -18
net/netfilter/ipvs/ip_vs_core.c
··· 2402 2402 return -ENOMEM; 2403 2403 } 2404 2404 2405 - static void __net_exit __ip_vs_cleanup(struct net *net) 2405 + static void __net_exit __ip_vs_cleanup_batch(struct list_head *net_list) 2406 2406 { 2407 - struct netns_ipvs *ipvs = net_ipvs(net); 2407 + struct netns_ipvs *ipvs; 2408 + struct net *net; 2408 2409 2409 - ip_vs_service_net_cleanup(ipvs); /* ip_vs_flush() with locks */ 2410 - ip_vs_conn_net_cleanup(ipvs); 2411 - ip_vs_app_net_cleanup(ipvs); 2412 - ip_vs_protocol_net_cleanup(ipvs); 2413 - ip_vs_control_net_cleanup(ipvs); 2414 - ip_vs_estimator_net_cleanup(ipvs); 2415 - IP_VS_DBG(2, "ipvs netns %d released\n", ipvs->gen); 2416 - net->ipvs = NULL; 2410 + ip_vs_service_nets_cleanup(net_list); /* ip_vs_flush() with locks */ 2411 + list_for_each_entry(net, net_list, exit_list) { 2412 + ipvs = net_ipvs(net); 2413 + ip_vs_conn_net_cleanup(ipvs); 2414 + ip_vs_app_net_cleanup(ipvs); 2415 + ip_vs_protocol_net_cleanup(ipvs); 2416 + ip_vs_control_net_cleanup(ipvs); 2417 + ip_vs_estimator_net_cleanup(ipvs); 2418 + IP_VS_DBG(2, "ipvs netns %d released\n", ipvs->gen); 2419 + net->ipvs = NULL; 2420 + } 2417 2421 } 2418 2422 2419 2423 static int __net_init __ip_vs_dev_init(struct net *net) ··· 2433 2429 return ret; 2434 2430 } 2435 2431 2436 - static void __net_exit __ip_vs_dev_cleanup(struct net *net) 2432 + static void __net_exit __ip_vs_dev_cleanup_batch(struct list_head *net_list) 2437 2433 { 2438 - struct netns_ipvs *ipvs = net_ipvs(net); 2434 + struct netns_ipvs *ipvs; 2435 + struct net *net; 2436 + 2439 2437 EnterFunction(2); 2440 - nf_unregister_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); 2441 - ipvs->enable = 0; /* Disable packet reception */ 2442 - smp_wmb(); 2443 - ip_vs_sync_net_cleanup(ipvs); 2438 + list_for_each_entry(net, net_list, exit_list) { 2439 + ipvs = net_ipvs(net); 2440 + nf_unregister_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); 2441 + ipvs->enable = 0; /* Disable packet reception */ 2442 + smp_wmb(); 2443 + ip_vs_sync_net_cleanup(ipvs); 2444 + } 2444 2445 LeaveFunction(2); 2445 2446 } 2446 2447 2447 2448 static struct pernet_operations ipvs_core_ops = { 2448 2449 .init = __ip_vs_init, 2449 - .exit = __ip_vs_cleanup, 2450 + .exit_batch = __ip_vs_cleanup_batch, 2450 2451 .id = &ip_vs_net_id, 2451 2452 .size = sizeof(struct netns_ipvs), 2452 2453 }; 2453 2454 2454 2455 static struct pernet_operations ipvs_core_dev_ops = { 2455 2456 .init = __ip_vs_dev_init, 2456 - .exit = __ip_vs_dev_cleanup, 2457 + .exit_batch = __ip_vs_dev_cleanup_batch, 2457 2458 }; 2458 2459 2459 2460 /*
+9 -3
net/netfilter/ipvs/ip_vs_ctl.c
··· 1607 1607 1608 1608 /* 1609 1609 * Delete service by {netns} in the service table. 1610 - * Called by __ip_vs_cleanup() 1610 + * Called by __ip_vs_batch_cleanup() 1611 1611 */ 1612 - void ip_vs_service_net_cleanup(struct netns_ipvs *ipvs) 1612 + void ip_vs_service_nets_cleanup(struct list_head *net_list) 1613 1613 { 1614 + struct netns_ipvs *ipvs; 1615 + struct net *net; 1616 + 1614 1617 EnterFunction(2); 1615 1618 /* Check for "full" addressed entries */ 1616 1619 mutex_lock(&__ip_vs_mutex); 1617 - ip_vs_flush(ipvs, true); 1620 + list_for_each_entry(net, net_list, exit_list) { 1621 + ipvs = net_ipvs(net); 1622 + ip_vs_flush(ipvs, true); 1623 + } 1618 1624 mutex_unlock(&__ip_vs_mutex); 1619 1625 LeaveFunction(2); 1620 1626 }
+6 -12
net/netfilter/ipvs/ip_vs_xmit.c
··· 407 407 goto err_put; 408 408 409 409 skb_dst_drop(skb); 410 - if (noref) { 411 - if (!local) 412 - skb_dst_set_noref(skb, &rt->dst); 413 - else 414 - skb_dst_set(skb, dst_clone(&rt->dst)); 415 - } else 410 + if (noref) 411 + skb_dst_set_noref(skb, &rt->dst); 412 + else 416 413 skb_dst_set(skb, &rt->dst); 417 414 418 415 return local; ··· 571 574 goto err_put; 572 575 573 576 skb_dst_drop(skb); 574 - if (noref) { 575 - if (!local) 576 - skb_dst_set_noref(skb, &rt->dst); 577 - else 578 - skb_dst_set(skb, dst_clone(&rt->dst)); 579 - } else 577 + if (noref) 578 + skb_dst_set_noref(skb, &rt->dst); 579 + else 580 580 skb_dst_set(skb, &rt->dst); 581 581 582 582 return local;
-2
net/netfilter/nf_conntrack_core.c
··· 573 573 void nf_ct_tmpl_free(struct nf_conn *tmpl) 574 574 { 575 575 nf_ct_ext_destroy(tmpl); 576 - nf_ct_ext_free(tmpl); 577 576 578 577 if (ARCH_KMALLOC_MINALIGN <= NFCT_INFOMASK) 579 578 kfree((char *)tmpl - tmpl->proto.tmpl_padto); ··· 1416 1417 WARN_ON(atomic_read(&ct->ct_general.use) != 0); 1417 1418 1418 1419 nf_ct_ext_destroy(ct); 1419 - nf_ct_ext_free(ct); 1420 1420 kmem_cache_free(nf_conntrack_cachep, ct); 1421 1421 smp_mb__before_atomic(); 1422 1422 atomic_dec(&net->ct.count);
+18 -5
net/netfilter/nf_conntrack_ecache.c
··· 30 30 static DEFINE_MUTEX(nf_ct_ecache_mutex); 31 31 32 32 #define ECACHE_RETRY_WAIT (HZ/10) 33 + #define ECACHE_STACK_ALLOC (256 / sizeof(void *)) 33 34 34 35 enum retry_state { 35 36 STATE_CONGESTED, ··· 40 39 41 40 static enum retry_state ecache_work_evict_list(struct ct_pcpu *pcpu) 42 41 { 43 - struct nf_conn *refs[16]; 42 + struct nf_conn *refs[ECACHE_STACK_ALLOC]; 43 + enum retry_state ret = STATE_DONE; 44 44 struct nf_conntrack_tuple_hash *h; 45 45 struct hlist_nulls_node *n; 46 46 unsigned int evicted = 0; 47 - enum retry_state ret = STATE_DONE; 48 47 49 48 spin_lock(&pcpu->lock); 50 49 ··· 55 54 if (!nf_ct_is_confirmed(ct)) 56 55 continue; 57 56 57 + /* This ecache access is safe because the ct is on the 58 + * pcpu dying list and we hold the spinlock -- the entry 59 + * cannot be free'd until after the lock is released. 60 + * 61 + * This is true even if ct has a refcount of 0: the 62 + * cpu that is about to free the entry must remove it 63 + * from the dying list and needs the lock to do so. 64 + */ 58 65 e = nf_ct_ecache_find(ct); 59 66 if (!e || e->state != NFCT_ECACHE_DESTROY_FAIL) 60 67 continue; 61 68 69 + /* ct is in NFCT_ECACHE_DESTROY_FAIL state, this means 70 + * the worker owns this entry: the ct will remain valid 71 + * until the worker puts its ct reference. 72 + */ 62 73 if (nf_conntrack_event(IPCT_DESTROY, ct)) { 63 74 ret = STATE_CONGESTED; 64 75 break; ··· 202 189 if (notify == NULL) 203 190 goto out_unlock; 204 191 192 + if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct)) 193 + goto out_unlock; 194 + 205 195 e = nf_ct_ecache_find(ct); 206 196 if (e == NULL) 207 197 goto out_unlock; 208 198 209 199 events = xchg(&e->cache, 0); 210 - 211 - if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct)) 212 - goto out_unlock; 213 200 214 201 /* We make a copy of the missed event cache without taking 215 202 * the lock, thus we may send missed events twice. However,
+10 -11
net/netfilter/nf_conntrack_extend.c
··· 34 34 t->destroy(ct); 35 35 rcu_read_unlock(); 36 36 } 37 + 38 + kfree(ct->ext); 37 39 } 38 40 EXPORT_SYMBOL(nf_ct_ext_destroy); 39 41 40 42 void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) 41 43 { 42 44 unsigned int newlen, newoff, oldlen, alloc; 43 - struct nf_ct_ext *old, *new; 44 45 struct nf_ct_ext_type *t; 46 + struct nf_ct_ext *new; 45 47 46 48 /* Conntrack must not be confirmed to avoid races on reallocation. */ 47 49 WARN_ON(nf_ct_is_confirmed(ct)); 48 50 49 - old = ct->ext; 50 51 51 - if (old) { 52 + if (ct->ext) { 53 + const struct nf_ct_ext *old = ct->ext; 54 + 52 55 if (__nf_ct_ext_exist(old, id)) 53 56 return NULL; 54 57 oldlen = old->len; ··· 71 68 rcu_read_unlock(); 72 69 73 70 alloc = max(newlen, NF_CT_EXT_PREALLOC); 74 - kmemleak_not_leak(old); 75 - new = __krealloc(old, alloc, gfp); 71 + new = krealloc(ct->ext, alloc, gfp); 76 72 if (!new) 77 73 return NULL; 78 74 79 - if (!old) { 75 + if (!ct->ext) 80 76 memset(new->offset, 0, sizeof(new->offset)); 81 - ct->ext = new; 82 - } else if (new != old) { 83 - kfree_rcu(old, rcu); 84 - rcu_assign_pointer(ct->ext, new); 85 - } 86 77 87 78 new->offset[id] = newoff; 88 79 new->len = newlen; 89 80 memset((void *)new + newoff, 0, newlen - newoff); 81 + 82 + ct->ext = new; 90 83 return (void *)new + newoff; 91 84 } 92 85 EXPORT_SYMBOL(nf_ct_ext_add);
+50 -26
net/netfilter/nf_conntrack_netlink.c
··· 506 506 return -1; 507 507 } 508 508 509 + /* all these functions access ct->ext. Caller must either hold a reference 510 + * on ct or prevent its deletion by holding either the bucket spinlock or 511 + * pcpu dying list lock. 512 + */ 513 + static int ctnetlink_dump_extinfo(struct sk_buff *skb, 514 + struct nf_conn *ct, u32 type) 515 + { 516 + if (ctnetlink_dump_acct(skb, ct, type) < 0 || 517 + ctnetlink_dump_timestamp(skb, ct) < 0 || 518 + ctnetlink_dump_helpinfo(skb, ct) < 0 || 519 + ctnetlink_dump_labels(skb, ct) < 0 || 520 + ctnetlink_dump_ct_seq_adj(skb, ct) < 0 || 521 + ctnetlink_dump_ct_synproxy(skb, ct) < 0) 522 + return -1; 523 + 524 + return 0; 525 + } 526 + 527 + static int ctnetlink_dump_info(struct sk_buff *skb, struct nf_conn *ct) 528 + { 529 + if (ctnetlink_dump_status(skb, ct) < 0 || 530 + ctnetlink_dump_mark(skb, ct) < 0 || 531 + ctnetlink_dump_secctx(skb, ct) < 0 || 532 + ctnetlink_dump_id(skb, ct) < 0 || 533 + ctnetlink_dump_use(skb, ct) < 0 || 534 + ctnetlink_dump_master(skb, ct) < 0) 535 + return -1; 536 + 537 + if (!test_bit(IPS_OFFLOAD_BIT, &ct->status) && 538 + (ctnetlink_dump_timeout(skb, ct) < 0 || 539 + ctnetlink_dump_protoinfo(skb, ct) < 0)) 540 + return -1; 541 + 542 + return 0; 543 + } 544 + 509 545 static int 510 546 ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, 511 - struct nf_conn *ct) 547 + struct nf_conn *ct, bool extinfo) 512 548 { 513 549 const struct nf_conntrack_zone *zone; 514 550 struct nlmsghdr *nlh; ··· 588 552 NF_CT_DEFAULT_ZONE_DIR) < 0) 589 553 goto nla_put_failure; 590 554 591 - if (ctnetlink_dump_status(skb, ct) < 0 || 592 - ctnetlink_dump_acct(skb, ct, type) < 0 || 593 - ctnetlink_dump_timestamp(skb, ct) < 0 || 594 - ctnetlink_dump_helpinfo(skb, ct) < 0 || 595 - ctnetlink_dump_mark(skb, ct) < 0 || 596 - ctnetlink_dump_secctx(skb, ct) < 0 || 597 - ctnetlink_dump_labels(skb, ct) < 0 || 598 - ctnetlink_dump_id(skb, ct) < 0 || 599 - ctnetlink_dump_use(skb, ct) < 0 || 600 - ctnetlink_dump_master(skb, ct) < 0 || 601 - ctnetlink_dump_ct_seq_adj(skb, ct) < 0 || 602 - ctnetlink_dump_ct_synproxy(skb, ct) < 0) 555 + if (ctnetlink_dump_info(skb, ct) < 0) 603 556 goto nla_put_failure; 604 - 605 - if (!test_bit(IPS_OFFLOAD_BIT, &ct->status) && 606 - (ctnetlink_dump_timeout(skb, ct) < 0 || 607 - ctnetlink_dump_protoinfo(skb, ct) < 0)) 557 + if (extinfo && ctnetlink_dump_extinfo(skb, ct, type) < 0) 608 558 goto nla_put_failure; 609 559 610 560 nlmsg_end(skb, nlh); ··· 975 953 if (!ctnetlink_filter_match(ct, cb->data)) 976 954 continue; 977 955 978 - rcu_read_lock(); 979 956 res = 980 957 ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid, 981 958 cb->nlh->nlmsg_seq, 982 959 NFNL_MSG_TYPE(cb->nlh->nlmsg_type), 983 - ct); 984 - rcu_read_unlock(); 960 + ct, true); 985 961 if (res < 0) { 986 962 nf_conntrack_get(&ct->ct_general); 987 963 cb->args[1] = (unsigned long)ct; ··· 1384 1364 return -ENOMEM; 1385 1365 } 1386 1366 1387 - rcu_read_lock(); 1388 1367 err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 1389 - NFNL_MSG_TYPE(nlh->nlmsg_type), ct); 1390 - rcu_read_unlock(); 1368 + NFNL_MSG_TYPE(nlh->nlmsg_type), ct, true); 1391 1369 nf_ct_put(ct); 1392 1370 if (err <= 0) 1393 1371 goto free; ··· 1447 1429 continue; 1448 1430 cb->args[1] = 0; 1449 1431 } 1450 - rcu_read_lock(); 1432 + 1433 + /* We can't dump extension info for the unconfirmed 1434 + * list because unconfirmed conntracks can have 1435 + * ct->ext reallocated (and thus freed). 1436 + * 1437 + * In the dying list case ct->ext can't be free'd 1438 + * until after we drop pcpu->lock. 1439 + */ 1451 1440 res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid, 1452 1441 cb->nlh->nlmsg_seq, 1453 1442 NFNL_MSG_TYPE(cb->nlh->nlmsg_type), 1454 - ct); 1455 - rcu_read_unlock(); 1443 + ct, dying ? true : false); 1456 1444 if (res < 0) { 1457 1445 if (!atomic_inc_not_zero(&ct->ct_general.use)) 1458 1446 continue;
+403 -169
net/netfilter/nf_tables_api.c
··· 151 151 } 152 152 } 153 153 154 + static int nft_netdev_register_hooks(struct net *net, 155 + struct list_head *hook_list) 156 + { 157 + struct nft_hook *hook; 158 + int err, j; 159 + 160 + j = 0; 161 + list_for_each_entry(hook, hook_list, list) { 162 + err = nf_register_net_hook(net, &hook->ops); 163 + if (err < 0) 164 + goto err_register; 165 + 166 + j++; 167 + } 168 + return 0; 169 + 170 + err_register: 171 + list_for_each_entry(hook, hook_list, list) { 172 + if (j-- <= 0) 173 + break; 174 + 175 + nf_unregister_net_hook(net, &hook->ops); 176 + } 177 + return err; 178 + } 179 + 180 + static void nft_netdev_unregister_hooks(struct net *net, 181 + struct list_head *hook_list) 182 + { 183 + struct nft_hook *hook; 184 + 185 + list_for_each_entry(hook, hook_list, list) 186 + nf_unregister_net_hook(net, &hook->ops); 187 + } 188 + 189 + static int nft_register_basechain_hooks(struct net *net, int family, 190 + struct nft_base_chain *basechain) 191 + { 192 + if (family == NFPROTO_NETDEV) 193 + return nft_netdev_register_hooks(net, &basechain->hook_list); 194 + 195 + return nf_register_net_hook(net, &basechain->ops); 196 + } 197 + 198 + static void nft_unregister_basechain_hooks(struct net *net, int family, 199 + struct nft_base_chain *basechain) 200 + { 201 + if (family == NFPROTO_NETDEV) 202 + nft_netdev_unregister_hooks(net, &basechain->hook_list); 203 + else 204 + nf_unregister_net_hook(net, &basechain->ops); 205 + } 206 + 154 207 static int nf_tables_register_hook(struct net *net, 155 208 const struct nft_table *table, 156 209 struct nft_chain *chain) 157 210 { 158 - const struct nft_base_chain *basechain; 211 + struct nft_base_chain *basechain; 159 212 const struct nf_hook_ops *ops; 160 213 161 214 if (table->flags & NFT_TABLE_F_DORMANT || ··· 221 168 if (basechain->type->ops_register) 222 169 return basechain->type->ops_register(net, ops); 223 170 224 - return nf_register_net_hook(net, ops); 171 + return nft_register_basechain_hooks(net, table->family, basechain); 225 172 } 226 173 227 174 static void nf_tables_unregister_hook(struct net *net, 228 175 const struct nft_table *table, 229 176 struct nft_chain *chain) 230 177 { 231 - const struct nft_base_chain *basechain; 178 + struct nft_base_chain *basechain; 232 179 const struct nf_hook_ops *ops; 233 180 234 181 if (table->flags & NFT_TABLE_F_DORMANT || ··· 240 187 if (basechain->type->ops_unregister) 241 188 return basechain->type->ops_unregister(net, ops); 242 189 243 - nf_unregister_net_hook(net, ops); 190 + nft_unregister_basechain_hooks(net, table->family, basechain); 244 191 } 245 192 246 193 static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) ··· 795 742 if (cnt && i++ == cnt) 796 743 break; 797 744 798 - nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); 745 + nft_unregister_basechain_hooks(net, table->family, 746 + nft_base_chain(chain)); 799 747 } 800 748 } 801 749 ··· 811 757 if (!nft_is_base_chain(chain)) 812 758 continue; 813 759 814 - err = nf_register_net_hook(net, &nft_base_chain(chain)->ops); 760 + err = nft_register_basechain_hooks(net, table->family, 761 + nft_base_chain(chain)); 815 762 if (err < 0) 816 - goto err; 763 + goto err_register_hooks; 817 764 818 765 i++; 819 766 } 820 767 return 0; 821 - err: 768 + 769 + err_register_hooks: 822 770 if (i) 823 771 nft_table_disable(net, table, i); 824 772 return err; ··· 1281 1225 return -ENOSPC; 1282 1226 } 1283 1227 1228 + static int nft_dump_basechain_hook(struct sk_buff *skb, int family, 1229 + const struct nft_base_chain *basechain) 1230 + { 1231 + const struct nf_hook_ops *ops = &basechain->ops; 1232 + struct nft_hook *hook, *first = NULL; 1233 + struct nlattr *nest, *nest_devs; 1234 + int n = 0; 1235 + 1236 + nest = nla_nest_start_noflag(skb, NFTA_CHAIN_HOOK); 1237 + if (nest == NULL) 1238 + goto nla_put_failure; 1239 + if (nla_put_be32(skb, NFTA_HOOK_HOOKNUM, htonl(ops->hooknum))) 1240 + goto nla_put_failure; 1241 + if (nla_put_be32(skb, NFTA_HOOK_PRIORITY, htonl(ops->priority))) 1242 + goto nla_put_failure; 1243 + 1244 + if (family == NFPROTO_NETDEV) { 1245 + nest_devs = nla_nest_start_noflag(skb, NFTA_HOOK_DEVS); 1246 + list_for_each_entry(hook, &basechain->hook_list, list) { 1247 + if (!first) 1248 + first = hook; 1249 + 1250 + if (nla_put_string(skb, NFTA_DEVICE_NAME, 1251 + hook->ops.dev->name)) 1252 + goto nla_put_failure; 1253 + n++; 1254 + } 1255 + nla_nest_end(skb, nest_devs); 1256 + 1257 + if (n == 1 && 1258 + nla_put_string(skb, NFTA_HOOK_DEV, first->ops.dev->name)) 1259 + goto nla_put_failure; 1260 + } 1261 + nla_nest_end(skb, nest); 1262 + 1263 + return 0; 1264 + nla_put_failure: 1265 + return -1; 1266 + } 1267 + 1284 1268 static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, 1285 1269 u32 portid, u32 seq, int event, u32 flags, 1286 1270 int family, const struct nft_table *table, ··· 1349 1253 1350 1254 if (nft_is_base_chain(chain)) { 1351 1255 const struct nft_base_chain *basechain = nft_base_chain(chain); 1352 - const struct nf_hook_ops *ops = &basechain->ops; 1353 1256 struct nft_stats __percpu *stats; 1354 - struct nlattr *nest; 1355 1257 1356 - nest = nla_nest_start_noflag(skb, NFTA_CHAIN_HOOK); 1357 - if (nest == NULL) 1258 + if (nft_dump_basechain_hook(skb, family, basechain)) 1358 1259 goto nla_put_failure; 1359 - if (nla_put_be32(skb, NFTA_HOOK_HOOKNUM, htonl(ops->hooknum))) 1360 - goto nla_put_failure; 1361 - if (nla_put_be32(skb, NFTA_HOOK_PRIORITY, htonl(ops->priority))) 1362 - goto nla_put_failure; 1363 - if (basechain->dev_name[0] && 1364 - nla_put_string(skb, NFTA_HOOK_DEV, basechain->dev_name)) 1365 - goto nla_put_failure; 1366 - nla_nest_end(skb, nest); 1367 1260 1368 1261 if (nla_put_be32(skb, NFTA_CHAIN_POLICY, 1369 1262 htonl(basechain->policy))) ··· 1570 1485 static void nf_tables_chain_destroy(struct nft_ctx *ctx) 1571 1486 { 1572 1487 struct nft_chain *chain = ctx->chain; 1488 + struct nft_hook *hook, *next; 1573 1489 1574 1490 if (WARN_ON(chain->use > 0)) 1575 1491 return; ··· 1581 1495 if (nft_is_base_chain(chain)) { 1582 1496 struct nft_base_chain *basechain = nft_base_chain(chain); 1583 1497 1498 + if (ctx->family == NFPROTO_NETDEV) { 1499 + list_for_each_entry_safe(hook, next, 1500 + &basechain->hook_list, list) { 1501 + list_del_rcu(&hook->list); 1502 + kfree_rcu(hook, rcu); 1503 + } 1504 + } 1584 1505 module_put(basechain->type->owner); 1585 1506 if (rcu_access_pointer(basechain->stats)) { 1586 1507 static_branch_dec(&nft_counters_enabled); ··· 1601 1508 } 1602 1509 } 1603 1510 1511 + static struct nft_hook *nft_netdev_hook_alloc(struct net *net, 1512 + const struct nlattr *attr) 1513 + { 1514 + struct net_device *dev; 1515 + char ifname[IFNAMSIZ]; 1516 + struct nft_hook *hook; 1517 + int err; 1518 + 1519 + hook = kmalloc(sizeof(struct nft_hook), GFP_KERNEL); 1520 + if (!hook) { 1521 + err = -ENOMEM; 1522 + goto err_hook_alloc; 1523 + } 1524 + 1525 + nla_strlcpy(ifname, attr, IFNAMSIZ); 1526 + dev = __dev_get_by_name(net, ifname); 1527 + if (!dev) { 1528 + err = -ENOENT; 1529 + goto err_hook_dev; 1530 + } 1531 + hook->ops.dev = dev; 1532 + 1533 + return hook; 1534 + 1535 + err_hook_dev: 1536 + kfree(hook); 1537 + err_hook_alloc: 1538 + return ERR_PTR(err); 1539 + } 1540 + 1541 + static bool nft_hook_list_find(struct list_head *hook_list, 1542 + const struct nft_hook *this) 1543 + { 1544 + struct nft_hook *hook; 1545 + 1546 + list_for_each_entry(hook, hook_list, list) { 1547 + if (this->ops.dev == hook->ops.dev) 1548 + return true; 1549 + } 1550 + 1551 + return false; 1552 + } 1553 + 1554 + static int nf_tables_parse_netdev_hooks(struct net *net, 1555 + const struct nlattr *attr, 1556 + struct list_head *hook_list) 1557 + { 1558 + struct nft_hook *hook, *next; 1559 + const struct nlattr *tmp; 1560 + int rem, n = 0, err; 1561 + 1562 + nla_for_each_nested(tmp, attr, rem) { 1563 + if (nla_type(tmp) != NFTA_DEVICE_NAME) { 1564 + err = -EINVAL; 1565 + goto err_hook; 1566 + } 1567 + 1568 + hook = nft_netdev_hook_alloc(net, tmp); 1569 + if (IS_ERR(hook)) { 1570 + err = PTR_ERR(hook); 1571 + goto err_hook; 1572 + } 1573 + if (nft_hook_list_find(hook_list, hook)) { 1574 + err = -EEXIST; 1575 + goto err_hook; 1576 + } 1577 + list_add_tail(&hook->list, hook_list); 1578 + n++; 1579 + 1580 + if (n == NFT_NETDEVICE_MAX) { 1581 + err = -EFBIG; 1582 + goto err_hook; 1583 + } 1584 + } 1585 + if (!n) 1586 + return -EINVAL; 1587 + 1588 + return 0; 1589 + 1590 + err_hook: 1591 + list_for_each_entry_safe(hook, next, hook_list, list) { 1592 + list_del(&hook->list); 1593 + kfree(hook); 1594 + } 1595 + return err; 1596 + } 1597 + 1604 1598 struct nft_chain_hook { 1605 1599 u32 num; 1606 1600 s32 priority; 1607 1601 const struct nft_chain_type *type; 1608 - struct net_device *dev; 1602 + struct list_head list; 1609 1603 }; 1604 + 1605 + static int nft_chain_parse_netdev(struct net *net, 1606 + struct nlattr *tb[], 1607 + struct list_head *hook_list) 1608 + { 1609 + struct nft_hook *hook; 1610 + int err; 1611 + 1612 + if (tb[NFTA_HOOK_DEV]) { 1613 + hook = nft_netdev_hook_alloc(net, tb[NFTA_HOOK_DEV]); 1614 + if (IS_ERR(hook)) 1615 + return PTR_ERR(hook); 1616 + 1617 + list_add_tail(&hook->list, hook_list); 1618 + } else if (tb[NFTA_HOOK_DEVS]) { 1619 + err = nf_tables_parse_netdev_hooks(net, tb[NFTA_HOOK_DEVS], 1620 + hook_list); 1621 + if (err < 0) 1622 + return err; 1623 + } else { 1624 + return -EINVAL; 1625 + } 1626 + 1627 + return 0; 1628 + } 1610 1629 1611 1630 static int nft_chain_parse_hook(struct net *net, 1612 1631 const struct nlattr * const nla[], ··· 1727 1522 { 1728 1523 struct nlattr *ha[NFTA_HOOK_MAX + 1]; 1729 1524 const struct nft_chain_type *type; 1730 - struct net_device *dev; 1731 1525 int err; 1732 1526 1733 1527 lockdep_assert_held(&net->nft.commit_mutex); ··· 1764 1560 1765 1561 hook->type = type; 1766 1562 1767 - hook->dev = NULL; 1563 + INIT_LIST_HEAD(&hook->list); 1768 1564 if (family == NFPROTO_NETDEV) { 1769 - char ifname[IFNAMSIZ]; 1770 - 1771 - if (!ha[NFTA_HOOK_DEV]) { 1565 + err = nft_chain_parse_netdev(net, ha, &hook->list); 1566 + if (err < 0) { 1772 1567 module_put(type->owner); 1773 - return -EOPNOTSUPP; 1568 + return err; 1774 1569 } 1775 - 1776 - nla_strlcpy(ifname, ha[NFTA_HOOK_DEV], IFNAMSIZ); 1777 - dev = __dev_get_by_name(net, ifname); 1778 - if (!dev) { 1779 - module_put(type->owner); 1780 - return -ENOENT; 1781 - } 1782 - hook->dev = dev; 1783 - } else if (ha[NFTA_HOOK_DEV]) { 1570 + } else if (ha[NFTA_HOOK_DEV] || ha[NFTA_HOOK_DEVS]) { 1784 1571 module_put(type->owner); 1785 1572 return -EOPNOTSUPP; 1786 1573 } ··· 1781 1586 1782 1587 static void nft_chain_release_hook(struct nft_chain_hook *hook) 1783 1588 { 1589 + struct nft_hook *h, *next; 1590 + 1591 + list_for_each_entry_safe(h, next, &hook->list, list) { 1592 + list_del(&h->list); 1593 + kfree(h); 1594 + } 1784 1595 module_put(hook->type->owner); 1785 1596 } 1786 1597 ··· 1811 1610 return kvmalloc(alloc, GFP_KERNEL); 1812 1611 } 1813 1612 1613 + static void nft_basechain_hook_init(struct nf_hook_ops *ops, u8 family, 1614 + const struct nft_chain_hook *hook, 1615 + struct nft_chain *chain) 1616 + { 1617 + ops->pf = family; 1618 + ops->hooknum = hook->num; 1619 + ops->priority = hook->priority; 1620 + ops->priv = chain; 1621 + ops->hook = hook->type->hooks[ops->hooknum]; 1622 + } 1623 + 1624 + static int nft_basechain_init(struct nft_base_chain *basechain, u8 family, 1625 + struct nft_chain_hook *hook, u32 flags) 1626 + { 1627 + struct nft_chain *chain; 1628 + struct nft_hook *h; 1629 + 1630 + basechain->type = hook->type; 1631 + INIT_LIST_HEAD(&basechain->hook_list); 1632 + chain = &basechain->chain; 1633 + 1634 + if (family == NFPROTO_NETDEV) { 1635 + list_splice_init(&hook->list, &basechain->hook_list); 1636 + list_for_each_entry(h, &basechain->hook_list, list) 1637 + nft_basechain_hook_init(&h->ops, family, hook, chain); 1638 + 1639 + basechain->ops.hooknum = hook->num; 1640 + basechain->ops.priority = hook->priority; 1641 + } else { 1642 + nft_basechain_hook_init(&basechain->ops, family, hook, chain); 1643 + } 1644 + 1645 + chain->flags |= NFT_BASE_CHAIN | flags; 1646 + basechain->policy = NF_ACCEPT; 1647 + if (chain->flags & NFT_CHAIN_HW_OFFLOAD && 1648 + nft_chain_offload_priority(basechain) < 0) 1649 + return -EOPNOTSUPP; 1650 + 1651 + flow_block_init(&basechain->flow_block); 1652 + 1653 + return 0; 1654 + } 1655 + 1814 1656 static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, 1815 1657 u8 policy, u32 flags) 1816 1658 { ··· 1872 1628 1873 1629 if (nla[NFTA_CHAIN_HOOK]) { 1874 1630 struct nft_chain_hook hook; 1875 - struct nf_hook_ops *ops; 1876 1631 1877 1632 err = nft_chain_parse_hook(net, nla, &hook, family, true); 1878 1633 if (err < 0) ··· 1882 1639 nft_chain_release_hook(&hook); 1883 1640 return -ENOMEM; 1884 1641 } 1885 - 1886 - if (hook.dev != NULL) 1887 - strncpy(basechain->dev_name, hook.dev->name, IFNAMSIZ); 1642 + chain = &basechain->chain; 1888 1643 1889 1644 if (nla[NFTA_CHAIN_COUNTERS]) { 1890 1645 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); ··· 1895 1654 static_branch_inc(&nft_counters_enabled); 1896 1655 } 1897 1656 1898 - basechain->type = hook.type; 1899 - chain = &basechain->chain; 1900 - 1901 - ops = &basechain->ops; 1902 - ops->pf = family; 1903 - ops->hooknum = hook.num; 1904 - ops->priority = hook.priority; 1905 - ops->priv = chain; 1906 - ops->hook = hook.type->hooks[ops->hooknum]; 1907 - ops->dev = hook.dev; 1908 - 1909 - chain->flags |= NFT_BASE_CHAIN | flags; 1910 - basechain->policy = NF_ACCEPT; 1911 - if (chain->flags & NFT_CHAIN_HW_OFFLOAD && 1912 - nft_chain_offload_priority(basechain) < 0) 1913 - return -EOPNOTSUPP; 1914 - 1915 - flow_block_init(&basechain->flow_block); 1657 + err = nft_basechain_init(basechain, family, &hook, flags); 1658 + if (err < 0) { 1659 + nft_chain_release_hook(&hook); 1660 + kfree(basechain); 1661 + return err; 1662 + } 1916 1663 } else { 1917 1664 chain = kzalloc(sizeof(*chain), GFP_KERNEL); 1918 1665 if (chain == NULL) ··· 1960 1731 return err; 1961 1732 } 1962 1733 1734 + static bool nft_hook_list_equal(struct list_head *hook_list1, 1735 + struct list_head *hook_list2) 1736 + { 1737 + struct nft_hook *hook; 1738 + int n = 0, m = 0; 1739 + 1740 + n = 0; 1741 + list_for_each_entry(hook, hook_list2, list) { 1742 + if (!nft_hook_list_find(hook_list1, hook)) 1743 + return false; 1744 + 1745 + n++; 1746 + } 1747 + list_for_each_entry(hook, hook_list1, list) 1748 + m++; 1749 + 1750 + return n == m; 1751 + } 1752 + 1963 1753 static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, 1964 1754 u32 flags) 1965 1755 { ··· 2010 1762 return -EBUSY; 2011 1763 } 2012 1764 2013 - ops = &basechain->ops; 2014 - if (ops->hooknum != hook.num || 2015 - ops->priority != hook.priority || 2016 - ops->dev != hook.dev) { 2017 - nft_chain_release_hook(&hook); 2018 - return -EBUSY; 1765 + if (ctx->family == NFPROTO_NETDEV) { 1766 + if (!nft_hook_list_equal(&basechain->hook_list, 1767 + &hook.list)) { 1768 + nft_chain_release_hook(&hook); 1769 + return -EBUSY; 1770 + } 1771 + } else { 1772 + ops = &basechain->ops; 1773 + if (ops->hooknum != hook.num || 1774 + ops->priority != hook.priority) { 1775 + nft_chain_release_hook(&hook); 1776 + return -EBUSY; 1777 + } 2019 1778 } 2020 1779 nft_chain_release_hook(&hook); 2021 1780 } ··· 5883 5628 return ERR_PTR(-ENOENT); 5884 5629 } 5885 5630 5886 - static int nf_tables_parse_devices(const struct nft_ctx *ctx, 5887 - const struct nlattr *attr, 5888 - struct net_device *dev_array[], int *len) 5889 - { 5890 - const struct nlattr *tmp; 5891 - struct net_device *dev; 5892 - char ifname[IFNAMSIZ]; 5893 - int rem, n = 0, err; 5894 - 5895 - nla_for_each_nested(tmp, attr, rem) { 5896 - if (nla_type(tmp) != NFTA_DEVICE_NAME) { 5897 - err = -EINVAL; 5898 - goto err1; 5899 - } 5900 - 5901 - nla_strlcpy(ifname, tmp, IFNAMSIZ); 5902 - dev = __dev_get_by_name(ctx->net, ifname); 5903 - if (!dev) { 5904 - err = -ENOENT; 5905 - goto err1; 5906 - } 5907 - 5908 - dev_array[n++] = dev; 5909 - if (n == NFT_FLOWTABLE_DEVICE_MAX) { 5910 - err = -EFBIG; 5911 - goto err1; 5912 - } 5913 - } 5914 - if (!len) 5915 - return -EINVAL; 5916 - 5917 - err = 0; 5918 - err1: 5919 - *len = n; 5920 - return err; 5921 - } 5922 - 5923 5631 static const struct nla_policy nft_flowtable_hook_policy[NFTA_FLOWTABLE_HOOK_MAX + 1] = { 5924 5632 [NFTA_FLOWTABLE_HOOK_NUM] = { .type = NLA_U32 }, 5925 5633 [NFTA_FLOWTABLE_HOOK_PRIORITY] = { .type = NLA_U32 }, ··· 5893 5675 const struct nlattr *attr, 5894 5676 struct nft_flowtable *flowtable) 5895 5677 { 5896 - struct net_device *dev_array[NFT_FLOWTABLE_DEVICE_MAX]; 5897 5678 struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1]; 5898 - struct nf_hook_ops *ops; 5679 + struct nft_hook *hook; 5899 5680 int hooknum, priority; 5900 - int err, n = 0, i; 5681 + int err; 5901 5682 5902 5683 err = nla_parse_nested_deprecated(tb, NFTA_FLOWTABLE_HOOK_MAX, attr, 5903 5684 nft_flowtable_hook_policy, NULL); ··· 5914 5697 5915 5698 priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY])); 5916 5699 5917 - err = nf_tables_parse_devices(ctx, tb[NFTA_FLOWTABLE_HOOK_DEVS], 5918 - dev_array, &n); 5700 + err = nf_tables_parse_netdev_hooks(ctx->net, 5701 + tb[NFTA_FLOWTABLE_HOOK_DEVS], 5702 + &flowtable->hook_list); 5919 5703 if (err < 0) 5920 5704 return err; 5921 5705 5922 - ops = kcalloc(n, sizeof(struct nf_hook_ops), GFP_KERNEL); 5923 - if (!ops) 5924 - return -ENOMEM; 5706 + flowtable->hooknum = hooknum; 5707 + flowtable->data.priority = priority; 5925 5708 5926 - flowtable->hooknum = hooknum; 5927 - flowtable->priority = priority; 5928 - flowtable->ops = ops; 5929 - flowtable->ops_len = n; 5930 - 5931 - for (i = 0; i < n; i++) { 5932 - flowtable->ops[i].pf = NFPROTO_NETDEV; 5933 - flowtable->ops[i].hooknum = hooknum; 5934 - flowtable->ops[i].priority = priority; 5935 - flowtable->ops[i].priv = &flowtable->data; 5936 - flowtable->ops[i].hook = flowtable->data.type->hook; 5937 - flowtable->ops[i].dev = dev_array[i]; 5709 + list_for_each_entry(hook, &flowtable->hook_list, list) { 5710 + hook->ops.pf = NFPROTO_NETDEV; 5711 + hook->ops.hooknum = hooknum; 5712 + hook->ops.priority = priority; 5713 + hook->ops.priv = &flowtable->data; 5714 + hook->ops.hook = flowtable->data.type->hook; 5938 5715 } 5939 5716 5940 5717 return err; ··· 5968 5757 static void nft_unregister_flowtable_net_hooks(struct net *net, 5969 5758 struct nft_flowtable *flowtable) 5970 5759 { 5971 - int i; 5760 + struct nft_hook *hook; 5972 5761 5973 - for (i = 0; i < flowtable->ops_len; i++) { 5974 - if (!flowtable->ops[i].dev) 5975 - continue; 5762 + list_for_each_entry(hook, &flowtable->hook_list, list) 5763 + nf_unregister_net_hook(net, &hook->ops); 5764 + } 5976 5765 5977 - nf_unregister_net_hook(net, &flowtable->ops[i]); 5766 + static int nft_register_flowtable_net_hooks(struct net *net, 5767 + struct nft_table *table, 5768 + struct nft_flowtable *flowtable) 5769 + { 5770 + struct nft_hook *hook, *hook2, *next; 5771 + struct nft_flowtable *ft; 5772 + int err, i = 0; 5773 + 5774 + list_for_each_entry(hook, &flowtable->hook_list, list) { 5775 + list_for_each_entry(ft, &table->flowtables, list) { 5776 + list_for_each_entry(hook2, &ft->hook_list, list) { 5777 + if (hook->ops.dev == hook2->ops.dev && 5778 + hook->ops.pf == hook2->ops.pf) { 5779 + err = -EBUSY; 5780 + goto err_unregister_net_hooks; 5781 + } 5782 + } 5783 + } 5784 + 5785 + err = nf_register_net_hook(net, &hook->ops); 5786 + if (err < 0) 5787 + goto err_unregister_net_hooks; 5788 + 5789 + i++; 5978 5790 } 5791 + 5792 + return 0; 5793 + 5794 + err_unregister_net_hooks: 5795 + list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { 5796 + if (i-- <= 0) 5797 + break; 5798 + 5799 + nf_unregister_net_hook(net, &hook->ops); 5800 + list_del_rcu(&hook->list); 5801 + kfree_rcu(hook, rcu); 5802 + } 5803 + 5804 + return err; 5979 5805 } 5980 5806 5981 5807 static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, ··· 6023 5775 { 6024 5776 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 6025 5777 const struct nf_flowtable_type *type; 6026 - struct nft_flowtable *flowtable, *ft; 6027 5778 u8 genmask = nft_genmask_next(net); 6028 5779 int family = nfmsg->nfgen_family; 5780 + struct nft_flowtable *flowtable; 5781 + struct nft_hook *hook, *next; 6029 5782 struct nft_table *table; 6030 5783 struct nft_ctx ctx; 6031 - int err, i, k; 5784 + int err; 6032 5785 6033 5786 if (!nla[NFTA_FLOWTABLE_TABLE] || 6034 5787 !nla[NFTA_FLOWTABLE_NAME] || ··· 6068 5819 6069 5820 flowtable->table = table; 6070 5821 flowtable->handle = nf_tables_alloc_handle(table); 5822 + INIT_LIST_HEAD(&flowtable->hook_list); 6071 5823 6072 5824 flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); 6073 5825 if (!flowtable->name) { ··· 6092 5842 if (err < 0) 6093 5843 goto err4; 6094 5844 6095 - for (i = 0; i < flowtable->ops_len; i++) { 6096 - if (!flowtable->ops[i].dev) 6097 - continue; 6098 - 6099 - list_for_each_entry(ft, &table->flowtables, list) { 6100 - for (k = 0; k < ft->ops_len; k++) { 6101 - if (!ft->ops[k].dev) 6102 - continue; 6103 - 6104 - if (flowtable->ops[i].dev == ft->ops[k].dev && 6105 - flowtable->ops[i].pf == ft->ops[k].pf) { 6106 - err = -EBUSY; 6107 - goto err5; 6108 - } 6109 - } 6110 - } 6111 - 6112 - err = nf_register_net_hook(net, &flowtable->ops[i]); 6113 - if (err < 0) 6114 - goto err5; 6115 - } 5845 + err = nft_register_flowtable_net_hooks(ctx.net, table, flowtable); 5846 + if (err < 0) 5847 + goto err4; 6116 5848 6117 5849 err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); 6118 5850 if (err < 0) 6119 - goto err6; 5851 + goto err5; 6120 5852 6121 5853 list_add_tail_rcu(&flowtable->list, &table->flowtables); 6122 5854 table->use++; 6123 5855 6124 5856 return 0; 6125 - err6: 6126 - i = flowtable->ops_len; 6127 5857 err5: 6128 - for (k = i - 1; k >= 0; k--) 6129 - nf_unregister_net_hook(net, &flowtable->ops[k]); 6130 - 6131 - kfree(flowtable->ops); 5858 + list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { 5859 + nf_unregister_net_hook(net, &hook->ops); 5860 + list_del_rcu(&hook->list); 5861 + kfree_rcu(hook, rcu); 5862 + } 6132 5863 err4: 6133 5864 flowtable->data.type->free(&flowtable->data); 6134 5865 err3: ··· 6176 5945 { 6177 5946 struct nlattr *nest, *nest_devs; 6178 5947 struct nfgenmsg *nfmsg; 5948 + struct nft_hook *hook; 6179 5949 struct nlmsghdr *nlh; 6180 - int i; 6181 5950 6182 5951 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); 6183 5952 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); ··· 6200 5969 if (!nest) 6201 5970 goto nla_put_failure; 6202 5971 if (nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_NUM, htonl(flowtable->hooknum)) || 6203 - nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(flowtable->priority))) 5972 + nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(flowtable->data.priority))) 6204 5973 goto nla_put_failure; 6205 5974 6206 5975 nest_devs = nla_nest_start_noflag(skb, NFTA_FLOWTABLE_HOOK_DEVS); 6207 5976 if (!nest_devs) 6208 5977 goto nla_put_failure; 6209 5978 6210 - for (i = 0; i < flowtable->ops_len; i++) { 6211 - const struct net_device *dev = READ_ONCE(flowtable->ops[i].dev); 6212 - 6213 - if (dev && 6214 - nla_put_string(skb, NFTA_DEVICE_NAME, dev->name)) 5979 + list_for_each_entry_rcu(hook, &flowtable->hook_list, list) { 5980 + if (nla_put_string(skb, NFTA_DEVICE_NAME, hook->ops.dev->name)) 6215 5981 goto nla_put_failure; 6216 5982 } 6217 5983 nla_nest_end(skb, nest_devs); ··· 6399 6171 6400 6172 static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) 6401 6173 { 6402 - kfree(flowtable->ops); 6174 + struct nft_hook *hook, *next; 6175 + 6176 + list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { 6177 + list_del_rcu(&hook->list); 6178 + kfree(hook); 6179 + } 6403 6180 kfree(flowtable->name); 6404 6181 flowtable->data.type->free(&flowtable->data); 6405 6182 module_put(flowtable->data.type->owner); ··· 6444 6211 static void nft_flowtable_event(unsigned long event, struct net_device *dev, 6445 6212 struct nft_flowtable *flowtable) 6446 6213 { 6447 - int i; 6214 + struct nft_hook *hook; 6448 6215 6449 - for (i = 0; i < flowtable->ops_len; i++) { 6450 - if (flowtable->ops[i].dev != dev) 6216 + list_for_each_entry(hook, &flowtable->hook_list, list) { 6217 + if (hook->ops.dev != dev) 6451 6218 continue; 6452 6219 6453 - nf_unregister_net_hook(dev_net(dev), &flowtable->ops[i]); 6454 - flowtable->ops[i].dev = NULL; 6220 + nf_unregister_net_hook(dev_net(dev), &hook->ops); 6221 + list_del_rcu(&hook->list); 6222 + kfree_rcu(hook, rcu); 6455 6223 break; 6456 6224 } 6457 6225 }
+125 -63
net/netfilter/nf_tables_offload.c
··· 132 132 common->extack = extack; 133 133 } 134 134 135 - static int nft_setup_cb_call(struct nft_base_chain *basechain, 136 - enum tc_setup_type type, void *type_data) 135 + static int nft_setup_cb_call(enum tc_setup_type type, void *type_data, 136 + struct list_head *cb_list) 137 137 { 138 138 struct flow_block_cb *block_cb; 139 139 int err; 140 140 141 - list_for_each_entry(block_cb, &basechain->flow_block.cb_list, list) { 141 + list_for_each_entry(block_cb, cb_list, list) { 142 142 err = block_cb->cb(type, type_data, block_cb->cb_priv); 143 143 if (err < 0) 144 144 return err; ··· 155 155 return 0; 156 156 } 157 157 158 + static void nft_flow_cls_offload_setup(struct flow_cls_offload *cls_flow, 159 + const struct nft_base_chain *basechain, 160 + const struct nft_rule *rule, 161 + const struct nft_flow_rule *flow, 162 + enum flow_cls_command command) 163 + { 164 + struct netlink_ext_ack extack; 165 + __be16 proto = ETH_P_ALL; 166 + 167 + memset(cls_flow, 0, sizeof(*cls_flow)); 168 + 169 + if (flow) 170 + proto = flow->proto; 171 + 172 + nft_flow_offload_common_init(&cls_flow->common, proto, 173 + basechain->ops.priority, &extack); 174 + cls_flow->command = command; 175 + cls_flow->cookie = (unsigned long) rule; 176 + if (flow) 177 + cls_flow->rule = flow->rule; 178 + } 179 + 158 180 static int nft_flow_offload_rule(struct nft_chain *chain, 159 181 struct nft_rule *rule, 160 182 struct nft_flow_rule *flow, 161 183 enum flow_cls_command command) 162 184 { 163 - struct flow_cls_offload cls_flow = {}; 185 + struct flow_cls_offload cls_flow; 164 186 struct nft_base_chain *basechain; 165 - struct netlink_ext_ack extack; 166 - __be16 proto = ETH_P_ALL; 167 187 168 188 if (!nft_is_base_chain(chain)) 169 189 return -EOPNOTSUPP; 170 190 171 191 basechain = nft_base_chain(chain); 192 + nft_flow_cls_offload_setup(&cls_flow, basechain, rule, flow, command); 172 193 173 - if (flow) 174 - proto = flow->proto; 175 - 176 - nft_flow_offload_common_init(&cls_flow.common, proto, 177 - basechain->ops.priority, &extack); 178 - cls_flow.command = command; 179 - cls_flow.cookie = (unsigned long) rule; 180 - if (flow) 181 - cls_flow.rule = flow->rule; 182 - 183 - return nft_setup_cb_call(basechain, TC_SETUP_CLSFLOWER, &cls_flow); 194 + return nft_setup_cb_call(TC_SETUP_CLSFLOWER, &cls_flow, 195 + &basechain->flow_block.cb_list); 184 196 } 185 197 186 198 static int nft_flow_offload_bind(struct flow_block_offload *bo, ··· 206 194 struct nft_base_chain *basechain) 207 195 { 208 196 struct flow_block_cb *block_cb, *next; 197 + struct flow_cls_offload cls_flow; 198 + struct nft_chain *chain; 199 + struct nft_rule *rule; 200 + 201 + chain = &basechain->chain; 202 + list_for_each_entry(rule, &chain->rules, list) { 203 + nft_flow_cls_offload_setup(&cls_flow, basechain, rule, NULL, 204 + FLOW_CLS_DESTROY); 205 + nft_setup_cb_call(TC_SETUP_CLSFLOWER, &cls_flow, &bo->cb_list); 206 + } 209 207 210 208 list_for_each_entry_safe(block_cb, next, &bo->cb_list, list) { 211 209 list_del(&block_cb->list); ··· 246 224 return err; 247 225 } 248 226 227 + static void nft_flow_block_offload_init(struct flow_block_offload *bo, 228 + struct net *net, 229 + enum flow_block_command cmd, 230 + struct nft_base_chain *basechain, 231 + struct netlink_ext_ack *extack) 232 + { 233 + memset(bo, 0, sizeof(*bo)); 234 + bo->net = net; 235 + bo->block = &basechain->flow_block; 236 + bo->command = cmd; 237 + bo->binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; 238 + bo->extack = extack; 239 + INIT_LIST_HEAD(&bo->cb_list); 240 + } 241 + 249 242 static int nft_block_offload_cmd(struct nft_base_chain *chain, 250 243 struct net_device *dev, 251 244 enum flow_block_command cmd) 252 245 { 253 246 struct netlink_ext_ack extack = {}; 254 - struct flow_block_offload bo = {}; 247 + struct flow_block_offload bo; 255 248 int err; 256 249 257 - bo.net = dev_net(dev); 258 - bo.block = &chain->flow_block; 259 - bo.command = cmd; 260 - bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; 261 - bo.extack = &extack; 262 - INIT_LIST_HEAD(&bo.cb_list); 250 + nft_flow_block_offload_init(&bo, dev_net(dev), cmd, chain, &extack); 263 251 264 252 err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo); 265 253 if (err < 0) ··· 285 253 enum flow_block_command cmd) 286 254 { 287 255 struct netlink_ext_ack extack = {}; 288 - struct flow_block_offload bo = {}; 256 + struct flow_block_offload bo; 289 257 290 258 if (!chain) 291 259 return; 292 260 293 - bo.net = dev_net(dev); 294 - bo.block = &chain->flow_block; 295 - bo.command = cmd; 296 - bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; 297 - bo.extack = &extack; 298 - INIT_LIST_HEAD(&bo.cb_list); 261 + nft_flow_block_offload_init(&bo, dev_net(dev), cmd, chain, &extack); 299 262 300 263 cb(dev, cb_priv, TC_SETUP_BLOCK, &bo); 301 264 ··· 301 274 struct net_device *dev, 302 275 enum flow_block_command cmd) 303 276 { 304 - struct flow_block_offload bo = {}; 305 277 struct netlink_ext_ack extack = {}; 278 + struct flow_block_offload bo; 306 279 307 - bo.net = dev_net(dev); 308 - bo.block = &chain->flow_block; 309 - bo.command = cmd; 310 - bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; 311 - bo.extack = &extack; 312 - INIT_LIST_HEAD(&bo.cb_list); 280 + nft_flow_block_offload_init(&bo, dev_net(dev), cmd, chain, &extack); 313 281 314 282 flow_indr_block_call(dev, &bo, cmd); 315 283 ··· 316 294 317 295 #define FLOW_SETUP_BLOCK TC_SETUP_BLOCK 318 296 319 - static int nft_flow_offload_chain(struct nft_chain *chain, 320 - u8 *ppolicy, 297 + static int nft_chain_offload_cmd(struct nft_base_chain *basechain, 298 + struct net_device *dev, 299 + enum flow_block_command cmd) 300 + { 301 + int err; 302 + 303 + if (dev->netdev_ops->ndo_setup_tc) 304 + err = nft_block_offload_cmd(basechain, dev, cmd); 305 + else 306 + err = nft_indr_block_offload_cmd(basechain, dev, cmd); 307 + 308 + return err; 309 + } 310 + 311 + static int nft_flow_block_chain(struct nft_base_chain *basechain, 312 + const struct net_device *this_dev, 313 + enum flow_block_command cmd) 314 + { 315 + struct net_device *dev; 316 + struct nft_hook *hook; 317 + int err, i = 0; 318 + 319 + list_for_each_entry(hook, &basechain->hook_list, list) { 320 + dev = hook->ops.dev; 321 + if (this_dev && this_dev != dev) 322 + continue; 323 + 324 + err = nft_chain_offload_cmd(basechain, dev, cmd); 325 + if (err < 0 && cmd == FLOW_BLOCK_BIND) { 326 + if (!this_dev) 327 + goto err_flow_block; 328 + 329 + return err; 330 + } 331 + i++; 332 + } 333 + 334 + return 0; 335 + 336 + err_flow_block: 337 + list_for_each_entry(hook, &basechain->hook_list, list) { 338 + if (i-- <= 0) 339 + break; 340 + 341 + dev = hook->ops.dev; 342 + nft_chain_offload_cmd(basechain, dev, FLOW_BLOCK_UNBIND); 343 + } 344 + return err; 345 + } 346 + 347 + static int nft_flow_offload_chain(struct nft_chain *chain, u8 *ppolicy, 321 348 enum flow_block_command cmd) 322 349 { 323 350 struct nft_base_chain *basechain; 324 - struct net_device *dev; 325 351 u8 policy; 326 352 327 353 if (!nft_is_base_chain(chain)) 328 354 return -EOPNOTSUPP; 329 355 330 356 basechain = nft_base_chain(chain); 331 - dev = basechain->ops.dev; 332 - if (!dev) 333 - return -EOPNOTSUPP; 334 - 335 357 policy = ppolicy ? *ppolicy : basechain->policy; 336 358 337 359 /* Only default policy to accept is supported for now. */ 338 360 if (cmd == FLOW_BLOCK_BIND && policy == NF_DROP) 339 361 return -EOPNOTSUPP; 340 362 341 - if (dev->netdev_ops->ndo_setup_tc) 342 - return nft_block_offload_cmd(basechain, dev, cmd); 343 - else 344 - return nft_indr_block_offload_cmd(basechain, dev, cmd); 363 + return nft_flow_block_chain(basechain, NULL, cmd); 345 364 } 346 365 347 366 int nft_flow_rule_offload_commit(struct net *net) ··· 448 385 { 449 386 struct nft_base_chain *basechain; 450 387 struct net *net = dev_net(dev); 388 + struct nft_hook *hook, *found; 451 389 const struct nft_table *table; 452 390 struct nft_chain *chain; 453 391 ··· 461 397 !(chain->flags & NFT_CHAIN_HW_OFFLOAD)) 462 398 continue; 463 399 400 + found = NULL; 464 401 basechain = nft_base_chain(chain); 465 - if (strncmp(basechain->dev_name, dev->name, IFNAMSIZ)) 402 + list_for_each_entry(hook, &basechain->hook_list, list) { 403 + if (hook->ops.dev != dev) 404 + continue; 405 + 406 + found = hook; 407 + break; 408 + } 409 + if (!found) 466 410 continue; 467 411 468 412 return chain; ··· 498 426 mutex_unlock(&net->nft.commit_mutex); 499 427 } 500 428 501 - static void nft_offload_chain_clean(struct nft_chain *chain) 502 - { 503 - struct nft_rule *rule; 504 - 505 - list_for_each_entry(rule, &chain->rules, list) { 506 - nft_flow_offload_rule(chain, rule, 507 - NULL, FLOW_CLS_DESTROY); 508 - } 509 - 510 - nft_flow_offload_chain(chain, NULL, FLOW_BLOCK_UNBIND); 511 - } 512 - 513 429 static int nft_offload_netdev_event(struct notifier_block *this, 514 430 unsigned long event, void *ptr) 515 431 { ··· 508 448 mutex_lock(&net->nft.commit_mutex); 509 449 chain = __nft_offload_get_chain(dev); 510 450 if (chain) 511 - nft_offload_chain_clean(chain); 451 + nft_flow_block_chain(nft_base_chain(chain), dev, 452 + FLOW_BLOCK_UNBIND); 453 + 512 454 mutex_unlock(&net->nft.commit_mutex); 513 455 514 456 return NOTIFY_DONE;
+25 -18
net/netfilter/nft_chain_filter.c
··· 287 287 struct nft_ctx *ctx) 288 288 { 289 289 struct nft_base_chain *basechain = nft_base_chain(ctx->chain); 290 + struct nft_hook *hook, *found = NULL; 291 + int n = 0; 290 292 291 - switch (event) { 292 - case NETDEV_UNREGISTER: 293 - if (strcmp(basechain->dev_name, dev->name) != 0) 294 - return; 293 + if (event != NETDEV_UNREGISTER) 294 + return; 295 295 296 - /* UNREGISTER events are also happpening on netns exit. 297 - * 298 - * Altough nf_tables core releases all tables/chains, only 299 - * this event handler provides guarantee that 300 - * basechain.ops->dev is still accessible, so we cannot 301 - * skip exiting net namespaces. 302 - */ 303 - __nft_release_basechain(ctx); 304 - break; 305 - case NETDEV_CHANGENAME: 306 - if (dev->ifindex != basechain->ops.dev->ifindex) 307 - return; 296 + list_for_each_entry(hook, &basechain->hook_list, list) { 297 + if (hook->ops.dev == dev) 298 + found = hook; 308 299 309 - strncpy(basechain->dev_name, dev->name, IFNAMSIZ); 310 - break; 300 + n++; 311 301 } 302 + if (!found) 303 + return; 304 + 305 + if (n > 1) { 306 + nf_unregister_net_hook(ctx->net, &found->ops); 307 + list_del_rcu(&found->list); 308 + kfree_rcu(found, rcu); 309 + return; 310 + } 311 + 312 + /* UNREGISTER events are also happening on netns exit. 313 + * 314 + * Although nf_tables core releases all tables/chains, only this event 315 + * handler provides guarantee that hook->ops.dev is still accessible, 316 + * so we cannot skip exiting net namespaces. 317 + */ 318 + __nft_release_basechain(ctx); 312 319 } 313 320 314 321 static int nf_tables_netdev_event(struct notifier_block *this,
+1 -1
tools/testing/selftests/netfilter/Makefile
··· 2 2 # Makefile for netfilter selftests 3 3 4 4 TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \ 5 - conntrack_icmp_related.sh nft_flowtable.sh 5 + conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh 6 6 7 7 include ../lib.mk
+228
tools/testing/selftests/netfilter/ipvs.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # End-to-end ipvs test suite 5 + # Topology: 6 + #--------------------------------------------------------------+ 7 + # | | 8 + # ns0 | ns1 | 9 + # ----------- | ----------- ----------- | 10 + # | veth01 | --------- | veth10 | | veth12 | | 11 + # ----------- peer ----------- ----------- | 12 + # | | | | 13 + # ----------- | | | 14 + # | br0 | |----------------- peer |--------------| 15 + # ----------- | | | 16 + # | | | | 17 + # ---------- peer ---------- ----------- | 18 + # | veth02 | --------- | veth20 | | veth21 | | 19 + # ---------- | ---------- ----------- | 20 + # | ns2 | 21 + # | | 22 + #--------------------------------------------------------------+ 23 + # 24 + # We assume that all network driver are loaded 25 + # 26 + 27 + # Kselftest framework requirement - SKIP code is 4. 28 + ksft_skip=4 29 + ret=0 30 + GREEN='\033[0;92m' 31 + RED='\033[0;31m' 32 + NC='\033[0m' # No Color 33 + 34 + readonly port=8080 35 + 36 + readonly vip_v4=207.175.44.110 37 + readonly cip_v4=10.0.0.2 38 + readonly gip_v4=10.0.0.1 39 + readonly dip_v4=172.16.0.1 40 + readonly rip_v4=172.16.0.2 41 + readonly sip_v4=10.0.0.3 42 + 43 + readonly infile="$(mktemp)" 44 + readonly outfile="$(mktemp)" 45 + readonly datalen=32 46 + 47 + sysipvsnet="/proc/sys/net/ipv4/vs/" 48 + if [ ! -d $sysipvsnet ]; then 49 + modprobe -q ip_vs 50 + if [ $? -ne 0 ]; then 51 + echo "skip: could not run test without ipvs module" 52 + exit $ksft_skip 53 + fi 54 + fi 55 + 56 + ip -Version > /dev/null 2>&1 57 + if [ $? -ne 0 ]; then 58 + echo "SKIP: Could not run test without ip tool" 59 + exit $ksft_skip 60 + fi 61 + 62 + ipvsadm -v > /dev/null 2>&1 63 + if [ $? -ne 0 ]; then 64 + echo "SKIP: Could not run test without ipvsadm" 65 + exit $ksft_skip 66 + fi 67 + 68 + setup() { 69 + ip netns add ns0 70 + ip netns add ns1 71 + ip netns add ns2 72 + 73 + ip link add veth01 netns ns0 type veth peer name veth10 netns ns1 74 + ip link add veth02 netns ns0 type veth peer name veth20 netns ns2 75 + ip link add veth12 netns ns1 type veth peer name veth21 netns ns2 76 + 77 + ip netns exec ns0 ip link set veth01 up 78 + ip netns exec ns0 ip link set veth02 up 79 + ip netns exec ns0 ip link add br0 type bridge 80 + ip netns exec ns0 ip link set veth01 master br0 81 + ip netns exec ns0 ip link set veth02 master br0 82 + ip netns exec ns0 ip link set br0 up 83 + ip netns exec ns0 ip addr add ${cip_v4}/24 dev br0 84 + 85 + ip netns exec ns1 ip link set lo up 86 + ip netns exec ns1 ip link set veth10 up 87 + ip netns exec ns1 ip addr add ${gip_v4}/24 dev veth10 88 + ip netns exec ns1 ip link set veth12 up 89 + ip netns exec ns1 ip addr add ${dip_v4}/24 dev veth12 90 + 91 + ip netns exec ns2 ip link set lo up 92 + ip netns exec ns2 ip link set veth21 up 93 + ip netns exec ns2 ip addr add ${rip_v4}/24 dev veth21 94 + ip netns exec ns2 ip link set veth20 up 95 + ip netns exec ns2 ip addr add ${sip_v4}/24 dev veth20 96 + 97 + sleep 1 98 + 99 + dd if=/dev/urandom of="${infile}" bs="${datalen}" count=1 status=none 100 + } 101 + 102 + cleanup() { 103 + for i in 0 1 2 104 + do 105 + ip netns del ns$i > /dev/null 2>&1 106 + done 107 + 108 + if [ -f "${outfile}" ]; then 109 + rm "${outfile}" 110 + fi 111 + if [ -f "${infile}" ]; then 112 + rm "${infile}" 113 + fi 114 + } 115 + 116 + server_listen() { 117 + ip netns exec ns2 nc -l -p 8080 > "${outfile}" & 118 + server_pid=$! 119 + sleep 0.2 120 + } 121 + 122 + client_connect() { 123 + ip netns exec ns0 timeout 2 nc -w 1 ${vip_v4} ${port} < "${infile}" 124 + } 125 + 126 + verify_data() { 127 + wait "${server_pid}" 128 + cmp "$infile" "$outfile" 2>/dev/null 129 + } 130 + 131 + test_service() { 132 + server_listen 133 + client_connect 134 + verify_data 135 + } 136 + 137 + 138 + test_dr() { 139 + ip netns exec ns0 ip route add ${vip_v4} via ${gip_v4} dev br0 140 + 141 + ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=1 142 + ip netns exec ns1 ipvsadm -A -t ${vip_v4}:${port} -s rr 143 + ip netns exec ns1 ipvsadm -a -t ${vip_v4}:${port} -r ${rip_v4}:${port} 144 + ip netns exec ns1 ip addr add ${vip_v4}/32 dev lo:1 145 + 146 + # avoid incorrect arp response 147 + ip netns exec ns2 sysctl -qw net.ipv4.conf.all.arp_ignore=1 148 + ip netns exec ns2 sysctl -qw net.ipv4.conf.all.arp_announce=2 149 + # avoid reverse route lookup 150 + ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=0 151 + ip netns exec ns2 sysctl -qw net.ipv4.conf.veth21.rp_filter=0 152 + ip netns exec ns2 ip addr add ${vip_v4}/32 dev lo:1 153 + 154 + test_service 155 + } 156 + 157 + test_nat() { 158 + ip netns exec ns0 ip route add ${vip_v4} via ${gip_v4} dev br0 159 + 160 + ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=1 161 + ip netns exec ns1 ipvsadm -A -t ${vip_v4}:${port} -s rr 162 + ip netns exec ns1 ipvsadm -a -m -t ${vip_v4}:${port} -r ${rip_v4}:${port} 163 + ip netns exec ns1 ip addr add ${vip_v4}/32 dev lo:1 164 + 165 + ip netns exec ns2 ip link del veth20 166 + ip netns exec ns2 ip route add default via ${dip_v4} dev veth21 167 + 168 + test_service 169 + } 170 + 171 + test_tun() { 172 + ip netns exec ns0 ip route add ${vip_v4} via ${gip_v4} dev br0 173 + 174 + ip netns exec ns1 modprobe ipip 175 + ip netns exec ns1 ip link set tunl0 up 176 + ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=0 177 + ip netns exec ns1 sysctl -qw net.ipv4.conf.all.send_redirects=0 178 + ip netns exec ns1 sysctl -qw net.ipv4.conf.default.send_redirects=0 179 + ip netns exec ns1 ipvsadm -A -t ${vip_v4}:${port} -s rr 180 + ip netns exec ns1 ipvsadm -a -i -t ${vip_v4}:${port} -r ${rip_v4}:${port} 181 + ip netns exec ns1 ip addr add ${vip_v4}/32 dev lo:1 182 + 183 + ip netns exec ns2 modprobe ipip 184 + ip netns exec ns2 ip link set tunl0 up 185 + ip netns exec ns2 sysctl -qw net.ipv4.conf.all.arp_ignore=1 186 + ip netns exec ns2 sysctl -qw net.ipv4.conf.all.arp_announce=2 187 + ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=0 188 + ip netns exec ns2 sysctl -qw net.ipv4.conf.tunl0.rp_filter=0 189 + ip netns exec ns2 sysctl -qw net.ipv4.conf.veth21.rp_filter=0 190 + ip netns exec ns2 ip addr add ${vip_v4}/32 dev lo:1 191 + 192 + test_service 193 + } 194 + 195 + run_tests() { 196 + local errors= 197 + 198 + echo "Testing DR mode..." 199 + cleanup 200 + setup 201 + test_dr 202 + errors=$(( $errors + $? )) 203 + 204 + echo "Testing NAT mode..." 205 + cleanup 206 + setup 207 + test_nat 208 + errors=$(( $errors + $? )) 209 + 210 + echo "Testing Tunnel mode..." 211 + cleanup 212 + setup 213 + test_tun 214 + errors=$(( $errors + $? )) 215 + 216 + return $errors 217 + } 218 + 219 + trap cleanup EXIT 220 + 221 + run_tests 222 + 223 + if [ $? -ne 0 ]; then 224 + echo -e "$(basename $0): ${RED}FAIL${NC}" 225 + exit 1 226 + fi 227 + echo -e "$(basename $0): ${GREEN}PASS${NC}" 228 + exit 0