Commit 7a4473a3 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

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: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent fa45a760
...@@ -54,7 +54,7 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt, ...@@ -54,7 +54,7 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
pkt->xt.state = state; pkt->xt.state = state;
} }
static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt, static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt,
struct sk_buff *skb) struct sk_buff *skb)
{ {
pkt->tprot_set = false; pkt->tprot_set = false;
...@@ -63,14 +63,6 @@ static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt, ...@@ -63,14 +63,6 @@ static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt,
pkt->xt.fragoff = 0; 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 * struct nft_verdict - nf_tables verdict
* *
......
...@@ -5,15 +5,11 @@ ...@@ -5,15 +5,11 @@
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
#include <net/ip.h> #include <net/ip.h>
static inline void static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, struct sk_buff *skb)
struct sk_buff *skb,
const struct nf_hook_state *state)
{ {
struct iphdr *ip; struct iphdr *ip;
nft_set_pktinfo(pkt, skb, state);
ip = ip_hdr(pkt->skb); ip = ip_hdr(pkt->skb);
pkt->tprot_set = true; pkt->tprot_set = true;
pkt->tprot = ip->protocol; pkt->tprot = ip->protocol;
...@@ -21,10 +17,8 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, ...@@ -21,10 +17,8 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
} }
static inline int static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
__nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, struct sk_buff *skb)
struct sk_buff *skb,
const struct nf_hook_state *state)
{ {
struct iphdr *iph, _iph; struct iphdr *iph, _iph;
u32 len, thoff; u32 len, thoff;
...@@ -52,14 +46,11 @@ __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, ...@@ -52,14 +46,11 @@ __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
return 0; return 0;
} }
static inline void static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, struct sk_buff *skb)
struct sk_buff *skb,
const struct nf_hook_state *state)
{ {
nft_set_pktinfo(pkt, skb, state); if (__nft_set_pktinfo_ipv4_validate(pkt, skb) < 0)
if (__nft_set_pktinfo_ipv4_validate(pkt, skb, state) < 0) nft_set_pktinfo_unspec(pkt, skb);
nft_set_pktinfo_proto_unspec(pkt, skb);
} }
extern struct nft_af_info nft_af_ipv4; extern struct nft_af_info nft_af_ipv4;
......
...@@ -5,20 +5,16 @@ ...@@ -5,20 +5,16 @@
#include <linux/netfilter_ipv6/ip6_tables.h> #include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ipv6.h> #include <net/ipv6.h>
static inline void static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, struct sk_buff *skb)
struct sk_buff *skb,
const struct nf_hook_state *state)
{ {
unsigned int flags = IP6_FH_F_AUTH; unsigned int flags = IP6_FH_F_AUTH;
int protohdr, thoff = 0; int protohdr, thoff = 0;
unsigned short frag_off; unsigned short frag_off;
nft_set_pktinfo(pkt, skb, state);
protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags); protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
if (protohdr < 0) { if (protohdr < 0) {
nft_set_pktinfo_proto_unspec(pkt, skb); nft_set_pktinfo_unspec(pkt, skb);
return; return;
} }
...@@ -28,10 +24,8 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, ...@@ -28,10 +24,8 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
pkt->xt.fragoff = frag_off; pkt->xt.fragoff = frag_off;
} }
static inline int static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
__nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, struct sk_buff *skb)
struct sk_buff *skb,
const struct nf_hook_state *state)
{ {
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
unsigned int flags = IP6_FH_F_AUTH; unsigned int flags = IP6_FH_F_AUTH;
...@@ -68,14 +62,11 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ...@@ -68,14 +62,11 @@ __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
#endif #endif
} }
static inline void static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, struct sk_buff *skb)
struct sk_buff *skb,
const struct nf_hook_state *state)
{ {
nft_set_pktinfo(pkt, skb, state); if (__nft_set_pktinfo_ipv6_validate(pkt, skb) < 0)
if (__nft_set_pktinfo_ipv6_validate(pkt, skb, state) < 0) nft_set_pktinfo_unspec(pkt, skb);
nft_set_pktinfo_proto_unspec(pkt, skb);
} }
extern struct nft_af_info nft_af_ipv6; extern struct nft_af_info nft_af_ipv6;
......
...@@ -25,15 +25,17 @@ nft_do_chain_bridge(void *priv, ...@@ -25,15 +25,17 @@ nft_do_chain_bridge(void *priv,
{ {
struct nft_pktinfo pkt; struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, skb, state);
switch (eth_hdr(skb)->h_proto) { switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
nft_set_pktinfo_ipv4_validate(&pkt, skb, state); nft_set_pktinfo_ipv4_validate(&pkt, skb);
break; break;
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
nft_set_pktinfo_ipv6_validate(&pkt, skb, state); nft_set_pktinfo_ipv6_validate(&pkt, skb);
break; break;
default: default:
nft_set_pktinfo_unspec(&pkt, skb, state); nft_set_pktinfo_unspec(&pkt, skb);
break; break;
} }
......
...@@ -21,7 +21,8 @@ nft_do_chain_arp(void *priv, ...@@ -21,7 +21,8 @@ nft_do_chain_arp(void *priv,
{ {
struct nft_pktinfo pkt; 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); return nft_do_chain(&pkt, priv);
} }
......
...@@ -24,7 +24,8 @@ static unsigned int nft_do_chain_ipv4(void *priv, ...@@ -24,7 +24,8 @@ static unsigned int nft_do_chain_ipv4(void *priv,
{ {
struct nft_pktinfo pkt; 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); return nft_do_chain(&pkt, priv);
} }
......
...@@ -33,7 +33,8 @@ static unsigned int nft_nat_do_chain(void *priv, ...@@ -33,7 +33,8 @@ static unsigned int nft_nat_do_chain(void *priv,
{ {
struct nft_pktinfo pkt; 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); return nft_do_chain(&pkt, priv);
} }
......
...@@ -38,7 +38,8 @@ static unsigned int nf_route_table_hook(void *priv, ...@@ -38,7 +38,8 @@ static unsigned int nf_route_table_hook(void *priv,
ip_hdrlen(skb) < sizeof(struct iphdr)) ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT; 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; mark = skb->mark;
iph = ip_hdr(skb); iph = ip_hdr(skb);
......
...@@ -22,7 +22,8 @@ static unsigned int nft_do_chain_ipv6(void *priv, ...@@ -22,7 +22,8 @@ static unsigned int nft_do_chain_ipv6(void *priv,
{ {
struct nft_pktinfo pkt; 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); return nft_do_chain(&pkt, priv);
} }
......
...@@ -31,7 +31,8 @@ static unsigned int nft_nat_do_chain(void *priv, ...@@ -31,7 +31,8 @@ static unsigned int nft_nat_do_chain(void *priv,
{ {
struct nft_pktinfo pkt; 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); return nft_do_chain(&pkt, priv);
} }
......
...@@ -33,7 +33,8 @@ static unsigned int nf_route_table_hook(void *priv, ...@@ -33,7 +33,8 @@ static unsigned int nf_route_table_hook(void *priv,
u32 mark, flowlabel; u32 mark, flowlabel;
int err; 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 */ /* save source/dest address, mark, hoplimit, flowlabel, priority */
memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));
......
...@@ -21,15 +21,17 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb, ...@@ -21,15 +21,17 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb,
{ {
struct nft_pktinfo pkt; struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, skb, state);
switch (skb->protocol) { switch (skb->protocol) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
nft_set_pktinfo_ipv4_validate(&pkt, skb, state); nft_set_pktinfo_ipv4_validate(&pkt, skb);
break; break;
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
nft_set_pktinfo_ipv6_validate(&pkt, skb, state); nft_set_pktinfo_ipv6_validate(&pkt, skb);
break; break;
default: default:
nft_set_pktinfo_unspec(&pkt, skb, state); nft_set_pktinfo_unspec(&pkt, skb);
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment