Included changes:

- change my email in MAINTAINERS and Doc files
 - create and export list of single hop neighs per interface
 - protect CRC in the BLA code by means of its own lock
 - minor fixes and code cleanups
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJWcRAcAAoJENpFlCjNi1MRxPQP/A8wAuHYUyMDu6ov5VRUR+24
 TYKgCVI1evuYlkOdgHkTQfTlOILgV2NHvORzKwQRNToyvtsd4VIeXZfFJ0UXB0Wo
 sMz9vrmmcndGkcYPWs+6IoVUbxMPZXjRGhme3Ig7nNTOQ4GvcSaQANbYWAMBfg61
 h6pxez67el9jzso2acHEgvOyaldOLDcbbdwt4vY7bPRgD9VXpE3nazBymaZXLLxs
 1ByXiCgJw32gXSWv8RQ/j13btjrbWCdmcEz9Ag1xO5i5u9BI1VJ8nmbLuNu63S0G
 Ftgvk5QBeMAxs3xDiTmtQD3bmiS87Jy+1d5rFb581/arM5SnYq6GZIrb81tdVTU6
 PMkMZ6/EUV2HSogq9PJ1ZDk/0oPYT5tqfLtJWcaAZplmWYt3ZUrQsPo4z5CtbBhU
 6Ar29G5slkgLslcBqn6YB00LxwOmj7elyVdPtL+wMCojtut+Ds4O+FzPdvd/145F
 hCtIe55b2ciBsfp1dDXP5P15HeEMjLiN2xWJKAPLhDCmGruJ6Pnly+ElzgV+zdKL
 7Qe1mOXwticMy3pH+ST7CP47tp5uyT0ak27eo+oOn4LI/ppM2qW1P9bNUZ6RrVwf
 dRRh0dzQruaLQauHK2Z6BWtA2Q36wY2anwmBONK34NH6VfRMB1GJMi3JF8gDgTds
 SWwU5FGWTn/cnCejtsbh
 =/Z+R
 -----END PGP SIGNATURE-----

Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge

Antonio Quartulli says:

====================
Included changes:
- change my email in MAINTAINERS and Doc files
- create and export list of single hop neighs per interface
- protect CRC in the BLA code by means of its own lock
- minor fixes and code cleanups
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2015-12-16 11:09:40 -05:00
commit 04ad37836c
13 changed files with 370 additions and 27 deletions

View File

@ -8,7 +8,7 @@ Description:
What: /sys/class/net/<mesh_iface>/mesh/<vlan_subdir>/ap_isolation What: /sys/class/net/<mesh_iface>/mesh/<vlan_subdir>/ap_isolation
Date: May 2011 Date: May 2011
Contact: Antonio Quartulli <antonio@meshcoding.com> Contact: Antonio Quartulli <a@unstable.cc>
Description: Description:
Indicates whether the data traffic going from a Indicates whether the data traffic going from a
wireless client to another wireless client will be wireless client to another wireless client will be
@ -70,7 +70,7 @@ Description:
What: /sys/class/net/<mesh_iface>/mesh/isolation_mark What: /sys/class/net/<mesh_iface>/mesh/isolation_mark
Date: Nov 2013 Date: Nov 2013
Contact: Antonio Quartulli <antonio@meshcoding.com> Contact: Antonio Quartulli <a@unstable.cc>
Description: Description:
Defines the isolation mark (and its bitmask) which Defines the isolation mark (and its bitmask) which
is used to classify clients as "isolated" by the is used to classify clients as "isolated" by the

View File

@ -2111,7 +2111,7 @@ F: include/linux/backlight.h
BATMAN ADVANCED BATMAN ADVANCED
M: Marek Lindner <mareklindner@neomailbox.ch> M: Marek Lindner <mareklindner@neomailbox.ch>
M: Simon Wunderlich <sw@simonwunderlich.de> M: Simon Wunderlich <sw@simonwunderlich.de>
M: Antonio Quartulli <antonio@meshcoding.com> M: Antonio Quartulli <a@unstable.cc>
L: b.a.t.m.a.n@lists.open-mesh.org L: b.a.t.m.a.n@lists.open-mesh.org
W: http://www.open-mesh.org/ W: http://www.open-mesh.org/
S: Maintained S: Maintained

View File

