[B.A.T.M.A.N.] [PATCH 1/2] batman-adv: Fix broadcast+ogm queue purging race condition
by Linus Lüssing
So far on purging broadcast and ogm queues we temporarily give up the
spin lock of these queues to be able to cancel any scheduled forwarding
work. However this is unsafe and can lead to a general protection error
in batadv_purge_outstanding_packets().
With this patch we split the queue purging into two steps: First
removing forward packets from those queues and signaling the
cancelation. Secondly, we are actively canceling any scheduled
forwarding, wait for any running forwarding to finish and only free a
forw_packet afterwards.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
Fixes issue #168
send.c | 117 ++++++++++++++++++++++++++++++++++++++-------------------------
types.h | 1 +
2 files changed, 71 insertions(+), 47 deletions(-)
diff --git a/send.c b/send.c
index 0a0bb45..f93476b 100644
--- a/send.c
+++ b/send.c
@@ -245,6 +245,10 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
bat_priv = netdev_priv(soft_iface);
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
+ if (hlist_unhashed(&forw_packet->list)) {
+ spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
+ return;
+ }
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
@@ -293,6 +297,10 @@ void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work)
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
+ if (hlist_unhashed(&forw_packet->list)) {
+ spin_unlock_bh(&bat_priv->forw_bat_list_lock);
+ return;
+ }
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
@@ -316,13 +324,68 @@ out:
batadv_forw_packet_free(forw_packet);
}
+/**
+ * batadv_cancel_packets - Cancels a list of forward packets
+ * @forw_list: The to be canceled forward packets
+ * @canceled_list: The backup list.
+ *
+ * This canceles any scheduled forwarding packet tasks in the provided
+ * forw_list. The packets are being moved from the forw_list to the
+ * canceled_list afterwards to unhash the forward packet list pointer,
+ * allowing any already running task to notice the cancelation.
+ */
+static void batadv_cancel_packets(struct hlist_head *forw_list,
+ struct hlist_head *canceled_list,
+ const struct batadv_hard_iface *hard_iface)
+{
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *tmp_node, *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
+ forw_list, list) {
+ /* if purge_outstanding_packets() was called with an argument
+ * we delete only packets belonging to the given interface
+ */
+ if ((hard_iface) &&
+ (forw_packet->if_incoming != hard_iface))
+ continue;
+
+ hlist_del_init(&forw_packet->list);
+ hlist_add_head(&forw_packet->canceled_list, canceled_list);
+ }
+}
+
+/**
+ * batadv_canceled_packets_free - Frees canceled forward packets
+ * @head: A list of to be freed forw_packets
+ *
+ * This function canceles the scheduling of any packet in the provided list,
+ * waits for any possibly running packet forwarding thread to finish and
+ * finally, safely frees this forward packet.
+ *
+ * This function might sleep.
+ */
+static void batadv_canceled_packets_free(struct hlist_head *head)
+{
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *tmp_node, *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, head,
+ canceled_list) {
+ cancel_delayed_work_sync(&forw_packet->delayed_work);
+
+ hlist_del(&forw_packet->canceled_list);
+ batadv_forw_packet_free(forw_packet);
+ }
+}
+
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface)
{
- struct batadv_forw_packet *forw_packet;
- struct hlist_node *tmp_node, *safe_tmp_node;
- bool pending;
+ struct hlist_head head;
+
+ INIT_HLIST_HEAD(&head);
if (hard_iface)
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -334,53 +397,13 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
/* free bcast list */
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
- hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
- &bat_priv->forw_bcast_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
-
- /* batadv_send_outstanding_bcast_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bcast_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_cancel_packets(&bat_priv->forw_bcast_list, &head, hard_iface);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
/* free batman packet list */
spin_lock_bh(&bat_priv->forw_bat_list_lock);
- hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
- &bat_priv->forw_bat_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bat_list_lock);
-
- /* send_outstanding_bat_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bat_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_cancel_packets(&bat_priv->forw_bat_list, &head, hard_iface);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
+
+ batadv_canceled_packets_free(&head);
}
diff --git a/types.h b/types.h
index aba8364..f62a35f 100644
--- a/types.h
+++ b/types.h
@@ -853,6 +853,7 @@ struct batadv_skb_cb {
*/
struct batadv_forw_packet {
struct hlist_node list;
+ struct hlist_node canceled_list;
unsigned long send_time;
uint8_t own;
struct sk_buff *skb;
--
1.7.10.4
6 years, 6 months
[B.A.T.M.A.N.] [PATCH 1/2] batman-adv: Fix broadcast queue limit on a removed interface
by Linus Lüssing
When removing a single interface while a broadcast or ogm packet is
still pending then we will free the forward packet without releasing the
queue slots again.
This patch is supposed to fix this issue.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
send.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/send.c b/send.c
index ed7072a..2d539d6 100644
--- a/send.c
+++ b/send.c
@@ -356,6 +356,9 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
if (pending) {
hlist_del(&forw_packet->list);
+ if (!forw_packet->own)
+ atomic_inc(&bat_priv->bcast_queue_left);
+
batadv_forw_packet_free(forw_packet);
}
}
@@ -382,6 +385,9 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
if (pending) {
hlist_del(&forw_packet->list);
+ if (!forw_packet->own)
+ atomic_inc(&bat_priv->batman_queue_left);
+
batadv_forw_packet_free(forw_packet);
}
}
--
1.7.10.4
6 years, 10 months
[B.A.T.M.A.N.] Classes and purposed classes (problem to solve)
by cmsv
Scenario:
I have recently moved 13 nodes previously using wds to batman-adv.
One problem that i am encountering is the gateway selection and its
actually defectiveness.
This problem has be seen when the client nodes are set on class 20.
The node clients in fact select the gateways that advertise better link
quality usually above 200 but at the same time some clients end up
connecting to a gateway that is either too slow or unusable either due
to routing or other factors such as distance and even clear visibility.
In one case the node connects to something that defies logic.
I thought about ways to work around this and came up with an idea that
may help which means the creation of 2 new classes.
- Preferred gateway fall-back
- Preferred fixed gateway
For Preferred gateway fall-back:
consider the gateway's advertised quality towards the gateway and stick
with the selection until the gateway disappears returning to it soon as
it returns regardless of any other data.
- Preferred fixed gateway
Manual gateway selection by the node owner or admin. (wds type)
If these classes cannot be created; maybe a plugin of some sort could
be. could be called "gordon".
I understand that this idea may sound useless the same way blocking
originators may be for someone but in some scenarios just like blocking
originators it look to me very valid.
My current problem is that the link quality seems to go up and down like
a roller coaster in a specific order which causes the clients to switch
constantly sometimes many times per hour.
While this does not seem to be an issue for most client nodes; for 2 of
them it means no internet access at all.
The solution for now seems to be having these 2 nodes forced to use 1
specific gateway.
I am quite open to any ideas that may help resolve this issue that has
been casing some "uninformed people" to become headaches.
--
Redes wireless
http://wirelesspt.net
7 years, 2 months
[B.A.T.M.A.N.] TVLV infrastructure (v2)
by Marek Lindner
Hi,
at the battlemesh we had plenty of time to discuss and test the tvlv
patchset. Therefore, a number of changes/fixes found their way into
v2 touching the tvlv API, network coding, unicast sending and gateway
announcements.
This looks like the final version which is going to be merged unless
objections are raised soon-ish.
Cheers,
Marek
7 years, 8 months
[B.A.T.M.A.N.] Batman-adv and Uevent (gateway/client modes)
by cmsv
I have reached a point where i need to start using the uevent
functionality to work around some network scenarios when the gateways
lose internet access but i am having a bit of a difficult time
understanding how to do it since making use of uevents which is
something new to me.
The explanation here is not helping much either
http://www.open-mesh.org/projects/batman-adv/wiki/Uevent
and i understand that i might need to go to the basics to understand it
and learn how to code.
My need to use uevents to change a nodes behaviour is to change a node
from server to client and vice versa when it loses connectivity to the
WAN (not for example losing connectivity to the dsl router that is
actually the gateway but that has the node as a LAN client)
I am assuming that uevents will allow me to work with this physical
setup correct?
As far as i understand now and if i am not mistaken when a gateway loses
WAN connectivity the node that is making use of uevents will change the
node from "server" to "client" on batman-adv .
Now my question is if i can also make it to change the dhcp setup from
dhcp server to inactive and receive it´s dhcp service from another
gateway node.
In theory something like this would be executed on openwrt when a
gateway node detects no connectivity to the wan:
uci set batman-adv.bat0.gw_mode=client ;
uci commit batman-adv ;
batman-adv reboot ;
uci set dhcp.lan.force=0 ;
uci set dhcp.lan.ignore=1 ;
uci commit dhcp ;
/etc/init.d/dnsmasq restart ;
when it detects wan connectivity it will want to become a server and
will auto execute:
uci set batman-adv.bat0.gw_mode=server ;
uci commit batman-adv ;
batman-adv reboot ;
uci set dhcp.lan.force=1 ;
uci set dhcp.lan.ignore=0 ;
uci commit dhcp ;
/etc/init.d/dnsmasq restart ;
A small script can even be made in order so simplify things either
automatically or manually and lets call it:
gateway-mode
client-mode
Upon detecting no WAN connectivity the script will be activated.
Am i on the right track so far (at least in theory) ?
Now the second part is how to detect WAN connectivity which is different
from noticing that there is no connectivity to the actual gw router that
has the node on it's LAN.
I thought about a ping test to a few address from which after 100% loss
reply from all; something or Uevent will activate the gateway/client
mode script but it creates another problem ahead.
In a quick conversation with ordex on irc i understand that i have to
invoke the wiki docs uevent functions with the parameters i want at the
moment i decide.
This can be the gateway/client mode script
correct ?
Since uevent is something new to me; can someone recommend some freshman
tutorial that may take me in the right direction. I have no clue where
or how to start looking to code it and also when coded; where will it be
added.
I also would like to ask anyone that has uevent working how they are
using it for the same type of need and maybe even share some recipe.
--
Site: http://wirelesspt.net
Mesh: http://tinyurl.com/wirelesspt
Admin: http://wirelesspt.net/wiki/Cmsv
Suporte técnico via sms: 91 19 11 798
Donativos/Paypal: http://tinyurl.com/doar-verba
Chave publica PGP/SSH: http://wirelesspt.net/arquivos/pk
Email assinado digitalmente pelo emissor assegurando autenticidade
9 years, 9 months
[B.A.T.M.A.N.] [PATCH] Made DAT more generic by adding support to any type of data
by Mihail
From: Mihail Costea <mihail.costea90(a)gmail.com>
Made DAT support more types by making its data a void*, adding type field
to dat_entry and adding data_type to necessary functions.
This change is needed in order to make DAT support any type of data, like IPv6 too.
Added generic function for transforming DAT data to string.
The function is used in order to avoid defining different debug messages
for different DAT data types. For example, if we had IPv6 as a DAT data,
then "%pI4" should be "%pI6c", but all
the other text of the debug message would be the same.
Signed-off-by: Mihail Costea <mihail.costea90(a)gmail.com>
Signed-off-by: Stefan Popa <Stefan.A.Popa(a)intel.com>
Reviewed-by: Stefan Popa <Stefan.A.Popa(a)intel.com>
---
distributed-arp-table.c | 229 ++++++++++++++++++++++++++++++++++++-----------
distributed-arp-table.h | 1 +
types.h | 14 ++-
3 files changed, 190 insertions(+), 54 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c
index 3a4b577..30af421 100644
--- a/distributed-arp-table.c
+++ b/distributed-arp-table.c
@@ -31,9 +31,29 @@
#include "translation-table.h"
#include "unicast.h"
+static char *batadv_dat_types_str_fmt[] = {
+ "%pI4",
+};
+
static void batadv_dat_purge(struct work_struct *work);
/**
+ * batadv_dat_data_to_str: transforms DAT data to string
+ * @data: the DAT data
+ * @type: type of data
+ * @buf: the buf where the data string is stored
+ * @buf_len: buf length
+ *
+ * Returns buf.
+ */
+static char *batadv_dat_data_to_str(void *data, uint8_t type,
+ char *buf, size_t buf_len)
+{
+ snprintf(buf, buf_len, batadv_dat_types_str_fmt[type], data);
+ return buf;
+}
+
+/**
* batadv_dat_start_timer - initialise the DAT periodic worker
* @bat_priv: the bat priv with all the soft interface information
*/
@@ -45,6 +65,19 @@ static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
}
/**
+ * batadv_dat_entry_free_ref_rcu - free a dat entry using its rcu
+ * @rcu: the dat entry rcu
+ */
+static void batadv_dat_entry_free_ref_rcu(struct rcu_head *rcu)
+{
+ struct batadv_dat_entry *dat_entry;
+
+ dat_entry = container_of(rcu, struct batadv_dat_entry, rcu);
+ kfree(dat_entry->data);
+ kfree(dat_entry);
+}
+
+/**
* batadv_dat_entry_free_ref - decrement the dat_entry refcounter and possibly
* free it
* @dat_entry: the entry to free
@@ -52,7 +85,7 @@ static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
{
if (atomic_dec_and_test(&dat_entry->refcount))
- kfree_rcu(dat_entry, rcu);
+ call_rcu(&dat_entry->rcu, batadv_dat_entry_free_ref_rcu);
}
/**
@@ -130,6 +163,22 @@ static void batadv_dat_purge(struct work_struct *work)
}
/**
+ * batadv_sizeof_dat_data - get sizeof DAT data based on its type
+ * @data_type: type of DAT data
+ *
+ * Returns sizeof data, or 0 if invalid.
+ */
+static size_t batadv_sizeof_dat_data(uint8_t data_type)
+{
+ switch (data_type) {
+ case BATADV_DAT_IPV4:
+ return sizeof(__be32);
+ default:
+ return 0;
+ }
+}
+
+/**
* batadv_compare_dat - comparing function used in the local DAT hash table
* @node: node in the local table
* @data2: second object to compare the node to
@@ -138,10 +187,22 @@ static void batadv_dat_purge(struct work_struct *work)
*/
static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
{
- const void *data1 = container_of(node, struct batadv_dat_entry,
- hash_entry);
+ struct batadv_dat_entry *dat_entry1 =
+ container_of(node, struct batadv_dat_entry,
+ hash_entry);
+ struct batadv_dat_entry *dat_entry2 =
+ container_of(data2,
+ struct batadv_dat_entry, data);
+ size_t data_size;
- return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
+ if (dat_entry1->type != dat_entry2->type)
+ return 0;
+ data_size = batadv_sizeof_dat_data(dat_entry1->type);
+ if (data_size == 0)
+ return 0;
+
+ return (memcmp(dat_entry1->data, dat_entry2->data,
+ data_size) == 0 ? 1 : 0);
}
/**
@@ -198,19 +259,25 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
}
/**
- * batadv_hash_dat - compute the hash value for an IP address
+ * batadv_hash_dat - compute the hash value for a DAT data
* @data: data to hash
+ * @data_type: type of data
* @size: size of the hash table
*
* Returns the selected index in the hash table for the given data.
*/
-static uint32_t batadv_hash_dat(const void *data, uint32_t size)
+static uint32_t batadv_hash_dat(const void *data, uint8_t data_type,
+ uint32_t size)
{
const unsigned char *key = data;
uint32_t hash = 0;
- size_t i;
+ size_t i, data_size;
- for (i = 0; i < 4; i++) {
+ data_size = batadv_sizeof_dat_data(data_type);
+ if (data_size == 0)
+ return 0;
+
+ for (i = 0; i < data_size; i++) {
hash += key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
@@ -223,31 +290,46 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size)
return hash % size;
}
+static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size)
+{
+ return batadv_hash_dat(data, BATADV_DAT_IPV4, size);
+}
+
+
/**
* batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
* table
* @bat_priv: the bat priv with all the soft interface information
- * @ip: search key
+ * @data: search key
+ * @data_type: type of data
*
* Returns the dat_entry if found, NULL otherwise.
*/
static struct batadv_dat_entry *
-batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
+batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, void *data,
+ uint8_t data_type)
{
struct hlist_head *head;
struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL;
struct batadv_hashtable *hash = bat_priv->dat.hash;
uint32_t index;
+ size_t data_size;
if (!hash)
return NULL;
- index = batadv_hash_dat(&ip, hash->size);
+ data_size = batadv_sizeof_dat_data(data_type);
+ if (data_size == 0)
+ return NULL;
+
+ index = batadv_hash_dat(data, data_type, hash->size);
head = &hash->table[index];
rcu_read_lock();
hlist_for_each_entry_rcu(dat_entry, head, hash_entry) {
- if (dat_entry->ip != ip)
+ if (dat_entry->type != data_type)
+ continue;
+ if (memcmp(dat_entry->data, data, data_size))
continue;
if (!atomic_inc_not_zero(&dat_entry->refcount))
@@ -264,23 +346,28 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
/**
* batadv_dat_entry_add - add a new dat entry or update it if already exists
* @bat_priv: the bat priv with all the soft interface information
- * @ip: ipv4 to add/edit
- * @mac_addr: mac address to assign to the given ipv4
+ * @data: the data to add/edit
+ * @data_type: type of the data added to DAT
+ * @mac_addr: mac address to assign to the given data
*/
-static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
- uint8_t *mac_addr)
+static void batadv_dat_entry_add(struct batadv_priv *bat_priv, void *data,
+ uint8_t data_type, uint8_t *mac_addr)
{
struct batadv_dat_entry *dat_entry;
int hash_added;
+ char dbg_data[BATADV_DAT_DATA_MAX_LEN];
+ size_t data_size;
+ batadv_hashdata_choose_cb choose;
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, data, data_type);
/* if this entry is already known, just update it */
if (dat_entry) {
if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
dat_entry->last_update = jiffies;
- batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "Entry updated: %pI4 %pM\n", &dat_entry->ip,
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "Entry updated: %s %pM\n",
+ batadv_dat_data_to_str(dat_entry->data, data_type,
+ dbg_data, sizeof(dbg_data)),
dat_entry->mac_addr);
goto out;
}
@@ -289,13 +376,29 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
if (!dat_entry)
goto out;
- dat_entry->ip = ip;
+ data_size = batadv_sizeof_dat_data(data_type);
+ if (data_size == 0)
+ goto out;
+ dat_entry->data = kmalloc(data_size, GFP_ATOMIC);
+ if (!dat_entry->data)
+ goto out;
+ memcpy(dat_entry->data, data, data_size);
+ dat_entry->type = data_type;
+
memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
dat_entry->last_update = jiffies;
atomic_set(&dat_entry->refcount, 2);
+ switch (data_type) {
+ case BATADV_DAT_IPV4:
+ choose = batadv_hash_dat_ipv4;
+ break;
+ default:
+ goto out;
+ }
+
hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
- batadv_hash_dat, &dat_entry->ip,
+ choose, dat_entry->data,
&dat_entry->hash_entry);
if (unlikely(hash_added != 0)) {
@@ -304,8 +407,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
goto out;
}
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n",
- &dat_entry->ip, dat_entry->mac_addr);
+
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %s %pM\n",
+ batadv_dat_data_to_str(dat_entry->data, data_type,
+ dbg_data, sizeof(dbg_data)),
+ dat_entry->mac_addr);
out:
if (dat_entry)
@@ -517,20 +623,23 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
* batadv_dat_select_candidates - select the nodes which the DHT message has to
* be sent to
* @bat_priv: the bat priv with all the soft interface information
- * @ip_dst: ipv4 to look up in the DHT
+ * @data: data to look up in the DHT
+ * @data_type: type of data
*
* 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
- * value of the key. ip_dst is the key.
+ * value of the key. data is the key.
*
* Returns 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, void *data,
+ uint8_t data_type)
{
int select;
- batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
+ batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, data_key;
struct batadv_dat_candidate *res;
+ char dbg_data[BATADV_DAT_DATA_MAX_LEN];
if (!bat_priv->orig_hash)
return NULL;
@@ -539,15 +648,17 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
if (!res)
return NULL;
- ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
- BATADV_DAT_ADDR_MAX);
+ data_key = (batadv_dat_addr_t)batadv_hash_dat(data, data_type,
+ BATADV_DAT_ADDR_MAX);
batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
- ip_key);
+ "dat_select_candidates(): DATA=%s hash(DATA)=%u\n",
+ batadv_dat_data_to_str(data, data_type, dbg_data,
+ sizeof(dbg_data)),
+ data_key);
for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
- batadv_choose_next_candidate(bat_priv, res, select, ip_key,
+ batadv_choose_next_candidate(bat_priv, res, select, data_key,
&last_max);
return res;
@@ -557,7 +668,8 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
* batadv_dat_send_data - send a payload to the selected candidates
* @bat_priv: the bat priv with all the soft interface information
* @skb: payload to send
- * @ip: the DHT key
+ * @data: the DHT key
+ * @data_type: type of data
* @packet_subtype: unicast4addr packet subtype to use
*
* This function copies the skb with pskb_copy() and is sent as unicast packet
@@ -567,8 +679,8 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
* otherwise.
*/
static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
- struct sk_buff *skb, __be32 ip,
- int packet_subtype)
+ struct sk_buff *skb, void *data,
+ uint8_t data_type, int packet_subtype)
{
int i;
bool ret = false;
@@ -576,12 +688,15 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
struct batadv_neigh_node *neigh_node = NULL;
struct sk_buff *tmp_skb;
struct batadv_dat_candidate *cand;
+ char dbg_data[BATADV_DAT_DATA_MAX_LEN];
- cand = batadv_dat_select_candidates(bat_priv, ip);
+ cand = batadv_dat_select_candidates(bat_priv, data, data_type);
if (!cand)
goto out;
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip);
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %s\n",
+ batadv_dat_data_to_str(data, data_type, dbg_data,
+ sizeof(dbg_data)));
for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) {
if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
@@ -771,9 +886,13 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
last_seen_msecs = last_seen_msecs % 60000;
last_seen_secs = last_seen_msecs / 1000;
- seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
- &dat_entry->ip, dat_entry->mac_addr,
- last_seen_mins, last_seen_secs);
+ switch (dat_entry->type) {
+ case BATADV_DAT_IPV4:
+ seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
+ dat_entry->data, dat_entry->mac_addr,
+ last_seen_mins, last_seen_secs);
+ break;
+ }
}
rcu_read_unlock();
}
@@ -894,9 +1013,10 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
hw_src = batadv_arp_hw_src(skb, 0);
ip_dst = batadv_arp_ip_dst(skb, 0);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst,
+ BATADV_DAT_IPV4);
if (dat_entry) {
skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
bat_priv->soft_iface, ip_dst, hw_src,
@@ -916,7 +1036,8 @@ 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,
+ BATADV_DAT_IPV4,
BATADV_P_DAT_DHT_GET);
}
out:
@@ -959,9 +1080,10 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
batadv_dbg_arp(bat_priv, skb, type, hdr_size,
"Parsing incoming ARP REQUEST");
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst,
+ BATADV_DAT_IPV4);
if (!dat_entry)
goto out;
@@ -1020,14 +1142,16 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
hw_dst = batadv_arp_hw_dst(skb, 0);
ip_dst = batadv_arp_ip_dst(skb, 0);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src);
+ batadv_dat_entry_add(bat_priv, &ip_dst, BATADV_DAT_IPV4, hw_dst);
/* 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, BATADV_DAT_IPV4,
+ BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, &ip_dst, BATADV_DAT_IPV4,
+ BATADV_P_DAT_DHT_PUT);
}
/**
* batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
@@ -1062,8 +1186,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
/* Update our internal cache with both the IP addresses the node got
* within the ARP reply
*/
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+ batadv_dat_entry_add(bat_priv, &ip_src, BATADV_DAT_IPV4, hw_src);
+ batadv_dat_entry_add(bat_priv, &ip_dst, BATADV_DAT_IPV4, hw_dst);
/* if this REPLY is directed to a client of mine, let's deliver the
* packet to the interface
@@ -1107,7 +1231,8 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
goto out;
ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, &ip_dst,
+ BATADV_DAT_IPV4);
/* check if the node already got this entry */
if (!dat_entry) {
batadv_dbg(BATADV_DBG_DAT, bat_priv,
diff --git a/distributed-arp-table.h b/distributed-arp-table.h
index 60d853b..557bab9 100644
--- a/distributed-arp-table.h
+++ b/distributed-arp-table.h
@@ -28,6 +28,7 @@
#include <linux/if_arp.h>
#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
+#define BATADV_DAT_DATA_MAX_LEN 16
void batadv_dat_status_update(struct net_device *net_dev);
bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
diff --git a/types.h b/types.h
index 71da448..75c0d87 100644
--- a/types.h
+++ b/types.h
@@ -995,7 +995,8 @@ struct batadv_algo_ops {
/**
* struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It
* is used to stored ARP entries needed for the global DAT cache
- * @ip: the IPv4 corresponding to this DAT/ARP entry
+ * @data: the data corresponding to this DAT entry
+ * @type: the type corresponding to this DAT entry
* @mac_addr: the MAC address associated to the stored IPv4
* @last_update: time in jiffies when this entry was refreshed last time
* @hash_entry: hlist node for batadv_priv_dat::hash
@@ -1003,7 +1004,8 @@ struct batadv_algo_ops {
* @rcu: struct used for freeing in an RCU-safe manner
*/
struct batadv_dat_entry {
- __be32 ip;
+ void *data;
+ uint8_t type;
uint8_t mac_addr[ETH_ALEN];
unsigned long last_update;
struct hlist_node hash_entry;
@@ -1012,6 +1014,14 @@ struct batadv_dat_entry {
};
/**
+ * batadv_dat_types - types used in batadv_dat_entry for IP
+ * @BATADV_DAT_IPv4: IPv4 address type
+ */
+enum batadv_dat_types {
+ BATADV_DAT_IPV4 = 0,
+};
+
+/**
* struct batadv_dat_candidate - candidate destination for DAT operations
* @type: the type of the selected candidate. It can one of the following:
* - BATADV_DAT_CANDIDATE_NOT_FOUND
--
1.7.10.4
9 years, 9 months
[B.A.T.M.A.N.] [PATCH 0/7] make the Translation Table component VLAN-aware
by Antonio Quartulli
Hello people,
with this patchset I want to introduce a new feature in the TT code which makes
it VLAN aware. This means that now clients belonging to different VLANs created
on top of a generic bat0 are treated differently.
This change gives the possibility to:
- enable AP isolation only on a selected VLAN rather than on all the traffic
- make DAT work correctly when the same IP subnet is used on different VLANs
- leave the possibility to future developers to implement more VLAN specific
attributes
This code is based on top of hundeboll/fragmentation.
Cheers,
Antonio Quartulli (7):
batman-adv: add the VLAN ID attribute to the TT entry
batman-adv: use vid when computing local and global TT CRC
batman-adv: print the VID together with the TT entries
batman-adv: make the GW module correctly talk to the new VLAN-TT
batman-adv: make the Distributed ARP Table vlan aware
batman-adv: add per VLAN interface attribute framework
batman-adv: make the AP isolation attribute VLAN specific
distributed-arp-table.c | 129 ++++++++++++------
gateway_client.c | 10 +-
main.c | 46 ++++++-
main.h | 11 +-
packet.h | 12 ++
routing.c | 27 +++-
send.c | 8 +-
send.h | 16 ++-
soft-interface.c | 99 ++++++++++++--
sysfs.c | 140 ++++++++++++++++++++
sysfs.h | 10 ++
translation-table.c | 343 +++++++++++++++++++++++++++++++++++-------------
translation-table.h | 25 ++--
types.h | 27 ++++
14 files changed, 732 insertions(+), 171 deletions(-)
--
1.8.1.5
9 years, 9 months
[B.A.T.M.A.N.] [PATCH master] batman-adv: remove white spaces at the beginning of the lines
by Antonio Quartulli
Intiroduced by: 3bcf1e15714b78e8581ccbf4724cda9e20ac4aa4
("batman-adv: reorder packet types")
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
packet.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packet.h b/packet.h
index 559c738..7d45890 100644
--- a/packet.h
+++ b/packet.h
@@ -34,7 +34,7 @@
* @BATADV_ICMP: unicast packet like IP ICMP used for ping or traceroute
* @BATADV_UNICAST_TVLV: unicast packet carrying TVLV containers
*/
- enum batadv_packettype {
+enum batadv_packettype {
/* 0x00 - 0x3f: local packets or special rules for handling */
BATADV_IV_OGM = 0x00,
BATADV_BCAST = 0x01,
@@ -80,7 +80,7 @@ enum batadv_iv_flags {
BATADV_NOT_BEST_NEXT_HOP = BIT(0),
BATADV_PRIMARIES_FIRST_HOP = BIT(1),
BATADV_DIRECTLINK = BIT(2),
- };
+};
/* ICMP message types */
enum batadv_icmp_packettype {
--
1.8.1.5
9 years, 9 months
[B.A.T.M.A.N.] [PATCH next] batman-adv: remove white spaces in indentation
by Antonio Quartulli
Introduced during the merge of maint into next
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
bridge_loop_avoidance.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c
index cc530a7..e95cf4b 100644
--- a/bridge_loop_avoidance.c
+++ b/bridge_loop_avoidance.c
@@ -344,7 +344,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
if (vid & BATADV_VLAN_HAS_TAG)
skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
- vid & BATADV_VID_MASK);
+ vid & BATADV_VID_MASK);
skb_reset_mac_header(skb);
skb->protocol = eth_type_trans(skb, soft_iface);
--
1.8.1.5
9 years, 9 months
[B.A.T.M.A.N.] [PATCHv2] batman-adv: use the BigEndian notation for variables sent over the wire
by Antonio Quartulli
All the variables sent over the wire must report the
BigEndian (__be*) notation so that sparse can easily spot
any bug due to missing conversions.
This patch changes the type used by the up and download
bandwidth in the new GW TVLV from uint32_t to __be32 and
adds all the related conversions.
Introduced by: 0853ec7fafe0a195754454832993c6b35e22b842
("batman-adv: tvlv - gateway download/upload bandwidth container")
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
v1 was:
batman-adv: properly handle Network Ordered variables
v2:
change subject and commit message
gateway_client.c | 24 +++++++++++++-----------
gateway_common.c | 4 ++--
packet.h | 4 ++--
3 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/gateway_client.c b/gateway_client.c
index f00db73..973f02d 100644
--- a/gateway_client.c
+++ b/gateway_client.c
@@ -344,8 +344,10 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
orig_node->orig,
- gateway->bandwidth_down / 10, gateway->bandwidth_down % 10,
- gateway->bandwidth_up / 10, gateway->bandwidth_up % 10);
+ ntohl(gateway->bandwidth_down) / 10,
+ ntohl(gateway->bandwidth_down) % 10,
+ ntohl(gateway->bandwidth_up) / 10,
+ ntohl(gateway->bandwidth_up) % 10);
}
/**
@@ -399,8 +401,8 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
goto out;
}
- if ((gw_node->bandwidth_down == gateway->bandwidth_down) &&
- (gw_node->bandwidth_up == gateway->bandwidth_up))
+ if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) &&
+ (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up)))
goto out;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -410,16 +412,16 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
gw_node->bandwidth_down % 10,
gw_node->bandwidth_up / 10,
gw_node->bandwidth_up % 10,
- gateway->bandwidth_down / 10,
- gateway->bandwidth_down % 10,
- gateway->bandwidth_up / 10,
- gateway->bandwidth_up % 10);
+ ntohl(gateway->bandwidth_down) / 10,
+ ntohl(gateway->bandwidth_down) % 10,
+ ntohl(gateway->bandwidth_up) / 10,
+ ntohl(gateway->bandwidth_up) % 10);
- gw_node->bandwidth_down = gateway->bandwidth_down;
- gw_node->bandwidth_up = gateway->bandwidth_up;
+ gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
+ gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
gw_node->deleted = 0;
- if (gateway->bandwidth_down == 0) {
+ if (ntohl(gateway->bandwidth_down) == 0) {
gw_node->deleted = jiffies;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Gateway %pM removed from gateway list\n",
diff --git a/gateway_common.c b/gateway_common.c
index 9904710..07fd877 100644
--- a/gateway_common.c
+++ b/gateway_common.c
@@ -202,8 +202,8 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
gateway.bandwidth_up = 0;
} else {
gateway_ptr = tvlv_value;
- gateway.bandwidth_down = ntohl(gateway_ptr->bandwidth_down);
- gateway.bandwidth_up = ntohl(gateway_ptr->bandwidth_up);
+ gateway.bandwidth_down = gateway_ptr->bandwidth_down;
+ gateway.bandwidth_up = gateway_ptr->bandwidth_up;
if ((gateway.bandwidth_down == 0) ||
(gateway.bandwidth_up == 0)) {
gateway.bandwidth_down = 0;
diff --git a/packet.h b/packet.h
index 58fe4eb..559c738 100644
--- a/packet.h
+++ b/packet.h
@@ -372,8 +372,8 @@ struct batadv_tvlv_long {
* @bandwidth_up: advertised uplink upload bandwidth
*/
struct batadv_tvlv_gateway_data {
- uint32_t bandwidth_down;
- uint32_t bandwidth_up;
+ __be32 bandwidth_down;
+ __be32 bandwidth_up;
};
/**
--
1.8.1.5
9 years, 9 months