diff options
| -rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 86 | ||||
| -rw-r--r-- | net/batman-adv/bridge_loop_avoidance.c | 4 | ||||
| -rw-r--r-- | net/batman-adv/sysfs.c | 5 | 
3 files changed, 60 insertions, 35 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 071f288b77a..f680ee10187 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -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 @@ out:  	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; diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 379061c7254..de27b3175cf 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -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); diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 15a22efa9a6..929e304dacb 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -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,  |