Merge tag 'batadv-net-for-davem-20190509' of git://git.open-mesh.org/linux-merge
authorDavid S. Miller <davem@davemloft.net>
Thu, 9 May 2019 16:44:17 +0000 (09:44 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 9 May 2019 16:44:17 +0000 (09:44 -0700)
Simon Wunderlich says:

====================
This feature/cleanup patchset includes the following patches:

 - bump version strings, by Simon Wunderlich (we forgot to include
   this patch previously ...)

 - fix multicast tt/tvlv worker locking, by Linus Lüssing
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
1  2 
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/multicast.c
net/batman-adv/types.h

diff --combined net/batman-adv/main.c
index dabcaff87e3499b416e762da173f0def4cdeac86,f8725786b5961ac3b663bf22c16738a8a55e51c8..4a89177def647db602edb96634f45cf1cfbcfd5f
@@@ -2,6 -2,18 +2,6 @@@
  /* Copyright (C) 2007-2019  B.A.T.M.A.N. contributors:
   *
   * Marek Lindner, Simon Wunderlich
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of version 2 of the GNU General Public
 - * License as published by the Free Software Foundation.
 - *
 - * This program is distributed in the hope that it will be useful, but
 - * WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 - * General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, see <http://www.gnu.org/licenses/>.
   */
  
  #include "main.h"
@@@ -10,7 -22,6 +10,7 @@@
  #include <linux/build_bug.h>
  #include <linux/byteorder/generic.h>
  #include <linux/crc32c.h>
 +#include <linux/device.h>
  #include <linux/errno.h>
  #include <linux/genetlink.h>
  #include <linux/gfp.h>
@@@ -20,7 -31,6 +20,7 @@@
  #include <linux/ip.h>
  #include <linux/ipv6.h>
  #include <linux/kernel.h>
 +#include <linux/kobject.h>
  #include <linux/kref.h>
  #include <linux/list.h>
  #include <linux/module.h>
@@@ -30,7 -40,6 +30,7 @@@
  #include <linux/rcupdate.h>
  #include <linux/seq_file.h>
  #include <linux/skbuff.h>
 +#include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/stddef.h>
  #include <linux/string.h>
@@@ -75,22 -84,6 +75,22 @@@ struct workqueue_struct *batadv_event_w
  
  static void batadv_recv_handler_init(void);
  
 +#define BATADV_UEV_TYPE_VAR   "BATTYPE="
 +#define BATADV_UEV_ACTION_VAR "BATACTION="
 +#define BATADV_UEV_DATA_VAR   "BATDATA="
 +
 +static char *batadv_uev_action_str[] = {
 +      "add",
 +      "del",
 +      "change",
 +      "loopdetect",
 +};
 +
 +static char *batadv_uev_type_str[] = {
 +      "gw",
 +      "bla",
 +};
 +
  static int __init batadv_init(void)
  {
        int ret;
@@@ -168,6 -161,7 +168,7 @@@ int batadv_mesh_init(struct net_device 
        spin_lock_init(&bat_priv->tt.commit_lock);
        spin_lock_init(&bat_priv->gw.list_lock);
  #ifdef CONFIG_BATMAN_ADV_MCAST
+       spin_lock_init(&bat_priv->mcast.mla_lock);
        spin_lock_init(&bat_priv->mcast.want_lists_lock);
  #endif
        spin_lock_init(&bat_priv->tvlv.container_list_lock);
@@@ -685,60 -679,6 +686,60 @@@ bool batadv_vlan_ap_isola_get(struct ba
        return ap_isolation_enabled;
  }
  
 +/**
 + * batadv_throw_uevent() - Send an uevent with batman-adv specific env data
 + * @bat_priv: the bat priv with all the soft interface information
 + * @type: subsystem type of event. Stored in uevent's BATTYPE
 + * @action: action type of event. Stored in uevent's BATACTION
 + * @data: string with additional information to the event (ignored for
 + *  BATADV_UEV_DEL). Stored in uevent's BATDATA
 + *
 + * Return: 0 on success or negative error number in case of failure
 + */
 +int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
 +                      enum batadv_uev_action action, const char *data)
 +{
 +      int ret = -ENOMEM;
 +      struct kobject *bat_kobj;
 +      char *uevent_env[4] = { NULL, NULL, NULL, NULL };
 +
 +      bat_kobj = &bat_priv->soft_iface->dev.kobj;
 +
 +      uevent_env[0] = kasprintf(GFP_ATOMIC,
 +                                "%s%s", BATADV_UEV_TYPE_VAR,
 +                                batadv_uev_type_str[type]);
 +      if (!uevent_env[0])
 +              goto out;
 +
 +      uevent_env[1] = kasprintf(GFP_ATOMIC,
 +                                "%s%s", BATADV_UEV_ACTION_VAR,
 +                                batadv_uev_action_str[action]);
 +      if (!uevent_env[1])
 +              goto out;
 +
 +      /* If the event is DEL, ignore the data field */
 +      if (action != BATADV_UEV_DEL) {
 +              uevent_env[2] = kasprintf(GFP_ATOMIC,
 +                                        "%s%s", BATADV_UEV_DATA_VAR, data);
 +              if (!uevent_env[2])
 +                      goto out;
 +      }
 +
 +      ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
 +out:
 +      kfree(uevent_env[0]);
 +      kfree(uevent_env[1]);
 +      kfree(uevent_env[2]);
 +
 +      if (ret)
 +              batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 +                         "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
 +                         batadv_uev_type_str[type],
 +                         batadv_uev_action_str[action],
 +                         (action == BATADV_UEV_DEL ? "NULL" : data), ret);
 +      return ret;
 +}
 +
  module_init(batadv_init);
  module_exit(batadv_exit);
  
diff --combined net/batman-adv/main.h
index f827e441025ff11df10945781e0da72ac4794b70,06880c650598416c97f4c6c18360d45b361c3a04..c59afcba31e0319c886a8bb8405449da54139536
@@@ -2,6 -2,18 +2,6 @@@
  /* Copyright (C) 2007-2019  B.A.T.M.A.N. contributors:
   *
   * Marek Lindner, Simon Wunderlich
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of version 2 of the GNU General Public
 - * License as published by the Free Software Foundation.
 - *
 - * This program is distributed in the hope that it will be useful, but
 - * WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 - * General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, see <http://www.gnu.org/licenses/>.
   */
  
  #ifndef _NET_BATMAN_ADV_MAIN_H_
@@@ -13,7 -25,7 +13,7 @@@
  #define BATADV_DRIVER_DEVICE "batman-adv"
  
  #ifndef BATADV_SOURCE_VERSION
- #define BATADV_SOURCE_VERSION "2019.1"
+ #define BATADV_SOURCE_VERSION "2019.2"
  #endif
  
  /* B.A.T.M.A.N. parameters */
@@@ -382,7 -394,5 +382,7 @@@ static inline void batadv_add_counter(s
  
  unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len);
  bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid);
 +int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
 +                      enum batadv_uev_action action, const char *data);
  
  #endif /* _NET_BATMAN_ADV_MAIN_H_ */