@ -1379,6 +1379,7 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
struct batadv_hard_iface *if_outgoing) struct batadv_hard_iface *if_outgoing)
{ {
struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
struct batadv_neigh_node *router = NULL; struct batadv_neigh_node *router = NULL;
struct batadv_neigh_node *router_router = NULL; struct batadv_neigh_node *router_router = NULL;
struct batadv_orig_node *orig_neigh_node; struct batadv_orig_node *orig_neigh_node;
@ -1423,6 +1424,13 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
goto out; goto out;
} }
if (is_single_hop_neigh) {
hardif_neigh = batadv_hardif_neigh_get(if_incoming,
ethhdr->h_source);
if (hardif_neigh)
hardif_neigh->last_seen = jiffies;
}
router = batadv_orig_router_get(orig_node, if_outgoing); router = batadv_orig_router_get(orig_node, if_outgoing);
if (router) { if (router) {
router_router = batadv_orig_router_get(router->orig_node, router_router = batadv_orig_router_get(router->orig_node,
@ -1557,6 +1565,8 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
batadv_neigh_node_free_ref(router_router); batadv_neigh_node_free_ref(router_router);
if (orig_neigh_router) if (orig_neigh_router)
batadv_neigh_node_free_ref(orig_neigh_router); batadv_neigh_node_free_ref(orig_neigh_router);
if (hardif_neigh)
batadv_hardif_neigh_free_ref(hardif_neigh);
kfree_skb(skb_priv); kfree_skb(skb_priv);
} }
@ -1861,6 +1871,58 @@ static void batadv_iv_ogm_orig_print(struct batadv_priv *bat_priv,
seq_puts(seq, "No batman nodes in range ...\n"); seq_puts(seq, "No batman nodes in range ...\n");
} }
/**
* batadv_iv_hardif_neigh_print - print a single hop neighbour node
* @seq: neighbour table seq_file struct
* @hardif_neigh: hardif neighbour information
*/
static void
batadv_iv_hardif_neigh_print(struct seq_file *seq,
struct batadv_hardif_neigh_node *hardif_neigh)
{
int last_secs, last_msecs;
last_secs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) / 1000;
last_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) % 1000;
seq_printf(seq, " %10s %pM %4i.%03is\n",
hardif_neigh->if_incoming->net_dev->name,
hardif_neigh->addr, last_secs, last_msecs);
}
/**
* batadv_iv_ogm_neigh_print - print the single hop neighbour list
* @bat_priv: the bat priv with all the soft interface information
* @seq: neighbour table seq_file struct
*/
static void batadv_iv_neigh_print(struct batadv_priv *bat_priv,
struct seq_file *seq)
{
struct net_device *net_dev = (struct net_device *)seq->private;
struct batadv_hardif_neigh_node *hardif_neigh;
struct batadv_hard_iface *hard_iface;
int batman_count = 0;
seq_printf(seq, " %10s %-13s %s\n",
"IF", "Neighbor", "last-seen");
rcu_read_lock();
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
if (hard_iface->soft_iface != net_dev)
continue;
hlist_for_each_entry_rcu(hardif_neigh,
&hard_iface->neigh_list, list) {
batadv_iv_hardif_neigh_print(seq, hardif_neigh);
batman_count++;
}
}
rcu_read_unlock();
if (batman_count == 0)
seq_puts(seq, "No batman nodes in range ...\n");
}
/** /**
* batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors
* @neigh1: the first neighbor object of the comparison * @neigh1: the first neighbor object of the comparison
@ -1902,8 +1964,8 @@ static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1,
} }
/** /**
* batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than * batadv_iv_ogm_neigh_is_sob - check if neigh1 is similarly good or better
* neigh2 from the metric prospective * than neigh2 from the metric prospective
* @neigh1: the first neighbor object of the comparison * @neigh1: the first neighbor object of the comparison
* @if_outgoing1: outgoing interface for the first neighbor * @if_outgoing1: outgoing interface for the first neighbor
* @neigh2: the second neighbor object of the comparison * @neigh2: the second neighbor object of the comparison
@ -1913,7 +1975,7 @@ static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1,
* the metric via neigh2, false otherwise. * the metric via neigh2, false otherwise.
*/ */
static bool static bool
batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1, batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1,
struct batadv_hard_iface *if_outgoing1, struct batadv_hard_iface *if_outgoing1,
struct batadv_neigh_node *neigh2, struct batadv_neigh_node *neigh2,
struct batadv_hard_iface *if_outgoing2) struct batadv_hard_iface *if_outgoing2)
@ -1953,7 +2015,8 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
.bat_ogm_schedule = batadv_iv_ogm_schedule, .bat_ogm_schedule = batadv_iv_ogm_schedule,
.bat_ogm_emit = batadv_iv_ogm_emit, .bat_ogm_emit = batadv_iv_ogm_emit,
.bat_neigh_cmp = batadv_iv_ogm_neigh_cmp, .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp,
.bat_neigh_is_equiv_or_better = batadv_iv_ogm_neigh_is_eob, .bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob,
.bat_neigh_print = batadv_iv_neigh_print,
.bat_orig_print = batadv_iv_ogm_orig_print, .bat_orig_print = batadv_iv_ogm_orig_print,
.bat_orig_free = batadv_iv_ogm_orig_free, .bat_orig_free = batadv_iv_ogm_orig_free,
.bat_orig_add_if = batadv_iv_ogm_orig_add_if, .bat_orig_add_if = batadv_iv_ogm_orig_add_if,

View File

@ -260,7 +260,9 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
} }
/* all claims gone, initialize CRC */ /* all claims gone, initialize CRC */
spin_lock_bh(&backbone_gw->crc_lock);
backbone_gw->crc = BATADV_BLA_CRC_INIT; backbone_gw->crc = BATADV_BLA_CRC_INIT;
spin_unlock_bh(&backbone_gw->crc_lock);
} }
/** /**
@ -408,6 +410,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig,
entry->lasttime = jiffies; entry->lasttime = jiffies;
entry->crc = BATADV_BLA_CRC_INIT; entry->crc = BATADV_BLA_CRC_INIT;
entry->bat_priv = bat_priv; entry->bat_priv = bat_priv;
spin_lock_init(&entry->crc_lock);
atomic_set(&entry->request_sent, 0); atomic_set(&entry->request_sent, 0);
atomic_set(&entry->wait_periods, 0); atomic_set(&entry->wait_periods, 0);
ether_addr_copy(entry->orig, orig); ether_addr_copy(entry->orig, orig);
@ -557,7 +560,9 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
__be16 crc; __be16 crc;
memcpy(mac, batadv_announce_mac, 4); memcpy(mac, batadv_announce_mac, 4);
spin_lock_bh(&backbone_gw->crc_lock);
crc = htons(backbone_gw->crc); crc = htons(backbone_gw->crc);
spin_unlock_bh(&backbone_gw->crc_lock);
memcpy(&mac[4], &crc, 2); memcpy(&mac[4], &crc, 2);
batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid, batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid,
@ -618,14 +623,18 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
"bla_add_claim(): changing ownership for %pM, vid %d\n", "bla_add_claim(): changing ownership for %pM, vid %d\n",
mac, BATADV_PRINT_VID(vid)); mac, BATADV_PRINT_VID(vid));
spin_lock_bh(&claim->backbone_gw->crc_lock);
claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
spin_unlock_bh(&claim->backbone_gw->crc_lock);
batadv_backbone_gw_free_ref(claim->backbone_gw); batadv_backbone_gw_free_ref(claim->backbone_gw);
} }
/* set (new) backbone gw */ /* set (new) backbone gw */
atomic_inc(&backbone_gw->refcount); atomic_inc(&backbone_gw->refcount);
claim->backbone_gw = backbone_gw; claim->backbone_gw = backbone_gw;
spin_lock_bh(&backbone_gw->crc_lock);
backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
spin_unlock_bh(&backbone_gw->crc_lock);
backbone_gw->lasttime = jiffies; backbone_gw->lasttime = jiffies;
claim_free_ref: claim_free_ref:
@ -653,7 +662,9 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
batadv_choose_claim, claim); batadv_choose_claim, claim);
batadv_claim_free_ref(claim); /* reference from the hash is gone */ batadv_claim_free_ref(claim); /* reference from the hash is gone */
spin_lock_bh(&claim->backbone_gw->crc_lock);
claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
spin_unlock_bh(&claim->backbone_gw->crc_lock);
/* don't need the reference from hash_find() anymore */ /* don't need the reference from hash_find() anymore */
batadv_claim_free_ref(claim); batadv_claim_free_ref(claim);
@ -664,7 +675,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
u8 *backbone_addr, unsigned short vid) u8 *backbone_addr, unsigned short vid)
{ {
struct batadv_bla_backbone_gw *backbone_gw; struct batadv_bla_backbone_gw *backbone_gw;
u16 crc; u16 backbone_crc, crc;
if (memcmp(an_addr, batadv_announce_mac, 4) != 0) if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
return 0; return 0;
@ -683,12 +694,16 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
"handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n", "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n",
BATADV_PRINT_VID(vid), backbone_gw->orig, crc); BATADV_PRINT_VID(vid), backbone_gw->orig, crc);
if (backbone_gw->crc != crc) { spin_lock_bh(&backbone_gw->crc_lock);
backbone_crc = backbone_gw->crc;
spin_unlock_bh(&backbone_gw->crc_lock);
if (backbone_crc != crc) {
batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv, batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
"handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n", "handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n",
backbone_gw->orig, backbone_gw->orig,
BATADV_PRINT_VID(backbone_gw->vid), BATADV_PRINT_VID(backbone_gw->vid),
backbone_gw->crc, crc); backbone_crc, crc);
batadv_bla_send_request(backbone_gw); batadv_bla_send_request(backbone_gw);
} else { } else {
@ -1647,6 +1662,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
struct batadv_bla_claim *claim; struct batadv_bla_claim *claim;
struct batadv_hard_iface *primary_if; struct batadv_hard_iface *primary_if;
struct hlist_head *head; struct hlist_head *head;
u16 backbone_crc;
u32 i; u32 i;
bool is_own; bool is_own;
u8 *primary_addr; u8 *primary_addr;
@ -1669,11 +1685,15 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
hlist_for_each_entry_rcu(claim, head, hash_entry) { hlist_for_each_entry_rcu(claim, head, hash_entry) {
is_own = batadv_compare_eth(claim->backbone_gw->orig, is_own = batadv_compare_eth(claim->backbone_gw->orig,
primary_addr); primary_addr);
spin_lock_bh(&claim->backbone_gw->crc_lock);
backbone_crc = claim->backbone_gw->crc;
spin_unlock_bh(&claim->backbone_gw->crc_lock);
seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n", seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n",
claim->addr, BATADV_PRINT_VID(claim->vid), claim->addr, BATADV_PRINT_VID(claim->vid),
claim->backbone_gw->orig, claim->backbone_gw->orig,
(is_own ? 'x' : ' '), (is_own ? 'x' : ' '),
claim->backbone_gw->crc); backbone_crc);
} }
rcu_read_unlock(); rcu_read_unlock();
} }
@ -1692,6 +1712,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
struct batadv_hard_iface *primary_if; struct batadv_hard_iface *primary_if;
struct hlist_head *head; struct hlist_head *head;
int secs, msecs; int secs, msecs;
u16 backbone_crc;
u32 i; u32 i;
bool is_own; bool is_own;
u8 *primary_addr; u8 *primary_addr;
@ -1722,10 +1743,14 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
if (is_own) if (is_own)
continue; continue;
spin_lock_bh(&backbone_gw->crc_lock);
backbone_crc = backbone_gw->crc;
spin_unlock_bh(&backbone_gw->crc_lock);
seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n", seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n",
backbone_gw->orig, backbone_gw->orig,
BATADV_PRINT_VID(backbone_gw->vid), secs, BATADV_PRINT_VID(backbone_gw->vid), secs,
msecs, backbone_gw->crc); msecs, backbone_crc);
} }
rcu_read_unlock(); rcu_read_unlock();
} }

