Hi,
this is the second take of my netlink API patches. As mentioned before, the
netlink API is superior to the current debugfs API in many aspects:
* debugfs is broken (see PATCH 1 for details)
* Netlink is namespace-aware, and can be used in unprivileged containers
without problems
* Netlink packets are more machine-readable than text files, and can be
easily extended without potentially breaking userspace
* On older kernels, seq_file can't fall back to vmalloc if kmalloc fails,
which often leads to OOM when reading "originators" in large meshes, as
the whole file must fit into a single buffer
Of course, are also a few downsides; when the data is too big to fit into
a single netlink packet, the provided data may be inconsistent (entries may
be missing or duplicated.) This will happen in large meshes only, and be
improbable in any case.
The patches have been developed on top of the netns patchset, but should
be applicable independently (maybe with minor changes.)
All netlink queries returning lists of any kind can only be used with
NLM_F_DUMP queries, so that arbitrarity large responses are possible (split
across multiple packets if necessary.)
At the moment, the following debugfs files have corresponding netlink APIs:
* routing_algos
* neighbors
* originators
* transtable_global
* transtable_local
* (hardinterfaces for a softif can be queried)
The following files are still missing:
* gateways
* bla_claim_table
* bla_backbone_table
* dat_cache
* nc_nodes
Obviously, documentation is also a TODO. Comments about the API design are
very welcome...
Regards,
Matthias
Matthias Schiffer (5):
batman-adv: add generic netlink query API to replace debugfs files
batman-adv: netlink: add translation table query
batman-adv: netlink: add originator and neighbor table queries
batman-adv: add B.A.T.M.A.N. IV bat_{orig,neigh}_dump implementations
batman-adv: add B.A.T.M.A.N. V bat_{orig,neigh}_dump implementations
Makefile | 1 +
include/uapi/linux/batman_adv.h | 101 ++++++++++++
net/batman-adv/Makefile | 1 +
net/batman-adv/bat_iv_ogm.c | 268 ++++++++++++++++++++++++++++++++
net/batman-adv/bat_v.c | 250 ++++++++++++++++++++++++++++++
net/batman-adv/main.c | 48 ++++++
net/batman-adv/main.h | 1 +
net/batman-adv/netlink.c | 276 +++++++++++++++++++++++++++++++++
net/batman-adv/netlink.h | 36 +++++
net/batman-adv/originator.c | 142 +++++++++++++++++
net/batman-adv/originator.h | 2 +
net/batman-adv/packet.h | 36 -----
net/batman-adv/translation-table.c | 305 +++++++++++++++++++++++++++++++++++++
net/batman-adv/translation-table.h | 2 +
net/batman-adv/types.h | 7 +
15 files changed, 1440 insertions(+), 36 deletions(-)
create mode 100644 include/uapi/linux/batman_adv.h
create mode 100644 net/batman-adv/netlink.c
create mode 100644 net/batman-adv/netlink.h
--
2.7.3
Hi,
when having Nodes with wired Mesh-Links, or on point-to-point
connections, rebroadcasts on the same interface are unnecessary, because
all Nodes receive the broadcast packets at the same time.
On non-gateway nodes (Freifunk-Routers) running firmware "Gluon", there
is a patch from Linus Lüssing adding the feature/option
"mesh_no_rebroadcast" to batman-adv, which is enabled by default on
mesh_vpn interface. Because of the good experience reducing traffic also
on other wired mesh links (Mesh-on-LAN / Mesh-on-WAN), this option will
also be enabled there by default with the upcoming Gluon v2016.2.
Gatways are not running Gluon, but typically Debian Linux, and there the
option "mesh_no_rebroadcast" does not exist on batban-adv.
Are there some (other) features already implemented in batman-adv to
prevent rebroadcast of unnecessary mesh packets?
If not, what is the chance to have the functionality implemented by the
mentioned patch as part of the original code base?
Background:
At Freifunk-Stuttgart we have multiple distributed gateways connected by
layer2-tinc, which is logically the same situation as using LAN-Cables
and physical Switch. Avoiding rebroadcast will reduce traffic between
the gateways.
Additional info:
On 12.03.2015 Ticket #207 was opened by Ruben Kelevra relating the same
issue, but immediately closed due to formal error.
Best regards,
Roland.
From: Simon Wunderlich <simon.wunderlich(a)open-mesh.com>
There are network setups where the current bridge loop avoidance can't
detect bridge loops. The minimal setup affected would consist of two
LANs and two separate meshes, connected in a ring like that:
A...(mesh1)...B
| |
(LAN1) (LAN2)
| |
C...(mesh2)...D
Since both the meshes and backbones are separate, the bridge loop
avoidance has not enough information to detect and avoid the loop
in this case. Even if these scenarios can't be fixed easily,
these kind of loops can be detected.
This patch implements a periodic check (running every 60 seconds for
now) which sends a broadcast frame with a random MAC address on
each backbone VLAN. If a broadcast frame with the same MAC address
is received shortly after on the mesh, we know that there must be a
loop and report that incident as well as throw an uevent to let others
handle that problem.
Signed-off-by: Simon Wunderlich <simon.wunderlich(a)open-mesh.com>
[sven(a)narfation.org: fix conflicts with current version]
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
v2:
- rebased patch
- fix checkpatch errors
- fix kernel-doc errors
Patch was resurrected from https://patchwork.open-mesh.org/patch/4154/
I've requested an rebased version at
https://lists.open-mesh.org/pipermail/b.a.t.m.a.n/2016-March/014640.html
but done it myself because it was rather trivial.
---
net/batman-adv/bridge_loop_avoidance.c | 139 +++++++++++++++++++++++++++++++++
net/batman-adv/main.h | 4 +
net/batman-adv/packet.h | 1 +
net/batman-adv/sysfs.c | 6 +-
net/batman-adv/types.h | 8 ++
5 files changed, 156 insertions(+), 2 deletions(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 0c951a7..c3b42e6 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -50,6 +50,7 @@
#include "hash.h"
#include "originator.h"
#include "packet.h"
+#include "sysfs.h"
#include "translation-table.h"
static const u8 batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
@@ -407,6 +408,14 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
ethhdr->h_source, ethhdr->h_dest,
BATADV_PRINT_VID(vid));
break;
+ case BATADV_CLAIM_TYPE_LOOPDETECT:
+ ether_addr_copy(ethhdr->h_source, mac);
+ batadv_dbg(BATADV_DBG_BLA, bat_priv,
+ "bla_send_claim(): LOOPDETECT of %pM to %pM on vid %d\n",
+ ethhdr->h_source, ethhdr->h_dest,
+ BATADV_PRINT_VID(vid));
+
+ break;
}
if (vid & BATADV_VLAN_HAS_TAG)
@@ -427,6 +436,36 @@ out:
}
/**
+ * batadv_bla_loopdetect_report - worker for reporting the loop
+ * @work: work queue item
+ *
+ * Throws an uevent, as the loopdetect check function can't do that itself
+ * since the kernel may sleep while throwing uevents.
+ */
+static void batadv_bla_loopdetect_report(struct work_struct *work)
+{
+ struct batadv_bla_backbone_gw *backbone_gw;
+ struct batadv_priv *bat_priv;
+ char vid_str[6] = { '\0' };
+
+ backbone_gw = container_of(work, struct batadv_bla_backbone_gw,
+ report_work);
+ bat_priv = backbone_gw->bat_priv;
+
+ batadv_info(bat_priv->soft_iface,
+ "Possible loop on VLAN %d detected which can't be handled by BLA - please check your network setup!\n",
+ BATADV_PRINT_VID(backbone_gw->vid));
+ snprintf(vid_str, sizeof(vid_str), "%d",
+ BATADV_PRINT_VID(backbone_gw->vid));
+ vid_str[sizeof(vid_str) - 1] = 0;
+
+ batadv_throw_uevent(bat_priv, BATADV_UEV_BLA, BATADV_UEV_LOOPDETECT,
+ vid_str);
+
+ batadv_backbone_gw_put(backbone_gw);
+}
+
+/**
* batadv_bla_get_backbone_gw - finds or creates a backbone gateway
* @bat_priv: the bat priv with all the soft interface information
* @orig: the mac address of the originator
@@ -464,6 +503,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig,
atomic_set(&entry->request_sent, 0);
atomic_set(&entry->wait_periods, 0);
ether_addr_copy(entry->orig, orig);
+ INIT_WORK(&entry->report_work, batadv_bla_loopdetect_report);
/* one for the hash, one for returning */
kref_init(&entry->refcount);
@@ -1060,6 +1100,10 @@ static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
if (vlan_depth > 1)
return true;
+ /* Let the loopdetect frames on the mesh in any case. */
+ if (bla_dst->type == BATADV_CLAIM_TYPE_LOOPDETECT)
+ return 0;
+
/* check if it is a claim frame. */
ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
ethhdr);
@@ -1265,6 +1309,26 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
}
/**
+ * batadv_bla_send_loopdetect - send a loopdetect frame
+ * @bat_priv: the bat priv with all the soft interface information
+ * @backbone_gw: the backbone gateway for which a loop should be detected
+ *
+ * To detect loops that the bridge loop avoidance can't handle, send a loop
+ * detection packet on the backbone. Unlike other BLA frames, this frame will
+ * be allowed on the mesh by other nodes. If it is received on the mesh, this
+ * indicates that there is a loop.
+ */
+static void
+batadv_bla_send_loopdetect(struct batadv_priv *bat_priv,
+ struct batadv_bla_backbone_gw *backbone_gw)
+{
+ batadv_dbg(BATADV_DBG_BLA, bat_priv, "Send loopdetect frame for vid %d\n",
+ backbone_gw->vid);
+ batadv_bla_send_claim(bat_priv, bat_priv->bla.loopdetect_addr,
+ backbone_gw->vid, BATADV_CLAIM_TYPE_LOOPDETECT);
+}
+
+/**
* batadv_bla_status_update - purge bla interfaces if necessary
* @net_dev: the soft interface net device
*/
@@ -1301,6 +1365,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
struct batadv_bla_backbone_gw *backbone_gw;
struct batadv_hashtable *hash;
struct batadv_hard_iface *primary_if;
+ bool send_loopdetect = false;
int i;
delayed_work = container_of(work, struct delayed_work, work);
@@ -1316,6 +1381,22 @@ static void batadv_bla_periodic_work(struct work_struct *work)
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
goto out;
+ if (atomic_dec_and_test(&bat_priv->bla.loopdetect_next)) {
+ /* set a new random mac address for the next bridge loop
+ * detection frames. Set the locally administered bit to avoid
+ * collisions with users mac addresses.
+ */
+ random_ether_addr(bat_priv->bla.loopdetect_addr);
+ bat_priv->bla.loopdetect_addr[0] = 0xba;
+ bat_priv->bla.loopdetect_addr[1] = 0xbe;
+ bat_priv->bla.loopdetect_lasttime = jiffies;
+ atomic_set(&bat_priv->bla.loopdetect_next,
+ BATADV_BLA_LOOPDETECT_PERIODS);
+
+ /* mark for sending loop detect on all VLANs */
+ send_loopdetect = true;
+ }
+
hash = bat_priv->bla.backbone_hash;
if (!hash)
goto out;
@@ -1332,6 +1413,9 @@ static void batadv_bla_periodic_work(struct work_struct *work)
backbone_gw->lasttime = jiffies;
batadv_bla_send_announce(bat_priv, backbone_gw);
+ if (send_loopdetect)
+ batadv_bla_send_loopdetect(bat_priv,
+ backbone_gw);
/* request_sent is only set after creation to avoid
* problems when we are not yet known as backbone gw
@@ -1405,6 +1489,9 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
bat_priv->bla.bcast_duplist_curr = 0;
+ atomic_set(&bat_priv->bla.loopdetect_next,
+ BATADV_BLA_LOOPDETECT_PERIODS);
+
if (bat_priv->bla.claim_hash)
return 0;
@@ -1603,6 +1690,55 @@ void batadv_bla_free(struct batadv_priv *bat_priv)
}
/**
+ * batadv_bla_loopdetect_check - check and handle a detected loop
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the packet to check
+ * @primary_if: interface where the request came on
+ * @vid: the VLAN ID of the frame
+ *
+ * Checks if this packet is a loop detect frame which has been sent by us,
+ * throw an uevent and log the event if that is the case.
+ *
+ * Return: true if it is a loop detect frame which is to be dropped, false
+ * otherwise.
+ */
+static bool
+batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
+ struct batadv_hard_iface *primary_if,
+ unsigned short vid)
+{
+ struct batadv_bla_backbone_gw *backbone_gw;
+ struct ethhdr *ethhdr;
+
+ ethhdr = eth_hdr(skb);
+
+ /* Only check for the MAC address and skip more checks here for
+ * performance reasons - this function is on the hotpath, after all.
+ */
+ if (!batadv_compare_eth(ethhdr->h_source,
+ bat_priv->bla.loopdetect_addr))
+ return false;
+
+ /* If the packet came too late, don't forward it on the mesh
+ * but don't consider that as loop. It might be a coincidence.
+ */
+ if (batadv_has_timed_out(bat_priv->bla.loopdetect_lasttime,
+ BATADV_BLA_LOOPDETECT_TIMEOUT))
+ return true;
+
+ backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
+ primary_if->net_dev->dev_addr,
+ vid, true);
+ if (unlikely(!backbone_gw))
+ return true;
+
+ queue_work(batadv_event_workqueue, &backbone_gw->report_work);
+ /* backbone_gw is unreferenced in the report work function function */
+
+ return true;
+}
+
+/**
* batadv_bla_rx - check packets coming from the mesh.
* @bat_priv: the bat priv with all the soft interface information
* @skb: the frame to be checked
@@ -1635,6 +1771,9 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
goto allow;
+ if (batadv_bla_loopdetect_check(bat_priv, skb, primary_if, vid))
+ goto handled;
+
if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
/* don't allow broadcasts while requests are in flight */
if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index e602408..70a0cc2 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -120,6 +120,8 @@
#define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 6)
#define BATADV_BLA_CLAIM_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 10)
#define BATADV_BLA_WAIT_PERIODS 3
+#define BATADV_BLA_LOOPDETECT_PERIODS 6
+#define BATADV_BLA_LOOPDETECT_TIMEOUT 3000 /* 3 seconds */
#define BATADV_DUPLIST_SIZE 16
#define BATADV_DUPLIST_TIMEOUT 500 /* 500 ms */
@@ -142,10 +144,12 @@ enum batadv_uev_action {
BATADV_UEV_ADD = 0,
BATADV_UEV_DEL,
BATADV_UEV_CHANGE,
+ BATADV_UEV_LOOPDETECT,
};
enum batadv_uev_type {
BATADV_UEV_GW = 0,
+ BATADV_UEV_BLA,
};
#define BATADV_GW_THRESHOLD 50
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 8a8d7ca..15d2117 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -175,6 +175,7 @@ enum batadv_bla_claimframe {
BATADV_CLAIM_TYPE_UNCLAIM = 0x01,
BATADV_CLAIM_TYPE_ANNOUNCE = 0x02,
BATADV_CLAIM_TYPE_REQUEST = 0x03,
+ BATADV_CLAIM_TYPE_LOOPDETECT = 0x04,
};
/**
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index e7cf513..fffa230 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -116,11 +116,13 @@ batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
static char *batadv_uev_action_str[] = {
"add",
"del",
- "change"
+ "change",
+ "loopdetect",
};
static char *batadv_uev_type_str[] = {
- "gw"
+ "gw",
+ "bla",
};
/* Use this, if you have customized show and store functions for vlan attrs */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 9abfb3e..cd5a070 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -655,6 +655,9 @@ struct batadv_priv_tt {
* @num_requests: number of bla requests in flight
* @claim_hash: hash table containing mesh nodes this host has claimed
* @backbone_hash: hash table containing all detected backbone gateways
+ * @loopdetect_addr: MAC address used for own loopdetection frames
+ * @loopdetect_lasttime: time when the loopdetection frames were sent
+ * @loopdetect_next: how many periods to wait for the next loopdetect process
* @bcast_duplist: recently received broadcast packets array (for broadcast
* duplicate suppression)
* @bcast_duplist_curr: index of last broadcast packet added to bcast_duplist
@@ -666,6 +669,9 @@ struct batadv_priv_bla {
atomic_t num_requests;
struct batadv_hashtable *claim_hash;
struct batadv_hashtable *backbone_hash;
+ u8 loopdetect_addr[ETH_ALEN];
+ unsigned long loopdetect_lasttime;
+ atomic_t loopdetect_next;
struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
int bcast_duplist_curr;
/* protects bcast_duplist & bcast_duplist_curr */
@@ -1010,6 +1016,7 @@ struct batadv_socket_packet {
* resolved
* @crc: crc16 checksum over all claims
* @crc_lock: lock protecting crc
+ * @report_work: work struct for reporting detected loops
* @refcount: number of contexts the object is used
* @rcu: struct used for freeing in an RCU-safe manner
*/
@@ -1023,6 +1030,7 @@ struct batadv_bla_backbone_gw {
atomic_t request_sent;
u16 crc;
spinlock_t crc_lock; /* protects crc */
+ struct work_struct report_work;
struct kref refcount;
struct rcu_head rcu;
};
--
2.7.0
From: Antonio Quartulli <a(a)unstable.cc>
Now that DAT is VLAN aware, it must use the VID when
computing the DHT address of the candidate nodes where
an entry is going to be stored/retrieved.
Fixes: 3e26722bc9f2 ("batman-adv: make the Distributed ARP Table vlan aware")
Signed-off-by: Antonio Quartulli <a(a)unstable.cc>
[sven(a)narfation.org: fix conflicts with current version]
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
v2:
- rebased patch
- added kernel-doc for new parameters
Patch was resurrected from https://patchwork.open-mesh.org/patch/3427/
I've requested an rebased version at
https://lists.open-mesh.org/pipermail/b.a.t.m.a.n/2016-March/014636.html
but done it myself because it was rather trivial.
---
net/batman-adv/distributed-arp-table.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 771708c..3b7b141 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -568,6 +568,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
* be sent to
* @bat_priv: the bat priv with all the soft interface information
* @ip_dst: ipv4 to look up in the DHT
+ * @vid: VLAN identifier
*
* An originator O is selected if and only if its DHT_ID value is one of three
* closest values (from the LEFT, with wrap around if needed) then the hash
@@ -576,7 +577,8 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
* Return: the candidate array of size BATADV_DAT_CANDIDATE_NUM.
*/
static struct batadv_dat_candidate *
-batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
+batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
+ unsigned short vid)
{
int select;
batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
@@ -592,7 +594,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
return NULL;
dat.ip = ip_dst;
- dat.vid = 0;
+ dat.vid = vid;
ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat,
BATADV_DAT_ADDR_MAX);
@@ -612,6 +614,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
* @bat_priv: the bat priv with all the soft interface information
* @skb: payload to send
* @ip: the DHT key
+ * @vid: VLAN identifier
* @packet_subtype: unicast4addr packet subtype to use
*
* This function copies the skb with pskb_copy() and is sent as unicast packet
@@ -622,7 +625,7 @@ 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,
- int packet_subtype)
+ unsigned short vid, int packet_subtype)
{
int i;
bool ret = false;
@@ -631,7 +634,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
struct sk_buff *tmp_skb;
struct batadv_dat_candidate *cand;
- cand = batadv_dat_select_candidates(bat_priv, ip);
+ cand = batadv_dat_select_candidates(bat_priv, ip, vid);
if (!cand)
goto out;
@@ -1022,7 +1025,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
ret = true;
} else {
/* Send the request to the DHT */
- ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
+ ret = batadv_dat_send_data(bat_priv, skb, ip_dst, vid,
BATADV_P_DAT_DHT_GET);
}
out:
@@ -1150,8 +1153,8 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
/* Send the ARP reply to the candidates for both the IP addresses that
* the node obtained from the ARP reply
*/
- batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
- batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT);
}
/**
--
2.7.0
From: Linus Lüssing <linus.luessing(a)c0d3.blue>
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.
Fixes: d5bbce8465af ("batman-adv: Add missing hardif_free_ref in forw_packet_free")
Signed-off-by: Linus Lüssing <linus.luessing(a)c0d3.blue>
[sven(a)narfation.org: fix conflicts with current version]
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
v2:
- rebased patch
Patch was resurrected from https://patchwork.open-mesh.org/patch/2921/
I've requested an rebased version at
https://lists.open-mesh.org/pipermail/b.a.t.m.a.n/2016-March/014635.html
but done it myself because it was rather trivial.
---
net/batman-adv/send.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 3ce06e0..7641785 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -675,6 +675,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);
}
}
@@ -702,6 +705,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);
}
}
--
2.7.0
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
Hi
I'm using the latest batmand with ns-3 to test routing.
I'm a bit of a newbie with this stuff, so this might be really simple
I'm not getting a ping through to 10.1.4.2, from a node that has this in its routing table
ip route ls table 66
10.1.4.2 via 10.1.2.2 dev eth 0 proto static src 10.1.2.3
// and so on
I'm guessing it's because of this
ip rule
0: from all lookup local
6600: from all to 10.1.2.0/24 lookup 66
6699: from all lookup 65
6700: from all to 10.1.2.0/24 lookup 67
32766: from all lookup main
32767: from all lookup default
It isn't being told to look for the route to 10.1.4.2 from the table 66 where the route is stored.
-mika
The number of rebroadcasts are currently not differenciated between
re-broadcasts on the same interface and the re-broadcasts on a different
interface. This differenciation can be important when the link medium
already guarantees to some extend that a packet received by one participant
is also received by all other participants.
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
net/batman-adv/hard-interface.c | 10 +++++++---
net/batman-adv/main.h | 3 ++-
net/batman-adv/send.c | 8 +++++++-
net/batman-adv/types.h | 8 ++++++--
4 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index f41b472..a8385fa 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -678,9 +678,13 @@ batadv_hardif_add_interface(struct net_device *net_dev)
spin_lock_init(&hard_iface->neigh_list_lock);
- hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
- if (batadv_is_wifi_netdev(net_dev))
- hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
+ if (batadv_is_wifi_netdev(net_dev)) {
+ hard_iface->num_bcasts_sameif = BATADV_NUM_BCASTS_WIRELESS;
+ hard_iface->num_bcasts_otherif = BATADV_NUM_BCASTS_WIRELESS;
+ } else {
+ hard_iface->num_bcasts_sameif = BATADV_NUM_BCASTS_SAMEIF;
+ hard_iface->num_bcasts_otherif = BATADV_NUM_BCASTS_OTHERIF;
+ }
/* extra reference for return */
kref_init(&hard_iface->refcount);
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 1565df0..aad4a3a 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -96,7 +96,8 @@
#define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */
/* number of packets to send for broadcasts on different interface types */
-#define BATADV_NUM_BCASTS_DEFAULT 1
+#define BATADV_NUM_BCASTS_SAMEIF 1
+#define BATADV_NUM_BCASTS_OTHERIF 1
#define BATADV_NUM_BCASTS_WIRELESS 3
#define BATADV_NUM_BCASTS_MAX 3
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 2e8433b..724bd6e 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -552,6 +552,7 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
struct sk_buff *skb1;
struct net_device *soft_iface;
struct batadv_priv *bat_priv;
+ u8 num_bcasts;
delayed_work = to_delayed_work(work);
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
@@ -575,7 +576,12 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
if (hard_iface->soft_iface != soft_iface)
continue;
- if (forw_packet->num_packets >= hard_iface->num_bcasts)
+ if (forw_packet->skb->dev == hard_iface->net_dev)
+ num_bcasts = hard_iface->num_bcasts_sameif;
+ else
+ num_bcasts = hard_iface->num_bcasts_otherif;
+
+ if (forw_packet->num_packets >= num_bcasts)
continue;
if (!kref_get_unless_zero(&hard_iface->refcount))
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 9abfb3e..5e80113 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -122,7 +122,10 @@ struct batadv_hard_iface_bat_v {
* @if_num: identificator of the interface
* @if_status: status of the interface for batman-adv
* @net_dev: pointer to the net_device
- * @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
+ * @num_bcasts_sameif: number of payload re-broadcasts on this interface (ARQ)
+ * when the packet was received on this interface
+ * @num_bcasts_otherif: number of payload re-broadcasts on this interface (ARQ)
+ * when the packet was received on a different interface
* @hardif_obj: kobject of the per interface sysfs "mesh" directory
* @refcount: number of contexts the object is used
* @batman_adv_ptype: packet type describing packets that should be processed by
@@ -141,7 +144,8 @@ struct batadv_hard_iface {
s16 if_num;
char if_status;
struct net_device *net_dev;
- u8 num_bcasts;
+ u8 num_bcasts_sameif;
+ u8 num_bcasts_otherif;
struct kobject *hardif_obj;
struct kref refcount;
struct packet_type batman_adv_ptype;
--
2.8.0.rc3