Skip to content

Commit

Permalink
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Aug 28, 2015
2 parents 9723e6a + ed29266 commit 8b72ca6
Showing 10 changed files with 117 additions and 116 deletions.
30 changes: 2 additions & 28 deletions net/batman-adv/bat_iv_ogm.c
Original file line number Diff line number Diff line change
@@ -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;
50 changes: 12 additions & 38 deletions net/batman-adv/gateway_client.c
Original file line number Diff line number Diff line change
@@ -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,24 +518,29 @@ 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);

/* 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;
2 changes: 1 addition & 1 deletion net/batman-adv/gateway_client.h
Original file line number Diff line number Diff line change
@@ -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
44 changes: 43 additions & 1 deletion net/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
@@ -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);

2 changes: 1 addition & 1 deletion net/batman-adv/main.c
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion net/batman-adv/main.h
Original file line number Diff line number Diff line change
@@ -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 */
90 changes: 54 additions & 36 deletions net/batman-adv/originator.c
Original file line number Diff line number Diff line change
@@ -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);
}

9 changes: 3 additions & 6 deletions net/batman-adv/originator.h
Original file line number Diff line number Diff line change
@@ -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,
2 changes: 0 additions & 2 deletions net/batman-adv/soft-interface.c
Original file line number Diff line number Diff line change
@@ -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);
Loading

0 comments on commit 8b72ca6

Please sign in to comment.