Re: [PATCH nf-next 1/3] netfilter: convert hook list to an array

2017-08-23 Thread Aaron Conole
Eric Dumazet  writes:

> On Wed, 2017-08-23 at 17:26 +0200, Florian Westphal wrote:
>> From: Aaron Conole 
>
> ...
>
>> -static struct nf_hook_entry __rcu **nf_hook_entry_head(struct net
>> *net, const struct nf_hook_ops *reg)
>> +static struct nf_hook_entries *allocate_hook_entries_size(u16 num)
>> +{
>> +struct nf_hook_entries *e;
>> +size_t alloc = sizeof(*e) +
>> +   sizeof(struct nf_hook_entry) * num +
>> +   sizeof(struct nf_hook_ops *) * num;
>> +
>> +if (num == 0)
>> +return NULL;
>> +
>> +e = kvmalloc(alloc, GFP_KERNEL);
>> +if (e) {
>> +memset(e, 0, alloc);
>> +e->num_hook_entries = num;
>> +}
>
>
> nit:
>
>   e = kvzalloc(alloc, GFP_KERNEL);
>   if (e)
>   e->num_hook_entries = num;

d'oh!  Thanks for spotting.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH nf-next 1/3] netfilter: convert hook list to an array

2017-08-23 Thread Eric Dumazet
On Wed, 2017-08-23 at 17:26 +0200, Florian Westphal wrote:
> From: Aaron Conole 

...

> -static struct nf_hook_entry __rcu **nf_hook_entry_head(struct net *net, 
> const struct nf_hook_ops *reg)
> +static struct nf_hook_entries *allocate_hook_entries_size(u16 num)
> +{
> + struct nf_hook_entries *e;
> + size_t alloc = sizeof(*e) +
> +sizeof(struct nf_hook_entry) * num +
> +sizeof(struct nf_hook_ops *) * num;
> +
> + if (num == 0)
> + return NULL;
> +
> + e = kvmalloc(alloc, GFP_KERNEL);
> + if (e) {
> + memset(e, 0, alloc);
> + e->num_hook_entries = num;
> + }


nit:

e = kvzalloc(alloc, GFP_KERNEL);
if (e)
e->num_hook_entries = num;


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next 1/3] netfilter: convert hook list to an array

2017-08-23 Thread Florian Westphal
From: Aaron Conole 

This converts the storage and layout of netfilter hook entries from a
linked list to an array.  After this commit, hook entries will be
stored adjacent in memory.  The next pointer is no longer required.

The ops pointers are stored at the end of the array as they are only
used in the register/unregister path and in the legacy br_netfilter code.

nf_unregister_net_hooks() is slower than needed as it just calls
nf_unregister_net_hook in a loop (i.e. at least n synchronize_net()
calls), this will be addressed in followup patch.

Test setup:
 - ixgbe 10gbit
 - netperf UDP_STREAM, 64 byte packets
 - 5 empty base hooks (2 * prerouting, 3 * input):

before: 353.9 mbit/s
after: 364.2 mbit/s

Signed-off-by: Aaron Conole 
Signed-off-by: Florian Westphal 
---
 NB: I did this test after merging
 net-next into my working branch.

 include/linux/netdevice.h |   2 +-
 include/linux/netfilter.h |  45 +++---
 include/linux/netfilter_ingress.h |   4 +-
 include/net/netfilter/nf_queue.h  |   2 +-
 include/net/netns/netfilter.h |   2 +-
 net/bridge/br_netfilter_hooks.c   |  19 ++-
 net/netfilter/core.c  | 299 --
 net/netfilter/nf_internals.h  |   3 +-
 net/netfilter/nf_queue.c  |  67 +
 9 files changed, 309 insertions(+), 134 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 614642eb7eb7..ca0a30127300 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1811,7 +1811,7 @@ struct net_device {
 #endif
struct netdev_queue __rcu *ingress_queue;
 #ifdef CONFIG_NETFILTER_INGRESS
-   struct nf_hook_entry __rcu *nf_hooks_ingress;
+   struct nf_hook_entries __rcu *nf_hooks_ingress;
 #endif
 
unsigned char   broadcast[MAX_ADDR_LEN];
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 22f081065d49..f84bca1703cd 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -72,25 +72,32 @@ struct nf_hook_ops {
 };
 
 struct nf_hook_entry {
-   struct nf_hook_entry __rcu  *next;
nf_hookfn   *hook;
void*priv;
-   const struct nf_hook_ops*orig_ops;
 };
 
-static inline void
-nf_hook_entry_init(struct nf_hook_entry *entry,const struct 
nf_hook_ops *ops)
-{
-   entry->next = NULL;
-   entry->hook = ops->hook;
-   entry->priv = ops->priv;
-   entry->orig_ops = ops;
-}
+struct nf_hook_entries {
+   u16 num_hook_entries;
+   /* padding */
+   struct nf_hook_entryhooks[];
+
+   /* trailer: pointers to original orig_ops of each hook.
+*
+* This is not part of struct nf_hook_entry since its only
+* needed in slow path (hook register/unregister).
+*
+* const struct nf_hook_ops *orig_ops[]
+*/
+};
 
-static inline int
-nf_hook_entry_priority(const struct nf_hook_entry *entry)
+static inline struct nf_hook_ops **nf_hook_entries_get_hook_ops(const struct 
nf_hook_entries *e)
 {
-   return entry->orig_ops->priority;
+   unsigned int n = e->num_hook_entries;
+   const void *hook_end;
+
+   hook_end = >hooks[n]; /* this is *past* ->hooks[]! */
+
+   return (struct nf_hook_ops **)hook_end;
 }
 
 static inline int
@@ -100,12 +107,6 @@ nf_hook_entry_hookfn(const struct nf_hook_entry *entry, 
struct sk_buff *skb,
return entry->hook(entry->priv, skb, state);
 }
 
-static inline const struct nf_hook_ops *
-nf_hook_entry_ops(const struct nf_hook_entry *entry)
-{
-   return entry->orig_ops;
-}
-
 static inline void nf_hook_state_init(struct nf_hook_state *p,
  unsigned int hook,
  u_int8_t pf,
@@ -168,7 +169,7 @@ extern struct static_key 
nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
 #endif
 
 int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
-struct nf_hook_entry *entry);
+const struct nf_hook_entries *e, unsigned int i);
 
 /**
  * nf_hook - call a netfilter hook
@@ -182,7 +183,7 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, 
struct net *net,
  struct net_device *indev, struct net_device *outdev,
  int (*okfn)(struct net *, struct sock *, struct 
sk_buff *))
 {
-   struct nf_hook_entry *hook_head;
+   struct nf_hook_entries *hook_head;
int ret = 1;
 
 #ifdef HAVE_JUMP_LABEL
@@ -200,7 +201,7 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, 
struct net *net,
nf_hook_state_init(, hook, pf, indev, outdev,
   sk, net, okfn);
 
-   ret = nf_hook_slow(skb, , hook_head);
+   ret = nf_hook_slow(skb, , hook_head, 0);
}
rcu_read_unlock();