index 3feb9435b715b66be8b67c4649a415e18a669278,1b985ab89c0879e7be782f11db6e52e5fc4f6332..ec54e236e345432496df8f55b2e00fbad92f3444
@@@ -2,6 -2,18 +2,6 @@@
  /* Copyright (C) 2014-2019  B.A.T.M.A.N. contributors:
   *
   * Linus Lüssing
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of version 2 of the GNU General Public
 - * License as published by the Free Software Foundation.
 - *
 - * This program is distributed in the hope that it will be useful, but
 - * WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 - * General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, see <http://www.gnu.org/licenses/>.
   */
  
  #include "multicast.h"
@@@ -54,7 -66,6 +54,7 @@@
  #include "hash.h"
  #include "log.h"
  #include "netlink.h"
 +#include "send.h"
  #include "soft-interface.h"
  #include "translation-table.h"
  #include "tvlv.h"
@@@ -314,8 -325,6 +314,6 @@@ static void batadv_mcast_mla_list_free(
   * translation table except the ones listed in the given mcast_list.
   *
   * If mcast_list is NULL then all are retracted.
-  *
-  * Do not call outside of the mcast worker! (or cancel mcast worker first)
   */
  static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
                                        struct hlist_head *mcast_list)
        struct batadv_hw_addr *mcast_entry;
        struct hlist_node *tmp;
  
