Commit 04ad3783 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 897ca373 5a1dd8a4
...@@ -8,7 +8,7 @@ Description: ...@@ -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: ...@@ -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
......
...@@ -2111,7 +2111,7 @@ F: include/linux/backlight.h ...@@ -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
......
...@@ -1379,6 +1379,7 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 = { ...@@ -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,
......
...@@ -260,7 +260,9 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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();
} }
......
...@@ -262,6 +262,13 @@ static int batadv_algorithms_open(struct inode *inode, struct file *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[] = { ...@@ -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); ...@@ -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,
......
...@@ -71,14 +71,14 @@ void batadv_frag_purge_orig(struct batadv_orig_node *orig_node, ...@@ -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);
} }
} }
......
...@@ -32,6 +32,7 @@ ...@@ -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) ...@@ -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;
......
...@@ -552,7 +552,7 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops) ...@@ -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, ...@@ -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, ...@@ -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
......
...@@ -201,6 +201,47 @@ void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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
......
...@@ -41,6 +41,11 @@ void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); ...@@ -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, ...@@ -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);
......
...@@ -497,7 +497,7 @@ batadv_find_router(struct batadv_priv *bat_priv, ...@@ -497,7 +497,7 @@ 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;
......
...@@ -1435,7 +1435,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
...@@ -100,6 +100,8 @@ struct batadv_hard_iface_bat_iv { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment