netfilter: nf_tables: explicit nft_set_pktinfo() call from hook path

Instead of calling this function from the family specific variant, this
reduces the code size in the fast path for the netdev, bridge and inet
families. After this change, we must call nft_set_pktinfo() upfront from
the chain hook indirection.

Before:

   text    data     bss     dec     hex filename
   2145     208       0    2353     931 net/netfilter/nf_tables_netdev.o

After:

   text    data     bss     dec     hex filename
   2125     208       0    2333     91d net/netfilter/nf_tables_netdev.o

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Pablo Neira Ayuso 2017-12-10 01:43:14 +01:00
parent fa45a76021
commit 7a4473a31a
12 changed files with 43 additions and 58 deletions

View File

@ -54,8 +54,8 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
pkt->xt.state = state;
}
static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt,
struct sk_buff *skb)
static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
pkt->tprot_set = false;
pkt->tprot = 0;
@ -63,14 +63,6 @@ static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt,
pkt->xt.fragoff = 0;
}
static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
nft_set_pktinfo(pkt, skb, state);
nft_set_pktinfo_proto_unspec(pkt, skb);
}
/**
* struct nft_verdict - nf_tables verdict
*

View File

@ -5,15 +5,11 @@
#include <net/netfilter/nf_tables.h>
#include <net/ip.h>
static inline void
nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
struct iphdr *ip;
nft_set_pktinfo(pkt, skb, state);
ip = ip_hdr(pkt->skb);
pkt->tprot_set = true;
pkt->tprot = ip->protocol;
@ -21,10 +17,8 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
}
static inline int
__nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
struct iphdr *iph, _iph;
u32 len, thoff;
@ -52,14 +46,11 @@ __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
return 0;
}
static inline void
nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
nft_set_pktinfo(pkt, skb, state);
if (__nft_set_pktinfo_ipv4_validate(pkt, skb, state) < 0)
nft_set_pktinfo_proto_unspec(pkt, skb);
if (__nft_set_pktinfo_ipv4_validate(pkt, skb) < 0)
nft_set_pktinfo_unspec(pkt, skb);
}
extern struct nft_af_info nft_af_ipv4;

View File

@ -5,20 +5,16 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ipv6.h>
static inline void
nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
unsigned int flags = IP6_FH_F_AUTH;
int protohdr, thoff = 0;
unsigned short frag_off;
nft_set_pktinfo(pkt, skb, state);
protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
if (protohdr < 0) {
nft_set_pktinfo_proto_unspec(pkt, skb);
nft_set_pktinfo_unspec(pkt, skb);
return;
}
@ -28,10 +24,8 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
pkt->xt.fragoff = frag_off;
}
static inline int
__nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_IPV6)
unsigned int flags = IP6_FH_F_AUTH;
@ -68,14 +62,11 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
#endif
}
static inline void
nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb,
const struct nf_hook_state *state)
static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
nft_set_pktinfo(pkt, skb, state);
if (__nft_set_pktinfo_ipv6_validate(pkt, skb, state) < 0)
nft_set_pktinfo_proto_unspec(pkt, skb);
if (__nft_set_pktinfo_ipv6_validate(pkt, skb) < 0)
nft_set_pktinfo_unspec(pkt, skb);
}
extern struct nft_af_info nft_af_ipv6;

View File

@ -25,15 +25,17 @@ nft_do_chain_bridge(void *priv,
{
struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, skb, state);
switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP):
nft_set_pktinfo_ipv4_validate(&pkt, skb, state);
nft_set_pktinfo_ipv4_validate(&pkt, skb);
break;
case htons(ETH_P_IPV6):
nft_set_pktinfo_ipv6_validate(&pkt, skb, state);
nft_set_pktinfo_ipv6_validate(&pkt, skb);
break;
default:
nft_set_pktinfo_unspec(&pkt, skb, state);
nft_set_pktinfo_unspec(&pkt, skb);
break;
}

View File

@ -21,7 +21,8 @@ nft_do_chain_arp(void *priv,
{
struct nft_pktinfo pkt;
nft_set_pktinfo_unspec(&pkt, skb, state);
nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_unspec(&pkt, skb);
return nft_do_chain(&pkt, priv);
}

View File

@ -24,7 +24,8 @@ static unsigned int nft_do_chain_ipv4(void *priv,
{
struct nft_pktinfo pkt;
nft_set_pktinfo_ipv4(&pkt, skb, state);
nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb);
return nft_do_chain(&pkt, priv);
}

View File

@ -33,7 +33,8 @@ static unsigned int nft_nat_do_chain(void *priv,
{
struct nft_pktinfo pkt;
nft_set_pktinfo_ipv4(&pkt, skb, state);
nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb);
return nft_do_chain(&pkt, priv);
}

View File

@ -38,7 +38,8 @@ static unsigned int nf_route_table_hook(void *priv,
ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
nft_set_pktinfo_ipv4(&pkt, skb, state);
nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb);
mark = skb->mark;
iph = ip_hdr(skb);

View File

@ -22,7 +22,8 @@ static unsigned int nft_do_chain_ipv6(void *priv,
{
struct nft_pktinfo pkt;
nft_set_pktinfo_ipv6(&pkt, skb, state);
nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv6(&pkt, skb);
return nft_do_chain(&pkt, priv);
}

View File

@ -31,7 +31,8 @@ static unsigned int nft_nat_do_chain(void *priv,
{
struct nft_pktinfo pkt;
nft_set_pktinfo_ipv6(&pkt, skb, state);
nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv6(&pkt, skb);
return nft_do_chain(&pkt, priv);
}

View File

@ -33,7 +33,8 @@ static unsigned int nf_route_table_hook(void *priv,
u32 mark, flowlabel;
int err;
nft_set_pktinfo_ipv6(&pkt, skb, state);
nft_set_pktinfo(&pkt, skb, state);
nft_set_pktinfo_ipv6(&pkt, skb);
/* save source/dest address, mark, hoplimit, flowlabel, priority */
memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));

View File

@ -21,15 +21,17 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb,
{
struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, skb, state);
switch (skb->protocol) {
case htons(ETH_P_IP):
nft_set_pktinfo_ipv4_validate(&pkt, skb, state);
nft_set_pktinfo_ipv4_validate(&pkt, skb);
break;
case htons(ETH_P_IPV6):
nft_set_pktinfo_ipv6_validate(&pkt, skb, state);
nft_set_pktinfo_ipv6_validate(&pkt, skb);
break;
default:
nft_set_pktinfo_unspec(&pkt, skb, state);
nft_set_pktinfo_unspec(&pkt, skb);
break;
}