aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHolger Eitzenberger <holger@eitzenberger.org>2009-03-25 16:50:59 -0400
committerPatrick McHardy <kaber@trash.net>2009-03-25 16:50:59 -0400
commit2732c4e45bb67006fdc9ae6669be866762711ab5 (patch)
treed9ab37014adad2709cbb0a198eb2c48921d62420 /net
parentea781f197d6a835cbb93a0bf88ee1696296ed8aa (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.c65
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 */
427static struct sk_buff *
428ctnetlink_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
408static int ctnetlink_conntrack_event(struct notifier_block *this, 471static 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