Commit 72b1e5e4 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: bridge: reduce nf_bridge_info to 32 bytes again

We can use union for most of the temporary cruft (original ipv4/ipv6
address, source mac, physoutdev) since they're used during different
stages of br netfilter traversal.

Also get rid of the last two ->mask users.

Shrinks struct from 48 to 32 on 64bit arch.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent d7ee3519
...@@ -17,9 +17,6 @@ enum nf_br_hook_priorities { ...@@ -17,9 +17,6 @@ enum nf_br_hook_priorities {
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
#define BRNF_BRIDGED_DNAT 0x02
#define BRNF_NF_BRIDGE_PREROUTING 0x08
int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb); int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb);
static inline void br_drop_fake_rtable(struct sk_buff *skb) static inline void br_drop_fake_rtable(struct sk_buff *skb)
...@@ -63,8 +60,17 @@ nf_bridge_get_physoutdev(const struct sk_buff *skb) ...@@ -63,8 +60,17 @@ nf_bridge_get_physoutdev(const struct sk_buff *skb)
{ {
return skb->nf_bridge ? skb->nf_bridge->physoutdev : NULL; return skb->nf_bridge ? skb->nf_bridge->physoutdev : NULL;
} }
static inline bool nf_bridge_in_prerouting(const struct sk_buff *skb)
{
return skb->nf_bridge && skb->nf_bridge->in_prerouting;
}
#else #else
#define br_drop_fake_rtable(skb) do { } while (0) #define br_drop_fake_rtable(skb) do { } while (0)
static inline bool nf_bridge_in_prerouting(const struct sk_buff *skb)
{
return false;
}
#endif /* CONFIG_BRIDGE_NETFILTER */ #endif /* CONFIG_BRIDGE_NETFILTER */
#endif #endif
...@@ -173,17 +173,24 @@ struct nf_bridge_info { ...@@ -173,17 +173,24 @@ struct nf_bridge_info {
BRNF_PROTO_8021Q, BRNF_PROTO_8021Q,
BRNF_PROTO_PPPOE BRNF_PROTO_PPPOE
} orig_proto:8; } orig_proto:8;
bool pkt_otherhost; u8 pkt_otherhost:1;
u8 in_prerouting:1;
u8 bridged_dnat:1;
__u16 frag_max_size; __u16 frag_max_size;
unsigned int mask;
struct net_device *physindev; struct net_device *physindev;
union { union {
struct net_device *physoutdev; /* prerouting: detect dnat in orig/reply direction */
char neigh_header[8];
};
union {
__be32 ipv4_daddr; __be32 ipv4_daddr;
struct in6_addr ipv6_daddr; struct in6_addr ipv6_daddr;
/* after prerouting + nat detected: store original source
* mac since neigh resolution overwrites it, only used while
* skb is out in neigh layer.
*/
char neigh_header[8];
/* always valid & non-NULL from FORWARD on, for physdev match */
struct net_device *physoutdev;
}; };
}; };
#endif #endif
......
...@@ -284,7 +284,7 @@ int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb) ...@@ -284,7 +284,7 @@ int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb)
nf_bridge->neigh_header, nf_bridge->neigh_header,
ETH_HLEN-ETH_ALEN); ETH_HLEN-ETH_ALEN);
/* tell br_dev_xmit to continue with forwarding */ /* tell br_dev_xmit to continue with forwarding */
nf_bridge->mask |= BRNF_BRIDGED_DNAT; nf_bridge->bridged_dnat = 1;
/* FIXME Need to refragment */ /* FIXME Need to refragment */
ret = neigh->output(neigh, skb); ret = neigh->output(neigh, skb);
} }
...@@ -356,7 +356,7 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb) ...@@ -356,7 +356,7 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb)
skb->pkt_type = PACKET_OTHERHOST; skb->pkt_type = PACKET_OTHERHOST;
nf_bridge->pkt_otherhost = false; nf_bridge->pkt_otherhost = false;
} }
nf_bridge->mask &= ~BRNF_NF_BRIDGE_PREROUTING; nf_bridge->in_prerouting = 0;
if (br_nf_ipv4_daddr_was_changed(skb, nf_bridge)) { if (br_nf_ipv4_daddr_was_changed(skb, nf_bridge)) {
if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
struct in_device *in_dev = __in_dev_get_rcu(dev); struct in_device *in_dev = __in_dev_get_rcu(dev);
...@@ -444,7 +444,7 @@ struct net_device *setup_pre_routing(struct sk_buff *skb) ...@@ -444,7 +444,7 @@ struct net_device *setup_pre_routing(struct sk_buff *skb)
nf_bridge->pkt_otherhost = true; nf_bridge->pkt_otherhost = true;
} }
nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; nf_bridge->in_prerouting = 1;
nf_bridge->physindev = skb->dev; nf_bridge->physindev = skb->dev;
skb->dev = brnf_get_logical_dev(skb, skb->dev); skb->dev = brnf_get_logical_dev(skb, skb->dev);
...@@ -850,10 +850,8 @@ static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops, ...@@ -850,10 +850,8 @@ static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops,
struct sk_buff *skb, struct sk_buff *skb,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
if (skb->nf_bridge && if (skb->nf_bridge && !skb->nf_bridge->in_prerouting)
!(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
return NF_STOP; return NF_STOP;
}
return NF_ACCEPT; return NF_ACCEPT;
} }
...@@ -872,7 +870,7 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) ...@@ -872,7 +870,7 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
skb_pull(skb, ETH_HLEN); skb_pull(skb, ETH_HLEN);
nf_bridge->mask &= ~BRNF_BRIDGED_DNAT; nf_bridge->bridged_dnat = 0;
BUILD_BUG_ON(sizeof(nf_bridge->neigh_header) != (ETH_HLEN - ETH_ALEN)); BUILD_BUG_ON(sizeof(nf_bridge->neigh_header) != (ETH_HLEN - ETH_ALEN));
...@@ -887,7 +885,7 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) ...@@ -887,7 +885,7 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)
static int br_nf_dev_xmit(struct sk_buff *skb) static int br_nf_dev_xmit(struct sk_buff *skb)
{ {
if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { if (skb->nf_bridge && skb->nf_bridge->bridged_dnat) {
br_nf_pre_routing_finish_bridge_slow(skb); br_nf_pre_routing_finish_bridge_slow(skb);
return 1; return 1;
} }
......
...@@ -174,7 +174,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) ...@@ -174,7 +174,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb)
skb->pkt_type = PACKET_OTHERHOST; skb->pkt_type = PACKET_OTHERHOST;
nf_bridge->pkt_otherhost = false; nf_bridge->pkt_otherhost = false;
} }
nf_bridge->mask &= ~BRNF_NF_BRIDGE_PREROUTING; nf_bridge->in_prerouting = 0;
if (br_nf_ipv6_daddr_was_changed(skb, nf_bridge)) { if (br_nf_ipv6_daddr_was_changed(skb, nf_bridge)) {
skb_dst_drop(skb); skb_dst_drop(skb);
v6ops->route_input(skb); v6ops->route_input(skb);
......
...@@ -49,12 +49,9 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, ...@@ -49,12 +49,9 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
if (skb->nfct) if (skb->nfct)
zone = nf_ct_zone((struct nf_conn *)skb->nfct); zone = nf_ct_zone((struct nf_conn *)skb->nfct);
#endif #endif
if (nf_bridge_in_prerouting(skb))
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (skb->nf_bridge &&
skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone; return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
#endif
if (hooknum == NF_INET_PRE_ROUTING) if (hooknum == NF_INET_PRE_ROUTING)
return IP_DEFRAG_CONNTRACK_IN + zone; return IP_DEFRAG_CONNTRACK_IN + zone;
else else
......
...@@ -39,12 +39,9 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, ...@@ -39,12 +39,9 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
if (skb->nfct) if (skb->nfct)
zone = nf_ct_zone((struct nf_conn *)skb->nfct); zone = nf_ct_zone((struct nf_conn *)skb->nfct);
#endif #endif
if (nf_bridge_in_prerouting(skb))
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (skb->nf_bridge &&
skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
#endif
if (hooknum == NF_INET_PRE_ROUTING) if (hooknum == NF_INET_PRE_ROUTING)
return IP6_DEFRAG_CONNTRACK_IN + zone; return IP6_DEFRAG_CONNTRACK_IN + zone;
else else
......
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