In this small batch of patches you have:
- a fix for our Distributed ARP Table that makes sure that the input provided to the hash function during a query is the same as the one provided during an insert (so to prevent false negatives), by Antonio Quartulli - a fix for our new protocol implementation B.A.T.M.A.N. V that ensures that a hard interface is properly re-activated when it is brought down and then up again, by Antonio Quartulli - two fixes respectively to the reference counting of the tt_local_entry and neigh_node objects, by Sven Eckelmann. Such bug is rather severe as it would prevent the netdev objects references by batman-adv from being released after shutdown. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJXJOPeAAoJEJ4aZjxxc6bKFaoP/jsY4MelcsGUGQhjfEfm/gbo H7Xd5TUydiq9tfbIGwAjbS4Ti+e69ROolyiNQrvxc5PcJFhpQlsSe17+o0NdnCOE tBLjuCLjpnj+FzghnQYb54Qb2CEllsSLJcOLh+CnbFiHos+pvhxA/NeC6FufyPMF Zrdsjf/v4rzghWQerToKEcIgCXcRE3Zo2txunUnFXSzQGai4AJnljD1Hk1YcbQdn O8+6lXYN+j4Swo6yrPB0URzJRIWdjoQ1OfdvggCDTuMW664jyv9gZmsF/fzL2ksj SGldxkFOX+4x8NenRxs5OFMXHHAJGu8kU8uoXmOCuv6b59F2KWi27rP1MJqxYDcB pTpq4nAx3IooNSSvpU97SFW3WBQgIsNHMFZwZbGkxqXP1UhPEoUcsuFTPVj/hqDI h9xBLK/buNbYnMULTW8hMvxOUHqxjPvr37Vbj1uPdbfmwbrvUvwyMSWFn5k/JmAF CASMwUC4C7IQtEinVYHmT/+QsPGMcmom1WZ1/OlhlxnmOwAcglI/mZnXl0wD7ptg 3KETNlrsNHC6YuOLKIKI08l3Ke2DOZLHdV5PvHcdPgTy7EYbSvZTaDwK422pSiuy 8kcQjN8g6I81drwJqkEiUkJA6kRxkKbXYxosudbRT07IkzUZo7TPAFv7iMNDSHUW vuJV/rtYAp3bRDyLrxnb =ksVs -----END PGP SIGNATURE----- Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge Antonio Quartulli says: ==================== In this small batch of patches you have: - a fix for our Distributed ARP Table that makes sure that the input provided to the hash function during a query is the same as the one provided during an insert (so to prevent false negatives), by Antonio Quartulli - a fix for our new protocol implementation B.A.T.M.A.N. V that ensures that a hard interface is properly re-activated when it is brought down and then up again, by Antonio Quartulli - two fixes respectively to the reference counting of the tt_local_entry and neigh_node objects, by Sven Eckelmann. Such bug is rather severe as it would prevent the netdev objects references by batman-adv from being released after shutdown. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9b40d5aaef
|
@ -32,10 +32,21 @@
|
|||
|
||||
#include "bat_v_elp.h"
|
||||
#include "bat_v_ogm.h"
|
||||
#include "hard-interface.h"
|
||||
#include "hash.h"
|
||||
#include "originator.h"
|
||||
#include "packet.h"
|
||||
|
||||
static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
/* B.A.T.M.A.N. V does not use any queuing mechanism, therefore it can
|
||||
* set the interface as ACTIVE right away, without any risk of race
|
||||
* condition
|
||||
*/
|
||||
if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
|
||||
hard_iface->if_status = BATADV_IF_ACTIVE;
|
||||
}
|
||||
|
||||
static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
int ret;
|
||||
|
@ -274,6 +285,7 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
|
|||
|
||||
static struct batadv_algo_ops batadv_batman_v __read_mostly = {
|
||||
.name = "BATMAN_V",
|
||||
.bat_iface_activate = batadv_v_iface_activate,
|
||||
.bat_iface_enable = batadv_v_iface_enable,
|
||||
.bat_iface_disable = batadv_v_iface_disable,
|
||||
.bat_iface_update_mac = batadv_v_iface_update_mac,
|
||||
|
|
|
@ -568,6 +568,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
|
|||
* be sent to
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
* @ip_dst: ipv4 to look up in the DHT
|
||||
* @vid: VLAN identifier
|
||||
*
|
||||
* An originator O is selected if and only if its DHT_ID value is one of three
|
||||
* closest values (from the LEFT, with wrap around if needed) then the hash
|
||||
|
@ -576,7 +577,8 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
|
|||
* Return: the candidate array of size BATADV_DAT_CANDIDATE_NUM.
|
||||
*/
|
||||
static struct batadv_dat_candidate *
|
||||
batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
|
||||
batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
|
||||
unsigned short vid)
|
||||
{
|
||||
int select;
|
||||
batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
|
||||
|
@ -592,7 +594,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
|
|||
return NULL;
|
||||
|
||||
dat.ip = ip_dst;
|
||||
dat.vid = 0;
|
||||
dat.vid = vid;
|
||||
ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat,
|
||||
BATADV_DAT_ADDR_MAX);
|
||||
|
||||
|
@ -612,6 +614,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
|
|||
* @bat_priv: the bat priv with all the soft interface information
|
||||
* @skb: payload to send
|
||||
* @ip: the DHT key
|
||||
* @vid: VLAN identifier
|
||||
* @packet_subtype: unicast4addr packet subtype to use
|
||||
*
|
||||
* This function copies the skb with pskb_copy() and is sent as unicast packet
|
||||
|
@ -622,7 +625,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
|
|||
*/
|
||||
static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, __be32 ip,
|
||||
int packet_subtype)
|
||||
unsigned short vid, int packet_subtype)
|
||||
{
|
||||
int i;
|
||||
bool ret = false;
|
||||
|
@ -631,7 +634,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
|
|||
struct sk_buff *tmp_skb;
|
||||
struct batadv_dat_candidate *cand;
|
||||
|
||||
cand = batadv_dat_select_candidates(bat_priv, ip);
|
||||
cand = batadv_dat_select_candidates(bat_priv, ip, vid);
|
||||
if (!cand)
|
||||
goto out;
|
||||
|
||||
|
@ -1022,7 +1025,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
|
|||
ret = true;
|
||||
} else {
|
||||
/* Send the request to the DHT */
|
||||
ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
|
||||
ret = batadv_dat_send_data(bat_priv, skb, ip_dst, vid,
|
||||
BATADV_P_DAT_DHT_GET);
|
||||
}
|
||||
out:
|
||||
|
@ -1150,8 +1153,8 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
|
|||
/* Send the ARP reply to the candidates for both the IP addresses that
|
||||
* the node obtained from the ARP reply
|
||||
*/
|
||||
batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
|
||||
batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
|
||||
batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT);
|
||||
batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -407,6 +407,9 @@ batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface)
|
|||
|
||||
batadv_update_min_mtu(hard_iface->soft_iface);
|
||||
|
||||
if (bat_priv->bat_algo_ops->bat_iface_activate)
|
||||
bat_priv->bat_algo_ops->bat_iface_activate(hard_iface);
|
||||
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_put(primary_if);
|
||||
|
|
|
@ -250,7 +250,6 @@ static void batadv_neigh_node_release(struct kref *ref)
|
|||
{
|
||||
struct hlist_node *node_tmp;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
struct batadv_algo_ops *bao;
|
||||
|
||||
|
@ -262,13 +261,7 @@ static void batadv_neigh_node_release(struct kref *ref)
|
|||
batadv_neigh_ifinfo_put(neigh_ifinfo);
|
||||
}
|
||||
|
||||
hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming,
|
||||
neigh_node->addr);
|
||||
if (hardif_neigh) {
|
||||
/* batadv_hardif_neigh_get() increases refcount too */
|
||||
batadv_hardif_neigh_put(hardif_neigh);
|
||||
batadv_hardif_neigh_put(hardif_neigh);
|
||||
}
|
||||
batadv_hardif_neigh_put(neigh_node->hardif_neigh);
|
||||
|
||||
if (bao->bat_neigh_free)
|
||||
bao->bat_neigh_free(neigh_node);
|
||||
|
@ -665,6 +658,10 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
|
|||
neigh_node->orig_node = orig_node;
|
||||
neigh_node->last_seen = jiffies;
|
||||
|
||||
/* increment unique neighbor refcount */
|
||||
kref_get(&hardif_neigh->refcount);
|
||||
neigh_node->hardif_neigh = hardif_neigh;
|
||||
|
||||
/* extra reference for return */
|
||||
kref_init(&neigh_node->refcount);
|
||||
kref_get(&neigh_node->refcount);
|
||||
|
@ -673,9 +670,6 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
|
|||
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
|
||||
spin_unlock_bh(&orig_node->neigh_list_lock);
|
||||
|
||||
/* increment unique neighbor refcount */
|
||||
kref_get(&hardif_neigh->refcount);
|
||||
|
||||
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);
|
||||
|
|
|
@ -215,6 +215,8 @@ static void batadv_tt_local_entry_release(struct kref *ref)
|
|||
tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
|
||||
common.refcount);
|
||||
|
||||
batadv_softif_vlan_put(tt_local_entry->vlan);
|
||||
|
||||
kfree_rcu(tt_local_entry, common.rcu);
|
||||
}
|
||||
|
||||
|
@ -673,6 +675,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
|
|||
kref_get(&tt_local->common.refcount);
|
||||
tt_local->last_seen = jiffies;
|
||||
tt_local->common.added_at = tt_local->last_seen;
|
||||
tt_local->vlan = vlan;
|
||||
|
||||
/* the batman interface mac and multicast addresses should never be
|
||||
* purged
|
||||
|
@ -991,7 +994,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
|||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_softif_vlan *vlan;
|
||||
struct hlist_head *head;
|
||||
unsigned short vid;
|
||||
u32 i;
|
||||
|
@ -1027,14 +1029,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
|||
last_seen_msecs = last_seen_msecs % 1000;
|
||||
|
||||
no_purge = tt_common_entry->flags & np_flag;
|
||||
|
||||
vlan = batadv_softif_vlan_get(bat_priv, vid);
|
||||
if (!vlan) {
|
||||
seq_printf(seq, "Cannot retrieve VLAN %d\n",
|
||||
BATADV_PRINT_VID(vid));
|
||||
continue;
|
||||
}
|
||||
|
||||
seq_printf(seq,
|
||||
" * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n",
|
||||
tt_common_entry->addr,
|
||||
|
@ -1052,9 +1046,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
|||
BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
|
||||
no_purge ? 0 : last_seen_secs,
|
||||
no_purge ? 0 : last_seen_msecs,
|
||||
vlan->tt.crc);
|
||||
|
||||
batadv_softif_vlan_put(vlan);
|
||||
tt_local->vlan->tt.crc);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -1099,7 +1091,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
|
|||
{
|
||||
struct batadv_tt_local_entry *tt_local_entry;
|
||||
u16 flags, curr_flags = BATADV_NO_FLAGS;
|
||||
struct batadv_softif_vlan *vlan;
|
||||
void *tt_entry_exists;
|
||||
|
||||
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
|
||||
|
@ -1139,14 +1130,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
|
|||
/* extra call to free the local tt entry */
|
||||
batadv_tt_local_entry_put(tt_local_entry);
|
||||
|
||||
/* decrease the reference held for this vlan */
|
||||
vlan = batadv_softif_vlan_get(bat_priv, vid);
|
||||
if (!vlan)
|
||||
goto out;
|
||||
|
||||
batadv_softif_vlan_put(vlan);
|
||||
batadv_softif_vlan_put(vlan);
|
||||
|
||||
out:
|
||||
if (tt_local_entry)
|
||||
batadv_tt_local_entry_put(tt_local_entry);
|
||||
|
@ -1219,7 +1202,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
|
|||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct batadv_softif_vlan *vlan;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
u32 i;
|
||||
|
@ -1241,14 +1223,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
|
|||
struct batadv_tt_local_entry,
|
||||
common);
|
||||
|
||||
/* decrease the reference held for this vlan */
|
||||
vlan = batadv_softif_vlan_get(bat_priv,
|
||||
tt_common_entry->vid);
|
||||
if (vlan) {
|
||||
batadv_softif_vlan_put(vlan);
|
||||
batadv_softif_vlan_put(vlan);
|
||||
}
|
||||
|
||||
batadv_tt_local_entry_put(tt_local);
|
||||
}
|
||||
spin_unlock_bh(list_lock);
|
||||
|
@ -3309,7 +3283,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
|
|||
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
||||
struct batadv_tt_common_entry *tt_common;
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct batadv_softif_vlan *vlan;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
|
@ -3339,13 +3312,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
|
|||
struct batadv_tt_local_entry,
|
||||
common);
|
||||
|
||||
/* decrease the reference held for this vlan */
|
||||
vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
|
||||
if (vlan) {
|
||||
batadv_softif_vlan_put(vlan);
|
||||
batadv_softif_vlan_put(vlan);
|
||||
}
|
||||
|
||||
batadv_tt_local_entry_put(tt_local);
|
||||
}
|
||||
spin_unlock_bh(list_lock);
|
||||
|
|
|
@ -433,6 +433,7 @@ struct batadv_hardif_neigh_node {
|
|||
* @ifinfo_lock: lock protecting private ifinfo members and list
|
||||
* @if_incoming: pointer to incoming hard-interface
|
||||
* @last_seen: when last packet via this neighbor was received
|
||||
* @hardif_neigh: hardif_neigh of this neighbor
|
||||
* @refcount: number of contexts the object is used
|
||||
* @rcu: struct used for freeing in an RCU-safe manner
|
||||
*/
|
||||
|
@ -444,6 +445,7 @@ struct batadv_neigh_node {
|
|||
spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */
|
||||
struct batadv_hard_iface *if_incoming;
|
||||
unsigned long last_seen;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh;
|
||||
struct kref refcount;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
@ -1073,10 +1075,12 @@ struct batadv_tt_common_entry {
|
|||
* struct batadv_tt_local_entry - translation table local entry data
|
||||
* @common: general translation table data
|
||||
* @last_seen: timestamp used for purging stale tt local entries
|
||||
* @vlan: soft-interface vlan of the entry
|
||||
*/
|
||||
struct batadv_tt_local_entry {
|
||||
struct batadv_tt_common_entry common;
|
||||
unsigned long last_seen;
|
||||
struct batadv_softif_vlan *vlan;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1250,6 +1254,8 @@ struct batadv_forw_packet {
|
|||
* struct batadv_algo_ops - mesh algorithm callbacks
|
||||
* @list: list node for the batadv_algo_list
|
||||
* @name: name of the algorithm
|
||||
* @bat_iface_activate: start routing mechanisms when hard-interface is brought
|
||||
* up
|
||||
* @bat_iface_enable: init routing info when hard-interface is enabled
|
||||
* @bat_iface_disable: de-init routing info when hard-interface is disabled
|
||||
* @bat_iface_update_mac: (re-)init mac addresses of the protocol information
|
||||
|
@ -1277,6 +1283,7 @@ struct batadv_forw_packet {
|
|||
struct batadv_algo_ops {
|
||||
struct hlist_node list;
|
||||
char *name;
|
||||
void (*bat_iface_activate)(struct batadv_hard_iface *hard_iface);
|
||||
int (*bat_iface_enable)(struct batadv_hard_iface *hard_iface);
|
||||
void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface);
|
||||
void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface);
|
||||
|
|
Loading…
Reference in New Issue
Block a user