View File

@ -262,6 +262,13 @@ static int batadv_algorithms_open(struct inode *inode, struct file *file)
return single_open(file, batadv_algo_seq_print_text, NULL); return single_open(file, batadv_algo_seq_print_text, NULL);
} }
static int neighbors_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, batadv_hardif_neigh_seq_print_text, net_dev);
}
static int batadv_originators_open(struct inode *inode, struct file *file) static int batadv_originators_open(struct inode *inode, struct file *file)
{ {
struct net_device *net_dev = (struct net_device *)inode->i_private; struct net_device *net_dev = (struct net_device *)inode->i_private;
@ -375,6 +382,7 @@ static struct batadv_debuginfo *batadv_general_debuginfos[] = {
}; };
/* The following attributes are per soft interface */ /* The following attributes are per soft interface */
static BATADV_DEBUGINFO(neighbors, S_IRUGO, neighbors_open);
static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open); static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open); static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
static BATADV_DEBUGINFO(transtable_global, S_IRUGO, static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
@ -394,6 +402,7 @@ static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
#endif #endif
static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
&batadv_debuginfo_neighbors,
&batadv_debuginfo_originators, &batadv_debuginfo_originators,
&batadv_debuginfo_gateways, &batadv_debuginfo_gateways,
&batadv_debuginfo_transtable_global, &batadv_debuginfo_transtable_global,

View File

@ -71,14 +71,14 @@ void batadv_frag_purge_orig(struct batadv_orig_node *orig_node,
for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) { for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
chain = &orig_node->fragments[i]; chain = &orig_node->fragments[i];
spin_lock_bh(&orig_node->fragments[i].lock); spin_lock_bh(&chain->lock);
if (!check_cb || check_cb(chain)) { if (!check_cb || check_cb(chain)) {
batadv_frag_clear_chain(&orig_node->fragments[i].head); batadv_frag_clear_chain(&chain->head);
orig_node->fragments[i].size = 0; chain->size = 0;
} }
spin_unlock_bh(&orig_node->fragments[i].lock); spin_unlock_bh(&chain->lock);
} }
} }

