This patchset enables the usage of the batman-adv multicast optimizations
for scenarios involving bridges on top of e.g. bat0, too.
The first one alters the forwarding behaviour for IGMP and MLD reports
which is a prerequisite before enabling multicast optimizations in
bridged setups. It also increases the MCAST TVLV version number to 2.
More on the issue of insufficient report handling with the v1
MCAST TVLV can be found here:
http://www.open-mesh.org/projects/batman-adv/wiki/Multicast-optimizations-l…
The second patch finally enables the multicast optimizations for
bridged setups.
Along come two more patches adding according debugging facilities
to make it possible for the user to check why the multicast
optimizations might not work ideally to give hints about
what they might change about their topology.
This patchset can be found in the current linus/multicast-bridge
branch.
Cheers, Linus
-----
Thanks for the many valuable feedback at the battlemesh and beyond!
Changes in v11:
* Rewording of commit messages (PATCH 1/4+2/4)
* Rebasing to master (solving conflict with kernel doc "return" changes)
* Updating kerneldoc to proper "Return:" syntax
* Using eth_zero_addr() over memset (fixes a new checkpatch warning)
* Changing uint8_t to u8 and uint32_t to u32 (fixes new checkpatch warnings)
* Turning some batadv_dbg() into batadv_info(), making querier presence more
visible (i.e. in dmesg too) (PATCH 3/4)
Changes in v10:
- PATCH 1/4:
* Former "[PATCH 4/4] batman-adv: Forward IGMP/MLD reports to selected querier (only)"
substituted by the interim branch "batman-adv: Always flood IGMP/MLD reports"
with the following changes:
* Increased compatibility to mcast-v1-tvlv nodes by
registering a v1 tvlv container and handler, too
(note: PATCH 2/4 needs to still unregister the handler
if the node is bridged bc. it can't "trust" v1 nodes)
* Removed skb_set_network_header() call
(extra patch pending for review for maint)
* Compared to patchset v9 this substitution makes things
compilable again for kernels < 2.6.35
- PATCH 2/4:
* Moved enum introduction of BATADV_DBG_MCAST to PATCH 3/4,
not needed in PATCH 2/4 yet
* Adjusted compat code to new compat layout
* Adjustments to batadv_mcast_mla_tvlv_update() to fit now
preceding PATCH 1/4
* bat_priv->mcast.bridged flag already introduced here
(instead of in PATCH 3/4) because we need it for the new
mcast-v1-tvlv handling
---
Interim Changlog of
"batman-adv: Always flood IGMP/MLD reports"
v1:
* Removed query snooping and state
* Squashed all three patches into one
* Renamed "batadv_mcast_tvlv_ogm_handler_v1()" to *_v2()
* Added explicit icmpv6.h include
* Rebased on top of master
-----
Interim Interim Changelog of
"batman-adv: Unicasting multicast reports to querier-node only"
v6:
* compat: copied copyright headers from original upstream c files
* compat: unified ordering in compat c files:
-> copyright header, then includes, then kernel specific functions
v5:
* Removed RFC tag: Needed exports got merged to net-next and are going to
be available with Linux 4.2
* Redid compat solution - now fully backwards compatible down to 2.6.33
v4:
* excluded bridge part from this patchset, they should
hopefully be added to net-next soon
* Added a compat solution (PATCH 3/3)
* Removed Kconfig-depends as by David's suggestion the needed parsing
functions for MLD are going to be forced built-ins even if IPv6 is
going to be built as a module
* Removed unused variable 'int ret' in batadv_mcast_is_report_ipv6()
* Adjusted to new folder structure
v3:
* Adding Kconfig-depends and #if's
(so basically adding similar dependancy constraints as the bridge code
has, except that there are no depends if batman-adv gets compiled without
multicast optimizations)
-> the case of IPv6=M and batman-adv=y is still impossible if multicast
optimizations are enabled; but I don't see the practical demand for that
either - people who use IPv6 as a module will probably also want to
use batman-adv as a module
v2:
* various bugfixes (now runtime tested, too - should(tm) work)
* added netdev+bridge mailinglists
-----
---
Changes in v9:
- PATCH 1/4:
* fix: added compat code for pr_warn_once()
* compat fix for bridge export stubs: fixes compile error
with kernels < 3.16 without bridge (snooping) support
- PATCH 2/4:
* perform updates of variables within bat_priv->mcast.querier_ipv{4,6}
individually (there's a new, third member in 4/4 which shouldn't be
overriden)
* PATCH 4/4: NEW
Changes in v8 (thanks to Simon's suggestions):
- PATCH 2/3:
* print shadowing status log of an appearing and shadowing querier, too
(the bridge-querier-existence call has an additional 10s delay
to ensure reports had their time to arrive -
the bridge-querier-port call doesn't have that)
- PATCH 3/3:
* changing debugfs output from "+" and "-" to "U/4/6" and "."
* fixing "no querier present" logic (introduced in [PATCHv7 3/3])
Changes in v7 (thanks to Simon's suggestions):
- PATCH 2/3:
* renaming old/new_querier to old/new_state
* slightly extended kerneldoc of batadv_mcast_querier_log()
* removing words "good" and "bad" from debug output
* simplified batadv_mcast_flags_log()
* assignment instead of memset in batadv_mcast_mla_tvlv_update()
and batadv_softif_init_late()
* simple struct member assignments instead of one complex struct
assigment
* removing unnecessary memcmp's
* substituting return statement for an if-block in
batadv_mcast_querier_log() and batadv_mcast_bridge_log()
* print "Unsnoopables(U)-flag" instead of just "U-flag"
- PATCH 3/3:
* use bat_priv values instead of querying bridge ABI in
batadv_mcast_flags_print_header()
Changes in v6:
* New PATCH 2/3 inserted, moving logging to separate patch
* More verbose logging added to PATCH 2/3:
Bridge and querier state changes are logged too
* upper case to lower case for kernel doc of batadv_mcast_flags_open
(PATCH 2/3)
* Adding note to kernel doc of batadv_mcast_get_bridge about
increased refcount (PATCH 1/3)
* Printing some lines about current bridge and querier state to
debugfs too (PATCH 3/3)
Changes in v5 (PATCH 2/2 only):
* s/dat_cache/mcast_flags/ in kerneldoc (copy&paste error)
Changes in v4 (PATCH 2/2 only):
* initial {ad,e}dition of this patch
Changes in v3 (PATCH 1/2 only):
* Removed "RFC" tag in title again: The stubs and new export are upstream
in net-next and therefore going to be included in 3.17
* Added some debug output:
* Two warning messages:
-> Old kernel version or no bridge IGMP/MLD snooping compiled
* New batman-adv log-level "mcast":
-> Logging mcast flag changes
(a third debugging facility, a new table for debugfs for a global
mcast flag overview will be added in a separate patch later
as discussed with Simon)
Changes in v2 (PATCH 1/2 only):
* fetching local (= on this same kernel) multicast listeners from
the bridge instead of the bat0 interface if a bridge is present
- just like ip addresses and routes should be used from br0, the
same goes for multicast listeners
* beautification of batadv_mcast_mla_br_addr_cpy(), now using already
present functions from the kernel instead of own, hackish approach
* changed names of some goto-labels (not using "skip" anymore)
* using new, third bridge multicast export (because this export is
not upstream yet, I've added the "RFC" in the title):
br_multicast_has_querier_anywhere()
* adding compat stubs for two bridge multicast exports, to make
batman-adv compile- and usable even if a 3.16 kernel was compiled
without bridge code - the stubs are supposed to be upstream in the
bridge code in 3.17 (therefore just 'compat')
* updated kerneldocs for batadv_mcast_mla_bridge_get() and
batadv_mcast_mla_softif_get()
* The two sentences in the commit message starting with "Queriers: ..."
were slightly modified to include the third bridge multicast export
From: Simon Wunderlich <simon(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(a)open-mesh.com>
---
bridge_loop_avoidance.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++
main.h | 4 ++
packet.h | 1 +
sysfs.c | 6 ++-
types.h | 8 +++
5 files changed, 155 insertions(+), 2 deletions(-)
diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c
index 0f0ca43..db88b5f 100644
--- a/bridge_loop_avoidance.c
+++ b/bridge_loop_avoidance.c
@@ -22,6 +22,7 @@
#include "bridge_loop_avoidance.h"
#include "translation-table.h"
#include "send.h"
+#include "sysfs.h"
#include <linux/etherdevice.h>
#include <linux/crc16.h>
@@ -340,6 +341,14 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *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)
@@ -360,6 +369,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_free_ref(backbone_gw);
+}
+
+/**
* batadv_bla_get_backbone_gw
* @bat_priv: the bat priv with all the soft interface information
* @orig: the mac address of the originator
@@ -397,6 +436,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *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 */
atomic_set(&entry->refcount, 2);
@@ -943,6 +983,10 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
if (vlan_depth > 1)
return 1;
+ /* 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);
@@ -1142,6 +1186,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);
+}
+
/* periodic work to do:
* * purge structures when they are too old
* * send announcements
@@ -1155,6 +1219,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);
@@ -1170,6 +1235,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;
@@ -1186,6 +1267,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
@@ -1254,6 +1338,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;
@@ -1449,6 +1536,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.
+ *
+ * Returns 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
* @bat_priv: the bat priv with all the soft interface information
* @skb: the frame to be checked
@@ -1480,6 +1616,8 @@ int 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 */
diff --git a/main.h b/main.h
index 4c557eb..d109434 100644
--- a/main.h
+++ b/main.h
@@ -112,6 +112,8 @@
#define BATADV_BLA_BACKBONE_TIMEOUT (BATADV_BLA_PERIOD_LENGTH * 3)
#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 */
@@ -134,10 +136,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/packet.h b/packet.h
index 34e096d..9df747a 100644
--- a/packet.h
+++ b/packet.h
@@ -169,6 +169,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/sysfs.c b/sysfs.c
index fc47baa..8150f77 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -94,11 +94,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/types.h b/types.h
index 462a70c..7456928 100644
--- a/types.h
+++ b/types.h
@@ -536,6 +536,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
@@ -548,6 +551,9 @@ struct batadv_priv_bla {
atomic_t num_requests;
struct batadv_hashtable *claim_hash;
struct batadv_hashtable *backbone_hash;
+ uint8_t 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 */
@@ -866,6 +872,7 @@ struct batadv_socket_packet {
* backbone gateway - no bcast traffic is formwared until the situation was
* resolved
* @crc: crc16 checksum over all claims
+ * @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
*/
@@ -879,6 +886,7 @@ struct batadv_bla_backbone_gw {
atomic_t wait_periods;
atomic_t request_sent;
uint16_t crc;
+ struct work_struct report_work;
atomic_t refcount;
struct rcu_head rcu;
};
--
2.1.0.rc1
When comparing Ethernet address it is better to use the more
generic batadv_compare_eth. The latter is also optimised for
architectures having a fast unaligned access.
Signed-off-by: Antonio Quartulli <antonio(a)meshcoding.com>
---
network-coding.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/network-coding.c b/network-coding.c
index f1b604d..0049e7a 100644
--- a/network-coding.c
+++ b/network-coding.c
@@ -481,12 +481,10 @@ static int batadv_nc_hash_compare(const struct hlist_node *node,
nc_path2 = data2;
/* Return 1 if the two keys are identical */
- if (memcmp(nc_path1->prev_hop, nc_path2->prev_hop,
- sizeof(nc_path1->prev_hop)) != 0)
+ if (!batadv_compare_eth(nc_path1->prev_hop, nc_path2->prev_hop))
return 0;
- if (memcmp(nc_path1->next_hop, nc_path2->next_hop,
- sizeof(nc_path1->next_hop)) != 0)
+ if (!batadv_compare_eth(nc_path1->next_hop, nc_path2->next_hop))
return 0;
return 1;
--
1.8.5.2
If none of the backbone gateways in a bla setup has already knowledge of
the mac address searched for in an incoming ARP request from the backbone
it must be prevented that multiple ARP replies are generated and returned
to the backbone by the dat address resolution mechanism of other dat
enabled nodes of the mesh.
Signed-off-by: Andreas Pape <apape(a)phoenixcontact.com>
---
net/batman-adv/distributed-arp-table.c | 65 +++++++++++++++++++++++++++++++-
1 files changed, 64 insertions(+), 1 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 0f899b9..f60fccb 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -1081,6 +1081,8 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
u8 *hw_src;
struct sk_buff *skb_new;
struct batadv_dat_entry *dat_entry = NULL;
+ struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+ struct batadv_orig_node *orig_node = NULL;
bool ret = false;
unsigned short vid;
int err;
@@ -1104,8 +1106,38 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
- if (!dat_entry)
+ if (!dat_entry) {
+ /* Check if this is a 4addr unicast DAT_DHT_GET frame from
+ * another backbone gw of the same backbone. If yes, drop
+ * it as this leads to multiplication of arp requests in bla
+ * setups as long as there is no dat_entry fo this answer.
+ * In this case better drop the DHT_GET. Normal bla code
+ * doesn't take care of these packets as they are tunneled
+ * via unicast.
+ */
+ unicast_4addr_packet =
+ (struct batadv_unicast_4addr_packet *)skb->data;
+ orig_node =
+ batadv_orig_hash_find(bat_priv,
+ unicast_4addr_packet->src);
+ if (orig_node) {
+ if ((unicast_4addr_packet->u.packet_type ==
+ BATADV_UNICAST_4ADDR) &&
+ (unicast_4addr_packet->subtype ==
+ BATADV_P_DAT_DHT_GET) &&
+ (batadv_bla_is_backbone_gw(skb, orig_node,
+ hdr_size))) {
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "Doubled ARP request removed: ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]; originator: %pM\n",
+ hw_src, &ip_src,
+ batadv_arp_hw_dst(skb, hdr_size),
+ &ip_dst, unicast_4addr_packet->src);
+ ret = true;
+ }
+ batadv_orig_node_put(orig_node);
+ }
+
goto out;
+ }
skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
bat_priv->soft_iface, ip_dst, hw_src,
@@ -1204,6 +1236,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
__be32 ip_src, ip_dst;
u8 *hw_src, *hw_dst;
bool dropped = false;
+ struct batadv_dat_entry *dat_entry = NULL;
unsigned short vid;
if (!atomic_read(&bat_priv->distributed_arp_table))
@@ -1223,12 +1256,40 @@ bool batadv_dat_snoop_incoming_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);
+ /* If ip_dst is already in cache and has the right mac address,
+ * drop this frame if this ARP reply is destined for us. We have
+ * most probably received already a reply from someone else. Delivering
+ * this frame would lead to doubled receive of an ARP reply.
+ */
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_src, vid);
+ if ((dat_entry) && (batadv_compare_eth(hw_src, dat_entry->mac_addr))) {
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "Doubled ARP reply removed: ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]; dat_entry: %pM-%pI4\n",
+ hw_src, &ip_src, hw_dst, &ip_dst,
+ dat_entry->mac_addr, &dat_entry->ip);
+ dropped = true;
+ goto out;
+ }
+
/* 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);
+ /* 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
+ * already claimed that client. This prevents that different gateways
+ * to the same backbone all forward the ARP reply leading to multiple
+ * replies in the backbone.
+ */
+ if (!batadv_bla_handle_local_claim(bat_priv, hw_src, vid)) {
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "Device %pM claimed by another backbone gw. Drop ARP reply.\n",
+ hw_src);
+ dropped = true;
+ goto out;
+ }
+
/* if this REPLY is directed to a client of mine, let's deliver the
* packet to the interface
*/
@@ -1241,6 +1302,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
out:
if (dropped)
kfree_skb(skb);
+ if (dat_entry)
+ batadv_dat_entry_put(dat_entry);
/* if dropped == false -> deliver to the interface */
return dropped;
}
--
1.7.0.4
..................................................................
PHOENIX CONTACT ELECTRONICS GmbH
Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
USt-Id-Nr.: DE811742156
Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
___________________________________________________________________
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren, jegliche anderweitige Verwendung sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
----------------------------------------------------------------------------------------------------
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden.
___________________________________________________________________
Additional dropping of unicast packets received from another backbone gw of
the same backbone network before being forwarded to the same backbone again
is necessary. It was observed in a test setup that in rare cases these
frames lead to looping unicast traffic backbone->mesh->backbone.
Signed-off-by: Andreas Pape <apape(a)phoenixcontact.com>
---
net/batman-adv/routing.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 4dd646a..606fd22 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -854,9 +854,11 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
int check, hdr_size = sizeof(*unicast_packet);
enum batadv_subtype subtype;
bool is4addr;
+ struct ethhdr *ethhdr;
unicast_packet = (struct batadv_unicast_packet *)skb->data;
unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+ ethhdr = eth_hdr(skb);
is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
/* the caller function should have already pulled 2 bytes */
@@ -896,6 +898,19 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
}
}
+ /* If this is a unicast packet from another backgone gw,
+ * drop it.
+ */
+ orig_addr = ethhdr->h_source;
+ orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
+ if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) {
+ batadv_dbg(BATADV_DBG_BLA, bat_priv,
+ "Dropped unicast pkt received from another backbone gw %pM.\n",
+ orig_addr);
+
+ return NET_RX_DROP;
+ }
+
if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
hdr_size))
goto rx_success;
--
1.7.0.4
..................................................................
PHOENIX CONTACT ELECTRONICS GmbH
Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
USt-Id-Nr.: DE811742156
Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
___________________________________________________________________
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren, jegliche anderweitige Verwendung sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
----------------------------------------------------------------------------------------------------
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden.
___________________________________________________________________
Some of the bla debug messages are extended and additional messages are
added for easier bla debugging. Some debug messages introduced with the
dat changes in prior patches of this patch series have been changed to
be more compliant to other existing debug messages.
Signed-off-by: Andreas Pape <apape(a)phoenixcontact.com>
---
net/batman-adv/bridge_loop_avoidance.c | 22 ++++++++++++++++------
net/batman-adv/routing.c | 2 +-
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 07dba86..739f80f 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -675,8 +675,8 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
goto claim_free_ref;
batadv_dbg(BATADV_DBG_BLA, bat_priv,
- "bla_add_claim(): changing ownership for %pM, vid %d\n",
- mac, BATADV_PRINT_VID(vid));
+ "bla_add_claim(): changing ownership for %pM, vid %d to gw %pM\n",
+ mac, BATADV_PRINT_VID(vid), backbone_gw->orig);
spin_lock_bh(&claim->backbone_gw->crc_lock);
claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
@@ -1196,10 +1196,13 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
continue;
batadv_dbg(BATADV_DBG_BLA, bat_priv,
- "bla_purge_claims(): %pM, vid %d, time out\n",
+ "bla_purge_claims(): timed out.\n");
+
+purge_now:
+ batadv_dbg(BATADV_DBG_BLA, bat_priv,
+ "bla_purge_claims(): %pM, vid %d\n",
claim->addr, claim->vid);
-purge_now:
batadv_handle_unclaim(bat_priv, primary_if,
claim->backbone_gw->orig,
claim->addr, claim->vid);
@@ -1647,9 +1650,16 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
/* possible optimization: race for a claim */
/* 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);
+ primary_if->net_dev->dev_addr,
+ ethhdr->h_source, vid);
goto allow;
}
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 606fd22..5ac55e4 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -905,7 +905,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) {
batadv_dbg(BATADV_DBG_BLA, bat_priv,
- "Dropped unicast pkt received from another backbone gw %pM.\n",
+ "recv_unicast_packet(): Dropped unicast pkt received from another backbone gw %pM.\n",
orig_addr);
return NET_RX_DROP;
--
1.7.0.4
..................................................................
PHOENIX CONTACT ELECTRONICS GmbH
Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
USt-Id-Nr.: DE811742156
Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
___________________________________________________________________
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren, jegliche anderweitige Verwendung sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
----------------------------------------------------------------------------------------------------
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden.
___________________________________________________________________
Make sure that claiming of devices due to dat handling is only done
for non-local mac addresses. As dat is handled after the normal bla
code this does not break the roaming client scenario for bla.
Signed-off-by: Andreas Pape <apape(a)phoenixcontact.com>
---
net/batman-adv/bridge_loop_avoidance.c | 18 ++++++++++++------
1 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 739f80f..32a6168 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1959,13 +1959,19 @@ bool batadv_bla_handle_local_claim(struct batadv_priv *bat_priv,
primary_if->net_dev->dev_addr))
ret = false;
} else {
- /* If there is no claim, claim the device */
- batadv_dbg(BATADV_DBG_BLA, bat_priv,
- "Handle claim locally for currently not claimed mac %pM.\n",
- search_claim.addr);
+ /* If there is no claim, claim the device
+ * but only if this isn't a mac address
+ * out of the local tt
+ */
+ if (!batadv_is_my_client(bat_priv, addr, vid)) {
+ batadv_dbg(BATADV_DBG_BLA, bat_priv,
+ "bla_handle_local_claim(): Handle claim locally for currently not claimed mac %pM.\n",
+ search_claim.addr);
- batadv_handle_claim(bat_priv, primary_if,
- primary_if->net_dev->dev_addr, addr, vid);
+ batadv_handle_claim(bat_priv, primary_if,
+ primary_if->net_dev->dev_addr,
+ addr, vid);
+ }
}
out:
--
1.7.0.4
..................................................................
PHOENIX CONTACT ELECTRONICS GmbH
Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
USt-Id-Nr.: DE811742156
Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
___________________________________________________________________
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren, jegliche anderweitige Verwendung sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
----------------------------------------------------------------------------------------------------
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden.
___________________________________________________________________