Use bit 0 to distinguish port-VLAN pointers from bridge port pointers in
struct net_bridge_dst. Add helpers for constructing and decoding VLAN
destinations. No caller creates one yet, so behavior remains unchanged.

Reviewed-by: Ido Schimmel <[email protected]>
Signed-off-by: Nikolay Aleksandrov <[email protected]>
---
 net/bridge/br_private.h | 50 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bbb59b53e745..2bf7f4429a3b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -306,6 +306,8 @@ struct net_bridge_fdb_key {
        u16 vlan_id;
 };
 
+#define BR_DST_VLAN_TAG        BIT(0)
+
 struct net_bridge_dst {
        unsigned long __private value;
 };
@@ -702,10 +704,56 @@ br_port_to_dst(const struct net_bridge_port *p)
        return dst;
 }
 
+static inline struct net_bridge_dst
+br_vlan_to_dst(const struct net_bridge_vlan *v)
+{
+       struct net_bridge_dst dst;
+
+       ACCESS_PRIVATE(&dst, value) = (unsigned long)v | BR_DST_VLAN_TAG;
+
+       return dst;
+}
+
+static inline void br_dst_decode(struct net_bridge_dst dst,
+                                struct net_bridge_port **port,
+                                struct net_bridge_vlan **vlan)
+{
+       struct net_bridge_vlan *v;
+       unsigned long value;
+
+       value = ACCESS_PRIVATE(&dst, value);
+       if (!(value & BR_DST_VLAN_TAG)) {
+               *port = (struct net_bridge_port *)value;
+               *vlan = NULL;
+               return;
+       }
+
+       v = (struct net_bridge_vlan *)(value & ~BR_DST_VLAN_TAG);
+       *port = v->port;
+       *vlan = v;
+}
+
 static inline struct net_bridge_port *
 br_dst_port(struct net_bridge_dst dst)
 {
-       return (struct net_bridge_port *)ACCESS_PRIVATE(&dst, value);
+       struct net_bridge_port *p;
+       struct net_bridge_vlan *v;
+
+       br_dst_decode(dst, &p, &v);
+
+       return p;
+}
+
+static inline struct net_bridge_vlan *
+br_dst_vlan(struct net_bridge_dst dst)
+{
+       unsigned long value;
+
+       value = ACCESS_PRIVATE(&dst, value);
+       if (!(value & BR_DST_VLAN_TAG))
+               return NULL;
+
+       return (struct net_bridge_vlan *)(value & ~BR_DST_VLAN_TAG);
 }
 
 static inline struct net_bridge_dst
-- 
2.47.3


Reply via email to