View File

@ -32,6 +32,7 @@
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
@ -639,9 +640,12 @@ batadv_hardif_add_interface(struct net_device *net_dev)
goto free_sysfs; goto free_sysfs;
INIT_LIST_HEAD(&hard_iface->list); INIT_LIST_HEAD(&hard_iface->list);
INIT_HLIST_HEAD(&hard_iface->neigh_list);
INIT_WORK(&hard_iface->cleanup_work, INIT_WORK(&hard_iface->cleanup_work,
batadv_hardif_remove_interface_finish); batadv_hardif_remove_interface_finish);
spin_lock_init(&hard_iface->neigh_list_lock);
hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT; hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
if (batadv_is_wifi_netdev(net_dev)) if (batadv_is_wifi_netdev(net_dev))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;

View File

@ -552,7 +552,7 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops)
!bat_algo_ops->bat_ogm_schedule || !bat_algo_ops->bat_ogm_schedule ||
!bat_algo_ops->bat_ogm_emit || !bat_algo_ops->bat_ogm_emit ||
!bat_algo_ops->bat_neigh_cmp || !bat_algo_ops->bat_neigh_cmp ||
!bat_algo_ops->bat_neigh_is_equiv_or_better) { !bat_algo_ops->bat_neigh_is_similar_or_better) {
pr_info("Routing algo '%s' does not implement required ops\n", pr_info("Routing algo '%s' does not implement required ops\n",
bat_algo_ops->name); bat_algo_ops->name);
return -EINVAL; return -EINVAL;
@ -908,7 +908,7 @@ u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
* appropriate handlers * appropriate handlers
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
* @tvlv_handler: tvlv callback function handling the tvlv content * @tvlv_handler: tvlv callback function handling the tvlv content
* @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet
* @orig_node: orig node emitting the ogm packet * @orig_node: orig node emitting the ogm packet
* @src: source mac address of the unicast packet * @src: source mac address of the unicast packet
* @dst: destination mac address of the unicast packet * @dst: destination mac address of the unicast packet
@ -961,7 +961,7 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
* batadv_tvlv_containers_process - parse the given tvlv buffer to call the * batadv_tvlv_containers_process - parse the given tvlv buffer to call the
* appropriate handlers * appropriate handlers
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
* @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet
* @orig_node: orig node emitting the ogm packet * @orig_node: orig node emitting the ogm packet
* @src: source mac address of the unicast packet * @src: source mac address of the unicast packet
* @dst: destination mac address of the unicast packet * @dst: destination mac address of the unicast packet

View File

@ -201,6 +201,47 @@ void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo)
call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu); call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu);
} }
/**
* batadv_hardif_neigh_free_rcu - free the hardif neigh_node
* @rcu: rcu pointer of the neigh_node
*/
static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu)
{
struct batadv_hardif_neigh_node *hardif_neigh;
hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu);
spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
hlist_del_init_rcu(&hardif_neigh->list);
spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
batadv_hardif_free_ref_now(hardif_neigh->if_incoming);
kfree(hardif_neigh);
}
/**
* batadv_hardif_neigh_free_now - decrement the hardif neighbors refcounter
* and possibly free it (without rcu callback)
* @hardif_neigh: hardif neigh neighbor to free
*/
static void
batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh)
{
if (atomic_dec_and_test(&hardif_neigh->refcount))
batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu);
}
/**
* batadv_hardif_neigh_free_ref - decrement the hardif neighbors refcounter
* and possibly free it
* @hardif_neigh: hardif neigh neighbor to free
*/
void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh)
{
if (atomic_dec_and_test(&hardif_neigh->refcount))
call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu);
}
/** /**
* batadv_neigh_node_free_rcu - free the neigh_node * batadv_neigh_node_free_rcu - free the neigh_node
* @rcu: rcu pointer of the neigh_node * @rcu: rcu pointer of the neigh_node
@ -209,6 +250,7 @@ static void batadv_neigh_node_free_rcu(struct rcu_head *rcu)
{ {
struct hlist_node *node_tmp; struct hlist_node *node_tmp;
struct batadv_neigh_node *neigh_node; struct batadv_neigh_node *neigh_node;
struct batadv_hardif_neigh_node *hardif_neigh;
struct batadv_neigh_ifinfo *neigh_ifinfo; struct batadv_neigh_ifinfo *neigh_ifinfo;
struct batadv_algo_ops *bao; struct batadv_algo_ops *bao;
@ -220,6 +262,14 @@ static void batadv_neigh_node_free_rcu(struct rcu_head *rcu)
batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo); batadv_neigh_ifinfo_free_ref_now(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_free_now(hardif_neigh);
batadv_hardif_neigh_free_now(hardif_neigh);
}
if (bao->bat_neigh_free) if (bao->bat_neigh_free)
bao->bat_neigh_free(neigh_node); bao->bat_neigh_free(neigh_node);
@ -478,6 +528,106 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
return res; return res;
} }
/**
* batadv_hardif_neigh_create - create a hardif neighbour node
* @hard_iface: the interface this neighbour is connected to
* @neigh_addr: the interface address of the neighbour to retrieve
*
* Returns the hardif neighbour node if found or created or NULL otherwise.
*/
static struct batadv_hardif_neigh_node *
batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
spin_lock_bh(&hard_iface->neigh_list_lock);
/* check if neighbor hasn't been added in the meantime */
hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
if (hardif_neigh)
goto out;
if (!atomic_inc_not_zero(&hard_iface->refcount))
goto out;
hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC);
if (!hardif_neigh) {
batadv_hardif_free_ref(hard_iface);
goto out;
}
INIT_HLIST_NODE(&hardif_neigh->list);
ether_addr_copy(hardif_neigh->addr, neigh_addr);
hardif_neigh->if_incoming = hard_iface;
hardif_neigh->last_seen = jiffies;
atomic_set(&hardif_neigh->refcount, 1);
if (bat_priv->bat_algo_ops->bat_hardif_neigh_init)
bat_priv->bat_algo_ops->bat_hardif_neigh_init(hardif_neigh);
hlist_add_head(&hardif_neigh->list, &hard_iface->neigh_list);
out:
spin_unlock_bh(&hard_iface->neigh_list_lock);
return hardif_neigh;
}
/**
* batadv_hardif_neigh_get_or_create - retrieve or create a hardif neighbour
* node
* @hard_iface: the interface this neighbour is connected to
* @neigh_addr: the interface address of the neighbour to retrieve
*
* Returns the hardif neighbour node if found or created or NULL otherwise.
*/
static struct batadv_hardif_neigh_node *
batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr)
{
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
/* first check without locking to avoid the overhead */
hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
if (hardif_neigh)
return hardif_neigh;
return batadv_hardif_neigh_create(hard_iface, neigh_addr);
}
/**
* batadv_hardif_neigh_get - retrieve a hardif neighbour from the list
* @hard_iface: the interface where this neighbour is connected to
* @neigh_addr: the address of the neighbour
*
* Looks for and possibly returns a neighbour belonging to this hard interface.
* Returns NULL if the neighbour is not found.
*/
struct batadv_hardif_neigh_node *
batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr)
{
struct batadv_hardif_neigh_node *tmp_hardif_neigh, *hardif_neigh = NULL;
rcu_read_lock();
hlist_for_each_entry_rcu(tmp_hardif_neigh,
&hard_iface->neigh_list, list) {
if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr))
continue;
if (!atomic_inc_not_zero(&tmp_hardif_neigh->refcount))
continue;
hardif_neigh = tmp_hardif_neigh;
break;
}
rcu_read_unlock();
return hardif_neigh;
}
/** /**
* batadv_neigh_node_new - create and init a new neigh_node object * batadv_neigh_node_new - create and init a new neigh_node object
* @orig_node: originator object representing the neighbour * @orig_node: originator object representing the neighbour
@ -493,11 +643,17 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
const u8 *neigh_addr) const u8 *neigh_addr)
{ {
struct batadv_neigh_node *neigh_node; struct batadv_neigh_node *neigh_node;
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
if (neigh_node) if (neigh_node)
goto out; goto out;
hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface,
neigh_addr);
if (!hardif_neigh)
goto out;
neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC); neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
if (!neigh_node) if (!neigh_node)
goto out; goto out;
@ -523,14 +679,53 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
spin_unlock_bh(&orig_node->neigh_list_lock); spin_unlock_bh(&orig_node->neigh_list_lock);
/* increment unique neighbor refcount */
atomic_inc(&hardif_neigh->refcount);
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
"Creating new neighbor %pM for orig_node %pM on interface %s\n", "Creating new neighbor %pM for orig_node %pM on interface %s\n",
neigh_addr, orig_node->orig, hard_iface->net_dev->name); neigh_addr, orig_node->orig, hard_iface->net_dev->name);
out: out:
if (hardif_neigh)
batadv_hardif_neigh_free_ref(hardif_neigh);
return neigh_node; return neigh_node;
} }
/**
* batadv_hardif_neigh_seq_print_text - print the single hop neighbour list
* @seq: neighbour table seq_file struct
* @offset: not used
*
* Always returns 0.
*/
int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset)
{
struct net_device *net_dev = (struct net_device *)seq->private;
struct batadv_priv *bat_priv = netdev_priv(net_dev);
struct batadv_hard_iface *primary_if;
primary_if = batadv_seq_print_text_primary_if_get(seq);
if (!primary_if)
return 0;
seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s %s)]\n",
BATADV_SOURCE_VERSION, primary_if->net_dev->name,
primary_if->net_dev->dev_addr, net_dev->name,
bat_priv->bat_algo_ops->name);
batadv_hardif_free_ref(primary_if);
if (!bat_priv->bat_algo_ops->bat_neigh_print) {
seq_puts(seq,
"No printing function for this routing protocol\n");
return 0;
}
bat_priv->bat_algo_ops->bat_neigh_print(bat_priv, seq);
return 0;
}
/** /**
* batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
* @rcu: rcu pointer of the orig_ifinfo object * @rcu: rcu pointer of the orig_ifinfo object

View File

@ -41,6 +41,11 @@ void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node);
void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); 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, struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
const u8 *addr); const u8 *addr);
struct batadv_hardif_neigh_node *
batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr);
void
batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh);
struct batadv_neigh_node * struct batadv_neigh_node *
batadv_neigh_node_new(struct batadv_orig_node *orig_node, batadv_neigh_node_new(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *hard_iface, struct batadv_hard_iface *hard_iface,
@ -57,6 +62,8 @@ batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
struct batadv_hard_iface *if_outgoing); struct batadv_hard_iface *if_outgoing);
void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo); void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo);
int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset);
struct batadv_orig_ifinfo * struct batadv_orig_ifinfo *
batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *if_outgoing); struct batadv_hard_iface *if_outgoing);

View File

@ -497,9 +497,9 @@ batadv_find_router(struct batadv_priv *bat_priv,
/* alternative candidate should be good enough to be /* alternative candidate should be good enough to be
* considered * considered
*/ */
if (!bao->bat_neigh_is_equiv_or_better(cand_router, if (!bao->bat_neigh_is_similar_or_better(cand_router,
cand->if_outgoing, cand->if_outgoing,
router, recv_if)) router, recv_if))
goto next; goto next;
/* don't use the same router twice */ /* don't use the same router twice */