-       WARN_ON(delayed_work_pending(&bat_priv->mcast.work));
        hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
                                  list) {
                if (mcast_list &&
   *
   * Adds multicast listener announcements from the given mcast_list to the
   * translation table if they have not been added yet.
-  *
-  * Do not call outside of the mcast worker! (or cancel mcast worker first)
   */
  static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
                                    struct hlist_head *mcast_list)
        struct batadv_hw_addr *mcast_entry;
        struct hlist_node *tmp;
  
-       WARN_ON(delayed_work_pending(&bat_priv->mcast.work));
        if (!mcast_list)
                return;
  
@@@ -647,7 -650,10 +639,10 @@@ static void batadv_mcast_mla_update(str
        priv_mcast = container_of(delayed_work, struct batadv_priv_mcast, work);
        bat_priv = container_of(priv_mcast, struct batadv_priv, mcast);
  
+       spin_lock(&bat_priv->mcast.mla_lock);
        __batadv_mcast_mla_update(bat_priv);
+       spin_unlock(&bat_priv->mcast.mla_lock);
        batadv_mcast_start_timer(bat_priv);
  }
  
@@@ -980,7 -986,6 +975,7 @@@ batadv_mcast_forw_mode(struct batadv_pr
  {
        int ret, tt_count, ip_count, unsnoop_count, total_count;
        bool is_unsnoopable = false;
 +      unsigned int mcast_fanout;
        struct ethhdr *ethhdr;
  
        ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable);
        case 0:
                return BATADV_FORW_NONE;
        default:
 -              return BATADV_FORW_ALL;
 +              mcast_fanout = atomic_read(&bat_priv->multicast_fanout);
 +
 +              if (!unsnoop_count && total_count <= mcast_fanout)
 +                      return BATADV_FORW_SOME;
 +      }
 +
 +      return BATADV_FORW_ALL;
 +}
 +
 +/**
 + * batadv_mcast_forw_tt() - forwards a packet to multicast listeners
 + * @bat_priv: the bat priv with all the soft interface information
 + * @skb: the multicast packet to transmit
 + * @vid: the vlan identifier
 + *
 + * Sends copies of a frame with multicast destination to any multicast
 + * listener registered in the translation table. A transmission is performed
 + * via a batman-adv unicast packet for each such destination node.
 + *
 + * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
 + * otherwise.
 + */
 +static int
 +batadv_mcast_forw_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
 +                   unsigned short vid)
 +{
 +      int ret = NET_XMIT_SUCCESS;
 +      struct sk_buff *newskb;
 +
 +      struct batadv_tt_orig_list_entry *orig_entry;
 +
 +      struct batadv_tt_global_entry *tt_global;
 +      const u8 *addr = eth_hdr(skb)->h_dest;
 +
 +      tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
 +      if (!tt_global)
 +              goto out;
 +
 +      rcu_read_lock();
 +      hlist_for_each_entry_rcu(orig_entry, &tt_global->orig_list, list) {
 +              newskb = skb_copy(skb, GFP_ATOMIC);
 +              if (!newskb) {
 +                      ret = NET_XMIT_DROP;
 +                      break;
 +              }
 +
 +              batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
 +                                      orig_entry->orig_node, vid);
        }
 +      rcu_read_unlock();
 +
 +      batadv_tt_global_entry_put(tt_global);
 +
 +out:
 +      return ret;
 +}
 +
 +/**
 + * batadv_mcast_forw_want_all_ipv4() - forward to nodes with want-all-ipv4
 + * @bat_priv: the bat priv with all the soft interface information
 + * @skb: the multicast packet to transmit
 + * @vid: the vlan identifier
 + *
 + * Sends copies of a frame with multicast destination to any node with a
 + * BATADV_MCAST_WANT_ALL_IPV4 flag set. A transmission is performed via a
 + * batman-adv unicast packet for each such destination node.
 + *
 + * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
 + * otherwise.
 + */
 +static int
 +batadv_mcast_forw_want_all_ipv4(struct batadv_priv *bat_priv,
 +                              struct sk_buff *skb, unsigned short vid)
 +{
 +      struct batadv_orig_node *orig_node;
 +      int ret = NET_XMIT_SUCCESS;
 +      struct sk_buff *newskb;
 +
 +      rcu_read_lock();
 +      hlist_for_each_entry_rcu(orig_node,
 +                               &bat_priv->mcast.want_all_ipv4_list,
 +                               mcast_want_all_ipv4_node) {
 +              newskb = skb_copy(skb, GFP_ATOMIC);
 +              if (!newskb) {
 +                      ret = NET_XMIT_DROP;
 +                      break;
 +              }
 +
 +              batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
 +                                      orig_node, vid);
 +      }
 +      rcu_read_unlock();
 +      return ret;
 +}
 +
 +/**
 + * batadv_mcast_forw_want_all_ipv6() - forward to nodes with want-all-ipv6
 + * @bat_priv: the bat priv with all the soft interface information
 + * @skb: The multicast packet to transmit
 + * @vid: the vlan identifier
 + *
 + * Sends copies of a frame with multicast destination to any node with a
 + * BATADV_MCAST_WANT_ALL_IPV6 flag set. A transmission is performed via a
 + * batman-adv unicast packet for each such destination node.
 + *
 + * Return: NET_XMIT_DROP on memory allocation failure, NET_XMIT_SUCCESS
 + * otherwise.
 + */
 +static int
 +batadv_mcast_forw_want_all_ipv6(struct batadv_priv *bat_priv,
 +                              struct sk_buff *skb, unsigned short vid)
 +{
 +      struct batadv_orig_node *orig_node;
 +      int ret = NET_XMIT_SUCCESS;
 +      struct sk_buff *newskb;
 +
 +      rcu_read_lock();
 +      hlist_for_each_entry_rcu(orig_node,
 +                               &bat_priv->mcast.want_all_ipv6_list,
 +                               mcast_want_all_ipv6_node) {
 +              newskb = skb_copy(skb, GFP_ATOMIC);
 +              if (!newskb) {
 +                      ret = NET_XMIT_DROP;
 +                      break;
 +              }
 +
 +              batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
 +                                      orig_node, vid);
 +      }
 +      rcu_read_unlock();
 +      return ret;
 +}
 +
 +/**
 + * batadv_mcast_forw_want_all() - forward packet to nodes in a want-all list
 + * @bat_priv: the bat priv with all the soft interface information
 + * @skb: the multicast packet to transmit
 + * @vid: the vlan identifier
 + *
 + * Sends copies of a frame with multicast destination to any node with a
 + * BATADV_MCAST_WANT_ALL_IPV4 or BATADV_MCAST_WANT_ALL_IPV6 flag set. A
 + * transmission is performed via a batman-adv unicast packet for each such
 + * destination node.
 + *
 + * Return: NET_XMIT_DROP on memory allocation failure or if the protocol family
 + * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
 + */
 +static int
 +batadv_mcast_forw_want_all(struct batadv_priv *bat_priv,
 +                         struct sk_buff *skb, unsigned short vid)
 +{
 +      switch (ntohs(eth_hdr(skb)->h_proto)) {
 +      case ETH_P_IP:
 +              return batadv_mcast_forw_want_all_ipv4(bat_priv, skb, vid);
 +      case ETH_P_IPV6:
 +              return batadv_mcast_forw_want_all_ipv6(bat_priv, skb, vid);
 +      default:
 +              /* we shouldn't be here... */
 +              return NET_XMIT_DROP;
 +      }
 +}
 +
 +/**
 + * batadv_mcast_forw_send() - send packet to any detected multicast recpient
 + * @bat_priv: the bat priv with all the soft interface information
 + * @skb: the multicast packet to transmit
 + * @vid: the vlan identifier
 + *
 + * 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
 + * want-all flags. A transmission is performed via a batman-adv unicast packet
 + * for each such destination node.
 + *
 + * The given skb is consumed/freed.
 + *
 + * Return: NET_XMIT_DROP on memory allocation failure or if the protocol family
 + * 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)
 +{
 +      int ret;
 +
 +      ret = batadv_mcast_forw_tt(bat_priv, skb, vid);
 +      if (ret != NET_XMIT_SUCCESS) {
 +              kfree_skb(skb);
 +              return ret;
 +      }
 +
 +      ret = batadv_mcast_forw_want_all(bat_priv, skb, vid);
 +      if (ret != NET_XMIT_SUCCESS) {
 +              kfree_skb(skb);
 +              return ret;
 +      }
 +
 +      consume_skb(skb);
 +      return ret;
  }
  
  /**
diff --combined net/batman-adv/types.h
index 357ca119329a58efa77534c3397e08411bd5f578,ed0f6a519de55cb9cbab447a4ab8f885da56da8c..74b644738a36bfe063eef6df016278b45a1a0256
@@@ -2,6 -2,18 +2,6 @@@
  /* Copyright (C) 2007-2019  B.A.T.M.A.N. contributors:
   *
   * Marek Lindner, Simon Wunderlich
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of version 2 of the GNU General Public
 - * License as published by the Free Software Foundation.
 - *
 - * This program is distributed in the hope that it will be useful, but
 - * WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 - * General Public License for more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program; if not, see <http://www.gnu.org/licenses/>.
   */
  
  #ifndef _NET_BATMAN_ADV_TYPES_H_
@@@ -1211,6 -1223,11 +1211,11 @@@ struct batadv_priv_mcast 
        /** @bridged: whether the soft interface has a bridge on top */
        unsigned char bridged:1;
  
+       /**
+        * @mla_lock: a lock protecting mla_list and mla_flags
+        */
+       spinlock_t mla_lock;
        /**
         * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP
         *  traffic
@@@ -1553,12 -1570,6 +1558,12 @@@ struct batadv_priv 
         *  node's sender/originating side
         */
        atomic_t multicast_mode;
 +
 +      /**
 +       * @multicast_fanout: Maximum number of packet copies to generate for a
 +       *  multicast-to-unicast conversion
 +       */
 +      atomic_t multicast_fanout;
  #endif
  
        /** @orig_interval: OGM broadcast interval in milliseconds */