[B.A.T.M.A.N.] batman-adv and/or batmand porting effort to FreeBSD
by Mahdi Mokhtari
Hi,
After some time of playing with the B.A.T.M.A.N protocol and
net-interface on OpenWRT and Debian I was thinking to use it with
the servers I use everyday (and maybe on routers/appliances I have
nanoBSD on).
So I started an effort...
(As a background) I already ported some applications to FreeBSD [and I'm
maintaining them] and
also I did work already on the Linux emulation layer of FreeBSD (FreeBSD
has a Linux syscall-emulation and Linux-KPI layers).
So my approach (as naturally I didn't expect the build of batman-adv.ko
to be successful as is),
was based on the approach that we [at FreeBSD] did to port Linux's
drm... <https://github.com/FreeBSDDesktop/kms-drm>
I ended up in adding some header-files to FreeBSD Linux-KPI (like
average.h, percpu.h, ...).
Now I'm at a state that Netlink blocks me and I'm to determine next step :-)
[Which I don't assume it being trivial with my current approach]
So I'd like to ask:
1- Is it better approach to "rewrite" batman-adv.ko [at least
Netlink-ish (let's call "Linuxism") parts] than what I'm doing now?
2- Any other efforts are being done out there?
3- is batmand deprecated [So I should mainly focus on batman-adv.ko]?
4- any other comments do you have? :D
P.S. sorry if I'm not really good at starting conversation from scratch
and out-of-nowhere :D
but I hope by continuing the collaboration we can have better (more
enriched) FreeBSD and better (as in more portable) B.A.T.M.A.N :-)
--
Best regards, MMokhi.
3 years, 1 month
[B.A.T.M.A.N.] [PATCH v5 0/7] B.A.T.M.A.N. V - fallback to tp meter estimation if throughput otherwise not available
by Marek Lindner
Under normal circumstances B.A.T.M.A.N. V retrieves the neighbor
throughput values to populate its metric tables from the various
drivers such as WiFi throughput tables and Ethernet throughput..
Whenever the interface drivers do not export link throughput
information manual overrides become necessary. To further
automate and thus better support these setups, ELP may call the
batman-adv throughput meter to schedule a throughput estimation
to be used to populate the metric table.
v5:
* fix tp_vars refcount on queue_work() failure
* squash batadv_tp_start_work() into batadv_tp_start()
v4:
* read tp measurement result only once
v3:
* fix ELP tp meter result computation
* use batadv_has_timed_out() instead of custom implementation
* set ELP tp meter test duration to 1000ms in patch #6
* add comment explaining periodic scheduling
v2:
* added sysfs attribute to configure tp meter test duration
* fixed null pointer dereference in TP meter packet sending routine
* fixed storing the measured throughput in the correct variable
* checkpatch/kerneldoc/sparse/smatch cleanup
Antonio Quartulli (3):
batman-adv: tp_meter - prevent concurrent tp_meter sessions by using
workqueue
batman-adv: tp_meter - don't check for existing session
batman-adv: tp_meter - add option to perform one-hop test
Marek Lindner (4):
batman-adv: tp_meter - allow up to 10 queued sessions
batman-adv: tp_meter - add caller distinction
batman-adv: ELP - use tp meter to estimate the throughput if otherwise
not available
batman-adv: ELP - add throughput meter test duration attribute
.../ABI/testing/sysfs-class-net-batman-adv | 7 +
include/uapi/linux/batadv_packet.h | 2 +
net/batman-adv/bat_v.c | 1 +
net/batman-adv/bat_v_elp.c | 69 ++-
net/batman-adv/bat_v_elp.h | 21 +
net/batman-adv/main.c | 10 +-
net/batman-adv/main.h | 7 +-
net/batman-adv/netlink.c | 3 +-
net/batman-adv/routing.c | 6 +-
net/batman-adv/sysfs.c | 3 +
net/batman-adv/tp_meter.c | 484 +++++++++++-------
net/batman-adv/tp_meter.h | 11 +-
net/batman-adv/types.h | 36 ++
13 files changed, 453 insertions(+), 207 deletions(-)
--
2.18.0
3 years, 2 months
[B.A.T.M.A.N.] [PATCH] batman-adv: handle race condition for claims also in batadv_bla_rx
by Simon Wunderlich
From: Andreas Pape <apape(a)phoenixcontact.com>
Like in the case of the patch for batadv_bla_tx to handle a race
condition when claiming a mac address for bla, a similar situation
can occur when claiming is triggered via batadv_bla_rx. This patch
solves this with a similar approach as for batadv_bla_tx.
Signed-off-by: Andreas Pape <apape(a)phoenixcontact.com>
---
net/batman-adv/bridge_loop_avoidance.c | 31 ++++++++++++++++++++-----------
net/batman-adv/translation-table.c | 26 ++++++++++++++++++++++++++
net/batman-adv/translation-table.h | 3 +++
3 files changed, 49 insertions(+), 11 deletions(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index d07e89e..cab8980 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1847,19 +1847,28 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
if (!claim) {
/* possible optimization: race for a claim */
- /* No claim exists yet, claim it for us!
+ /* Make sure this packet is not looping back
+ * from our own backbone.
*/
- batadv_dbg(BATADV_DBG_BLA, bat_priv,
- "bla_rx(): Unclaimed MAC %pM found. Claim it. Local: %s\n",
- ethhdr->h_source,
- batadv_is_my_client(bat_priv,
- ethhdr->h_source, vid) ?
- "yes" : "no");
- batadv_handle_claim(bat_priv, primary_if,
- primary_if->net_dev->dev_addr,
- ethhdr->h_source, vid);
- goto allow;
+ if (batadv_tt_local_has_timed_out(bat_priv, ethhdr->h_source,
+ vid, 100)) {
+ /* No claim exists yet, claim it for us!
+ */
+ batadv_dbg(BATADV_DBG_BLA, bat_priv,
+ "bla_rx(): Unclaimed MAC %pM found. Claim it. Local: %s\n",
+ ethhdr->h_source,
+ batadv_is_my_client(bat_priv,
+ ethhdr->h_source, vid) ?
+ "yes" : "no");
+
+ batadv_handle_claim(bat_priv, primary_if,
+ primary_if->net_dev->dev_addr,
+ ethhdr->h_source, vid);
+ goto allow;
+ } else {
+ goto handled;
+ }
}
/* if it is our own claim ... */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index e75b493..b908195 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -4380,3 +4380,29 @@ void batadv_tt_cache_destroy(void)
kmem_cache_destroy(batadv_tt_req_cache);
kmem_cache_destroy(batadv_tt_roam_cache);
}
+
+bool batadv_tt_local_has_timed_out(struct batadv_priv *bat_priv,
+ const u8 *addr, unsigned short vid,
+ unsigned int timeout)
+{
+ struct batadv_tt_local_entry *tt_local_entry;
+ bool ret = true;
+
+ tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
+ if (!tt_local_entry)
+ goto out;
+ /* Check if the client has been logically deleted (but is kept for
+ * consistency purpose)
+ */
+ if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
+ (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
+ goto out;
+ /* Check that the tt_local_entry has a certain age */
+ if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
+ ret = false;
+
+out:
+ if (tt_local_entry)
+ batadv_tt_local_entry_put(tt_local_entry);
+ return ret;
+}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 411d586..b05d0d8 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -65,5 +65,8 @@ bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
int batadv_tt_cache_init(void);
void batadv_tt_cache_destroy(void);
+bool batadv_tt_local_has_timed_out(struct batadv_priv *bat_priv,
+ const u8 *addr, unsigned short vid,
+ unsigned int timeout);
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
--
1.7.0.4
3 years, 7 months
[B.A.T.M.A.N.] [RFC maint v2] batman-adv: fix adding VLANs with partial state
by Marek Lindner
Whenever a new VLAN is created on top of batman virtual interfaces
the batman-adv kernel module creates internal structures to track
the status of said VLAN. Amongst other things, the MAC address of
the VLAN interface itself has to be stored.
Without this change a VLAN and its infrastructure could be created
while the interface MAC address is not stored without triggering
any error, thus creating issues in other parts of the code.
Prevent the VLAN from being created if the MAC address can not
be stored.
Fixes: 952cebb57518 ("batman-adv: add per VLAN interface attribute framework")
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
---
net/batman-adv/hard-interface.c | 2 +-
net/batman-adv/soft-interface.c | 105 ++++++++++++++++++++++++--------
net/batman-adv/soft-interface.h | 3 +-
3 files changed, 83 insertions(+), 27 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index c405d15b..0b22cc4d 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -1000,7 +1000,7 @@ static int batadv_hard_if_event(struct notifier_block *this,
if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
batadv_sysfs_add_meshif(net_dev);
bat_priv = netdev_priv(net_dev);
- batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS);
+ batadv_softif_create_vlan_late(bat_priv, BATADV_NO_FLAGS);
return NOTIFY_DONE;
}
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index edeffcb9..728d9d40 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -563,16 +563,36 @@ struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
}
/**
- * batadv_softif_create_vlan() - allocate the needed resources for a new vlan
+ * batadv_softif_destroy_vlan() - remove and destroy a softif_vlan object
+ * @bat_priv: the bat priv with all the soft interface information
+ * @vlan: the object to remove
+ */
+static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv,
+ struct batadv_softif_vlan *vlan)
+{
+ /* explicitly remove the associated TT local entry because it is marked
+ * with the NOPURGE flag
+ */
+ batadv_tt_local_remove(bat_priv, bat_priv->soft_iface->dev_addr,
+ vlan->vid, "vlan interface destroyed", false);
+
+ batadv_sysfs_del_vlan(bat_priv, vlan);
+ batadv_softif_vlan_put(vlan);
+}
+
+/**
+ * batadv_softif_create_vlan_early() - allocate the needed resources for a new
+ * vlan, defer sysfs creation till later
* @bat_priv: the bat priv with all the soft interface information
* @vid: the VLAN identifier
*
* Return: 0 on success, a negative error otherwise.
*/
-int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
+static int batadv_softif_create_vlan_early(struct batadv_priv *bat_priv,
+ unsigned short vid)
{
struct batadv_softif_vlan *vlan;
- int err;
+ bool client_added;
vlan = batadv_softif_vlan_get(bat_priv, vid);
if (vlan) {
@@ -590,12 +610,6 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
atomic_set(&vlan->ap_isolation, 0);
- err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan);
- if (err) {
- kfree(vlan);
- return err;
- }
-
spin_lock_bh(&bat_priv->softif_vlan_list_lock);
kref_get(&vlan->refcount);
hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list);
@@ -604,32 +618,63 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
/* add a new TT local entry. This one will be marked with the NOPURGE
* flag
*/
- batadv_tt_local_add(bat_priv->soft_iface,
- bat_priv->soft_iface->dev_addr, vid,
- BATADV_NULL_IFINDEX, BATADV_NO_MARK);
+ client_added = batadv_tt_local_add(bat_priv->soft_iface,
+ bat_priv->soft_iface->dev_addr, vid,
+ BATADV_NULL_IFINDEX, BATADV_NO_MARK);
/* don't return reference to new softif_vlan */
batadv_softif_vlan_put(vlan);
+ if (!client_added) {
+ batadv_softif_destroy_vlan(bat_priv, vlan);
+ return -ENOENT;
+ }
+
return 0;
}
/**
- * batadv_softif_destroy_vlan() - remove and destroy a softif_vlan object
+ * batadv_softif_create_vlan_late() - complete softif vlan creation with the
+ * sysfs entries
* @bat_priv: the bat priv with all the soft interface information
- * @vlan: the object to remove
+ * @vid: the VLAN identifier
+ *
+ * Return: 0 on success, a negative error otherwise.
*/
-static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv,
- struct batadv_softif_vlan *vlan)
+int batadv_softif_create_vlan_late(struct batadv_priv *bat_priv,
+ unsigned short vid)
{
- /* explicitly remove the associated TT local entry because it is marked
- * with the NOPURGE flag
- */
- batadv_tt_local_remove(bat_priv, bat_priv->soft_iface->dev_addr,
- vlan->vid, "vlan interface destroyed", false);
+ struct batadv_softif_vlan *vlan;
+ int ret;
+
+ vlan = batadv_softif_vlan_get(bat_priv, vid);
+ if (!vlan)
+ return -ENOENT;
+
+ ret = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan);
- batadv_sysfs_del_vlan(bat_priv, vlan);
batadv_softif_vlan_put(vlan);
+ return ret;
+}
+
+/**
+ * batadv_softif_create_vlan() - allocate the needed resources for a new vlan
+ * @bat_priv: the bat priv with all the soft interface information
+ * @vid: the VLAN identifier
+ *
+ * Return: 0 on success, a negative error otherwise.
+ */
+static int batadv_softif_create_vlan(struct batadv_priv *bat_priv,
+ unsigned short vid)
+{
+ int err;
+
+ err = batadv_softif_create_vlan_early(bat_priv, vid);
+ if (err)
+ return err;
+
+ err = batadv_softif_create_vlan_late(bat_priv, vid);
+ return err;
}
/**
@@ -648,6 +693,7 @@ static int batadv_interface_add_vid(struct net_device *dev, __be16 proto,
{
struct batadv_priv *bat_priv = netdev_priv(dev);
struct batadv_softif_vlan *vlan;
+ bool client_added;
int ret;
/* only 802.1Q vlans are supported.
@@ -683,9 +729,14 @@ static int batadv_interface_add_vid(struct net_device *dev, __be16 proto,
* flag. This must be added again, even if the vlan object already
* exists, because the entry was deleted by kill_vid()
*/
- batadv_tt_local_add(bat_priv->soft_iface,
- bat_priv->soft_iface->dev_addr, vid,
- BATADV_NULL_IFINDEX, BATADV_NO_MARK);
+ client_added = batadv_tt_local_add(bat_priv->soft_iface,
+ bat_priv->soft_iface->dev_addr, vid,
+ BATADV_NULL_IFINDEX, BATADV_NO_MARK);
+
+ if (!client_added) {
+ batadv_softif_destroy_vlan(bat_priv, vlan);
+ return -ENOENT;
+ }
return 0;
}
@@ -850,6 +901,10 @@ static int batadv_softif_init_late(struct net_device *dev)
if (ret < 0)
goto unreg_debugfs;
+ ret = batadv_softif_create_vlan_early(bat_priv, BATADV_NO_FLAGS);
+ if (ret < 0)
+ goto unreg_debugfs;
+
return 0;
unreg_debugfs:
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index daf87f07..b8a9a3c8 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -36,7 +36,8 @@ struct net_device *batadv_softif_create(struct net *net, const char *name);
void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
bool batadv_softif_is_valid(const struct net_device *net_dev);
extern struct rtnl_link_ops batadv_link_ops;
-int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid);
+int batadv_softif_create_vlan_late(struct batadv_priv *bat_priv,
+ unsigned short vid);
void batadv_softif_vlan_put(struct batadv_softif_vlan *softif_vlan);
struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
unsigned short vid);
--
2.17.0
3 years, 8 months
[B.A.T.M.A.N.] [RFC PATCH] batman-adv: Increase DHCP snooped DAT entry purge timeout in DHT
by Linus Lüssing
This patch increases the DAT entry purge timeout in the DHT for DHT_PUT
messages which were triggered by DHCP snooping from 5 to 60 minutes.
DHCP snooping will ensure a timely update in case of a reassignment
of an IP address to a new host in the DHT. This allows us to
increase the DAT entry timeout for entries inserted via an incoming
DHT_PUT message triggered by DHCP snooping without risking
inconsistencies.
To signalize to a remote node that a DHT_PUT message was triggered
by DHCP snooping and that it is suitable for such an extended purge
timeout an according flag in the unicast 4addr header was introduced.
Signed-off-by: Linus Lüssing <linus.luessing(a)c0d3.blue>
---
Unverified/untested so far! Expecting:
Reduction of (unanswered) ARP Requests from gateways:
60min: 98.95%
Other potential timeout periods for comparison:
45min: 97.95%
30min: 91.71%
https://www.open-mesh.org/projects/batman-adv/wiki/DAT_DHCP_Snooping
This patch requires:
"batman-adv: DHCP snooping for DAT"
---
include/uapi/linux/batadv_packet.h | 13 ++++-
net/batman-adv/distributed-arp-table.c | 86 +++++++++++++++++++++++++++-------
net/batman-adv/main.h | 1 +
net/batman-adv/send.c | 9 ++--
net/batman-adv/send.h | 3 +-
net/batman-adv/types.h | 6 +++
6 files changed, 94 insertions(+), 24 deletions(-)
diff --git a/include/uapi/linux/batadv_packet.h b/include/uapi/linux/batadv_packet.h
index 6a48f36c..0841ee0e 100644
--- a/include/uapi/linux/batadv_packet.h
+++ b/include/uapi/linux/batadv_packet.h
@@ -79,6 +79,15 @@ enum batadv_subtype {
BATADV_P_DAT_CACHE_REPLY = 0x04,
};
+/**
+ * enum batadv_dat_dht_put_flags - flags used in DHT_PUT messages
+ * @BATADV_DAT_EXTENDED_TIMEOUT: flag is set when the DHT_PUT receiver should
+ * store an according DAT entry for an extended period
+ */
+enum batadv_dat_dht_put_flags {
+ BATADV_DAT_EXTENDED_TIMEOUT = 1UL << 0,
+};
+
/* this file is included by batctl which needs these defines */
#define BATADV_COMPAT_VERSION 15
@@ -422,13 +431,13 @@ struct batadv_unicast_packet {
* @u: common unicast packet header
* @src: address of the source
* @subtype: packet subtype
- * @reserved: reserved byte for alignment
+ * @flags: unicast 4addr flags
*/
struct batadv_unicast_4addr_packet {
struct batadv_unicast_packet u;
__u8 src[ETH_ALEN];
__u8 subtype;
- __u8 reserved;
+ __u8 flags;
/* "4 bytes boundary + 2 bytes" long to make the payload after the
* following ethernet header again 4 bytes boundary aligned
*/
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 5fa06ef3..7185319a 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -109,7 +109,9 @@ static void batadv_dat_entry_put(struct batadv_dat_entry *dat_entry)
static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
{
return batadv_has_timed_out(dat_entry->last_update,
- BATADV_DAT_ENTRY_TIMEOUT);
+ BATADV_DAT_ENTRY_TIMEOUT) &&
+ batadv_has_timed_out(dat_entry->last_extended_update,
+ BATADV_DAT_EXT_ENTRY_TIMEOUT);
}
/**
@@ -326,9 +328,11 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
* @ip: ipv4 to add/edit
* @mac_addr: mac address to assign to the given ipv4
* @vid: VLAN identifier
+ * @extended_timeout: triggered by a DHT_PUT with an extended timeout flag
*/
-static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
- u8 *mac_addr, unsigned short vid)
+static void
+batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
+ u8 *mac_addr, unsigned short vid, bool extended_timeout)
{
struct batadv_dat_entry *dat_entry;
int hash_added;
@@ -338,7 +342,12 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
if (dat_entry) {
if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
ether_addr_copy(dat_entry->mac_addr, mac_addr);
+
dat_entry->last_update = jiffies;
+
+ if (extended_timeout)
+ dat_entry->last_extended_update = jiffies;
+
batadv_dbg(BATADV_DBG_DAT, bat_priv,
"Entry updated: %pI4 %pM (vid: %d)\n",
&dat_entry->ip, dat_entry->mac_addr,
@@ -354,6 +363,7 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
dat_entry->vid = vid;
ether_addr_copy(dat_entry->mac_addr, mac_addr);
dat_entry->last_update = jiffies;
+ dat_entry->last_extended_update = extended_timeout ? jiffies : 0;
kref_init(&dat_entry->refcount);
kref_get(&dat_entry->refcount);
@@ -630,6 +640,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
* @ip: the DHT key
* @vid: VLAN identifier
* @packet_subtype: unicast4addr packet subtype to use
+ * @flags: flags to set in the unicast4addr header
*
* This function copies the skb with pskb_copy() and is sent as unicast packet
* to each of the selected candidates.
@@ -639,7 +650,8 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
*/
static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
struct sk_buff *skb, __be32 ip,
- unsigned short vid, int packet_subtype)
+ unsigned short vid, int packet_subtype,
+ u8 flags)
{
int i;
bool ret = false;
@@ -666,7 +678,8 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
tmp_skb = pskb_copy_for_clone(skb, GFP_ATOMIC);
if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, tmp_skb,
cand[i].orig_node,
- packet_subtype)) {
+ packet_subtype,
+ flags)) {
kfree_skb(tmp_skb);
goto free_neigh;
}
@@ -1182,7 +1195,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
hw_src = batadv_arp_hw_src(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid, false);
dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
if (dat_entry) {
@@ -1231,7 +1244,8 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
} else {
/* Send the request to the DHT */
ret = batadv_dat_send_data(bat_priv, skb, ip_dst, vid,
- BATADV_P_DAT_DHT_GET);
+ BATADV_P_DAT_DHT_GET,
+ BATADV_NO_FLAGS);
}
out:
if (dat_entry)
@@ -1275,7 +1289,7 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing incoming ARP REQUEST");
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid, false);
dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
if (!dat_entry)
@@ -1339,14 +1353,42 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
hw_dst = batadv_arp_hw_dst(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid, false);
+ batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid, false);
/* 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, vid, BATADV_P_DAT_DHT_PUT);
- batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT,
+ BATADV_NO_FLAGS);
+ batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT,
+ BATADV_NO_FLAGS);
+}
+
+/**
+ * batadv_dat_get_dht_put_flags() - retrieves DHT_PUT flags from a 4addr packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ * @hdr_size: size of the encapsulation header
+ *
+ * Return: The DHT_PUT flags if the provided packet contains a valid DHT_PUT
+ * message, BATADV_NO_FLAGS otherwise.
+ */
+static u8 batadv_dat_get_dht_put_flags(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size)
+{
+ struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+
+ if (hdr_size < sizeof(struct batadv_unicast_packet))
+ return BATADV_NO_FLAGS;
+
+ unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+
+ if (unicast_4addr_packet->u.packet_type != BATADV_UNICAST_4ADDR ||
+ unicast_4addr_packet->subtype != BATADV_P_DAT_DHT_PUT)
+ return BATADV_NO_FLAGS;
+
+ return unicast_4addr_packet->flags;
}
/**
@@ -1363,11 +1405,13 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size)
{
struct batadv_dat_entry *dat_entry = NULL;
+ bool extended_timeout = false;
u16 type;
__be32 ip_src, ip_dst;
u8 *hw_src, *hw_dst;
bool dropped = false;
unsigned short vid;
+ u8 dht_put_flags;
if (!atomic_read(&bat_priv->distributed_arp_table))
goto out;
@@ -1400,11 +1444,15 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
goto out;
}
+ dht_put_flags = batadv_dat_get_dht_put_flags(bat_priv, skb, hdr_size);
+ if (dht_put_flags & BATADV_DAT_EXTENDED_TIMEOUT)
+ extended_timeout = true;
+
/* 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, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid, extended_timeout);
+ batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid, extended_timeout);
/* If BLA is enabled, only forward ARP replies if we have claimed the
* source of the ARP reply or if no one else of the same backbone has
@@ -1658,11 +1706,13 @@ static bool batadv_dat_put_pairs(struct batadv_priv *bat_priv, u8 *hw_src,
if (type != ARPOP_REPLY)
goto err_skip_commit;
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid, false);
+ batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid, false);
- batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT);
- batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT,
+ BATADV_DAT_EXTENDED_TIMEOUT);
+ batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT,
+ BATADV_DAT_EXTENDED_TIMEOUT);
ret = true;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 8da3c933..0227aae0 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -51,6 +51,7 @@
#define BATADV_ORIG_WORK_PERIOD 1000 /* 1 second */
#define BATADV_MCAST_WORK_PERIOD 500 /* 0.5 seconds */
#define BATADV_DAT_ENTRY_TIMEOUT (5 * 60000) /* 5 mins in milliseconds */
+#define BATADV_DAT_EXT_ENTRY_TIMEOUT (60 * 60000) /* 60 mins in milliseconds */
/* sliding packet range of received originator messages in sequence numbers
* (should be a multiple of our word size)
*/
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 4a35f5c2..edccfa0b 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -289,13 +289,15 @@ static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb,
* @skb: the skb containing the payload to encapsulate
* @orig: the destination node
* @packet_subtype: the unicast 4addr packet subtype to use
+ * @flags: the unicast 4addr packet flags to set
*
* Return: false if the payload could not be encapsulated or true otherwise.
*/
bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
struct sk_buff *skb,
struct batadv_orig_node *orig,
- int packet_subtype)
+ int packet_subtype,
+ u8 flags)
{
struct batadv_hard_iface *primary_if;
struct batadv_unicast_4addr_packet *uc_4addr_packet;
@@ -317,7 +319,7 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR;
ether_addr_copy(uc_4addr_packet->src, primary_if->net_dev->dev_addr);
uc_4addr_packet->subtype = packet_subtype;
- uc_4addr_packet->reserved = 0;
+ uc_4addr_packet->flags = flags;
ret = true;
out:
@@ -363,7 +365,8 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
case BATADV_UNICAST_4ADDR:
if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb,
orig_node,
- packet_subtype))
+ packet_subtype,
+ BATADV_NO_FLAGS))
goto out;
break;
default:
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 64cce07b..278994af 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -62,7 +62,8 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
struct sk_buff *skb,
struct batadv_orig_node *orig_node,
- int packet_subtype);
+ int packet_subtype,
+ u8 flags);
int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
struct sk_buff *skb, int packet_type,
int packet_subtype,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 7d5d9987..2eed2001 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -2308,6 +2308,12 @@ struct batadv_dat_entry {
*/
unsigned long last_update;
+ /**
+ * @last_extended_update: time in jiffies when a DHT_PUT with extended
+ * timeout flag was last received
+ */
+ unsigned long last_extended_update;
+
/** @hash_entry: hlist node for &batadv_priv_dat.hash */
struct hlist_node hash_entry;
--
2.11.0
4 years, 1 month
[B.A.T.M.A.N.] broadcast storms
by Jake.Harris@zf.com
I'm sure a similar question to this has been answered, but I am new to this mailing list format and don't know an efficient way to search https://lists.open-mesh.org/pipermail/b.a.t.m.a.n/
I'm having problems with broadcast messages effectively echoing around the network of 50ish nodes. I attached a few seconds of the batctl tcpdump output. I can't seem to find a pattern to what causes this, it tends to happen once every two or three weeks, the storm causes problems with the batman program where during the storm nodes drop all their neighbors (batctl n shows an empty list) indefinitely, which I have worked around that issue via a batch script that reloads batman if the neighbor list is empty. Reloading successfully reconnects to the network but the storm still persists.
The only way I've found to fix this is to reboot all the nodes at the same time such that the whole network is down to kill the echos.
I believe I had this problem much more frequently (every 4 days or so) a while ago on the same network when using discrete tcp destinations for the nodes to communicate, the storm frequency was reduced to what it is now by using broadcast packets and reducing the communication rate from 12 seconds to once every 40 seconds.
Rebooting the nodes that are responsible for the echoing messages has no effect, I rebooted 192.168.1.230 before running tcpdump that is attached and as it shows packets from 230 continued to bounce around while the node was powered off and after it rejoined the network. It doesn't appear broadcast uses a time-to-live parameter to limit the hops the packets will make.
I'm at a loss for a way to remedy this, there seems to only be multicast optimizations.
4 years, 2 months
[B.A.T.M.A.N.] [PATCH] batctl: Fix minor typos in manpage
by Sven Eckelmann
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
man/batctl.8 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/man/batctl.8 b/man/batctl.8
index d5fc5302ffd5d6a5ab1dfcb164c57a9f7f8e398f..3e210281fcf4d5d3c1d76b1f9c02459f4828979e 100644
--- a/man/batctl.8
+++ b/man/batctl.8
@@ -338,7 +338,7 @@ given batctl will not replace the MAC addresses with bat\-host names in the outp
This command starts a throughput test entirely controlled by batman module in
kernel space: the computational resources needed to align memory and copy data
between user and kernel space that are required by other user space tools may
-represent a bootleneck on some low profile device.
+represent a bottleneck on some low profile device.
The test consist of the transfer of 14 MB of data between the two nodes. The
protocol used to transfer the data is somehow similar to TCP, but simpler: some
@@ -346,9 +346,9 @@ TCP features are still missing, thus protocol performances could be worst. Since
a fixed amount of data is transferred the experiment duration depends on the
network conditions. The experiment can be interrupted with CTRL + C. At the end
of a successful experiment the throughput in KBytes per second is returned,
-togheter with the experiment duration in millisecond and the amount of bytes
+together with the experiment duration in millisecond and the amount of bytes
transferred. If too many packets are lost or the specified MAC address is not
-reachable, a message notifing the error is returned instead of the result.
+reachable, a message notifying the error is returned instead of the result.
.RE
.br
.SH FILES
4 years, 3 months
[B.A.T.M.A.N.] [PATCH v3 00/42] batctl: pre-netlink restructuring, part 1
by Sven Eckelmann
Hi,
the batctl command already has support to get (previously debugfs) tables
via netlink. It does this while still being able to fall back to the old
debugfs tables on kernels which don't support the new generic netlink
family.
Something similar should be done in the future for the settings which
are currently part of sysfs. But we can already see that the current
integration of netlink in batctl only done in a single file - netlink.c
But this file is already starting to be so big that working with it
is rather cumbersome.
So as first steps:
* restructure command registration
* move commands in separate files (which should store their actual implementation)
* add a new helper command to receive multicast group messages from the kernel
More things will follow in the future.
Changes:
v3:
* correctly split ap_isolation and bonding patch
* fix copyright headers for new files
* move more routing_algo specific code to its command specific file
* fix build problems with musl in OpenWrt 18.06
* switch Makefile's OBJ + OBJ_BISECT to obj-y and obj-n
* add way to "freely" disable some commands for size optimization reasons
- it is for example now possible to reduce the size of the batctl on
mips_24kc_musl from 64604 bytes to 14252 bytes when only the interface
commands are required (I know, stupid example)
- the binary to generate the debug tables output for the same architectur
used 26988 bytes
v2:
* Add missing orig_interval.c
Kind regards,
Sven
Sven Eckelmann (42):
batctl: Drop unused define SOCKET_PATH_FMT
batctl: Use common code organization for statistics
batctl: Drop legacy vis_* related warning messages
batctl: Move loglevel command to separate file
batctl: Move log command to separate file
batctl: Move gw_mode command to separate file
batctl: Move routing_algo command to separate file
batctl: Rename tp_meter to throughputmeter
batctl: Introduce datastructure for subcommands
batctl: Add per command flags
batctl: Use command structure for remaining subcommands
batctl: Use getopt to parse main options
batctl: Store usage line next to command
batctl: Prepare command infrastructure for shared functions
batctl: Add type to command to structure usage output
batctl: Convert debug table to command infrastructure
batctl: Convert sysfs settings to command infrastructure
batctl: Move backbonetable debug table to own file
batctl: Move claimtable debug table to own file
batctl: Move dat_cache debug table to own file
batctl: Move gateways debug table to own file
batctl: Move mcast_flags debug table to own file
batctl: Move nc_nodes debug table to own file
batctl: Move neighbors debug table to own file
batctl: Move originators debug table to own file
batctl: Move transglobal debug table to own file
batctl: Move translocal debug table to own file
batctl: Move aggregation setting to own file
batctl: Move ap_isolation setting to own file
batctl: Move bonding setting to own file
batctl: Move bridge_loop_avoidance setting to own file
batctl: Move distributed_arp_table setting to own file
batctl: Move fragmentation setting to own file
batctl: Move isolation_mark setting to own file
batctl: Move multicast_mode setting to own file
batctl: Move network_coding setting to own file
batctl: Move orig_interval setting to own file
batctl: Use external netlink socket for debug tables
batctl: Move routing_algo specific code it command source file
batctl: Add command to monitor for netlink events
batctl: Simplify enabling for bisect_iv subcommand
batctl: Allow to enable/disable subcommands
Makefile | 91 ++-
translate.h => aggregation.c | 15 +-
ap_isolation.c | 33 +
backbonetable.c | 126 ++++
bisect_iv.c | 6 +-
bisect_iv.h | 4 -
traceroute.h => bonding.c | 15 +-
bridge_loop_avoidance.c | 33 +
claimtable.c | 131 ++++
dat_cache.c | 147 +++++
debug.c | 218 +------
debug.h | 38 +-
distributed_arp_table.c | 33 +
event.c | 246 ++++++++
ping.h => fragmentation.c | 15 +-
functions.c | 28 +-
functions.h | 1 -
gateways.c | 175 +++++
gw_mode.c | 171 +++++
interface.c | 23 +-
ioctl.h | 28 -
isolation_mark.c | 35 +
log.c | 73 +++
loglevel.c | 147 +++++
main.c | 274 ++++----
main.h | 65 +-
man/batctl.8 | 4 +
mcast_flags.c | 180 ++++++
multicast_mode.c | 33 +
interface.h => nc_nodes.c | 14 +-
neighbors.c | 142 +++++
netlink.c | 1332 ++++-----------------------------------
netlink.h | 55 +-
network_coding.c | 33 +
orig_interval.c | 35 +
originators.c | 228 +++++++
ping.c | 10 +-
routing_algo.c | 263 ++++++++
ioctl.c => statistics.c | 10 +-
sys.c | 432 +------------
sys.h | 39 +-
tcpdump.c | 5 +-
tcpdump.h | 2 -
tp_meter.c => throughputmeter.c | 10 +-
tp_meter.h | 28 -
traceroute.c | 10 +-
transglobal.c | 162 +++++
translate.c | 8 +-
translocal.c | 158 +++++
49 files changed, 3156 insertions(+), 2208 deletions(-)
rename translate.h => aggregation.c (67%)
create mode 100644 ap_isolation.c
create mode 100644 backbonetable.c
rename traceroute.h => bonding.c (68%)
create mode 100644 bridge_loop_avoidance.c
create mode 100644 claimtable.c
create mode 100644 dat_cache.c
create mode 100644 distributed_arp_table.c
create mode 100644 event.c
rename ping.h => fragmentation.c (67%)
create mode 100644 gateways.c
create mode 100644 gw_mode.c
delete mode 100644 ioctl.h
create mode 100644 isolation_mark.c
create mode 100644 log.c
create mode 100644 loglevel.c
create mode 100644 mcast_flags.c
create mode 100644 multicast_mode.c
rename interface.h => nc_nodes.c (73%)
create mode 100644 neighbors.c
create mode 100644 network_coding.c
create mode 100644 orig_interval.c
create mode 100644 originators.c
create mode 100644 routing_algo.c
rename ioctl.c => statistics.c (90%)
rename tp_meter.c => throughputmeter.c (97%)
delete mode 100644 tp_meter.h
create mode 100644 transglobal.c
create mode 100644 translocal.c
--
2.11.0
4 years, 3 months
[B.A.T.M.A.N.] [PATCH maint] batman-adv: Use explicit tvlv padding for ELP packets
by Sven Eckelmann
The announcement messages of batman-adv COMPAT_VERSION 15 have the
possibility to announce additional information via a dynamic TVLV part.
This part is optional for the ELP packets and currently not parsed by the
Linux implementation. Still out-of-tree versions are using it to transport
things like neighbor hashes to optimize the rebroadcast behavior.
Since the ELP broadcast packets are smaller than the minimal ethernet
packet, it often has to be padded. This is often done (as specified in
RFC894) with octets of zero and thus work perfectly fine with the TVLV
part (making it a zero length and thus empty). But not all ethernet
compatible hardware seems to follow this advice. To avoid ambiguous
situations when parsing the TVLV header, just force the 4 bytes (TVLV
length + padding) after the required ELP header to zero.
Fixes: a4b88af77e28 ("batman-adv: ELP - adding basic infrastructure")
Reported-by: Linus Lüssing <linus.luessing(a)c0d3.blue>
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
net/batman-adv/bat_v_elp.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index 9f481cfd..e8090f09 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -352,19 +352,21 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
*/
int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
{
+ static const size_t tvlv_padding = sizeof(__be32);
struct batadv_elp_packet *elp_packet;
unsigned char *elp_buff;
u32 random_seqno;
size_t size;
int res = -ENOMEM;
- size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN;
+ size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN + tvlv_padding;
hard_iface->bat_v.elp_skb = dev_alloc_skb(size);
if (!hard_iface->bat_v.elp_skb)
goto out;
skb_reserve(hard_iface->bat_v.elp_skb, ETH_HLEN + NET_IP_ALIGN);
- elp_buff = skb_put_zero(hard_iface->bat_v.elp_skb, BATADV_ELP_HLEN);
+ elp_buff = skb_put_zero(hard_iface->bat_v.elp_skb,
+ BATADV_ELP_HLEN + tvlv_padding);
elp_packet = (struct batadv_elp_packet *)elp_buff;
elp_packet->packet_type = BATADV_ELP;
--
2.19.1
4 years, 3 months
[B.A.T.M.A.N.] [PATCH v3] alfred: Request MAC resolution for IPv4 address not in ARP cache
by Jonathan Haws
When using IPv4, if the remote server is not yet in the ARP cache, the
MAC resolution will fail and data appear to not be shared via alfred.
Add a routine (modified from batctl sources) to request MAC resolution
by simply sending a datagram to the discard port (UDP/9). This adds the
remote MAC to the ARP cache, resulting in successful MAC resolution.
Fixes: c7da798113a2 ("alfred: IPv4 multicast distribution support.")
Signed-off-by: Jonathan Haws <jhaws(a)sdl.usu.edu>
---
util.c | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/util.c b/util.c
index dd3f00f..0794792 100644
--- a/util.c
+++ b/util.c
@@ -30,6 +30,7 @@
#include <sys/ioctl.h>
#include <sys/time.h>
#include <time.h>
+#include <unistd.h>
#include "alfred.h"
int time_diff(struct timespec *tv1, struct timespec *tv2,
@@ -80,11 +81,35 @@ bool is_valid_ether_addr(uint8_t addr[ETH_ALEN])
return true;
}
+static void ipv4_request_mac_resolve(const alfred_addr *addr)
+{
+ const struct sockaddr *sockaddr;
+ struct sockaddr_in inet4;
+ size_t sockaddr_len;
+ int sock;
+ char t = 0;
+
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ return;
+
+ memset(&inet4, 0, sizeof(inet4));
+ inet4.sin_family = AF_INET;
+ inet4.sin_port = htons(9);
+ inet4.sin_addr.s_addr = addr->ipv4.s_addr;
+ sockaddr = (const struct sockaddr *)&inet4;
+ sockaddr_len = sizeof(inet4);
+
+ sendto(sock, &t, sizeof(t), 0, sockaddr, sockaddr_len);
+ close(sock);
+}
+
int ipv4_arp_request(struct interface *interface, const alfred_addr *addr,
struct ether_addr *mac)
{
struct arpreq arpreq;
struct sockaddr_in *sin;
+ int retries = 1;
memset(&arpreq, 0, sizeof(arpreq));
memset(mac, 0, ETH_ALEN);
@@ -96,8 +121,13 @@ int ipv4_arp_request(struct interface *interface, const alfred_addr *addr,
strncpy(arpreq.arp_dev, interface->interface, sizeof(arpreq.arp_dev));
arpreq.arp_dev[sizeof(arpreq.arp_dev) - 1] = '\0';
- if (ioctl(interface->netsock, SIOCGARP, &arpreq) < 0)
- return -1;
+ while ((ioctl(interface->netsock, SIOCGARP, &arpreq) < 0) || !(arpreq.arp_flags & ATF_COM)) {
+ ipv4_request_mac_resolve(addr);
+ usleep(200000);
+
+ if (retries-- == 0)
+ break;
+ }
if (arpreq.arp_flags & ATF_COM) {
memcpy(mac, arpreq.arp_ha.sa_data, sizeof(*mac));
--
2.17.1
4 years, 3 months