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>
This commit is contained in:
parent
ea781f197d
commit
2732c4e45b
|
@ -405,6 +405,69 @@ nla_put_failure:
|
|||
}
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
/*
|
||||
* The general structure of a ctnetlink event is
|
||||
*
|
||||
* CTA_TUPLE_ORIG
|
||||
* <l3/l4-proto-attributes>
|
||||
* CTA_TUPLE_REPLY
|
||||
* <l3/l4-proto-attributes>
|
||||
* CTA_ID
|
||||
* ...
|
||||
* CTA_PROTOINFO
|
||||
* <l4-proto-attributes>
|
||||
* CTA_TUPLE_MASTER
|
||||
* <l3/l4-proto-attributes>
|
||||
*
|
||||
* Therefore the formular is
|
||||
*
|
||||
* size = sizeof(headers) + sizeof(generic_nlas) + 3 * sizeof(tuple_nlas)
|
||||
* + sizeof(protoinfo_nlas)
|
||||
*/
|
||||
static struct sk_buff *
|
||||
ctnetlink_alloc_skb(const struct nf_conntrack_tuple *tuple, gfp_t gfp)
|
||||
{
|
||||
struct nf_conntrack_l3proto *l3proto;
|
||||
struct nf_conntrack_l4proto *l4proto;
|
||||
int len;
|
||||
|
||||
#define NLA_TYPE_SIZE(type) nla_total_size(sizeof(type))
|
||||
|
||||
/* proto independant part */
|
||||
len = NLMSG_SPACE(sizeof(struct nfgenmsg))
|
||||
+ 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */
|
||||
+ 3 * nla_total_size(0) /* CTA_TUPLE_IP */
|
||||
+ 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */
|
||||
+ 3 * NLA_TYPE_SIZE(u_int8_t) /* CTA_PROTO_NUM */
|
||||
+ NLA_TYPE_SIZE(u_int32_t) /* CTA_ID */
|
||||
+ NLA_TYPE_SIZE(u_int32_t) /* CTA_STATUS */
|
||||
+ 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */
|
||||
+ 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_PACKETS */
|
||||
+ 2 * NLA_TYPE_SIZE(uint64_t) /* CTA_COUNTERS_BYTES */
|
||||
+ NLA_TYPE_SIZE(u_int32_t) /* CTA_TIMEOUT */
|
||||
+ nla_total_size(0) /* CTA_PROTOINFO */
|
||||
+ nla_total_size(0) /* CTA_HELP */
|
||||
+ nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */
|
||||
+ NLA_TYPE_SIZE(u_int32_t) /* CTA_SECMARK */
|
||||
+ 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */
|
||||
+ 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_POS */
|
||||
+ 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_BEFORE */
|
||||
+ 2 * NLA_TYPE_SIZE(u_int32_t) /* CTA_NAT_SEQ_CORRECTION_AFTER */
|
||||
+ NLA_TYPE_SIZE(u_int32_t); /* CTA_MARK */
|
||||
|
||||
#undef NLA_TYPE_SIZE
|
||||
|
||||
rcu_read_lock();
|
||||
l3proto = __nf_ct_l3proto_find(tuple->src.l3num);
|
||||
len += l3proto->nla_size;
|
||||
|
||||
l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum);
|
||||
len += l4proto->nla_size;
|
||||
rcu_read_unlock();
|
||||
|
||||
return alloc_skb(len, gfp);
|
||||
}
|
||||
|
||||
static int ctnetlink_conntrack_event(struct notifier_block *this,
|
||||
unsigned long events, void *ptr)
|
||||
{
|
||||
|
@ -438,7 +501,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
|
|||
if (!item->report && !nfnetlink_has_listeners(group))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
|
||||
skb = ctnetlink_alloc_skb(tuple(ct, IP_CT_DIR_ORIGINAL), GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
|
|
Loading…
Reference in New Issue