mirror of https://gitee.com/openkylin/linux.git
Included changes:
- code beautification - remove obsolete 'deleted' attribute for bat-gw node - increase internal version number - prevent potential access to netdev object after deregistration - set needed_head/tail_room for batman virtual interface -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJV4CMzAAoJEOb/4TMchkvfsjYP/1IckH6GA4vMROXZ6+Y89ZVl Ii6uQck+0FUCkzld+sn8RYPDClqmNTB9PcYAVrrKDMFxOZVCdIvK+iLh1s2PQK4o eiab+V93VNK3DTlouvszsW0mdWCaBXiKR01PpEcr528d4LxFnGbiCKDGkcr/A0HM yMW9ZwmpohFk0/CRZPZlDJjTlTAUsvp+YXqA2vBUdBT1zN8Lb3BB7jK/rXXreLJ9 nnNNn+AEw6Fy/FXTDc3QKMrCdyFlN+bHnyXds6345p5asy0JCVh0Sk2zuySi2MDh LT4cujIP5LtAhp8i52R5ZjOvNOQfGAyRxvBd20gZM/lKfMcIK3KEaMe7Se87NySR IhQ1nwE5S4AWnlmU+xfmX4vReojb9sCLhBN8oMC5bm3uqa4kLR9e4CBaPdRSpZex P3Z9DPaV1GAe3yyGFz9pRUTXzAuVMtYKjkObDkOVq+oKqBpG5UMf5gwEkycILvzb wwqHbjE7QY1izE8TgDe1y+GKPR8Qivwm7X8gwuHqmkKCNCmrqNkGjPkp1W4RGkzg BGJmS9FENxxILvt68rXZYqQ2JUg3Z+k/Jiw5gmQGPjwH62JnEMkKD4NMphDf6hxm 85bT9J8mF2AJJKDvEYwDu+KFEhX0LyhcN38SGq5QYRS+9nf0JoZzWujHJ7oXHJiw o7mwRayOYPLzeLLWpjWy =KKXM -----END PGP SIGNATURE----- Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge Antonio Quartulli says: ==================== Included changes: - code beautification - remove obsolete 'deleted' attribute for bat-gw node - increase internal version number - prevent potential access to netdev object after deregistration - set needed_head/tail_room for batman virtual interface ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8b72ca67fe
|
@ -296,39 +296,13 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
|
|||
struct batadv_orig_node *orig_node,
|
||||
struct batadv_orig_node *orig_neigh)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
||||
struct batadv_neigh_node *neigh_node, *tmp_neigh_node;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
|
||||
neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node);
|
||||
neigh_node = batadv_neigh_node_new(orig_node, hard_iface, neigh_addr);
|
||||
if (!neigh_node)
|
||||
goto out;
|
||||
|
||||
if (!atomic_inc_not_zero(&hard_iface->refcount)) {
|
||||
kfree(neigh_node);
|
||||
neigh_node = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
neigh_node->orig_node = orig_neigh;
|
||||
neigh_node->if_incoming = hard_iface;
|
||||
|
||||
spin_lock_bh(&orig_node->neigh_list_lock);
|
||||
tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface,
|
||||
neigh_addr);
|
||||
if (!tmp_neigh_node) {
|
||||
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
|
||||
} else {
|
||||
kfree(neigh_node);
|
||||
batadv_hardif_free_ref(hard_iface);
|
||||
neigh_node = tmp_neigh_node;
|
||||
}
|
||||
spin_unlock_bh(&orig_node->neigh_list_lock);
|
||||
|
||||
if (!tmp_neigh_node)
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"Creating new neighbor %pM for orig_node %pM on interface %s\n",
|
||||
neigh_addr, orig_node->orig,
|
||||
hard_iface->net_dev->name);
|
||||
|
||||
out:
|
||||
return neigh_node;
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
@ -161,9 +160,6 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
|
|||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
|
||||
if (gw_node->deleted)
|
||||
continue;
|
||||
|
||||
orig_node = gw_node->orig_node;
|
||||
router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
|
||||
if (!router)
|
||||
|
@ -473,9 +469,6 @@ batadv_gw_node_get(struct batadv_priv *bat_priv,
|
|||
if (gw_node_tmp->orig_node != orig_node)
|
||||
continue;
|
||||
|
||||
if (gw_node_tmp->deleted)
|
||||
continue;
|
||||
|
||||
if (!atomic_inc_not_zero(&gw_node_tmp->refcount))
|
||||
continue;
|
||||
|
||||
|
@ -525,9 +518,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
|
|||
gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
|
||||
gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
|
||||
|
||||
gw_node->deleted = 0;
|
||||
if (ntohl(gateway->bandwidth_down) == 0) {
|
||||
gw_node->deleted = jiffies;
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"Gateway %pM removed from gateway list\n",
|
||||
orig_node->orig);
|
||||
|
@ -535,14 +526,21 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
|
|||
/* Note: We don't need a NULL check here, since curr_gw never
|
||||
* gets dereferenced.
|
||||
*/
|
||||
spin_lock_bh(&bat_priv->gw.list_lock);
|
||||
hlist_del_init_rcu(&gw_node->list);
|
||||
spin_unlock_bh(&bat_priv->gw.list_lock);
|
||||
|
||||
batadv_gw_node_free_ref(gw_node);
|
||||
|
||||
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
|
||||
if (gw_node == curr_gw)
|
||||
batadv_gw_reselect(bat_priv);
|
||||
|
||||
if (curr_gw)
|
||||
batadv_gw_node_free_ref(curr_gw);
|
||||
}
|
||||
|
||||
out:
|
||||
if (curr_gw)
|
||||
batadv_gw_node_free_ref(curr_gw);
|
||||
if (gw_node)
|
||||
batadv_gw_node_free_ref(gw_node);
|
||||
}
|
||||
|
@ -558,39 +556,18 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv,
|
|||
batadv_gw_node_update(bat_priv, orig_node, &gateway);
|
||||
}
|
||||
|
||||
void batadv_gw_node_purge(struct batadv_priv *bat_priv)
|
||||
void batadv_gw_node_free(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_gw_node *gw_node, *curr_gw;
|
||||
struct batadv_gw_node *gw_node;
|
||||
struct hlist_node *node_tmp;
|
||||
unsigned long timeout = msecs_to_jiffies(2 * BATADV_PURGE_TIMEOUT);
|
||||
int do_reselect = 0;
|
||||
|
||||
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
|
||||
|
||||
spin_lock_bh(&bat_priv->gw.list_lock);
|
||||
|
||||
hlist_for_each_entry_safe(gw_node, node_tmp,
|
||||
&bat_priv->gw.list, list) {
|
||||
if (((!gw_node->deleted) ||
|
||||
(time_before(jiffies, gw_node->deleted + timeout))) &&
|
||||
atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE)
|
||||
continue;
|
||||
|
||||
if (curr_gw == gw_node)
|
||||
do_reselect = 1;
|
||||
|
||||
hlist_del_rcu(&gw_node->list);
|
||||
hlist_del_init_rcu(&gw_node->list);
|
||||
batadv_gw_node_free_ref(gw_node);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&bat_priv->gw.list_lock);
|
||||
|
||||
/* gw_reselect() needs to acquire the gw_list_lock */
|
||||
if (do_reselect)
|
||||
batadv_gw_reselect(bat_priv);
|
||||
|
||||
if (curr_gw)
|
||||
batadv_gw_node_free_ref(curr_gw);
|
||||
}
|
||||
|
||||
/* fails if orig_node has no router */
|
||||
|
@ -654,9 +631,6 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
|
|||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
|
||||
if (gw_node->deleted)
|
||||
continue;
|
||||
|
||||
/* fails if orig_node has no router */
|
||||
if (batadv_write_buffer_text(bat_priv, seq, gw_node) < 0)
|
||||
continue;
|
||||
|
|
|
@ -38,7 +38,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
|
|||
struct batadv_tvlv_gateway_data *gateway);
|
||||
void batadv_gw_node_delete(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node);
|
||||
void batadv_gw_node_purge(struct batadv_priv *bat_priv);
|
||||
void batadv_gw_node_free(struct batadv_priv *bat_priv);
|
||||
int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset);
|
||||
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb);
|
||||
enum batadv_dhcp_recipient
|
||||
|
|
|
@ -252,6 +252,44 @@ static void batadv_check_known_mac_addr(const struct net_device *net_dev)
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_recalc_extra_skbroom() - Recalculate skbuff extra head/tailroom
|
||||
* @soft_iface: netdev struct of the mesh interface
|
||||
*/
|
||||
static void batadv_hardif_recalc_extra_skbroom(struct net_device *soft_iface)
|
||||
{
|
||||
const struct batadv_hard_iface *hard_iface;
|
||||
unsigned short lower_header_len = ETH_HLEN;
|
||||
unsigned short lower_headroom = 0;
|
||||
unsigned short lower_tailroom = 0;
|
||||
unsigned short needed_headroom;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
|
||||
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
|
||||
continue;
|
||||
|
||||
if (hard_iface->soft_iface != soft_iface)
|
||||
continue;
|
||||
|
||||
lower_header_len = max_t(unsigned short, lower_header_len,
|
||||
hard_iface->net_dev->hard_header_len);
|
||||
|
||||
lower_headroom = max_t(unsigned short, lower_headroom,
|
||||
hard_iface->net_dev->needed_headroom);
|
||||
|
||||
lower_tailroom = max_t(unsigned short, lower_tailroom,
|
||||
hard_iface->net_dev->needed_tailroom);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
needed_headroom = lower_headroom + (lower_header_len - ETH_HLEN);
|
||||
needed_headroom += batadv_max_header_len();
|
||||
|
||||
soft_iface->needed_headroom = needed_headroom;
|
||||
soft_iface->needed_tailroom = lower_tailroom;
|
||||
}
|
||||
|
||||
int batadv_hardif_min_mtu(struct net_device *soft_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
|
||||
|
@ -474,6 +512,8 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
"Not using interface %s (retrying later): interface not active\n",
|
||||
hard_iface->net_dev->name);
|
||||
|
||||
batadv_hardif_recalc_extra_skbroom(soft_iface);
|
||||
|
||||
/* begin scheduling originator messages on that interface */
|
||||
batadv_schedule_bat_ogm(hard_iface);
|
||||
|
||||
|
@ -528,6 +568,9 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
|
|||
batadv_purge_outstanding_packets(bat_priv, hard_iface);
|
||||
dev_put(hard_iface->soft_iface);
|
||||
|
||||
netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface);
|
||||
batadv_hardif_recalc_extra_skbroom(hard_iface->soft_iface);
|
||||
|
||||
/* nobody uses this interface anymore */
|
||||
if (!bat_priv->num_ifaces) {
|
||||
batadv_gw_check_client_stop(bat_priv);
|
||||
|
@ -536,7 +579,6 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
|
|||
batadv_softif_destroy_sysfs(hard_iface->soft_iface);
|
||||
}
|
||||
|
||||
netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface);
|
||||
hard_iface->soft_iface = NULL;
|
||||
batadv_hardif_free_ref(hard_iface);
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ void batadv_mesh_free(struct net_device *soft_iface)
|
|||
|
||||
batadv_purge_outstanding_packets(bat_priv, NULL);
|
||||
|
||||
batadv_gw_node_purge(bat_priv);
|
||||
batadv_gw_node_free(bat_priv);
|
||||
batadv_nc_mesh_free(bat_priv);
|
||||
batadv_dat_free(bat_priv);
|
||||
batadv_bla_free(bat_priv);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define BATADV_DRIVER_DEVICE "batman-adv"
|
||||
|
||||
#ifndef BATADV_SOURCE_VERSION
|
||||
#define BATADV_SOURCE_VERSION "2015.1"
|
||||
#define BATADV_SOURCE_VERSION "2015.2"
|
||||
#endif
|
||||
|
||||
/* B.A.T.M.A.N. parameters */
|
||||
|
|
|
@ -442,40 +442,6 @@ batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
|
|||
return neigh_ifinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_neigh_node_new - create and init a new neigh_node object
|
||||
* @hard_iface: the interface where the neighbour is connected to
|
||||
* @neigh_addr: the mac address of the neighbour interface
|
||||
* @orig_node: originator object representing the neighbour
|
||||
*
|
||||
* Allocates a new neigh_node object and initialises all the generic fields.
|
||||
* Returns the new object or NULL on failure.
|
||||
*/
|
||||
struct batadv_neigh_node *
|
||||
batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
|
||||
const u8 *neigh_addr, struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
|
||||
neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
|
||||
if (!neigh_node)
|
||||
goto out;
|
||||
|
||||
INIT_HLIST_NODE(&neigh_node->list);
|
||||
INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
|
||||
spin_lock_init(&neigh_node->ifinfo_lock);
|
||||
|
||||
ether_addr_copy(neigh_node->addr, neigh_addr);
|
||||
neigh_node->if_incoming = hard_iface;
|
||||
neigh_node->orig_node = orig_node;
|
||||
|
||||
/* extra reference for return */
|
||||
atomic_set(&neigh_node->refcount, 2);
|
||||
|
||||
out:
|
||||
return neigh_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_neigh_node_get - retrieve a neighbour from the list
|
||||
* @orig_node: originator which the neighbour belongs to
|
||||
|
@ -486,7 +452,7 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
|
|||
* which is connected through the provided hard interface.
|
||||
* Returns NULL if the neighbour is not found.
|
||||
*/
|
||||
struct batadv_neigh_node *
|
||||
static struct batadv_neigh_node *
|
||||
batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
|
||||
const struct batadv_hard_iface *hard_iface,
|
||||
const u8 *addr)
|
||||
|
@ -512,6 +478,59 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_neigh_node_new - create and init a new neigh_node object
|
||||
* @orig_node: originator object representing the neighbour
|
||||
* @hard_iface: the interface where the neighbour is connected to
|
||||
* @neigh_addr: the mac address of the neighbour interface
|
||||
*
|
||||
* Allocates a new neigh_node object and initialises all the generic fields.
|
||||
* Returns the new object or NULL on failure.
|
||||
*/
|
||||
struct batadv_neigh_node *
|
||||
batadv_neigh_node_new(struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *hard_iface,
|
||||
const u8 *neigh_addr)
|
||||
{
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
|
||||
neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
|
||||
if (neigh_node)
|
||||
goto out;
|
||||
|
||||
neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
|
||||
if (!neigh_node)
|
||||
goto out;
|
||||
|
||||
if (!atomic_inc_not_zero(&hard_iface->refcount)) {
|
||||
kfree(neigh_node);
|
||||
neigh_node = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
INIT_HLIST_NODE(&neigh_node->list);
|
||||
INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
|
||||
spin_lock_init(&neigh_node->ifinfo_lock);
|
||||
|
||||
ether_addr_copy(neigh_node->addr, neigh_addr);
|
||||
neigh_node->if_incoming = hard_iface;
|
||||
neigh_node->orig_node = orig_node;
|
||||
|
||||
/* extra reference for return */
|
||||
atomic_set(&neigh_node->refcount, 2);
|
||||
|
||||
spin_lock_bh(&orig_node->neigh_list_lock);
|
||||
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
|
||||
spin_unlock_bh(&orig_node->neigh_list_lock);
|
||||
|
||||
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
|
||||
"Creating new neighbor %pM for orig_node %pM on interface %s\n",
|
||||
neigh_addr, orig_node->orig, hard_iface->net_dev->name);
|
||||
|
||||
out:
|
||||
return neigh_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
|
||||
* @rcu: rcu pointer of the orig_ifinfo object
|
||||
|
@ -1010,7 +1029,6 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
|
|||
spin_unlock_bh(list_lock);
|
||||
}
|
||||
|
||||
batadv_gw_node_purge(bat_priv);
|
||||
batadv_gw_election(bat_priv);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,9 @@ void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node);
|
|||
struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
|
||||
const u8 *addr);
|
||||
struct batadv_neigh_node *
|
||||
batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
|
||||
const struct batadv_hard_iface *hard_iface,
|
||||
const u8 *addr);
|
||||
struct batadv_neigh_node *
|
||||
batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
|
||||
const u8 *neigh_addr, struct batadv_orig_node *orig_node);
|
||||
batadv_neigh_node_new(struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *hard_iface,
|
||||
const u8 *neigh_addr);
|
||||
void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node);
|
||||
struct batadv_neigh_node *
|
||||
batadv_orig_router_get(struct batadv_orig_node *orig_node,
|
||||
|
|
|
@ -947,8 +947,6 @@ static void batadv_softif_init_early(struct net_device *dev)
|
|||
* have not been initialized yet
|
||||
*/
|
||||
dev->mtu = ETH_DATA_LEN;
|
||||
/* reserve more space in the skbuff for our header */
|
||||
dev->hard_header_len = batadv_max_header_len();
|
||||
|
||||
/* generate random address */
|
||||
eth_hw_addr_random(dev);
|
||||
|
|
|
@ -328,7 +328,6 @@ enum batadv_orig_capabilities {
|
|||
* @orig_node: pointer to corresponding orig node
|
||||
* @bandwidth_down: advertised uplink download bandwidth
|
||||
* @bandwidth_up: advertised uplink upload bandwidth
|
||||
* @deleted: this struct is scheduled for deletion
|
||||
* @refcount: number of contexts the object is used
|
||||
* @rcu: struct used for freeing in an RCU-safe manner
|
||||
*/
|
||||
|
@ -337,7 +336,6 @@ struct batadv_gw_node {
|
|||
struct batadv_orig_node *orig_node;
|
||||
u32 bandwidth_down;
|
||||
u32 bandwidth_up;
|
||||
unsigned long deleted;
|
||||
atomic_t refcount;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue