These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / bridge / br_private.h
index 3362c29..216018c 100644 (file)
@@ -18,7 +18,9 @@
 #include <linux/netpoll.h>
 #include <linux/u64_stats_sync.h>
 #include <net/route.h>
+#include <net/ip6_fib.h>
 #include <linux/if_vlan.h>
+#include <linux/rhashtable.h>
 
 #define BR_HASH_BITS 8
 #define BR_HASH_SIZE (1 << BR_HASH_BITS)
 
 #define BR_PORT_BITS   10
 #define BR_MAX_PORTS   (1<<BR_PORT_BITS)
-#define BR_VLAN_BITMAP_LEN     BITS_TO_LONGS(VLAN_N_VID)
 
 #define BR_VERSION     "2.3"
 
 /* Control of forwarding link local multicast */
 #define BR_GROUPFWD_DEFAULT    0
-/* Don't allow forwarding control protocols like STP and LLDP */
-#define BR_GROUPFWD_RESTRICTED 0x4007u
+/* Don't allow forwarding of control protocols like STP, MAC PAUSE and LACP */
+#define BR_GROUPFWD_RESTRICTED 0x0007u
 /* The Nearest Customer Bridge Group Address, 01-80-C2-00-00-[00,0B,0C,0D,0F] */
 #define BR_GROUPFWD_8021AD     0xB801u
 
@@ -76,17 +77,61 @@ struct bridge_mcast_querier {
 };
 #endif
 
-struct net_port_vlans {
-       u16                             port_idx;
-       u16                             pvid;
+/**
+ * struct net_bridge_vlan - per-vlan entry
+ *
+ * @vnode: rhashtable member
+ * @vid: VLAN id
+ * @flags: bridge vlan flags
+ * @br: if MASTER flag set, this points to a bridge struct
+ * @port: if MASTER flag unset, this points to a port struct
+ * @refcnt: if MASTER flag set, this is bumped for each port referencing it
+ * @brvlan: if MASTER flag unset, this points to the global per-VLAN context
+ *          for this VLAN entry
+ * @vlist: sorted list of VLAN entries
+ * @rcu: used for entry destruction
+ *
+ * This structure is shared between the global per-VLAN entries contained in
+ * the bridge rhashtable and the local per-port per-VLAN entries contained in
+ * the port's rhashtable. The union entries should be interpreted depending on
+ * the entry flags that are set.
+ */
+struct net_bridge_vlan {
+       struct rhash_head               vnode;
+       u16                             vid;
+       u16                             flags;
+       union {
+               struct net_bridge       *br;
+               struct net_bridge_port  *port;
+       };
        union {
-               struct net_bridge_port          *port;
-               struct net_bridge               *br;
-       }                               parent;
+               atomic_t                refcnt;
+               struct net_bridge_vlan  *brvlan;
+       };
+       struct list_head                vlist;
+
        struct rcu_head                 rcu;
-       unsigned long                   vlan_bitmap[BR_VLAN_BITMAP_LEN];
-       unsigned long                   untagged_bitmap[BR_VLAN_BITMAP_LEN];
+};
+
+/**
+ * struct net_bridge_vlan_group
+ *
+ * @vlan_hash: VLAN entry rhashtable
+ * @vlan_list: sorted VLAN entry list
+ * @num_vlans: number of total VLAN entries
+ * @pvid: PVID VLAN id
+ *
+ * IMPORTANT: Be careful when checking if there're VLAN entries using list
+ *            primitives because the bridge can have entries in its list which
+ *            are just for global context but not for filtering, i.e. they have
+ *            the master flag set but not the brentry flag. If you have to check
+ *            if there're "real" entries in the bridge please test @num_vlans
+ */
+struct net_bridge_vlan_group {
+       struct rhashtable               vlan_hash;
+       struct list_head                vlan_list;
        u16                             num_vlans;
+       u16                             pvid;
 };
 
 struct net_bridge_fdb_entry
@@ -94,15 +139,15 @@ struct net_bridge_fdb_entry
        struct hlist_node               hlist;
        struct net_bridge_port          *dst;
 
-       struct rcu_head                 rcu;
        unsigned long                   updated;
        unsigned long                   used;
        mac_addr                        addr;
