#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)
 {
        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
 
                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
 
                                                         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);
                }
                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);
                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);
 
                                   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;
 }
        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));
 
 
 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;
        }
 
                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);
 
        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
 
        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