Merge tag 'pci-v5.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[linux-2.6-microblaze.git] / net / bridge / br_input.c
index 59a318b..8ca1f1b 100644 (file)
@@ -35,12 +35,8 @@ static int br_pass_frame_up(struct sk_buff *skb)
        struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
        struct net_bridge *br = netdev_priv(brdev);
        struct net_bridge_vlan_group *vg;
-       struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats);
 
-       u64_stats_update_begin(&brstats->syncp);
-       brstats->rx_packets++;
-       brstats->rx_bytes += skb->len;
-       u64_stats_update_end(&brstats->syncp);
+       dev_sw_netstats_rx_add(brdev, skb->len);
 
        vg = br_vlan_group_rcu(br);
        /* Bridge is just like any other port.  Make sure the
@@ -134,7 +130,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        case BR_PKT_MULTICAST:
                mdst = br_mdb_get(br, skb, vid);
                if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
-                   br_multicast_querier_exists(br, eth_hdr(skb))) {
+                   br_multicast_querier_exists(br, eth_hdr(skb), mdst)) {
                        if ((mdst && mdst->host_joined) ||
                            br_multicast_is_router(br)) {
                                local_rcv = true;
@@ -254,6 +250,21 @@ frame_finish:
        return RX_HANDLER_CONSUMED;
 }
 
+/* Return 0 if the frame was not processed otherwise 1
+ * note: already called with rcu_read_lock
+ */
+static int br_process_frame_type(struct net_bridge_port *p,
+                                struct sk_buff *skb)
+{
+       struct br_frame_type *tmp;
+
+       hlist_for_each_entry_rcu(tmp, &p->br->frame_type_list, list)
+               if (unlikely(tmp->type == skb->protocol))
+                       return tmp->frame_handler(p, skb);
+
+       return 0;
+}
+
 /*
  * Return NULL if skb is handled
  * note: already called with rcu_read_lock
@@ -343,7 +354,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
                }
        }
 
-       if (unlikely(br_mrp_process(p, skb)))
+       if (unlikely(br_process_frame_type(p, skb)))
                return RX_HANDLER_PASS;
 
 forward:
@@ -380,3 +391,19 @@ rx_handler_func_t *br_get_rx_handler(const struct net_device *dev)
 
        return br_handle_frame;
 }
+
+void br_add_frame(struct net_bridge *br, struct br_frame_type *ft)
+{
+       hlist_add_head_rcu(&ft->list, &br->frame_type_list);
+}
+
+void br_del_frame(struct net_bridge *br, struct br_frame_type *ft)
+{
+       struct br_frame_type *tmp;
+
+       hlist_for_each_entry(tmp, &br->frame_type_list, list)
+               if (ft == tmp) {
+                       hlist_del_rcu(&ft->list);
+                       return;
+               }
+}