Repository : ssh://git@open-mesh.org/batctl
On branch : next
>---------------------------------------------------------------
commit f0611b54fdf7157f470daaa9f21c00c6d4926a36
Author: Antonio Quartulli <antonio(a)open-mesh.com>
Date: Sat Jan 16 16:40:12 2016 +0800
batctl: OGMv2 - add basic infrastructure
This is the initial implementation of the new OGM protocol
(version 2). It has been designed to work on top of the
newly added ELP.
In the previous version the OGM protocol was used to both
measure link qualities and flood the network with the metric
information. In this version the protocol is in charge of
the latter task only, leaving the former to ELP.
This means being able to decouple the interval used by the
neighbor discovery from the OGM broadcasting, which revealed
to be costly in dense networks and needed to be relaxed so
leading to a less responsive routing protocol.
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
>---------------------------------------------------------------
f0611b54fdf7157f470daaa9f21c00c6d4926a36
packet.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/packet.h b/packet.h
index c698b64..8a8d7ca 100644
--- a/packet.h
+++ b/packet.h
@@ -27,6 +27,7 @@
* @BATADV_BCAST: broadcast packets carrying broadcast payload
* @BATADV_CODED: network coded packets
* @BATADV_ELP: echo location packets for B.A.T.M.A.N. V
+ * @BATADV_OGM2: originator messages for B.A.T.M.A.N. V
*
* @BATADV_UNICAST: unicast packets carrying unicast payload traffic
* @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original
@@ -42,6 +43,7 @@ enum batadv_packettype {
BATADV_BCAST = 0x01,
BATADV_CODED = 0x02,
BATADV_ELP = 0x03,
+ BATADV_OGM2 = 0x04,
/* 0x40 - 0x7f: unicast */
#define BATADV_UNICAST_MIN 0x40
BATADV_UNICAST = 0x40,
@@ -237,6 +239,33 @@ struct batadv_ogm_packet {
#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
/**
+ * struct batadv_ogm2_packet - ogm2 (routing protocol) packet
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the general header
+ * @ttl: time to live for this packet, part of the general header
+ * @flags: reseved for routing relevant flags - currently always 0
+ * @seqno: sequence number
+ * @orig: originator mac address
+ * @tvlv_len: length of the appended tvlv buffer (in bytes)
+ * @throughput: the currently flooded path throughput
+ */
+struct batadv_ogm2_packet {
+ u8 packet_type;
+ u8 version;
+ u8 ttl;
+ u8 flags;
+ __be32 seqno;
+ u8 orig[ETH_ALEN];
+ __be16 tvlv_len;
+ __be32 throughput;
+ /* __packed is not needed as the struct size is divisible by 4,
+ * and the largest data type in this struct has a size of 4.
+ */
+};
+
+#define BATADV_OGM2_HLEN sizeof(struct batadv_ogm2_packet)
+
+/**
* struct batadv_elp_packet - elp (neighbor discovery) packet
* @packet_type: batman-adv packet type, part of the general header
* @version: batman-adv protocol version, part of the genereal header
Repository : ssh://git@open-mesh.org/batctl
On branch : next
>---------------------------------------------------------------
commit 3ce90d7311b697cb9402def914bf2bfd31a6ada6
Author: Linus Luessing <linus.luessing(a)web.de>
Date: Sat Jan 16 16:40:09 2016 +0800
batctl: ELP - adding basic infrastructure
The B.A.T.M.A.N. protocol originally only used a single
message type (called OGM) to determine the link qualities to
the direct neighbors and spreading these link quality
information through the whole mesh. This procedure is
summarized on the BATMAN concept page and explained in
details in the RFC draft published in 2008.
This approach was chosen for its simplicity during the
protocol design phase and the implementation. However, it
also bears some drawbacks:
* Wireless interfaces usually come with some packet loss,
therefore a higher broadcast rate is desirable to allow
a fast reaction on flaky connections.
Other interfaces of the same host might be connected to
Ethernet LANs / VPNs / etc which rarely exhibit packet
loss would benefit from a lower broadcast rate to reduce
overhead.
* It generally is more desirable to detect local link
quality changes at a faster rate than propagating all
these changes through the entire mesh (the far end of
the mesh does not need to care about local link quality
changes that much). Other optimizations strategies, like
reducing overhead, might be possible if OGMs weren't
used for all tasks in the mesh at the same time.
As a result detecting local link qualities shall be handled
by an independent message type, ELP, whereas the OGM message
type remains responsible for flooding the mesh with these
link quality information and determining the overall path
transmit qualities.
Developed by Linus during a 6 months trainee study period in
Ascom (Switzerland) AG.
Signed-off-by: Linus Luessing <linus.luessing(a)web.de>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
>---------------------------------------------------------------
3ce90d7311b697cb9402def914bf2bfd31a6ada6
packet.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/packet.h b/packet.h
index e7f9151..c698b64 100644
--- a/packet.h
+++ b/packet.h
@@ -26,6 +26,7 @@
* @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV
* @BATADV_BCAST: broadcast packets carrying broadcast payload
* @BATADV_CODED: network coded packets
+ * @BATADV_ELP: echo location packets for B.A.T.M.A.N. V
*
* @BATADV_UNICAST: unicast packets carrying unicast payload traffic
* @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original
@@ -40,6 +41,7 @@ enum batadv_packettype {
BATADV_IV_OGM = 0x00,
BATADV_BCAST = 0x01,
BATADV_CODED = 0x02,
+ BATADV_ELP = 0x03,
/* 0x40 - 0x7f: unicast */
#define BATADV_UNICAST_MIN 0x40
BATADV_UNICAST = 0x40,
@@ -235,6 +237,24 @@ struct batadv_ogm_packet {
#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
/**
+ * struct batadv_elp_packet - elp (neighbor discovery) packet
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @orig: originator mac address
+ * @seqno: sequence number
+ * @elp_interval: currently used ELP sending interval in ms
+ */
+struct batadv_elp_packet {
+ u8 packet_type;
+ u8 version;
+ u8 orig[ETH_ALEN];
+ __be32 seqno;
+ __be32 elp_interval;
+};
+
+#define BATADV_ELP_HLEN sizeof(struct batadv_elp_packet)
+
+/**
* struct batadv_icmp_header - common members among all the ICMP packets
* @packet_type: batman-adv packet type, part of the general header
* @version: batman-adv protocol version, part of the genereal header
The following commit has been merged in the merge/master branch:
commit 74a41ef403151c1a22e2b2509743453e93f873ab
Merge: 342f7f3acda95f70f25a58e31044c5f6e1a59407 ecdc9bc44b25bd1d99b79d5930998a1da2a6195e
Author: Simon Wunderlich <sw(a)simonwunderlich.de>
Date: Tue Jan 19 17:37:19 2016 +0100
Merge branch 'next'
diff --combined README.external
index 963343e,03825ab..833ece7
--- a/README.external
+++ b/README.external
@@@ -6,7 -6,7 +6,7 @@@ and as external module. The external m
new features without upgrading to a newer kernel version
and to get batman-adv specific bugfixes for kernels that are
not supported anymore. It compiles against and should work
- with Linux 2.6.29 - 4.4. Supporting older versions is not
+ with Linux 2.6.29 - 4.5. Supporting older versions is not
planned, but it's probably easy to backport it. If you work on a
backport, feel free to contact us. :-)
@@@ -40,7 -40,6 +40,7 @@@ module). Available options and thei
* CONFIG_BATMAN_ADV_DAT=[y*|n] (B.A.T.M.A.N. Distributed ARP Table)
* CONFIG_BATMAN_ADV_MCAST=[y*|n] (B.A.T.M.A.N. multicast optimizations)
* CONFIG_BATMAN_ADV_NC=[y|n*] (B.A.T.M.A.N. Network Coding)
+ * CONFIG_BATMAN_ADV_BATMAN_V=[y|n*] (B.A.T.M.A.N. V routing algorithm)
e.g., debugging can be enabled by
diff --combined net/batman-adv/main.h
index 1ccfb3e,d1e11d4..7b05f68
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@@ -1,4 -1,4 +1,4 @@@
-/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@@@ -24,21 -24,17 +24,21 @@@
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
- #define BATADV_SOURCE_VERSION "2016.0"
+ #define BATADV_SOURCE_VERSION "2016.1"
#endif
/* B.A.T.M.A.N. parameters */
#define BATADV_TQ_MAX_VALUE 255
+#define BATADV_THROUGHPUT_MAX_VALUE 0xFFFFFFFF
#define BATADV_JITTER 20
/* Time To Live of broadcast messages */
#define BATADV_TTL 50
+/* maximum sequence number age of broadcast messages */
+#define BATADV_BCAST_MAX_AGE 64
+
/* purge originators after time in seconds if no valid packet comes in
* -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE
*/
@@@ -61,15 -57,6 +61,15 @@@
#define BATADV_TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
#define BATADV_TQ_TOTAL_BIDRECT_LIMIT 1
+/* B.A.T.M.A.N. V */
+#define BATADV_THROUGHPUT_DEFAULT_VALUE 10
+#define BATADV_ELP_PROBES_PER_NODE 2
+#define BATADV_ELP_MIN_PROBE_SIZE 200 /* bytes */
+#define BATADV_ELP_PROBE_MAX_TX_DIFF 100 /* milliseconds */
+#define BATADV_ELP_MAX_AGE 64
+#define BATADV_OGM_MAX_ORIGDIFF 5
+#define BATADV_OGM_MAX_AGE 64
+
/* number of OGMs sent with the last tt diff */
#define BATADV_TT_OGM_APPEND_MAX 3
@@@ -110,6 -97,11 +110,6 @@@
*/
#define BATADV_TQ_SIMILARITY_THRESHOLD 50
-/* how much worse secondary interfaces may be to be considered as bonding
- * candidates
- */
-#define BATADV_BONDING_TQ_THRESHOLD 50
-
/* should not be bigger than 512 bytes or change the size of
* forw_packet->direct_link_flags
*/
--
linux integration
The following commit has been merged in the merge/master branch:
commit bedcadfaa92b167a4f7c3df21f3682a32e1cfdfd
Author: Antonio Quartulli <antonio(a)open-mesh.com>
Date: Tue Nov 10 18:51:22 2015 +0100
batman-adv: ELP - send unicast ELP packets for throughput sampling
In case of an unused wireless link, the mac80211 throughput estimation
won't get updated further. Consequently, the reported throughput metric
will become obsolete.
With this patch unicast sampling is introduced by periodically sending
unicast ELP packets to each neighbor on idle WiFi links. These sampling
packets will fill an entire frame, so that the measurement is as
reliable as possible
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index fa2d60f..f257897 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -163,6 +163,69 @@ void batadv_v_elp_throughput_metric_update(struct work_struct *work)
}
/**
+ * batadv_v_elp_wifi_neigh_probe - send link probing packets to a neighbour
+ * @neigh: the neighbour to probe
+ *
+ * Sends a predefined number of unicast wifi packets to a given neighbour in
+ * order to trigger the throughput estimation on this link by the RC algorithm.
+ * Packets are sent only if there there is not enough payload unicast traffic
+ * towards this neighbour..
+ *
+ * Return: True on success and false in case of error during skb preparation.
+ */
+static bool
+batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
+{
+ struct batadv_hard_iface *hard_iface = neigh->if_incoming;
+ struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+ unsigned long last_tx_diff;
+ struct sk_buff *skb;
+ int probe_len, i;
+ int elp_skb_len;
+
+ /* this probing routine is for Wifi neighbours only */
+ if (!batadv_is_wifi_netdev(hard_iface->net_dev))
+ return true;
+
+ /* probe the neighbor only if no unicast packets have been sent
+ * to it in the last 100 milliseconds: this is the rate control
+ * algorithm sampling interval (minstrel). In this way, if not
+ * enough traffic has been sent to the neighbor, batman-adv can
+ * generate 2 probe packets and push the RC algorithm to perform
+ * the sampling
+ */
+ last_tx_diff = jiffies_to_msecs(jiffies - neigh->bat_v.last_unicast_tx);
+ if (last_tx_diff <= BATADV_ELP_PROBE_MAX_TX_DIFF)
+ return true;
+
+ probe_len = max_t(int, sizeof(struct batadv_elp_packet),
+ BATADV_ELP_MIN_PROBE_SIZE);
+
+ for (i = 0; i < BATADV_ELP_PROBES_PER_NODE; i++) {
+ elp_skb_len = hard_iface->bat_v.elp_skb->len;
+ skb = skb_copy_expand(hard_iface->bat_v.elp_skb, 0,
+ probe_len - elp_skb_len,
+ GFP_ATOMIC);
+ if (!skb)
+ return false;
+
+ /* Tell the skb to get as big as the allocated space (we want
+ * the packet to be exactly of that size to make the link
+ * throughput estimation effective.
+ */
+ skb_put(skb, probe_len - hard_iface->bat_v.elp_skb->len);
+
+ batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+ "Sending unicast (probe) ELP packet on interface %s to %pM\n",
+ hard_iface->net_dev->name, neigh->addr);
+
+ batadv_send_skb_packet(skb, hard_iface, neigh->addr);
+ }
+
+ return true;
+}
+
+/**
* batadv_v_elp_periodic_work - ELP periodic task per interface
* @work: work queue item
*
@@ -225,6 +288,12 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
*/
rcu_read_lock();
hlist_for_each_entry_rcu(hardif_neigh, &hard_iface->neigh_list, list) {
+ if (!batadv_v_elp_wifi_neigh_probe(hardif_neigh))
+ /* if something goes wrong while probing, better to stop
+ * sending packets immediately and reschedule the task
+ */
+ break;
+
if (!kref_get_unless_zero(&hardif_neigh->refcount))
continue;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 2f8add6..1ccfb3e 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -63,6 +63,9 @@
/* B.A.T.M.A.N. V */
#define BATADV_THROUGHPUT_DEFAULT_VALUE 10
+#define BATADV_ELP_PROBES_PER_NODE 2
+#define BATADV_ELP_MIN_PROBE_SIZE 200 /* bytes */
+#define BATADV_ELP_PROBE_MAX_TX_DIFF 100 /* milliseconds */
#define BATADV_ELP_MAX_AGE 64
#define BATADV_OGM_MAX_ORIGDIFF 5
#define BATADV_OGM_MAX_AGE 64
--
linux integration
The following commit has been merged in the merge/master branch:
commit 5c3245172c01ed14ae0a38b3f320403088ed96b5
Author: Antonio Quartulli <antonio(a)open-mesh.com>
Date: Tue Nov 10 18:50:51 2015 +0100
batman-adv: ELP - compute the metric based on the estimated throughput
In case of wireless interface retrieve the throughput by
querying cfg80211. To perform this call a separate work
must be scheduled because the function may sleep and this
is not allowed within an RCU protected context (RCU in this
case is used to iterate over all the neighbours).
Use ethtool to retrieve information about an Ethernet link
like HALF/FULL_DUPLEX and advertised bandwidth (e.g.
100/10Mbps).
The metric is updated each time a new ELP packet is sent,
this way it is possible to timely react to a metric
variation which can imply (for example) a neighbour
disconnection.
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/compat.h b/compat.h
index 7152237..454fa4c 100644
--- a/compat.h
+++ b/compat.h
@@ -170,6 +170,27 @@ static int __batadv_interface_kill_vid(struct net_device *dev, __be16 proto,\
#endif /* < KERNEL_VERSION(3, 10, 0) */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
+
+/* the expected behaviour of this function is to return 0 on success, therefore
+ * it is possible to define it as 1 so that batman-adv thinks like something
+ * went wrong. It will then decide what to do.
+ */
+#define cfg80211_get_station(_a, _b, _c) (1)
+/* the following define substitute the expected_throughput field with a random
+ * one existing in the station_info struct. It can be random because due to the
+ * define above it will never be used. We need it only to make the code compile
+ */
+#define expected_throughput filled
+
+#ifdef CONFIG_BATMAN_ADV_BATMAN_V
+
+#warning cfg80211 based throughput metric is only supported with Linux 3.15+
+
+#endif
+
+#endif /* < KERNEL_VERSION(3, 15, 0) */
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
#define IFF_NO_QUEUE 0; dev->tx_queue_len = 0
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index d9cb5c4..ff31f2a 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -21,6 +21,7 @@
#include <linux/atomic.h>
#include <linux/cache.h>
#include <linux/init.h>
+#include <linux/workqueue.h>
#include "bat_v_elp.h"
#include "bat_v_ogm.h"
@@ -65,6 +66,8 @@ static void
batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
{
ewma_throughput_init(&hardif_neigh->bat_v.throughput);
+ INIT_WORK(&hardif_neigh->bat_v.metric_work,
+ batadv_v_elp_throughput_metric_update);
}
static void batadv_v_ogm_schedule(struct batadv_hard_iface *hard_iface)
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index 1e4d13c..fa2d60f 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -22,19 +22,23 @@
#include <linux/byteorder/generic.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
#include <linux/fs.h>
#include <linux/if_ether.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
+#include <linux/kref.h>
#include <linux/netdevice.h>
#include <linux/random.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
+#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/workqueue.h>
+#include <net/cfg80211.h>
#include "bat_algo.h"
#include "bat_v_ogm.h"
@@ -60,6 +64,105 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
}
/**
+ * batadv_v_elp_get_throughput - get the throughput towards a neighbour
+ * @neigh: the neighbour for which the throughput has to be obtained
+ *
+ * Return: the throughput towards the given neighbour.
+ */
+static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
+{
+ struct batadv_hard_iface *hard_iface = neigh->if_incoming;
+ struct station_info sinfo;
+ struct ethtool_cmd cmd;
+ u32 throughput;
+ int ret;
+
+ /* if the user specified a customised value for this interface, then
+ * return it directly
+ */
+ throughput = atomic_read(&hard_iface->bat_v.throughput_override);
+ if (throughput != 0)
+ return throughput;
+
+ /* if this is a wireless device, then ask its throughput through
+ * cfg80211 API
+ */
+ if (batadv_is_wifi_netdev(hard_iface->net_dev)) {
+ if (hard_iface->net_dev->ieee80211_ptr) {
+ ret = cfg80211_get_station(hard_iface->net_dev,
+ neigh->addr, &sinfo);
+ if (ret == -ENOENT) {
+ /* Node is not associated anymore! It would be
+ * possible to delete this neighbor. For now set
+ * the throughput metric to 0.
+ */
+ return 0;
+ }
+ if (!ret)
+ return sinfo.expected_throughput / 10;
+ }
+
+ /* unsupported WiFi driver version */
+ goto default_throughput;
+ }
+
+ /* if not a wifi interface, check if this device provides data via
+ * ethtool (e.g. an Ethernet adapter)
+ */
+ memset(&cmd, 0, sizeof(cmd));
+ rtnl_lock();
+ ret = __ethtool_get_settings(hard_iface->net_dev, &cmd);
+ rtnl_unlock();
+ if (ret == 0) {
+ /* link characteristics might change over time */
+ if (cmd.duplex == DUPLEX_FULL)
+ hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
+ else
+ hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
+
+ throughput = ethtool_cmd_speed(&cmd);
+ if (throughput && throughput != SPEED_UNKNOWN)
+ return throughput * 10;
+ }
+
+default_throughput:
+ if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
+ batadv_info(hard_iface->soft_iface,
+ "WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %d kbit/s. Consider overriding the throughput manually or checking your driver.\n",
+ hard_iface->net_dev->name,
+ BATADV_THROUGHPUT_DEFAULT_VALUE / 10);
+ hard_iface->bat_v.flags |= BATADV_WARNING_DEFAULT;
+ }
+
+ /* if none of the above cases apply, return the base_throughput */
+ return BATADV_THROUGHPUT_DEFAULT_VALUE;
+}
+
+/**
+ * batadv_v_elp_throughput_metric_update - worker updating the throughput metric
+ * of a single hop neighbour
+ * @work: the work queue item
+ */
+void batadv_v_elp_throughput_metric_update(struct work_struct *work)
+{
+ struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
+ struct batadv_hardif_neigh_node *neigh;
+
+ neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
+ metric_work);
+ neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
+ bat_v);
+
+ ewma_throughput_add(&neigh->bat_v.throughput,
+ batadv_v_elp_get_throughput(neigh));
+
+ /* decrement refcounter to balance increment performed before scheduling
+ * this task
+ */
+ batadv_hardif_neigh_put(neigh);
+}
+
+/**
* batadv_v_elp_periodic_work - ELP periodic task per interface
* @work: work queue item
*
@@ -67,6 +170,7 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
*/
static void batadv_v_elp_periodic_work(struct work_struct *work)
{
+ struct batadv_hardif_neigh_node *hardif_neigh;
struct batadv_hard_iface *hard_iface;
struct batadv_hard_iface_bat_v *bat_v;
struct batadv_elp_packet *elp_packet;
@@ -108,6 +212,31 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
atomic_inc(&hard_iface->bat_v.elp_seqno);
+ /* The throughput metric is updated on each sent packet. This way, if a
+ * node is dead and no longer sends packets, batman-adv is still able to
+ * react timely to its death.
+ *
+ * The throughput metric is updated by following these steps:
+ * 1) if the hard_iface is wifi => send a number of unicast ELPs for
+ * probing/sampling to each neighbor
+ * 2) update the throughput metric value of each neighbor (note that the
+ * value retrieved in this step might be 100ms old because the
+ * probing packets at point 1) could still be in the HW queue)
+ */
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(hardif_neigh, &hard_iface->neigh_list, list) {
+ if (!kref_get_unless_zero(&hardif_neigh->refcount))
+ continue;
+
+ /* Reading the estimated throughput from cfg80211 is a task that
+ * may sleep and that is not allowed in an rcu protected
+ * context. Therefore schedule a task for that.
+ */
+ queue_work(batadv_event_workqueue,
+ &hardif_neigh->bat_v.metric_work);
+ }
+ rcu_read_unlock();
+
restart_timer:
batadv_v_elp_start_timer(hard_iface);
out:
@@ -146,6 +275,15 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno);
atomic_set(&hard_iface->bat_v.elp_interval, 500);
+ /* assume full-duplex by default */
+ hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
+
+ /* warn the user (again) if there is no throughput data is available */
+ hard_iface->bat_v.flags &= ~BATADV_WARNING_DEFAULT;
+
+ if (batadv_is_wifi_netdev(hard_iface->net_dev))
+ hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
+
INIT_DELAYED_WORK(&hard_iface->bat_v.elp_wq,
batadv_v_elp_periodic_work);
batadv_v_elp_start_timer(hard_iface);
diff --git a/net/batman-adv/bat_v_elp.h b/net/batman-adv/bat_v_elp.h
index 5a7bc39..e95f1bc 100644
--- a/net/batman-adv/bat_v_elp.h
+++ b/net/batman-adv/bat_v_elp.h
@@ -21,11 +21,13 @@
#define _NET_BATMAN_ADV_BAT_V_ELP_H_
struct sk_buff;
+struct work_struct;
int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface);
void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface);
void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface);
int batadv_v_elp_packet_recv(struct sk_buff *skb,
struct batadv_hard_iface *if_incoming);
+void batadv_v_elp_throughput_metric_update(struct work_struct *work);
#endif /* _NET_BATMAN_ADV_BAT_V_ELP_H_ */
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index c800096..d9bcbe6 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -339,7 +339,7 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
*/
if ((throughput > 10) &&
(if_incoming == if_outgoing) &&
- (batadv_is_wifi_netdev(if_incoming->net_dev)))
+ !(if_incoming->bat_v.flags & BATADV_FULL_DUPLEX))
return throughput / 2;
/* hop penalty of 255 equals 100% */
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 2e79544..2f8add6 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -62,6 +62,7 @@
#define BATADV_TQ_TOTAL_BIDRECT_LIMIT 1
/* B.A.T.M.A.N. V */
+#define BATADV_THROUGHPUT_DEFAULT_VALUE 10
#define BATADV_ELP_MAX_AGE 64
#define BATADV_OGM_MAX_ORIGDIFF 5
#define BATADV_OGM_MAX_AGE 64
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index c56bb88..9abfb3e 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -87,12 +87,25 @@ struct batadv_hard_iface_bat_iv {
};
/**
+ * enum batadv_v_hard_iface_flags - interface flags useful to B.A.T.M.A.N. V
+ * @BATADV_FULL_DUPLEX: tells if the connection over this link is full-duplex
+ * @BATADV_WARNING_DEFAULT: tells whether we have warned the user that no
+ * throughput data is available for this interface and that default values are
+ * assumed.
+ */
+enum batadv_v_hard_iface_flags {
+ BATADV_FULL_DUPLEX = BIT(0),
+ BATADV_WARNING_DEFAULT = BIT(1),
+};
+
+/**
* struct batadv_hard_iface_bat_v - per hard-interface B.A.T.M.A.N. V data
* @elp_interval: time interval between two ELP transmissions
* @elp_seqno: current ELP sequence number
* @elp_skb: base skb containing the ELP message to send
* @elp_wq: workqueue used to schedule ELP transmissions
* @throughput_override: throughput override to disable link auto-detection
+ * @flags: interface specific flags
*/
struct batadv_hard_iface_bat_v {
atomic_t elp_interval;
@@ -100,6 +113,7 @@ struct batadv_hard_iface_bat_v {
struct sk_buff *elp_skb;
struct delayed_work elp_wq;
atomic_t throughput_override;
+ u8 flags;
};
/**
@@ -378,12 +392,14 @@ DECLARE_EWMA(throughput, 1024, 8)
* @elp_interval: time interval between two ELP transmissions
* @elp_latest_seqno: latest and best known ELP sequence number
* @last_unicast_tx: when the last unicast packet has been sent to this neighbor
+ * @metric_work: work queue callback item for metric update
*/
struct batadv_hardif_neigh_node_bat_v {
struct ewma_throughput throughput;
u32 elp_interval;
u32 elp_latest_seqno;
unsigned long last_unicast_tx;
+ struct work_struct metric_work;
};
/**
--
linux integration