diff options
author | Holger Eitzenberger <holger@eitzenberger.org> | 2009-03-25 16:50:59 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-03-25 16:50:59 -0400 |
commit | 2732c4e45bb67006fdc9ae6669be866762711ab5 (patch) | |
tree | d9ab37014adad2709cbb0a198eb2c48921d62420 /net | |
parent | ea781f197d6a835cbb93a0bf88ee1696296ed8aa (diff) |
netfilter: ctnetlink: allocate right-sized ctnetlink skb
Try to allocate a Netlink skb roughly the size of the actual
message, with the help from the l3 and l4 protocol helpers.
This is all to prevent a reallocation in netlink_trim() later.
The overhead of allocating the right-sized skb is rather small, with
ctnetlink_alloc_skb() actually being inlined away on my x86_64 box.
The size of the per-proto space is determined at registration time of
the protocol helper.
Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 349bbefe5517..03547c60f389 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -405,6 +405,69 @@ nla_put_failure: | |||
405 | } | 405 | } |
406 | 406 | ||
407 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 407 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
408 | /* | ||
409 | * The general structure of a ctnetlink event is | ||
410 | * | ||
411 | * CTA_TUPLE_ORIG | ||
412 | * <l3/l4-proto-attributes> | ||
413 | * CTA_TUPLE_REPLY | ||
414 | * <l3/l4-proto-attributes> | ||
415 | * CTA_ID | ||
416 | * ... | ||
417 | * CTA_PROTOINFO | ||
418 | * <l4-proto-attributes> | ||
419 | * CTA_TUPLE_MASTER | ||
420 | * <l3/l4-proto-attributes> | ||
421 | * | ||
422 | * Therefore the formular is | ||
423 | * | ||
424 | * size = sizeof(headers) + sizeof(generic_nlas) + 3 * sizeof(tuple_nlas) | ||
425 | * + sizeof(protoinfo_nlas) | ||
426 | */ | ||
427 | static struct sk_buff * | ||
428 | ctnetlink_alloc_skb(const struct nf_conntrack_tuple *tuple, gfp_t gfp) | ||
429 | { | ||
430 | struct nf_conntrack_l3proto *l3proto; | ||
431 | struct nf_conntrack_l4proto *l4proto; | ||
432 | int len; | ||
433 | |||
434 | #define NLA_TYPE_SIZE(type) nla_total_size(sizeof(type)) | ||
435 | |||
436 | /* proto independant part */ | ||
437 | len = NLMSG_SPACE(sizeof(struct nfgenmsg)) | ||
438 | + 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */ | ||
439 | + 3 * nla_total_size(0) /* CTA_TUPLE_IP */ | ||
440 | + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */ | ||
441 | + 3 * NLA_TYPE_SIZE(u_int8_t) /* CTA_PROTO_NUM */ | ||
442 | + NLA_TYPE_SIZE(u_int32_t) /* CTA_ID */ | ||
443 | + NLA_TYPE_SIZE(u_int32_t) /* CTA_STATUS */ | ||
444 | + 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ | ||
445 | + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_PACKETS */ | ||
446 | + 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_BYTES */ | ||
447 | + NLA_TYPE_SIZE(u_int32_t) /* CTA_TIMEOUT */ | ||
448 | + nla_total_size(0) /* CTA_PROTOINFO */ | ||
449 | + nla_total_size(0) /* CTA_HELP */ | ||
450 | + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ | ||
451 | + NLA_TYPE_SIZE(u_int32_t) /* CTA_SECMARK */ | ||
452 | + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ | ||
453 | + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_POS */ | ||
454 | + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_BEFORE */ | ||
455 | + 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_AFTER */ | ||
456 | + NLA_TYPE_SIZE(u_int32_t); /* CTA_MARK */ | ||
457 | |||
458 | #undef NLA_TYPE_SIZE | ||
459 | |||
460 | rcu_read_lock(); | ||
461 | l3proto = __nf_ct_l3proto_find(tuple->src.l3num); | ||
462 | len += l3proto->nla_size; | ||
463 | |||
464 | l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum); | ||
465 | len += l4proto->nla_size; | ||
466 | rcu_read_unlock(); | ||
467 | |||
468 | return alloc_skb(len, gfp); | ||
469 | } | ||
470 | |||
408 | static int ctnetlink_conntrack_event(struct notifier_block *this, | 471 | static int ctnetlink_conntrack_event(struct notifier_block *this, |
409 | unsigned long events, void *ptr) | 472 | unsigned long events, void *ptr) |
410 | { | 473 | { |
@@ -438,7 +501,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
438 | if (!item->report && !nfnetlink_has_listeners(group)) | 501 | if (!item->report && !nfnetlink_has_listeners(group)) |
439 | return NOTIFY_DONE; | 502 | return NOTIFY_DONE; |
440 | 503 | ||
441 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); | 504 | skb = ctnetlink_alloc_skb(tuple(ct, IP_CT_DIR_ORIGINAL), GFP_ATOMIC); |
442 | if (!skb) | 505 | if (!skb) |
443 | return NOTIFY_DONE; | 506 | return NOTIFY_DONE; |
444 | 507 | ||