+       __u16                           vlan_id;
        unsigned char                   is_local:1,
                                        is_static:1,
                                        added_by_user:1,
                                        added_by_external_learn:1;
-       __u16                           vlan_id;
+       struct rcu_head                 rcu;
 };
 
 struct net_bridge_port_group {
@@ -184,7 +229,7 @@ struct net_bridge_port
        struct netpoll                  *np;
 #endif
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
-       struct net_port_vlans __rcu     *vlan_info;
+       struct net_bridge_vlan_group    __rcu *vlgrp;
 #endif
 };
 
@@ -214,7 +259,10 @@ struct net_bridge
        spinlock_t                      hash_lock;
        struct hlist_head               hash[BR_HASH_SIZE];
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-       struct rtable                   fake_rtable;
+       union {
+               struct rtable           fake_rtable;
+               struct rt6_info         fake_rt6_info;
+       };
        bool                            nf_call_iptables;
        bool                            nf_call_ip6tables;
        bool                            nf_call_arptables;
@@ -289,10 +337,10 @@ struct net_bridge
        struct kobject                  *ifobj;
        u32                             auto_cnt;
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
+       struct net_bridge_vlan_group    __rcu *vlgrp;
        u8                              vlan_enabled;
        __be16                          vlan_proto;
        u16                             default_pvid;
-       struct net_port_vlans __rcu     *vlan_info;
 #endif
 };
 
@@ -304,7 +352,6 @@ struct br_input_skb_cb {
        int mrouters_only;
 #endif
 
-       u16 frag_max_size;
        bool proxyarp_replied;
 
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
@@ -341,6 +388,31 @@ static inline int br_is_root_bridge(const struct net_bridge *br)
        return !memcmp(&br->bridge_id, &br->designated_root, 8);
 }
 
+/* check if a VLAN entry is global */
+static inline bool br_vlan_is_master(const struct net_bridge_vlan *v)
+{
+       return v->flags & BRIDGE_VLAN_INFO_MASTER;
+}
+
+/* check if a VLAN entry is used by the bridge */
+static inline bool br_vlan_is_brentry(const struct net_bridge_vlan *v)
+{
+       return v->flags & BRIDGE_VLAN_INFO_BRENTRY;
+}
+
+/* check if we should use the vlan entry, returns false if it's only context */
+static inline bool br_vlan_should_use(const struct net_bridge_vlan *v)
+{
+       if (br_vlan_is_master(v)) {
+               if (br_vlan_is_brentry(v))
+                       return true;
+               else
+                       return false;
+       }
+
+       return true;
+}
+
 /* br_device.c */
 void br_dev_setup(struct net_device *dev);
 void br_dev_delete(struct net_device *dev, struct list_head *list);
@@ -384,7 +456,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr);
 void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr);
 void br_fdb_cleanup(unsigned long arg);
 void br_fdb_delete_by_port(struct net_bridge *br,
-                          const struct net_bridge_port *p, int do_all);
+                          const struct net_bridge_port *p, u16 vid, int do_all);
 struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
                                          const unsigned char *addr, __u16 vid);
 int br_fdb_test_addr(struct net_device *dev, unsigned char *addr);
@@ -410,10 +482,10 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 
 /* br_forward.c */
 void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb);
-int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb);
+int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb);
 void br_forward(const struct net_bridge_port *to,
                struct sk_buff *skb, struct sk_buff *skb0);
-int br_forward_finish(struct sock *sk, struct sk_buff *skb);
+int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
 void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast);
 void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
                      struct sk_buff *skb2, bool unicast);
@@ -431,7 +503,7 @@ void br_port_flags_change(struct net_bridge_port *port, unsigned long mask);
 void br_manage_promisc(struct net_bridge *br);
 
 /* br_input.c */
-int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb);
+int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
 rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
 
 static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
@@ -463,6 +535,7 @@ void br_multicast_disable_port(struct net_bridge_port *port);
 void br_multicast_init(struct net_bridge *br);
 void br_multicast_open(struct net_bridge *br);
 void br_multicast_stop(struct net_bridge *br);
