netfilter: bridge: reduce nf_bridge_info to 32 bytes again
authorFlorian Westphal <fw@strlen.de>
Thu, 23 Jul 2015 14:21:30 +0000 (16:21 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 30 Jul 2015 11:37:42 +0000 (13:37 +0200)
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: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter_bridge.h
include/linux/skbuff.h
net/bridge/br_netfilter_hooks.c
net/bridge/br_netfilter_ipv6.c
net/ipv4/netfilter/nf_defrag_ipv4.c
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c

index 6d80fc68632328c743f66d6370388b5406eb7fcb..2437b8a5d7a945d2a3ab5c4ff67dfd6f260bc95a 100644 (file)
@@ -17,9 +17,6 @@ enum nf_br_hook_priorities {
 
 #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);
 
 static inline void br_drop_fake_rtable(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;
 }
+
+static inline bool nf_bridge_in_prerouting(const struct sk_buff *skb)
+{
+       return skb->nf_bridge && skb->nf_bridge->in_prerouting;
+}
 #else
 #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
index d6cdd6e87d53bcd1b4f390f61f73b1c91b076bdd..ac732e67a6c81ba11e1128874a891ff395b25ccd 100644 (file)
@@ -173,17 +173,24 @@ struct nf_bridge_info {
                BRNF_PROTO_8021Q,
                BRNF_PROTO_PPPOE
        } orig_proto:8;
-       bool                    pkt_otherhost;
+       u8                      pkt_otherhost:1;
+       u8                      in_prerouting:1;
+       u8                      bridged_dnat:1;
        __u16                   frag_max_size;
-       unsigned int            mask;
        struct net_device       *physindev;
        union {
-               struct net_device *physoutdev;
-               char neigh_header[8];
-       };
-       union {
+               /* prerouting: detect dnat in orig/reply direction */
                __be32          ipv4_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
index c8b9bcfe997e48556cfc2633981e272e063f6880..ec51c2ba30e9aad8c3406eacc6493db07a1ab6a5 100644 (file)
@@ -284,7 +284,7 @@ int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb)
                                                         nf_bridge->neigh_header,
                                                         ETH_HLEN-ETH_ALEN);
                        /* tell br_dev_xmit to continue with forwarding */
-                       nf_bridge->mask |= BRNF_BRIDGED_DNAT;
+                       nf_bridge->bridged_dnat = 1;
                        /* FIXME Need to refragment */
                        ret = neigh->output(neigh, skb);
                }
@@ -356,7 +356,7 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb)
                skb->pkt_type = PACKET_OTHERHOST;
                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 ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, 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)
                nf_bridge->pkt_otherhost = true;
        }
 
-       nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
+       nf_bridge->in_prerouting = 1;
        nf_bridge->physindev = 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,
                                   struct sk_buff *skb,
                                   const struct nf_hook_state *state)
 {
-       if (skb->nf_bridge &&
-           !(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
+       if (skb->nf_bridge && !skb->nf_bridge->in_prerouting)
                return NF_STOP;
-       }
 
        return NF_ACCEPT;
 }
@@ -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);
 
        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));
 
@@ -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)
 {
-       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);
                return 1;
        }
index 13b7d1e3d1850e9aa408b55287c8ad72c950081a..77383bfe7ea38f888ce67619d03d1b7856bab84b 100644 (file)
@@ -174,7 +174,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb)
                skb->pkt_type = PACKET_OTHERHOST;
                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)) {
                skb_dst_drop(skb);
                v6ops->route_input(skb);
index c88b7d4347187260e789612c44f34059092dc41d..b69e82bda2159464b2eb0b0fd7c184c605947cc8 100644 (file)
@@ -49,12 +49,9 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
        if (skb->nfct)
                zone = nf_ct_zone((struct nf_conn *)skb->nfct);
 #endif
-
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-       if (skb->nf_bridge &&
-           skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+       if (nf_bridge_in_prerouting(skb))
                return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
-#endif
+
        if (hooknum == NF_INET_PRE_ROUTING)
                return IP_DEFRAG_CONNTRACK_IN + zone;
        else
index a45db0b4785c1e89f523ce28cb8e4231fbbc85b9..267fb8d5876e169f27e0e9a595dc89a20cfbea4e 100644 (file)
@@ -39,12 +39,9 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
        if (skb->nfct)
                zone = nf_ct_zone((struct nf_conn *)skb->nfct);
 #endif
-
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-       if (skb->nf_bridge &&
-           skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+       if (nf_bridge_in_prerouting(skb))
                return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
-#endif
+
        if (hooknum == NF_INET_PRE_ROUTING)
                return IP6_DEFRAG_CONNTRACK_IN + zone;
        else