net: bridge: mcast: add support for raw L2 multicast groups
[linux-2.6-microblaze.git] / net / bridge / br_private.h
index 345118e..4c691c3 100644 (file)
@@ -383,7 +383,7 @@ enum net_bridge_opts {
 struct net_bridge {
        spinlock_t                      lock;
        spinlock_t                      hash_lock;
-       struct list_head                port_list;
+       struct hlist_head               frame_type_list;
        struct net_device               *dev;
        struct pcpu_sw_netstats         __percpu *stats;
        unsigned long                   options;
@@ -395,6 +395,7 @@ struct net_bridge {
 #endif
 
        struct rhashtable               fdb_hash_tbl;
+       struct list_head                port_list;
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
        union {
                struct rtable           fake_rtable;
@@ -483,6 +484,9 @@ struct net_bridge {
 #if IS_ENABLED(CONFIG_BRIDGE_MRP)
        struct list_head                mrp_list;
 #endif
+#if IS_ENABLED(CONFIG_BRIDGE_CFM)
+       struct hlist_head               mep_list;
+#endif
 };
 
 struct br_input_skb_cb {
@@ -755,6 +759,16 @@ int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
 int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
 rx_handler_func_t *br_get_rx_handler(const struct net_device *dev);
 
+struct br_frame_type {
+       __be16                  type;
+       int                     (*frame_handler)(struct net_bridge_port *port,
+                                                struct sk_buff *skb);
+       struct hlist_node       list;
+};
+
+void br_add_frame(struct net_bridge *br, struct br_frame_type *ft);
+void br_del_frame(struct net_bridge *br, struct br_frame_type *ft);
+
 static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
 {
        return rcu_dereference(dev->rx_handler) == br_get_rx_handler(dev);
@@ -840,6 +854,11 @@ void br_multicast_star_g_handle_mode(struct net_bridge_port_group *pg,
 void br_multicast_sg_add_exclude_ports(struct net_bridge_mdb_entry *star_mp,
                                       struct net_bridge_port_group *sg);
 
+static inline bool br_group_is_l2(const struct br_ip *group)
+{
+       return group->proto == 0;
+}
+
 #define mlock_dereference(X, br) \
        rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
 
@@ -871,7 +890,8 @@ __br_multicast_querier_exists(struct net_bridge *br,
 }
 
 static inline bool br_multicast_querier_exists(struct net_bridge *br,
-                                              struct ethhdr *eth)
+                                              struct ethhdr *eth,
+                                              const struct net_bridge_mdb_entry *mdb)
 {
        switch (eth->h_proto) {
        case (htons(ETH_P_IP)):
@@ -883,7 +903,7 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br,
                        &br->ip6_other_query, true);
 #endif
        default:
-               return false;
+               return !!mdb && br_group_is_l2(&mdb->addr);
        }
 }
 
@@ -1417,7 +1437,6 @@ extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr)
 #if IS_ENABLED(CONFIG_BRIDGE_MRP)
 int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
                 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack);
-int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);
 bool br_mrp_enabled(struct net_bridge *br);
 void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p);
 int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br);
@@ -1429,11 +1448,6 @@ static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
        return -EOPNOTSUPP;
 }
 
-static inline int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
-{
-       return 0;
-}
-
 static inline bool br_mrp_enabled(struct net_bridge *br)
 {
        return false;
@@ -1451,12 +1465,67 @@ static inline int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
 
 #endif
 
+/* br_cfm.c */
+#if IS_ENABLED(CONFIG_BRIDGE_CFM)
+int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
+                struct nlattr *attr, int cmd, struct netlink_ext_ack *extack);
+bool br_cfm_created(struct net_bridge *br);
+void br_cfm_port_del(struct net_bridge *br, struct net_bridge_port *p);
+int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br);
+int br_cfm_status_fill_info(struct sk_buff *skb,
+                           struct net_bridge *br,
+                           bool getlink);
+int br_cfm_mep_count(struct net_bridge *br, u32 *count);
+int br_cfm_peer_mep_count(struct net_bridge *br, u32 *count);
+#else
+static inline int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
+                              struct nlattr *attr, int cmd,
+                              struct netlink_ext_ack *extack)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline bool br_cfm_created(struct net_bridge *br)
+{
+       return false;
+}
+
+static inline void br_cfm_port_del(struct net_bridge *br,
+                                  struct net_bridge_port *p)
+{
+}
+
+static inline int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int br_cfm_status_fill_info(struct sk_buff *skb,
+                                         struct net_bridge *br,
+                                         bool getlink)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int br_cfm_mep_count(struct net_bridge *br, u32 *count)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int br_cfm_peer_mep_count(struct net_bridge *br, u32 *count)
+{
+       return -EOPNOTSUPP;
+}
+#endif
+
 /* br_netlink.c */
 extern struct rtnl_link_ops br_link_ops;
 int br_netlink_init(void);
 void br_netlink_fini(void);
 void br_ifinfo_notify(int event, const struct net_bridge *br,
                      const struct net_bridge_port *port);
+void br_info_notify(int event, const struct net_bridge *br,
+                   const struct net_bridge_port *port, u32 filter);
 int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags,
               struct netlink_ext_ack *extack);
 int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);