+void br_multicast_dev_del(struct net_bridge *br);
 void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
                          struct sk_buff *skb);
 void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
@@ -485,7 +558,9 @@ br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
 void br_mdb_init(void);
 void br_mdb_uninit(void);
 void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
-                  struct br_ip *group, int type);
+                  struct br_ip *group, int type, u8 state);
+void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
+                  int type);
 
 #define mlock_dereference(X, br) \
        rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
@@ -562,6 +637,10 @@ static inline void br_multicast_stop(struct net_bridge *br)
 {
 }
 
+static inline void br_multicast_dev_del(struct net_bridge *br)
+{
+}
+
 static inline void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
                                        struct sk_buff *skb)
 {
@@ -591,39 +670,55 @@ static inline void br_mdb_uninit(void)
 
 /* br_vlan.c */
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
-bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
-                       struct sk_buff *skb, u16 *vid);
-bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v,
+bool br_allowed_ingress(const struct net_bridge *br,
+                       struct net_bridge_vlan_group *vg, struct sk_buff *skb,
+                       u16 *vid);
+bool br_allowed_egress(struct net_bridge_vlan_group *vg,
                       const struct sk_buff *skb);
 bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid);
 struct sk_buff *br_handle_vlan(struct net_bridge *br,
-                              const struct net_port_vlans *v,
+                              struct net_bridge_vlan_group *vg,
                               struct sk_buff *skb);
 int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags);
 int br_vlan_delete(struct net_bridge *br, u16 vid);
 void br_vlan_flush(struct net_bridge *br);
-bool br_vlan_find(struct net_bridge *br, u16 vid);
+struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid);
 void br_recalculate_fwd_mask(struct net_bridge *br);
+int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
 int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
+int __br_vlan_set_proto(struct net_bridge *br, __be16 proto);
 int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
 int br_vlan_init(struct net_bridge *br);
 int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
+int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid);
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
 void nbp_vlan_flush(struct net_bridge_port *port);
-bool nbp_vlan_find(struct net_bridge_port *port, u16 vid);
 int nbp_vlan_init(struct net_bridge_port *port);
+int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
 
-static inline struct net_port_vlans *br_get_vlan_info(
-                                               const struct net_bridge *br)
+static inline struct net_bridge_vlan_group *br_vlan_group(
+                                       const struct net_bridge *br)
 {
-       return rcu_dereference_rtnl(br->vlan_info);
+       return rtnl_dereference(br->vlgrp);
 }
 
