[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, 9 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, 7 months
[B.A.T.M.A.N.] Alfred Open Beta
by Simon Wunderlich
To those of you who actively follow the recent discussions it may come to no
big surprise that it was decided to remove the vis functionality from the
batman-adv kernel module in a not so distant future (with the next
compatibility bump). There always has been a debate whether or not such
functionality belongs into the kernel or not. The in-kernel solution bears the
disadvantage of being rather inflexible because every change has to go through
the official Linux channels. With the growing interest in flooding the network
with arbitrary data in addition to the visualization data realizing a solution
in user-space became the obvious choice.
A new, more general user-space daemon which takes over the old vis
functionality and much more, called A.L.F.R.E.D. (Almighty Lightweight Fact
Remote Exchange Daemon) came to life. Alfred is capable of distributing
information over your mesh network in a decentralized fashion, for example
graph information for vis, but also any other data which appears to be useful
- like hostnames, phone books, administration information, DNS information,
the local weather forecast, etc while requiring (almost) zero configuration.
As the development on the core functionality has been finished and alfred works
(at least on the developers boxes), we would like to call for an open beta!
There are bleeding edge downloads and an OpenWRT feed available [1]. Please
try alfred and report bugs, send patches and inform us about your experiences.
Alfred will be release along with the next batman-adv release.
Happy routing,
The B.A.T.M.A.N. team
[1] http://www.open-mesh.org/projects/open-mesh/wiki/Alfred#Download
9 years, 6 months
[B.A.T.M.A.N.] [RFC 00/10] Improving the routing protocol abstraction
by Antonio Quartulli
Hello list,
with this RFC I'd like to introduce some new routing API functions meant to
improve the routing protocol abstraction.
This changes have been written while developing batman V. The latter helped me
in understanding what batman iv and v have in common and what not.
The main problem was the metric: the two protocols use different metric domains
and different semantics.
Therefore all the functions handling/printing the metric needed to be
generalised and rearranged to let the protocols decide what to do.
Another issue was the way routing protocols handle the orig and neigh node
structures. Also these two have been changed and some small APIs have been
provided as well.
Moreover, after Simon's RFC about the new multi-interface optimisation, we saw
the need for a better abstraction so that mechanisms like that could easily be
re-used by new algorithms (like batman v) with little effort.
The new API functions are the following:
+ metric related:
- bat_metric_get
- bat_metric_is_similar
- bat_metric_compare
+ orig_node related:
- bat_orig_print: print the originator table
- bat_orig_add_if
- bat_orig_del_if
- bat_orig_free
Any feedback will surely be welcome :-)
Cheers,
p.s. there are some small "checkpatch glitches" but they will be removed before
this RFC becomes a real patchset :)
Antonio Quartulli (10):
batman-adv: make struct batadv_neigh_node algorithm agnostic
batman-adv: make struct batadv_orig_node algorithm agnostic
batman-adv: add bat_orig_print function API
batman-adv: add bat_metric_get API function
batman-adv: add bat_metric_is_similar API function
batman-adv: add bat_metric_compare API function
batman-adv: adapt bonding to use the new API functions
batman-adv: adapt the gateway feature to use the new API functions
batman-adv: adapt the neighbor purging routine to use the new API
functions
batman-adv: provide orig_node routing API
bat_iv_ogm.c | 373 +++++++++++++++++++++++++++++++++++++++++++---------
gateway_client.c | 74 ++++++-----
main.c | 5 +-
main.h | 7 +
network-coding.c | 8 +-
originator.c | 238 ++++++++-------------------------
originator.h | 5 +-
routing.c | 37 ++++--
routing.h | 3 +-
translation-table.c | 4 +-
types.h | 106 +++++++++------
11 files changed, 518 insertions(+), 342 deletions(-)
--
1.8.1.5
9 years, 7 months
[B.A.T.M.A.N.] [RFC 1/4] batman-adv: renamed batadv_dat_snoop_*_arp_* functions to batadv_dat_snoop_*_msg_*
by Mihail
From: "mihail.costea90(a)gmail.com" <mihail.costea90(a)gmail.com>
Renamed snooping functions in order to suggest that they should work on
more protocols than ARP.
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 | 16 ++++++++--------
distributed-arp-table.h | 16 ++++++++--------
routing.c | 12 ++++++------
soft-interface.c | 6 +++---
4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c
index af670d3..b2ca7e0 100644
--- a/distributed-arp-table.c
+++ b/distributed-arp-table.c
@@ -978,7 +978,7 @@ out:
}
/**
- * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
+ * batadv_dat_snoop_outgoing_msg_request - snoop the ARP request and try to
* answer using DAT
* @bat_priv: the bat priv with all the soft interface information
* @skb: packet to check
@@ -987,7 +987,7 @@ out:
* otherwise. In case of a positive return value the message has to be enqueued
* to permit the fallback.
*/
-bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv,
struct sk_buff *skb)
{
uint16_t type = 0;
@@ -1060,7 +1060,7 @@ out:
}
/**
- * batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to
+ * batadv_dat_snoop_incoming_msg_request - snoop the ARP request and try to
* answer using the local DAT storage
* @bat_priv: the bat priv with all the soft interface information
* @skb: packet to check
@@ -1068,7 +1068,7 @@ out:
*
* Returns true if the request has been answered, false otherwise.
*/
-bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+bool batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size)
{
uint16_t type;
@@ -1130,11 +1130,11 @@ out:
}
/**
- * batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT
+ * batadv_dat_snoop_outgoing_msg_reply - snoop the ARP reply and fill the DHT
* @bat_priv: the bat priv with all the soft interface information
* @skb: packet to check
*/
-void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb)
{
uint16_t type;
@@ -1167,13 +1167,13 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
BATADV_P_DAT_DHT_PUT);
}
/**
- * batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
+ * batadv_dat_snoop_incoming_msg_reply - snoop the ARP reply and fill the local
* DAT storage only
* @bat_priv: the bat priv with all the soft interface information
* @skb: packet to check
* @hdr_size: size of the encapsulation header
*/
-bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+bool batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size)
{
uint16_t type;
diff --git a/distributed-arp-table.h b/distributed-arp-table.h
index 557bab9..28c062b 100644
--- a/distributed-arp-table.h
+++ b/distributed-arp-table.h
@@ -31,13 +31,13 @@
#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,
+bool batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv,
struct sk_buff *skb);
-bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+bool batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size);
-void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+void batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb);
-bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+bool batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size);
bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
struct batadv_forw_packet *forw_packet);
@@ -105,28 +105,28 @@ static inline void batadv_dat_status_update(struct net_device *net_dev)
}
static inline bool
-batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+batadv_dat_snoop_outgoing_msg_request(struct batadv_priv *bat_priv,
struct sk_buff *skb)
{
return false;
}
static inline bool
-batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+batadv_dat_snoop_incoming_msg_request(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size)
{
return false;
}
static inline bool
-batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+batadv_dat_snoop_outgoing_msg_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb)
{
return false;
}
static inline bool
-batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+batadv_dat_snoop_incoming_msg_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size)
{
return false;
diff --git a/routing.c b/routing.c
index 7c372f1..1c43f55 100644
--- a/routing.c
+++ b/routing.c
@@ -967,10 +967,10 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
}
- if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
+ if (batadv_dat_snoop_incoming_msg_request(bat_priv, skb,
hdr_size))
goto rx_success;
- if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb,
+ if (batadv_dat_snoop_incoming_msg_reply(bat_priv, skb,
hdr_size))
goto rx_success;
@@ -1015,10 +1015,10 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
if (!new_skb)
return NET_RX_SUCCESS;
- if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
+ if (batadv_dat_snoop_incoming_msg_request(bat_priv, new_skb,
hdr_size))
goto rx_success;
- if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
+ if (batadv_dat_snoop_incoming_msg_reply(bat_priv, new_skb,
hdr_size))
goto rx_success;
@@ -1159,9 +1159,9 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size))
goto out;
- if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
+ if (batadv_dat_snoop_incoming_msg_request(bat_priv, skb, hdr_size))
goto rx_success;
- if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size))
+ if (batadv_dat_snoop_incoming_msg_reply(bat_priv, skb, hdr_size))
goto rx_success;
/* broadcast for me */
diff --git a/soft-interface.c b/soft-interface.c
index a6ab9e4..9e8fd44 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -232,7 +232,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
* packet, instead we first wait for DAT to try to retrieve the
* correct ARP entry
*/
- if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+ if (batadv_dat_snoop_outgoing_msg_request(bat_priv, skb))
brd_delay = msecs_to_jiffies(ARP_REQ_DELAY);
if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
@@ -271,10 +271,10 @@ static int batadv_interface_tx(struct sk_buff *skb,
goto dropped;
}
- if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+ if (batadv_dat_snoop_outgoing_msg_request(bat_priv, skb))
goto dropped;
- batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
+ batadv_dat_snoop_outgoing_msg_reply(bat_priv, skb);
ret = batadv_unicast_send_skb(bat_priv, skb);
if (ret != 0)
--
1.7.10.4
9 years, 7 months
[B.A.T.M.A.N.] [PATCHv2] batman-adv: forward late OGMs from best next hop
by Simon Wunderlich
From: Simon Wunderlich <simon(a)open-mesh.com>
When a packet is received from another node first and later from the
best next hop, this packet is dropped. However the first OGM was sent
with the BATADV_NOT_BEST_NEXT_HOP flag and thus dropped by neighbors.
The late OGM from the best neighbor is then dropped because it is a
duplicate.
If this situation happens constantly, a node might end up not forwarding
the "valid" OGMs anymore, and nodes behind will starve from not getting
valid OGMs.
Fix this by refining the duplicate checking behaviour: The actions
should depend on whether it was a duplicate for a neighbor only or for
the originator. OGMs which are not duplicates for a specific neighbor
will now be considered in batadv_iv_ogm_forward(), but only actually
forwarded for the best next hop. Therefore, late OGMs from the best
next hop are forwarded now and not dropped as duplicates anymore.
Signed-off-by: Simon Wunderlich <simon(a)open-mesh.com>
---
Changes to PATCHv1:
* use enum to distinguish different duplicate states
* fix typo "is_simlar -> is_similar"
* remove antonios sign off (the patch changed, feel free to add it if
he is ok with it, it was his idea originally ...)
---
bat_iv_ogm.c | 86 +++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 55 insertions(+), 31 deletions(-)
diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c
index 8d87f87..2b94fdd 100644
--- a/bat_iv_ogm.c
+++ b/bat_iv_ogm.c
@@ -701,6 +701,21 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
batadv_hardif_free_ref(primary_if);
}
+/**
+ * batadv_dup_status - duplicate status
+ * @BATADV_NO_DUP: the packet is a duplicate
+ * @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the
+ * neighbor)
+ * @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor
+ * @BATADV_PROTECTED: originator is currently protected (after reboot)
+ */
+enum batadv_dup_status {
+ BATADV_NO_DUP = 0,
+ BATADV_ORIG_DUP,
+ BATADV_NEIGH_DUP,
+ BATADV_PROTECTED,
+};
+
static void
batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
@@ -708,7 +723,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
const struct batadv_ogm_packet *batadv_ogm_packet,
struct batadv_hard_iface *if_incoming,
const unsigned char *tt_buff,
- int is_duplicate)
+ enum batadv_dup_status dup_status)
{
struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
struct batadv_neigh_node *router = NULL;
@@ -734,7 +749,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
continue;
}
- if (is_duplicate)
+ if (dup_status != BATADV_NO_DUP)
continue;
spin_lock_bh(&tmp_neigh_node->lq_update_lock);
@@ -774,7 +789,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv);
spin_unlock_bh(&neigh_node->lq_update_lock);
- if (!is_duplicate) {
+ if (dup_status == BATADV_NO_DUP) {
orig_node->last_ttl = batadv_ogm_packet->header.ttl;
neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
}
@@ -932,15 +947,16 @@ out:
return ret;
}
-/* processes a batman packet for all interfaces, adjusts the sequence number and
- * finds out whether it is a duplicate.
+/**
+ * batadv_iv_ogm_update_seqnos - processes a batman packet for all interfaces,
+ * adjusts the sequence number and finds out whether it is a duplicate.
+ * @ethhdr: Ethernet header of the packet
+ * @batadv_ogm_packet: OGM packet to be considered
+ * @if_incoming: interface where the OGM packet was received
+ * Returns: duplicate status as enum batadv_dup_status
* returns:
- * 1 the packet is a duplicate
- * 0 the packet has not yet been received
- * -1 the packet is old and has been received while the seqno window
- * was protected. Caller should drop it.
- */
-static int
+ */
+enum batadv_dup_status
batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
const struct batadv_ogm_packet *batadv_ogm_packet,
const struct batadv_hard_iface *if_incoming)
@@ -948,17 +964,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct batadv_orig_node *orig_node;
struct batadv_neigh_node *tmp_neigh_node;
- int is_duplicate = 0;
+ int is_dup;
int32_t seq_diff;
int need_update = 0;
- int set_mark, ret = -1;
+ int set_mark;
+ enum batadv_dup_status ret = BATADV_NO_DUP;
uint32_t seqno = ntohl(batadv_ogm_packet->seqno);
uint8_t *neigh_addr;
uint8_t packet_count;
orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig);
if (!orig_node)
- return 0;
+ return BATADV_NO_DUP;
spin_lock_bh(&orig_node->ogm_cnt_lock);
seq_diff = seqno - orig_node->last_real_seqno;
@@ -966,22 +983,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
/* signalize caller that the packet is to be dropped. */
if (!hlist_empty(&orig_node->neigh_list) &&
batadv_window_protected(bat_priv, seq_diff,
- &orig_node->batman_seqno_reset))
+ &orig_node->batman_seqno_reset)) {
+ ret = BATADV_PROTECTED;
goto out;
+ }
rcu_read_lock();
hlist_for_each_entry_rcu(tmp_neigh_node,
&orig_node->neigh_list, list) {
- is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits,
- orig_node->last_real_seqno,
- seqno);
-
neigh_addr = tmp_neigh_node->addr;
+ is_dup = batadv_test_bit(tmp_neigh_node->real_bits,
+ orig_node->last_real_seqno,
+ seqno);
+
if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
- tmp_neigh_node->if_incoming == if_incoming)
+ tmp_neigh_node->if_incoming == if_incoming) {
set_mark = 1;
- else
+ if (is_dup)
+ ret = BATADV_NEIGH_DUP;
+ } else {
set_mark = 0;
+ if (is_dup && (ret != BATADV_NEIGH_DUP))
+ ret = BATADV_ORIG_DUP;
+ }
/* if the window moved, set the update flag. */
need_update |= batadv_bit_get_packet(bat_priv,
@@ -1001,8 +1025,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
orig_node->last_real_seqno = seqno;
}
- ret = is_duplicate;
-
out:
spin_unlock_bh(&orig_node->ogm_cnt_lock);
batadv_orig_node_free_ref(orig_node);
@@ -1024,7 +1046,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
int is_bidirect;
bool is_single_hop_neigh = false;
bool is_from_best_next_hop = false;
- int is_duplicate, sameseq, simlar_ttl;
+ int sameseq, similar_ttl;
+ enum batadv_dup_status dup_status;
uint32_t if_incoming_seqno;
uint8_t *prev_sender;
@@ -1149,10 +1172,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
if (!orig_node)
return;
- is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
- if_incoming);
+ dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
+ if_incoming);
- if (is_duplicate == -1) {
+ if (dup_status == BATADV_PROTECTED) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: packet within seqno protection time (sender: %pM)\n",
ethhdr->h_source);
@@ -1224,11 +1247,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
* seqno and similar ttl as the non-duplicate
*/
sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
- simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
- if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl)))
+ similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
+ if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
+ (sameseq && similar_ttl)))
batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
batadv_ogm_packet, if_incoming,
- tt_buff, is_duplicate);
+ tt_buff, dup_status);
/* is single hop (direct) neighbor */
if (is_single_hop_neigh) {
@@ -1249,7 +1273,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
goto out_neigh;
}
- if (is_duplicate) {
+ if (dup_status == BATADV_NEIGH_DUP) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: duplicate packet received\n");
goto out_neigh;
--
1.7.10.4
9 years, 7 months
[B.A.T.M.A.N.] [PATCHv2] batman-adv: Add dummy soft-interface rx mode handler
by Linus Lüssing
We do not actually need to set any rx filters for the virtual batman
soft interface. However a dummy handler enables a user to set static
multicast listeners for instance.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
* Fixes issue #171
v2: added kernel doc
soft-interface.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/soft-interface.c b/soft-interface.c
index 2bad57f..54b3991 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -137,6 +137,18 @@ static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+/**
+ * batadv_interface_set_rx_mode - set the rx mode of a device
+ * @dev: registered network device to modify
+ *
+ * We do not actually need to set any rx filters for the virtual batman
+ * soft interface. However a dummy handler enables a user to set static
+ * multicast listeners for instance.
+ */
+static void batadv_interface_set_rx_mode(struct net_device *dev)
+{
+}
+
static int batadv_interface_tx(struct sk_buff *skb,
struct net_device *soft_iface)
{
@@ -572,6 +584,7 @@ static const struct net_device_ops batadv_netdev_ops = {
.ndo_get_stats = batadv_interface_stats,
.ndo_set_mac_address = batadv_interface_set_mac_addr,
.ndo_change_mtu = batadv_interface_change_mtu,
+ .ndo_set_rx_mode = batadv_interface_set_rx_mode,
.ndo_start_xmit = batadv_interface_tx,
.ndo_validate_addr = eth_validate_addr,
.ndo_add_slave = batadv_softif_slave_add,
--
1.7.10.4
9 years, 7 months
[B.A.T.M.A.N.] [PATCHv4 1/2] batman-adv: implement batadv_tt_entries
by Antonio Quartulli
From: Antonio Quartulli <antonio(a)open-mesh.com>
Implement batadv_tt_entries() to get the number of entries
fitting in a given amount of bytes. This computation is done
several times in the code and therefore it is useful to have
an helper function.
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
---
translation-table.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/translation-table.c b/translation-table.c
index 8d9f5cc..d1957af 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -232,6 +232,17 @@ static int batadv_tt_len(int changes_num)
return changes_num * sizeof(struct batadv_tvlv_tt_change);
}
+/**
+ * batadv_tt_entries - compute the number of entries fitting in tt_len bytes
+ * @tt_len: available space
+ *
+ * Return the number of entries.
+ */
+static uint16_t batadv_tt_entries(uint16_t tt_len)
+{
+ return tt_len / batadv_tt_len(1);
+}
+
static int batadv_tt_local_init(struct batadv_priv *bat_priv)
{
if (bat_priv->tt.local_hash)
@@ -406,7 +417,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
if (tt_diff_len == 0)
goto container_register;
- tt_diff_entries_num = tt_diff_len / batadv_tt_len(1);
+ tt_diff_entries_num = batadv_tt_entries(tt_diff_len);
spin_lock_bh(&bat_priv->tt.changes_list_lock);
atomic_set(&bat_priv->tt.local_changes, 0);
@@ -1616,7 +1627,7 @@ batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change);
}
- tt_tot = tt_len / sizeof(struct batadv_tvlv_tt_change);
+ tt_tot = batadv_tt_entries(tt_len);
tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
GFP_ATOMIC);
@@ -2567,7 +2578,7 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
tvlv_value_len -= sizeof(*tt_data);
- num_entries = tvlv_value_len / batadv_tt_len(1);
+ num_entries = batadv_tt_entries(tvlv_value_len);
batadv_tt_update_orig(bat_priv, orig,
(unsigned char *)(tt_data + 1),
@@ -2602,7 +2613,7 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
tvlv_value_len -= sizeof(*tt_data);
- num_entries = tvlv_value_len / batadv_tt_len(1);
+ num_entries = batadv_tt_entries(tvlv_value_len);
switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
case BATADV_TT_REQUEST:
--
1.8.1.5
9 years, 8 months