]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - net/batman-adv/multicast.c
ipv6: make mc_forwarding atomic
[mirror_ubuntu-jammy-kernel.git] / net / batman-adv / multicast.c
index a3b6658ed789919444a8ad341387ee06bdb5101c..2853634a39790ddbf77b4bf0b487b33f032ea3c0 100644 (file)
@@ -134,7 +134,7 @@ static u8 batadv_mcast_mla_rtr_flags_softif_get_ipv6(struct net_device *dev)
 {
        struct inet6_dev *in6_dev = __in6_dev_get(dev);
 
-       if (in6_dev && in6_dev->cnf.mc_forwarding)
+       if (in6_dev && atomic_read(&in6_dev->cnf.mc_forwarding))
                return BATADV_NO_FLAGS;
        else
                return BATADV_MCAST_WANT_NO_RTR6;
@@ -1339,6 +1339,7 @@ batadv_mcast_forw_rtr_node_get(struct batadv_priv *bat_priv,
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: The multicast packet to check
  * @orig: an originator to be set to forward the skb to
+ * @is_routable: stores whether the destination is routable
  *
  * Return: the forwarding mode as enum batadv_forw_mode and in case of
  * BATADV_FORW_SINGLE set the orig to the single originator the skb
@@ -1346,17 +1347,16 @@ batadv_mcast_forw_rtr_node_get(struct batadv_priv *bat_priv,
  */
 enum batadv_forw_mode
 batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
-                      struct batadv_orig_node **orig)
+                      struct batadv_orig_node **orig, int *is_routable)
 {
        int ret, tt_count, ip_count, unsnoop_count, total_count;
        bool is_unsnoopable = false;
        unsigned int mcast_fanout;
        struct ethhdr *ethhdr;
-       int is_routable = 0;
        int rtr_count = 0;
 
        ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable,
-                                          &is_routable);
+                                          is_routable);
        if (ret == -ENOMEM)
                return BATADV_FORW_NONE;
        else if (ret < 0)
@@ -1369,7 +1369,7 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
        ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr);
        unsnoop_count = !is_unsnoopable ? 0 :
                        atomic_read(&bat_priv->mcast.num_want_all_unsnoopables);
-       rtr_count = batadv_mcast_forw_rtr_count(bat_priv, is_routable);
+       rtr_count = batadv_mcast_forw_rtr_count(bat_priv, *is_routable);
 
        total_count = tt_count + ip_count + unsnoop_count + rtr_count;
 
@@ -1689,6 +1689,7 @@ batadv_mcast_forw_want_rtr(struct batadv_priv *bat_priv,
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: the multicast packet to transmit
  * @vid: the vlan identifier
+ * @is_routable: stores whether the destination is routable
  *
  * Sends copies of a frame with multicast destination to any node that signaled
  * interest in it, that is either via the translation table or the according
@@ -1701,7 +1702,7 @@ batadv_mcast_forw_want_rtr(struct batadv_priv *bat_priv,
  * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
  */
 int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
-                          unsigned short vid)
+                          unsigned short vid, int is_routable)
 {
        int ret;
 
@@ -1717,12 +1718,16 @@ int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
                return ret;
        }
 
+       if (!is_routable)
+               goto skip_mc_router;
+
        ret = batadv_mcast_forw_want_rtr(bat_priv, skb, vid);
        if (ret != NET_XMIT_SUCCESS) {
                kfree_skb(skb);
                return ret;
        }
 
+skip_mc_router:
        consume_skb(skb);
        return ret;
 }