-static inline struct net_port_vlans *nbp_get_vlan_info(
-                                               const struct net_bridge_port *p)
+static inline struct net_bridge_vlan_group *nbp_vlan_group(
+                                       const struct net_bridge_port *p)
 {
-       return rcu_dereference_rtnl(p->vlan_info);
+       return rtnl_dereference(p->vlgrp);
+}
+
+static inline struct net_bridge_vlan_group *br_vlan_group_rcu(
+                                       const struct net_bridge *br)
+{
+       return rcu_dereference(br->vlgrp);
+}
+
+static inline struct net_bridge_vlan_group *nbp_vlan_group_rcu(
+                                       const struct net_bridge_port *p)
+{
+       return rcu_dereference(p->vlgrp);
 }
 
 /* Since bridge now depends on 8021Q module, but the time bridge sees the
@@ -633,9 +728,9 @@ static inline int br_vlan_get_tag(const struct sk_buff *skb, u16 *vid)
 {
        int err = 0;
 
-       if (skb_vlan_tag_present(skb))
+       if (skb_vlan_tag_present(skb)) {
                *vid = skb_vlan_tag_get(skb) & VLAN_VID_MASK;
-       else {
+       else {
                *vid = 0;
                err = -EINVAL;
        }
@@ -643,13 +738,13 @@ static inline int br_vlan_get_tag(const struct sk_buff *skb, u16 *vid)
        return err;
 }
 
-static inline u16 br_get_pvid(const struct net_port_vlans *v)
+static inline u16 br_get_pvid(const struct net_bridge_vlan_group *vg)
 {
-       if (!v)
+       if (!vg)
                return 0;
 
        smp_rmb();
-       return v->pvid;
+       return vg->pvid;
 }
 
 static inline int br_vlan_enabled(struct net_bridge *br)
@@ -657,16 +752,15 @@ static inline int br_vlan_enabled(struct net_bridge *br)
        return br->vlan_enabled;
 }
 #else
-static inline bool br_allowed_ingress(struct net_bridge *br,
-                                     struct net_port_vlans *v,
+static inline bool br_allowed_ingress(const struct net_bridge *br,
+                                     struct net_bridge_vlan_group *vg,
                                      struct sk_buff *skb,
                                      u16 *vid)
 {
        return true;
 }
 
-static inline bool br_allowed_egress(struct net_bridge *br,
-                                    const struct net_port_vlans *v,
+static inline bool br_allowed_egress(struct net_bridge_vlan_group *vg,
                                     const struct sk_buff *skb)
 {
        return true;
@@ -679,7 +773,7 @@ static inline bool br_should_learn(struct net_bridge_port *p,
 }
 
 static inline struct sk_buff *br_handle_vlan(struct net_bridge *br,
-                                            const struct net_port_vlans *v,
+                                            struct net_bridge_vlan_group *vg,
                                             struct sk_buff *skb)
 {
        return skb;
@@ -699,11 +793,6 @@ static inline void br_vlan_flush(struct net_bridge *br)
 {
 }
 
-static inline bool br_vlan_find(struct net_bridge *br, u16 vid)
-{
-       return false;
-}
-
 static inline void br_recalculate_fwd_mask(struct net_bridge *br)
 {
 }
@@ -727,40 +816,68 @@ static inline void nbp_vlan_flush(struct net_bridge_port *port)
 {
 }
 
-static inline struct net_port_vlans *br_get_vlan_info(
-                                               const struct net_bridge *br)
+static inline struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg,
+                                                  u16 vid)
 {
        return NULL;
 }
-static inline struct net_port_vlans *nbp_get_vlan_info(
-                                               const struct net_bridge_port *p)
+
+static inline int nbp_vlan_init(struct net_bridge_port *port)
 {
-       return NULL;
+       return 0;
 }
 
-static inline bool nbp_vlan_find(struct net_bridge_port *port, u16 vid)
+static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag)
 {
-       return false;
+       return 0;
 }
 
-static inline int nbp_vlan_init(struct net_bridge_port *port)
+static inline u16 br_get_pvid(const struct net_bridge_vlan_group *vg)
 {
        return 0;
 }
 
-static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag)
+static inline int br_vlan_enabled(struct net_bridge *br)
 {
        return 0;
 }
-static inline u16 br_get_pvid(const struct net_port_vlans *v)
+
+static inline int __br_vlan_filter_toggle(struct net_bridge *br,
+                                         unsigned long val)
 {
-       return 0;
+       return -EOPNOTSUPP;
 }
 
-static inline int br_vlan_enabled(struct net_bridge *br)
+static inline int nbp_get_num_vlan_infos(struct net_bridge_port *p,
+                                        u32 filter_mask)
 {
        return 0;
 }
+
+static inline struct net_bridge_vlan_group *br_vlan_group(
+                                       const struct net_bridge *br)
+{
+       return NULL;
+}
+
+static inline struct net_bridge_vlan_group *nbp_vlan_group(
+                                       const struct net_bridge_port *p)
+{
+       return NULL;
+}
+
+static inline struct net_bridge_vlan_group *br_vlan_group_rcu(
+                                       const struct net_bridge *br)
+{
+       return NULL;
+}
+
+static inline struct net_bridge_vlan_group *nbp_vlan_group_rcu(
+                                       const struct net_bridge_port *p)
+{
+       return NULL;
+}
+
 #endif
 
 struct nf_br_ops {
@@ -790,6 +907,7 @@ void __br_set_forward_delay(struct net_bridge *br, unsigned long t);
 int br_set_forward_delay(struct net_bridge *br, unsigned long x);
 int br_set_hello_time(struct net_bridge *br, unsigned long x);
 int br_set_max_age(struct net_bridge *br, unsigned long x);
+int br_set_ageing_time(struct net_bridge *br, u32 ageing_time);
 
 
 /* br_stp_if.c */