View File

@ -1435,7 +1435,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
* TT_CLIENT_WIFI, therefore they have to be copied in the * TT_CLIENT_WIFI, therefore they have to be copied in the
* client entry * client entry
*/ */
tt_global_entry->common.flags |= flags; common->flags |= flags;
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
* one originator left in the list and we previously received a * one originator left in the list and we previously received a
@ -2411,8 +2411,8 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
{ {
struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp; struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
struct batadv_orig_node_vlan *vlan; struct batadv_orig_node_vlan *vlan;
int i, orig_num_vlan;
u32 crc; u32 crc;
int i;
/* check if each received CRC matches the locally stored one */ /* check if each received CRC matches the locally stored one */
for (i = 0; i < num_vlan; i++) { for (i = 0; i < num_vlan; i++) {
@ -2438,6 +2438,18 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
return false; return false;
} }
/* check if any excess VLANs exist locally for the originator
* which are not mentioned in the TVLV from the originator.
*/
rcu_read_lock();
orig_num_vlan = 0;
hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list)
orig_num_vlan++;
rcu_read_unlock();
if (orig_num_vlan > num_vlan)
return false;
return true; return true;
} }

View File

@ -100,6 +100,8 @@ struct batadv_hard_iface_bat_iv {
* @bat_iv: BATMAN IV specific per hard interface data * @bat_iv: BATMAN IV specific per hard interface data
* @cleanup_work: work queue callback item for hard interface deinit * @cleanup_work: work queue callback item for hard interface deinit
* @debug_dir: dentry for nc subdir in batman-adv directory in debugfs * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs
* @neigh_list: list of unique single hop neighbors via this interface
* @neigh_list_lock: lock protecting neigh_list
*/ */
struct batadv_hard_iface { struct batadv_hard_iface {
struct list_head list; struct list_head list;
@ -115,6 +117,9 @@ struct batadv_hard_iface {
struct batadv_hard_iface_bat_iv bat_iv; struct batadv_hard_iface_bat_iv bat_iv;
struct work_struct cleanup_work; struct work_struct cleanup_work;
struct dentry *debug_dir; struct dentry *debug_dir;
struct hlist_head neigh_list;
/* neigh_list_lock protects: neigh_list */
spinlock_t neigh_list_lock;
}; };
/** /**
@ -340,6 +345,23 @@ struct batadv_gw_node {
struct rcu_head rcu; struct rcu_head rcu;
}; };
/**
* batadv_hardif_neigh_node - unique neighbor per hard interface
* @list: list node for batadv_hard_iface::neigh_list
* @addr: the MAC address of the neighboring interface
* @if_incoming: pointer to incoming hard interface
* @refcount: number of contexts the object is used
* @rcu: struct used for freeing in a RCU-safe manner
*/
struct batadv_hardif_neigh_node {
struct hlist_node list;
u8 addr[ETH_ALEN];
struct batadv_hard_iface *if_incoming;
unsigned long last_seen;
atomic_t refcount;
struct rcu_head rcu;
};
/** /**
* struct batadv_neigh_node - structure for single hops neighbors * struct batadv_neigh_node - structure for single hops neighbors
* @list: list node for batadv_orig_node::neigh_list * @list: list node for batadv_orig_node::neigh_list
@ -884,6 +906,7 @@ struct batadv_socket_packet {
* backbone gateway - no bcast traffic is formwared until the situation was * backbone gateway - no bcast traffic is formwared until the situation was
* resolved * resolved
* @crc: crc16 checksum over all claims * @crc: crc16 checksum over all claims
* @crc_lock: lock protecting crc
* @refcount: number of contexts the object is used * @refcount: number of contexts the object is used
* @rcu: struct used for freeing in an RCU-safe manner * @rcu: struct used for freeing in an RCU-safe manner
*/ */
@ -897,6 +920,7 @@ struct batadv_bla_backbone_gw {
atomic_t wait_periods; atomic_t wait_periods;
atomic_t request_sent; atomic_t request_sent;
u16 crc; u16 crc;
spinlock_t crc_lock; /* protects crc */
atomic_t refcount; atomic_t refcount;
struct rcu_head rcu; struct rcu_head rcu;
}; };
@ -1131,11 +1155,13 @@ struct batadv_forw_packet {
* @bat_primary_iface_set: called when primary interface is selected / changed * @bat_primary_iface_set: called when primary interface is selected / changed
* @bat_ogm_schedule: prepare a new outgoing OGM for the send queue * @bat_ogm_schedule: prepare a new outgoing OGM for the send queue
* @bat_ogm_emit: send scheduled OGM * @bat_ogm_emit: send scheduled OGM
* @bat_hardif_neigh_init: called on creation of single hop entry
* @bat_neigh_cmp: compare the metrics of two neighbors for their respective * @bat_neigh_cmp: compare the metrics of two neighbors for their respective
* outgoing interfaces * outgoing interfaces
* @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or better * @bat_neigh_is_similar_or_better: check if neigh1 is equally similar or
* than neigh2 for their respective outgoing interface from the metric * better than neigh2 for their respective outgoing interface from the metric
* prospective * prospective
* @bat_neigh_print: print the single hop neighbor list (optional)
* @bat_neigh_free: free the resources allocated by the routing algorithm for a * @bat_neigh_free: free the resources allocated by the routing algorithm for a
* neigh_node object * neigh_node object
* @bat_orig_print: print the originator table (optional) * @bat_orig_print: print the originator table (optional)
@ -1156,15 +1182,17 @@ struct batadv_algo_ops {
void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface); void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface);
void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet); void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet);
/* neigh_node handling API */ /* neigh_node handling API */
void (*bat_hardif_neigh_init)(struct batadv_hardif_neigh_node *neigh);
int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1,
struct batadv_hard_iface *if_outgoing1, struct batadv_hard_iface *if_outgoing1,
struct batadv_neigh_node *neigh2, struct batadv_neigh_node *neigh2,
struct batadv_hard_iface *if_outgoing2); struct batadv_hard_iface *if_outgoing2);
bool (*bat_neigh_is_equiv_or_better) bool (*bat_neigh_is_similar_or_better)
(struct batadv_neigh_node *neigh1, (struct batadv_neigh_node *neigh1,
struct batadv_hard_iface *if_outgoing1, struct batadv_hard_iface *if_outgoing1,
struct batadv_neigh_node *neigh2, struct batadv_neigh_node *neigh2,
struct batadv_hard_iface *if_outgoing2); struct batadv_hard_iface *if_outgoing2);
void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq);
void (*bat_neigh_free)(struct batadv_neigh_node *neigh); void (*bat_neigh_free)(struct batadv_neigh_node *neigh);
/* orig_node handling API */ /* orig_node handling API */
void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq,