Included change:
- fix "rtnl locked" concurrent executions by using rtnl_lock instead of rtnl_trylock. This fix enables batman-adv initialisation to do not fail just because somewhere else in the system another code path is holding the rtnl lock. It is easy to see the problem when batman-adv is trying to start together with other networking components. - fix the routing protocol forwarding policy by enhancing the duplicate control packet detection. When the right circumstances trigger the issue, some nodes in the network become totally unreachable, so breaking the mesh connectivity. - fix the Bridge Loop Avoidance component by not running the originator address change handling routine when the component is disabled. The routine was generating useless packets that were sent over the network. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABCAAGBQJRtkFtAAoJEADl0hg6qKeOBHUP/1Ni8juzvoQwR/gYjq0p2lHM LvkZ/KI74QP96rfDog+nhP9fcOgjSt2MF+sSa6is92RavrKFZQyO2J/GKkrHu2HA gaLKxN6S28Hi2qVbVXgSqT9RQ3XvpzIaojtNvb0tC1onzGzLtd6V5FURIq0FRHvN RvP4w+1HwH2CsQlgjQq1OPwUllVqTUzGYH0fl/U+0mw7h+q0ZWCA1IZln/t08xjl ViCCydbD1Th2tgK7uzFg8X3EJZN1CkrBWflb7X3YK5zeps1NC+l4OuUOK+K2L+fx vCMu603FXKi+SjM24d+eGJx6kQPCapYThIrp1qy43SLkNazRIAmgbZpndme0QP/8 eSUozWAusWIESJI3Krneh3i70agMeg2MK4nAp51z54j52urDlOGURyNf7TkieaT4 Vti5QG0poXncIb1XQ+yaKDCORwkn18QjmtfNmCCgT2YF91pOSYCrlgONi65K6DIs F4eDk7sTgHAIgYO/XEet/V5p06SO86ksF/C13Dqug64s3rkw9ejqgLZBEy3OH1AF IFgws3qE6GiSiXLMiiheplBYD51au+V1Jihqvw/lo2JzlOw4PRNRYsaQgVaUH/MJ jupEjA8V0swMtDIi6ixcPE/P60OJR41VuT8gVGWbrTKnHZ0yyIfgZwPcLZaQ2X0e EIlTJdtS7lVpleZ2C/H1 =oGCV -----END PGP SIGNATURE----- Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge Included change: - fix "rtnl locked" concurrent executions by using rtnl_lock instead of rtnl_trylock. This fix enables batman-adv initialisation to do not fail just because somewhere else in the system another code path is holding the rtnl lock. It is easy to see the problem when batman-adv is trying to start together with other networking components. - fix the routing protocol forwarding policy by enhancing the duplicate control packet detection. When the right circumstances trigger the issue, some nodes in the network become totally unreachable, so breaking the mesh connectivity. - fix the Bridge Loop Avoidance component by not running the originator address change handling routine when the component is disabled. The routine was generating useless packets that were sent over the network. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e86c986137
3 changed files with 60 additions and 35 deletions
|
@ -29,6 +29,21 @@
|
|||
#include "bat_algo.h"
|
||||
#include "network-coding.h"
|
||||
|
||||
/**
|
||||
* batadv_dup_status - duplicate status
|
||||
* @BATADV_NO_DUP: the packet is a duplicate
|
||||
* @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the
|
||||
* neighbor)
|
||||
* @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor
|
||||
* @BATADV_PROTECTED: originator is currently protected (after reboot)
|
||||
*/
|
||||
enum batadv_dup_status {
|
||||
BATADV_NO_DUP = 0,
|
||||
BATADV_ORIG_DUP,
|
||||
BATADV_NEIGH_DUP,
|
||||
BATADV_PROTECTED,
|
||||
};
|
||||
|
||||
static struct batadv_neigh_node *
|
||||
batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
|
||||
const uint8_t *neigh_addr,
|
||||
|
@ -650,7 +665,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
|
|||
const struct batadv_ogm_packet *batadv_ogm_packet,
|
||||
struct batadv_hard_iface *if_incoming,
|
||||
const unsigned char *tt_buff,
|
||||
int is_duplicate)
|
||||
enum batadv_dup_status dup_status)
|
||||
{
|
||||
struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
|
@ -676,7 +691,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (is_duplicate)
|
||||
if (dup_status != BATADV_NO_DUP)
|
||||
continue;
|
||||
|
||||
spin_lock_bh(&tmp_neigh_node->lq_update_lock);
|
||||
|
@ -718,7 +733,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
|
|||
neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv);
|
||||
spin_unlock_bh(&neigh_node->lq_update_lock);
|
||||
|
||||
if (!is_duplicate) {
|
||||
if (dup_status == BATADV_NO_DUP) {
|
||||
orig_node->last_ttl = batadv_ogm_packet->header.ttl;
|
||||
neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
|
||||
}
|
||||
|
@ -902,15 +917,16 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* processes a batman packet for all interfaces, adjusts the sequence number and
|
||||
* finds out whether it is a duplicate.
|
||||
* returns:
|
||||
* 1 the packet is a duplicate
|
||||
* 0 the packet has not yet been received
|
||||
* -1 the packet is old and has been received while the seqno window
|
||||
* was protected. Caller should drop it.
|
||||
/**
|
||||
* batadv_iv_ogm_update_seqnos - process a batman packet for all interfaces,
|
||||
* adjust the sequence number and find out whether it is a duplicate
|
||||
* @ethhdr: ethernet header of the packet
|
||||
* @batadv_ogm_packet: OGM packet to be considered
|
||||
* @if_incoming: interface on which the OGM packet was received
|
||||
*
|
||||
* Returns duplicate status as enum batadv_dup_status
|
||||
*/
|
||||
static int
|
||||
static enum batadv_dup_status
|
||||
batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
|
||||
const struct batadv_ogm_packet *batadv_ogm_packet,
|
||||
const struct batadv_hard_iface *if_incoming)
|
||||
|
@ -918,17 +934,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
|
|||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct batadv_neigh_node *tmp_neigh_node;
|
||||
int is_duplicate = 0;
|
||||
int is_dup;
|
||||
int32_t seq_diff;
|
||||
int need_update = 0;
|
||||
int set_mark, ret = -1;
|
||||
int set_mark;
|
||||
enum batadv_dup_status ret = BATADV_NO_DUP;
|
||||
uint32_t seqno = ntohl(batadv_ogm_packet->seqno);
|
||||
uint8_t *neigh_addr;
|
||||
uint8_t packet_count;
|
||||
|
||||
orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig);
|
||||
if (!orig_node)
|
||||
return 0;
|
||||
return BATADV_NO_DUP;
|
||||
|
||||
spin_lock_bh(&orig_node->ogm_cnt_lock);
|
||||
seq_diff = seqno - orig_node->last_real_seqno;
|
||||
|
@ -936,22 +953,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
|
|||
/* signalize caller that the packet is to be dropped. */
|
||||
if (!hlist_empty(&orig_node->neigh_list) &&
|
||||
batadv_window_protected(bat_priv, seq_diff,
|
||||
&orig_node->batman_seqno_reset))
|
||||
&orig_node->batman_seqno_reset)) {
|
||||
ret = BATADV_PROTECTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(tmp_neigh_node,
|
||||
&orig_node->neigh_list, list) {
|
||||
is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits,
|
||||
orig_node->last_real_seqno,
|
||||
seqno);
|
||||
|
||||
neigh_addr = tmp_neigh_node->addr;
|
||||
is_dup = batadv_test_bit(tmp_neigh_node->real_bits,
|
||||
orig_node->last_real_seqno,
|
||||
seqno);
|
||||
|
||||
if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
|
||||
tmp_neigh_node->if_incoming == if_incoming)
|
||||
tmp_neigh_node->if_incoming == if_incoming) {
|
||||
set_mark = 1;
|
||||
else
|
||||
if (is_dup)
|
||||
ret = BATADV_NEIGH_DUP;
|
||||
} else {
|
||||
set_mark = 0;
|
||||
if (is_dup && (ret != BATADV_NEIGH_DUP))
|
||||
ret = BATADV_ORIG_DUP;
|
||||
}
|
||||
|
||||
/* if the window moved, set the update flag. */
|
||||
need_update |= batadv_bit_get_packet(bat_priv,
|
||||
|
@ -971,8 +995,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
|
|||
orig_node->last_real_seqno = seqno;
|
||||
}
|
||||
|
||||
ret = is_duplicate;
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&orig_node->ogm_cnt_lock);
|
||||
batadv_orig_node_free_ref(orig_node);
|
||||
|
@ -994,7 +1016,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
|
|||
int is_broadcast = 0, is_bidirect;
|
||||
bool is_single_hop_neigh = false;
|
||||
bool is_from_best_next_hop = false;
|
||||
int is_duplicate, sameseq, simlar_ttl;
|
||||
int sameseq, similar_ttl;
|
||||
enum batadv_dup_status dup_status;
|
||||
uint32_t if_incoming_seqno;
|
||||
uint8_t *prev_sender;
|
||||
|
||||
|
@ -1138,10 +1161,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
|
|||
if (!orig_node)
|
||||
return;
|
||||
|
||||
is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
|
||||
if_incoming);
|
||||
dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
|
||||
if_incoming);
|
||||
|
||||
if (is_duplicate == -1) {
|
||||
if (dup_status == BATADV_PROTECTED) {
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"Drop packet: packet within seqno protection time (sender: %pM)\n",
|
||||
ethhdr->h_source);
|
||||
|
@ -1211,11 +1234,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
|
|||
* seqno and similar ttl as the non-duplicate
|
||||
*/
|
||||
sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
|
||||
simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
|
||||
if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl)))
|
||||
similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
|
||||
if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
|
||||
(sameseq && similar_ttl)))
|
||||
batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
|
||||
batadv_ogm_packet, if_incoming,
|
||||
tt_buff, is_duplicate);
|
||||
tt_buff, dup_status);
|
||||
|
||||
/* is single hop (direct) neighbor */
|
||||
if (is_single_hop_neigh) {
|
||||
|
@ -1236,7 +1260,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
|
|||
goto out_neigh;
|
||||
}
|
||||
|
||||
if (is_duplicate) {
|
||||
if (dup_status == BATADV_NEIGH_DUP) {
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"Drop packet: duplicate packet received\n");
|
||||
goto out_neigh;
|
||||
|
|
|
@ -1067,6 +1067,10 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
|
|||
group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
|
||||
bat_priv->bla.claim_dest.group = group;
|
||||
|
||||
/* purge everything when bridge loop avoidance is turned off */
|
||||
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
|
||||
oldif = NULL;
|
||||
|
||||
if (!oldif) {
|
||||
batadv_bla_purge_claims(bat_priv, NULL, 1);
|
||||
batadv_bla_purge_backbone_gw(bat_priv, 1);
|
||||
|
|
|
@ -582,10 +582,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
|
|||
(strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
|
||||
goto out;
|
||||
|
||||
if (!rtnl_trylock()) {
|
||||
ret = -ERESTARTSYS;
|
||||
goto out;
|
||||
}
|
||||
rtnl_lock();
|
||||
|
||||
if (status_tmp == BATADV_IF_NOT_IN_USE) {
|
||||
batadv_hardif_disable_interface(hard_iface,
|
||||
|
|
Loading…
Reference in a new issue