Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Antonio Quartulli says: ==================== Included changes: - a set of codestyle rearrangements/fixes - new feature to early detect new joining (mesh-unaware) clients - a minor fix for the gw-feature - substitution of shift operations with the BIT() macro - reorganization of the main batman-adv structure (struct batadv_priv) - some more (very) minor cleanups and fixes =================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
				commit
				
					
						e6e94e392f
					
				
			
		
					 20 changed files with 820 additions and 560 deletions
				
			
		| 
						 | 
					@ -76,8 +76,9 @@ folder:
 | 
				
			||||||
There is a special folder for debugging information:
 | 
					There is a special folder for debugging information:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ls /sys/kernel/debug/batman_adv/bat0/
 | 
					# ls /sys/kernel/debug/batman_adv/bat0/
 | 
				
			||||||
# bla_claim_table    log                socket             transtable_local
 | 
					# bla_backbone_table  log                 transtable_global
 | 
				
			||||||
# gateways           originators        transtable_global  vis_data
 | 
					# bla_claim_table     originators         transtable_local
 | 
				
			||||||
 | 
					# gateways            socket              vis_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Some of the files contain all sort of status information  regard-
 | 
					Some of the files contain all sort of status information  regard-
 | 
				
			||||||
ing  the  mesh  network.  For  example, you can view the table of
 | 
					ing  the  mesh  network.  For  example, you can view the table of
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -166,13 +166,15 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
 | 
				
			||||||
	int16_t buff_pos;
 | 
						int16_t buff_pos;
 | 
				
			||||||
	struct batadv_ogm_packet *batadv_ogm_packet;
 | 
						struct batadv_ogm_packet *batadv_ogm_packet;
 | 
				
			||||||
	struct sk_buff *skb;
 | 
						struct sk_buff *skb;
 | 
				
			||||||
 | 
						uint8_t *packet_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (hard_iface->if_status != BATADV_IF_ACTIVE)
 | 
						if (hard_iface->if_status != BATADV_IF_ACTIVE)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	packet_num = 0;
 | 
						packet_num = 0;
 | 
				
			||||||
	buff_pos = 0;
 | 
						buff_pos = 0;
 | 
				
			||||||
	batadv_ogm_packet = (struct batadv_ogm_packet *)forw_packet->skb->data;
 | 
						packet_pos = forw_packet->skb->data;
 | 
				
			||||||
 | 
						batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* adjust all flags and log packets */
 | 
						/* adjust all flags and log packets */
 | 
				
			||||||
	while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
 | 
						while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
 | 
				
			||||||
| 
						 | 
					@ -181,15 +183,17 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
 | 
				
			||||||
		/* we might have aggregated direct link packets with an
 | 
							/* we might have aggregated direct link packets with an
 | 
				
			||||||
		 * ordinary base packet
 | 
							 * ordinary base packet
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if ((forw_packet->direct_link_flags & (1 << packet_num)) &&
 | 
							if (forw_packet->direct_link_flags & BIT(packet_num) &&
 | 
				
			||||||
		    (forw_packet->if_incoming == hard_iface))
 | 
							    forw_packet->if_incoming == hard_iface)
 | 
				
			||||||
			batadv_ogm_packet->flags |= BATADV_DIRECTLINK;
 | 
								batadv_ogm_packet->flags |= BATADV_DIRECTLINK;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK;
 | 
								batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
 | 
							if (packet_num > 0 || !forw_packet->own)
 | 
				
			||||||
							    "Sending own" :
 | 
								fwd_str = "Forwarding";
 | 
				
			||||||
							    "Forwarding"));
 | 
							else
 | 
				
			||||||
 | 
								fwd_str = "Sending own";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 | 
							batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 | 
				
			||||||
			   "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n",
 | 
								   "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n",
 | 
				
			||||||
			   fwd_str, (packet_num > 0 ? "aggregated " : ""),
 | 
								   fwd_str, (packet_num > 0 ? "aggregated " : ""),
 | 
				
			||||||
| 
						 | 
					@ -204,8 +208,8 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
 | 
				
			||||||
		buff_pos += BATADV_OGM_HLEN;
 | 
							buff_pos += BATADV_OGM_HLEN;
 | 
				
			||||||
		buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes);
 | 
							buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes);
 | 
				
			||||||
		packet_num++;
 | 
							packet_num++;
 | 
				
			||||||
		batadv_ogm_packet = (struct batadv_ogm_packet *)
 | 
							packet_pos = forw_packet->skb->data + buff_pos;
 | 
				
			||||||
					(forw_packet->skb->data + buff_pos);
 | 
							batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* create clone because function is called more than once */
 | 
						/* create clone because function is called more than once */
 | 
				
			||||||
| 
						 | 
					@ -227,9 +231,10 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
 | 
				
			||||||
	struct batadv_hard_iface *primary_if = NULL;
 | 
						struct batadv_hard_iface *primary_if = NULL;
 | 
				
			||||||
	struct batadv_ogm_packet *batadv_ogm_packet;
 | 
						struct batadv_ogm_packet *batadv_ogm_packet;
 | 
				
			||||||
	unsigned char directlink;
 | 
						unsigned char directlink;
 | 
				
			||||||
 | 
						uint8_t *packet_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_ogm_packet = (struct batadv_ogm_packet *)
 | 
						packet_pos = forw_packet->skb->data;
 | 
				
			||||||
						(forw_packet->skb->data);
 | 
						batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
 | 
				
			||||||
	directlink = (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 1 : 0);
 | 
						directlink = (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 1 : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!forw_packet->if_incoming) {
 | 
						if (!forw_packet->if_incoming) {
 | 
				
			||||||
| 
						 | 
					@ -454,6 +459,7 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr,
 | 
				
			||||||
				    int packet_len, bool direct_link)
 | 
									    int packet_len, bool direct_link)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned char *skb_buff;
 | 
						unsigned char *skb_buff;
 | 
				
			||||||
 | 
						unsigned long new_direct_link_flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
 | 
						skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
 | 
				
			||||||
	memcpy(skb_buff, packet_buff, packet_len);
 | 
						memcpy(skb_buff, packet_buff, packet_len);
 | 
				
			||||||
| 
						 | 
					@ -461,9 +467,10 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr,
 | 
				
			||||||
	forw_packet_aggr->num_packets++;
 | 
						forw_packet_aggr->num_packets++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* save packet direct link flag status */
 | 
						/* save packet direct link flag status */
 | 
				
			||||||
	if (direct_link)
 | 
						if (direct_link) {
 | 
				
			||||||
		forw_packet_aggr->direct_link_flags |=
 | 
							new_direct_link_flag = BIT(forw_packet_aggr->num_packets);
 | 
				
			||||||
			(1 << forw_packet_aggr->num_packets);
 | 
							forw_packet_aggr->direct_link_flags |= new_direct_link_flag;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
 | 
					static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
 | 
				
			||||||
| 
						 | 
					@ -586,6 +593,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 | 
				
			||||||
	struct batadv_ogm_packet *batadv_ogm_packet;
 | 
						struct batadv_ogm_packet *batadv_ogm_packet;
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
	int vis_server, tt_num_changes = 0;
 | 
						int vis_server, tt_num_changes = 0;
 | 
				
			||||||
 | 
						uint32_t seqno;
 | 
				
			||||||
 | 
						uint8_t bandwidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vis_server = atomic_read(&bat_priv->vis_mode);
 | 
						vis_server = atomic_read(&bat_priv->vis_mode);
 | 
				
			||||||
	primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
						primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
				
			||||||
| 
						 | 
					@ -599,12 +608,12 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 | 
				
			||||||
	batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
 | 
						batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* change sequence number to network order */
 | 
						/* change sequence number to network order */
 | 
				
			||||||
	batadv_ogm_packet->seqno =
 | 
						seqno = (uint32_t)atomic_read(&hard_iface->seqno);
 | 
				
			||||||
			htonl((uint32_t)atomic_read(&hard_iface->seqno));
 | 
						batadv_ogm_packet->seqno = htonl(seqno);
 | 
				
			||||||
	atomic_inc(&hard_iface->seqno);
 | 
						atomic_inc(&hard_iface->seqno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn);
 | 
						batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
 | 
				
			||||||
	batadv_ogm_packet->tt_crc = htons(bat_priv->tt_crc);
 | 
						batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
 | 
				
			||||||
	if (tt_num_changes >= 0)
 | 
						if (tt_num_changes >= 0)
 | 
				
			||||||
		batadv_ogm_packet->tt_num_changes = tt_num_changes;
 | 
							batadv_ogm_packet->tt_num_changes = tt_num_changes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -613,12 +622,13 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER;
 | 
							batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((hard_iface == primary_if) &&
 | 
						if (hard_iface == primary_if &&
 | 
				
			||||||
	    (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER))
 | 
						    atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) {
 | 
				
			||||||
		batadv_ogm_packet->gw_flags =
 | 
							bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
 | 
				
			||||||
				(uint8_t)atomic_read(&bat_priv->gw_bandwidth);
 | 
							batadv_ogm_packet->gw_flags = bandwidth;
 | 
				
			||||||
	else
 | 
						} else {
 | 
				
			||||||
		batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS;
 | 
							batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_slide_own_bcast_window(hard_iface);
 | 
						batadv_slide_own_bcast_window(hard_iface);
 | 
				
			||||||
	batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff,
 | 
						batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff,
 | 
				
			||||||
| 
						 | 
					@ -642,8 +652,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
 | 
				
			||||||
	struct batadv_neigh_node *router = NULL;
 | 
						struct batadv_neigh_node *router = NULL;
 | 
				
			||||||
	struct batadv_orig_node *orig_node_tmp;
 | 
						struct batadv_orig_node *orig_node_tmp;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
 | 
						uint8_t sum_orig, sum_neigh;
 | 
				
			||||||
	uint8_t *neigh_addr;
 | 
						uint8_t *neigh_addr;
 | 
				
			||||||
 | 
						uint8_t tq_avg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 | 
						batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 | 
				
			||||||
		   "update_originator(): Searching and updating originator entry of received packet\n");
 | 
							   "update_originator(): Searching and updating originator entry of received packet\n");
 | 
				
			||||||
| 
						 | 
					@ -667,8 +678,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
 | 
				
			||||||
		spin_lock_bh(&tmp_neigh_node->lq_update_lock);
 | 
							spin_lock_bh(&tmp_neigh_node->lq_update_lock);
 | 
				
			||||||
		batadv_ring_buffer_set(tmp_neigh_node->tq_recv,
 | 
							batadv_ring_buffer_set(tmp_neigh_node->tq_recv,
 | 
				
			||||||
				       &tmp_neigh_node->tq_index, 0);
 | 
									       &tmp_neigh_node->tq_index, 0);
 | 
				
			||||||
		tmp_neigh_node->tq_avg =
 | 
							tq_avg = batadv_ring_buffer_avg(tmp_neigh_node->tq_recv);
 | 
				
			||||||
			batadv_ring_buffer_avg(tmp_neigh_node->tq_recv);
 | 
							tmp_neigh_node->tq_avg = tq_avg;
 | 
				
			||||||
		spin_unlock_bh(&tmp_neigh_node->lq_update_lock);
 | 
							spin_unlock_bh(&tmp_neigh_node->lq_update_lock);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -727,17 +738,15 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
 | 
				
			||||||
	if (router && (neigh_node->tq_avg == router->tq_avg)) {
 | 
						if (router && (neigh_node->tq_avg == router->tq_avg)) {
 | 
				
			||||||
		orig_node_tmp = router->orig_node;
 | 
							orig_node_tmp = router->orig_node;
 | 
				
			||||||
		spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
							spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
				
			||||||
		bcast_own_sum_orig =
 | 
							sum_orig = orig_node_tmp->bcast_own_sum[if_incoming->if_num];
 | 
				
			||||||
			orig_node_tmp->bcast_own_sum[if_incoming->if_num];
 | 
					 | 
				
			||||||
		spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
							spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		orig_node_tmp = neigh_node->orig_node;
 | 
							orig_node_tmp = neigh_node->orig_node;
 | 
				
			||||||
		spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
							spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
				
			||||||
		bcast_own_sum_neigh =
 | 
							sum_neigh = orig_node_tmp->bcast_own_sum[if_incoming->if_num];
 | 
				
			||||||
			orig_node_tmp->bcast_own_sum[if_incoming->if_num];
 | 
					 | 
				
			||||||
		spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
							spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (bcast_own_sum_orig >= bcast_own_sum_neigh)
 | 
							if (sum_orig >= sum_neigh)
 | 
				
			||||||
			goto update_tt;
 | 
								goto update_tt;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -835,8 +844,10 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
 | 
				
			||||||
	spin_unlock_bh(&orig_node->ogm_cnt_lock);
 | 
						spin_unlock_bh(&orig_node->ogm_cnt_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* pay attention to not get a value bigger than 100 % */
 | 
						/* pay attention to not get a value bigger than 100 % */
 | 
				
			||||||
	total_count = (orig_eq_count > neigh_rq_count ?
 | 
						if (orig_eq_count > neigh_rq_count)
 | 
				
			||||||
		       neigh_rq_count : orig_eq_count);
 | 
							total_count = neigh_rq_count;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							total_count = orig_eq_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if we have too few packets (too less data) we set tq_own to zero
 | 
						/* if we have too few packets (too less data) we set tq_own to zero
 | 
				
			||||||
	 * if we receive too few packets it is not considered bidirectional
 | 
						 * if we receive too few packets it is not considered bidirectional
 | 
				
			||||||
| 
						 | 
					@ -910,6 +921,7 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
 | 
				
			||||||
	int set_mark, ret = -1;
 | 
						int set_mark, ret = -1;
 | 
				
			||||||
	uint32_t seqno = ntohl(batadv_ogm_packet->seqno);
 | 
						uint32_t seqno = ntohl(batadv_ogm_packet->seqno);
 | 
				
			||||||
	uint8_t *neigh_addr;
 | 
						uint8_t *neigh_addr;
 | 
				
			||||||
 | 
						uint8_t packet_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig);
 | 
						orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig);
 | 
				
			||||||
	if (!orig_node)
 | 
						if (!orig_node)
 | 
				
			||||||
| 
						 | 
					@ -944,9 +956,9 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
 | 
				
			||||||
						     tmp_neigh_node->real_bits,
 | 
											     tmp_neigh_node->real_bits,
 | 
				
			||||||
						     seq_diff, set_mark);
 | 
											     seq_diff, set_mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tmp_neigh_node->real_packet_count =
 | 
							packet_count = bitmap_weight(tmp_neigh_node->real_bits,
 | 
				
			||||||
			bitmap_weight(tmp_neigh_node->real_bits,
 | 
					 | 
				
			||||||
					     BATADV_TQ_LOCAL_WINDOW_SIZE);
 | 
										     BATADV_TQ_LOCAL_WINDOW_SIZE);
 | 
				
			||||||
 | 
							tmp_neigh_node->real_packet_count = packet_count;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1163,9 +1175,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
 | 
				
			||||||
	/* if sender is a direct neighbor the sender mac equals
 | 
						/* if sender is a direct neighbor the sender mac equals
 | 
				
			||||||
	 * originator mac
 | 
						 * originator mac
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	orig_neigh_node = (is_single_hop_neigh ?
 | 
						if (is_single_hop_neigh)
 | 
				
			||||||
			   orig_node :
 | 
							orig_neigh_node = orig_node;
 | 
				
			||||||
			   batadv_get_orig_node(bat_priv, ethhdr->h_source));
 | 
						else
 | 
				
			||||||
 | 
							orig_neigh_node = batadv_get_orig_node(bat_priv,
 | 
				
			||||||
 | 
											       ethhdr->h_source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!orig_neigh_node)
 | 
						if (!orig_neigh_node)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1251,6 +1266,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
 | 
				
			||||||
	int buff_pos = 0, packet_len;
 | 
						int buff_pos = 0, packet_len;
 | 
				
			||||||
	unsigned char *tt_buff, *packet_buff;
 | 
						unsigned char *tt_buff, *packet_buff;
 | 
				
			||||||
	bool ret;
 | 
						bool ret;
 | 
				
			||||||
 | 
						uint8_t *packet_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
 | 
						ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
 | 
				
			||||||
	if (!ret)
 | 
						if (!ret)
 | 
				
			||||||
| 
						 | 
					@ -1281,8 +1297,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
 | 
				
			||||||
		buff_pos += BATADV_OGM_HLEN;
 | 
							buff_pos += BATADV_OGM_HLEN;
 | 
				
			||||||
		buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes);
 | 
							buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		batadv_ogm_packet = (struct batadv_ogm_packet *)
 | 
							packet_pos = packet_buff + buff_pos;
 | 
				
			||||||
						(packet_buff + buff_pos);
 | 
							batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
 | 
				
			||||||
	} while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
 | 
						} while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
 | 
				
			||||||
					   batadv_ogm_packet->tt_num_changes));
 | 
										   batadv_ogm_packet->tt_num_changes));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,7 +133,7 @@ static void batadv_claim_free_ref(struct batadv_claim *claim)
 | 
				
			||||||
static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv,
 | 
					static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv,
 | 
				
			||||||
						   struct batadv_claim *data)
 | 
											   struct batadv_claim *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->claim_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct batadv_claim *claim;
 | 
						struct batadv_claim *claim;
 | 
				
			||||||
| 
						 | 
					@ -174,7 +174,7 @@ static struct batadv_backbone_gw *
 | 
				
			||||||
batadv_backbone_hash_find(struct batadv_priv *bat_priv,
 | 
					batadv_backbone_hash_find(struct batadv_priv *bat_priv,
 | 
				
			||||||
			  uint8_t *addr, short vid)
 | 
								  uint8_t *addr, short vid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->backbone_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct batadv_backbone_gw search_entry, *backbone_gw;
 | 
						struct batadv_backbone_gw search_entry, *backbone_gw;
 | 
				
			||||||
| 
						 | 
					@ -218,7 +218,7 @@ batadv_bla_del_backbone_claims(struct batadv_backbone_gw *backbone_gw)
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	spinlock_t *list_lock;	/* protects write access to the hash lists */
 | 
						spinlock_t *list_lock;	/* protects write access to the hash lists */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = backbone_gw->bat_priv->claim_hash;
 | 
						hash = backbone_gw->bat_priv->bla.claim_hash;
 | 
				
			||||||
	if (!hash)
 | 
						if (!hash)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -265,7 +265,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 | 
				
			||||||
	if (!primary_if)
 | 
						if (!primary_if)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(&local_claim_dest, &bat_priv->claim_dest,
 | 
						memcpy(&local_claim_dest, &bat_priv->bla.claim_dest,
 | 
				
			||||||
	       sizeof(local_claim_dest));
 | 
						       sizeof(local_claim_dest));
 | 
				
			||||||
	local_claim_dest.type = claimtype;
 | 
						local_claim_dest.type = claimtype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,7 +281,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 | 
				
			||||||
			 NULL,
 | 
								 NULL,
 | 
				
			||||||
			 /* Ethernet SRC/HW SRC:  originator mac */
 | 
								 /* Ethernet SRC/HW SRC:  originator mac */
 | 
				
			||||||
			 primary_if->net_dev->dev_addr,
 | 
								 primary_if->net_dev->dev_addr,
 | 
				
			||||||
			 /* HW DST: FF:43:05:XX:00:00
 | 
								 /* HW DST: FF:43:05:XX:YY:YY
 | 
				
			||||||
			  * with XX   = claim type
 | 
								  * with XX   = claim type
 | 
				
			||||||
			  * and YY:YY = group id
 | 
								  * and YY:YY = group id
 | 
				
			||||||
			  */
 | 
								  */
 | 
				
			||||||
| 
						 | 
					@ -295,7 +295,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* now we pretend that the client would have sent this ... */
 | 
						/* now we pretend that the client would have sent this ... */
 | 
				
			||||||
	switch (claimtype) {
 | 
						switch (claimtype) {
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_ADD:
 | 
						case BATADV_CLAIM_TYPE_CLAIM:
 | 
				
			||||||
		/* normal claim frame
 | 
							/* normal claim frame
 | 
				
			||||||
		 * set Ethernet SRC to the clients mac
 | 
							 * set Ethernet SRC to the clients mac
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
| 
						 | 
					@ -303,7 +303,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 | 
				
			||||||
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
 | 
							batadv_dbg(BATADV_DBG_BLA, bat_priv,
 | 
				
			||||||
			   "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid);
 | 
								   "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_DEL:
 | 
						case BATADV_CLAIM_TYPE_UNCLAIM:
 | 
				
			||||||
		/* unclaim frame
 | 
							/* unclaim frame
 | 
				
			||||||
		 * set HW SRC to the clients mac
 | 
							 * set HW SRC to the clients mac
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
| 
						 | 
					@ -323,7 +323,8 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_REQUEST:
 | 
						case BATADV_CLAIM_TYPE_REQUEST:
 | 
				
			||||||
		/* request frame
 | 
							/* request frame
 | 
				
			||||||
		 * set HW SRC to the special mac containg the crc
 | 
							 * set HW SRC and header destination to the receiving backbone
 | 
				
			||||||
 | 
							 * gws mac
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		memcpy(hw_src, mac, ETH_ALEN);
 | 
							memcpy(hw_src, mac, ETH_ALEN);
 | 
				
			||||||
		memcpy(ethhdr->h_dest, mac, ETH_ALEN);
 | 
							memcpy(ethhdr->h_dest, mac, ETH_ALEN);
 | 
				
			||||||
| 
						 | 
					@ -339,8 +340,9 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb_reset_mac_header(skb);
 | 
						skb_reset_mac_header(skb);
 | 
				
			||||||
	skb->protocol = eth_type_trans(skb, soft_iface);
 | 
						skb->protocol = eth_type_trans(skb, soft_iface);
 | 
				
			||||||
	bat_priv->stats.rx_packets++;
 | 
						batadv_inc_counter(bat_priv, BATADV_CNT_RX);
 | 
				
			||||||
	bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
 | 
						batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
 | 
				
			||||||
 | 
								   skb->len + ETH_HLEN);
 | 
				
			||||||
	soft_iface->last_rx = jiffies;
 | 
						soft_iface->last_rx = jiffies;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	netif_rx(skb);
 | 
						netif_rx(skb);
 | 
				
			||||||
| 
						 | 
					@ -389,7 +391,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
 | 
				
			||||||
	/* one for the hash, one for returning */
 | 
						/* one for the hash, one for returning */
 | 
				
			||||||
	atomic_set(&entry->refcount, 2);
 | 
						atomic_set(&entry->refcount, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash_added = batadv_hash_add(bat_priv->backbone_hash,
 | 
						hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
 | 
				
			||||||
				     batadv_compare_backbone_gw,
 | 
									     batadv_compare_backbone_gw,
 | 
				
			||||||
				     batadv_choose_backbone_gw, entry,
 | 
									     batadv_choose_backbone_gw, entry,
 | 
				
			||||||
				     &entry->hash_entry);
 | 
									     &entry->hash_entry);
 | 
				
			||||||
| 
						 | 
					@ -456,7 +458,7 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
 | 
				
			||||||
	if (!backbone_gw)
 | 
						if (!backbone_gw)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->claim_hash;
 | 
						hash = bat_priv->bla.claim_hash;
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
		head = &hash->table[i];
 | 
							head = &hash->table[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -467,7 +469,7 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
 | 
								batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
 | 
				
			||||||
					      BATADV_CLAIM_TYPE_ADD);
 | 
										      BATADV_CLAIM_TYPE_CLAIM);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -497,7 +499,7 @@ static void batadv_bla_send_request(struct batadv_backbone_gw *backbone_gw)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* no local broadcasts should be sent or received, for now. */
 | 
						/* no local broadcasts should be sent or received, for now. */
 | 
				
			||||||
	if (!atomic_read(&backbone_gw->request_sent)) {
 | 
						if (!atomic_read(&backbone_gw->request_sent)) {
 | 
				
			||||||
		atomic_inc(&backbone_gw->bat_priv->bla_num_requests);
 | 
							atomic_inc(&backbone_gw->bat_priv->bla.num_requests);
 | 
				
			||||||
		atomic_set(&backbone_gw->request_sent, 1);
 | 
							atomic_set(&backbone_gw->request_sent, 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -557,7 +559,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
 | 
				
			||||||
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
 | 
							batadv_dbg(BATADV_DBG_BLA, bat_priv,
 | 
				
			||||||
			   "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
 | 
								   "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
 | 
				
			||||||
			   mac, vid);
 | 
								   mac, vid);
 | 
				
			||||||
		hash_added = batadv_hash_add(bat_priv->claim_hash,
 | 
							hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
 | 
				
			||||||
					     batadv_compare_claim,
 | 
										     batadv_compare_claim,
 | 
				
			||||||
					     batadv_choose_claim, claim,
 | 
										     batadv_choose_claim, claim,
 | 
				
			||||||
					     &claim->hash_entry);
 | 
										     &claim->hash_entry);
 | 
				
			||||||
| 
						 | 
					@ -577,8 +579,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
 | 
				
			||||||
			   "bla_add_claim(): changing ownership for %pM, vid %d\n",
 | 
								   "bla_add_claim(): changing ownership for %pM, vid %d\n",
 | 
				
			||||||
			   mac, vid);
 | 
								   mac, vid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		claim->backbone_gw->crc ^=
 | 
							claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
 | 
				
			||||||
			crc16(0, claim->addr, ETH_ALEN);
 | 
					 | 
				
			||||||
		batadv_backbone_gw_free_ref(claim->backbone_gw);
 | 
							batadv_backbone_gw_free_ref(claim->backbone_gw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -610,7 +611,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
 | 
						batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n",
 | 
				
			||||||
		   mac, vid);
 | 
							   mac, vid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_hash_remove(bat_priv->claim_hash, batadv_compare_claim,
 | 
						batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim,
 | 
				
			||||||
			   batadv_choose_claim, claim);
 | 
								   batadv_choose_claim, claim);
 | 
				
			||||||
	batadv_claim_free_ref(claim); /* reference from the hash is gone */
 | 
						batadv_claim_free_ref(claim); /* reference from the hash is gone */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -657,7 +658,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv,
 | 
				
			||||||
		 * we can allow traffic again.
 | 
							 * we can allow traffic again.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (atomic_read(&backbone_gw->request_sent)) {
 | 
							if (atomic_read(&backbone_gw->request_sent)) {
 | 
				
			||||||
			atomic_dec(&backbone_gw->bat_priv->bla_num_requests);
 | 
								atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
 | 
				
			||||||
			atomic_set(&backbone_gw->request_sent, 0);
 | 
								atomic_set(&backbone_gw->request_sent, 0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -702,7 +703,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv,
 | 
				
			||||||
	if (primary_if && batadv_compare_eth(backbone_addr,
 | 
						if (primary_if && batadv_compare_eth(backbone_addr,
 | 
				
			||||||
					     primary_if->net_dev->dev_addr))
 | 
										     primary_if->net_dev->dev_addr))
 | 
				
			||||||
		batadv_bla_send_claim(bat_priv, claim_addr, vid,
 | 
							batadv_bla_send_claim(bat_priv, claim_addr, vid,
 | 
				
			||||||
				      BATADV_CLAIM_TYPE_DEL);
 | 
									      BATADV_CLAIM_TYPE_UNCLAIM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
 | 
						backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -738,7 +739,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv,
 | 
				
			||||||
	batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
 | 
						batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
 | 
				
			||||||
	if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
 | 
						if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
 | 
				
			||||||
		batadv_bla_send_claim(bat_priv, claim_addr, vid,
 | 
							batadv_bla_send_claim(bat_priv, claim_addr, vid,
 | 
				
			||||||
				      BATADV_CLAIM_TYPE_ADD);
 | 
									      BATADV_CLAIM_TYPE_CLAIM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TODO: we could call something like tt_local_del() here. */
 | 
						/* TODO: we could call something like tt_local_del() here. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -772,7 +773,7 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
 | 
				
			||||||
	struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
 | 
						struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
 | 
						bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
 | 
				
			||||||
	bla_dst_own = &bat_priv->claim_dest;
 | 
						bla_dst_own = &bat_priv->bla.claim_dest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* check if it is a claim packet in general */
 | 
						/* check if it is a claim packet in general */
 | 
				
			||||||
	if (memcmp(bla_dst->magic, bla_dst_own->magic,
 | 
						if (memcmp(bla_dst->magic, bla_dst_own->magic,
 | 
				
			||||||
| 
						 | 
					@ -783,12 +784,12 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
 | 
				
			||||||
	 * otherwise assume it is in the hw_src
 | 
						 * otherwise assume it is in the hw_src
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	switch (bla_dst->type) {
 | 
						switch (bla_dst->type) {
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_ADD:
 | 
						case BATADV_CLAIM_TYPE_CLAIM:
 | 
				
			||||||
		backbone_addr = hw_src;
 | 
							backbone_addr = hw_src;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_REQUEST:
 | 
						case BATADV_CLAIM_TYPE_REQUEST:
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_ANNOUNCE:
 | 
						case BATADV_CLAIM_TYPE_ANNOUNCE:
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_DEL:
 | 
						case BATADV_CLAIM_TYPE_UNCLAIM:
 | 
				
			||||||
		backbone_addr = ethhdr->h_source;
 | 
							backbone_addr = ethhdr->h_source;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
| 
						 | 
					@ -904,12 +905,12 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* check for the different types of claim frames ... */
 | 
						/* check for the different types of claim frames ... */
 | 
				
			||||||
	switch (bla_dst->type) {
 | 
						switch (bla_dst->type) {
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_ADD:
 | 
						case BATADV_CLAIM_TYPE_CLAIM:
 | 
				
			||||||
		if (batadv_handle_claim(bat_priv, primary_if, hw_src,
 | 
							if (batadv_handle_claim(bat_priv, primary_if, hw_src,
 | 
				
			||||||
					ethhdr->h_source, vid))
 | 
										ethhdr->h_source, vid))
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case BATADV_CLAIM_TYPE_DEL:
 | 
						case BATADV_CLAIM_TYPE_UNCLAIM:
 | 
				
			||||||
		if (batadv_handle_unclaim(bat_priv, primary_if,
 | 
							if (batadv_handle_unclaim(bat_priv, primary_if,
 | 
				
			||||||
					  ethhdr->h_source, hw_src, vid))
 | 
										  ethhdr->h_source, hw_src, vid))
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
| 
						 | 
					@ -945,7 +946,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
 | 
				
			||||||
	spinlock_t *list_lock;	/* protects write access to the hash lists */
 | 
						spinlock_t *list_lock;	/* protects write access to the hash lists */
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->backbone_hash;
 | 
						hash = bat_priv->bla.backbone_hash;
 | 
				
			||||||
	if (!hash)
 | 
						if (!hash)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -969,7 +970,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
 | 
				
			||||||
purge_now:
 | 
					purge_now:
 | 
				
			||||||
			/* don't wait for the pending request anymore */
 | 
								/* don't wait for the pending request anymore */
 | 
				
			||||||
			if (atomic_read(&backbone_gw->request_sent))
 | 
								if (atomic_read(&backbone_gw->request_sent))
 | 
				
			||||||
				atomic_dec(&bat_priv->bla_num_requests);
 | 
									atomic_dec(&bat_priv->bla.num_requests);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			batadv_bla_del_backbone_claims(backbone_gw);
 | 
								batadv_bla_del_backbone_claims(backbone_gw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -999,7 +1000,7 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
 | 
				
			||||||
	struct batadv_hashtable *hash;
 | 
						struct batadv_hashtable *hash;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->claim_hash;
 | 
						hash = bat_priv->bla.claim_hash;
 | 
				
			||||||
	if (!hash)
 | 
						if (!hash)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1046,11 +1047,12 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct batadv_hashtable *hash;
 | 
						struct batadv_hashtable *hash;
 | 
				
			||||||
 | 
						__be16 group;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* reset bridge loop avoidance group id */
 | 
						/* reset bridge loop avoidance group id */
 | 
				
			||||||
	bat_priv->claim_dest.group =
 | 
						group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
 | 
				
			||||||
		htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
 | 
						bat_priv->bla.claim_dest.group = group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!oldif) {
 | 
						if (!oldif) {
 | 
				
			||||||
		batadv_bla_purge_claims(bat_priv, NULL, 1);
 | 
							batadv_bla_purge_claims(bat_priv, NULL, 1);
 | 
				
			||||||
| 
						 | 
					@ -1058,7 +1060,7 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->backbone_hash;
 | 
						hash = bat_priv->bla.backbone_hash;
 | 
				
			||||||
	if (!hash)
 | 
						if (!hash)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1088,8 +1090,8 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 | 
				
			||||||
/* (re)start the timer */
 | 
					/* (re)start the timer */
 | 
				
			||||||
static void batadv_bla_start_timer(struct batadv_priv *bat_priv)
 | 
					static void batadv_bla_start_timer(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	INIT_DELAYED_WORK(&bat_priv->bla_work, batadv_bla_periodic_work);
 | 
						INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work);
 | 
				
			||||||
	queue_delayed_work(batadv_event_workqueue, &bat_priv->bla_work,
 | 
						queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
 | 
				
			||||||
			   msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
 | 
								   msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1099,9 +1101,9 @@ static void batadv_bla_start_timer(struct batadv_priv *bat_priv)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void batadv_bla_periodic_work(struct work_struct *work)
 | 
					static void batadv_bla_periodic_work(struct work_struct *work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct delayed_work *delayed_work =
 | 
						struct delayed_work *delayed_work;
 | 
				
			||||||
		container_of(work, struct delayed_work, work);
 | 
					 | 
				
			||||||
	struct batadv_priv *bat_priv;
 | 
						struct batadv_priv *bat_priv;
 | 
				
			||||||
 | 
						struct batadv_priv_bla *priv_bla;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct batadv_backbone_gw *backbone_gw;
 | 
						struct batadv_backbone_gw *backbone_gw;
 | 
				
			||||||
| 
						 | 
					@ -1109,7 +1111,9 @@ static void batadv_bla_periodic_work(struct work_struct *work)
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv = container_of(delayed_work, struct batadv_priv, bla_work);
 | 
						delayed_work = container_of(work, struct delayed_work, work);
 | 
				
			||||||
 | 
						priv_bla = container_of(delayed_work, struct batadv_priv_bla, work);
 | 
				
			||||||
 | 
						bat_priv = container_of(priv_bla, struct batadv_priv, bla);
 | 
				
			||||||
	primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
						primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
				
			||||||
	if (!primary_if)
 | 
						if (!primary_if)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					@ -1120,7 +1124,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
 | 
				
			||||||
	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
 | 
						if (!atomic_read(&bat_priv->bridge_loop_avoidance))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->backbone_hash;
 | 
						hash = bat_priv->bla.backbone_hash;
 | 
				
			||||||
	if (!hash)
 | 
						if (!hash)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1160,40 +1164,41 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
 | 
						uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
 | 
						uint16_t crc;
 | 
				
			||||||
 | 
						unsigned long entrytime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
 | 
						batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* setting claim destination address */
 | 
						/* setting claim destination address */
 | 
				
			||||||
	memcpy(&bat_priv->claim_dest.magic, claim_dest, 3);
 | 
						memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3);
 | 
				
			||||||
	bat_priv->claim_dest.type = 0;
 | 
						bat_priv->bla.claim_dest.type = 0;
 | 
				
			||||||
	primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
						primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
				
			||||||
	if (primary_if) {
 | 
						if (primary_if) {
 | 
				
			||||||
		bat_priv->claim_dest.group =
 | 
							crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN);
 | 
				
			||||||
			htons(crc16(0, primary_if->net_dev->dev_addr,
 | 
							bat_priv->bla.claim_dest.group = htons(crc);
 | 
				
			||||||
				    ETH_ALEN));
 | 
					 | 
				
			||||||
		batadv_hardif_free_ref(primary_if);
 | 
							batadv_hardif_free_ref(primary_if);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		bat_priv->claim_dest.group = 0; /* will be set later */
 | 
							bat_priv->bla.claim_dest.group = 0; /* will be set later */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* initialize the duplicate list */
 | 
						/* initialize the duplicate list */
 | 
				
			||||||
 | 
						entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
 | 
				
			||||||
	for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
 | 
						for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
 | 
				
			||||||
		bat_priv->bcast_duplist[i].entrytime =
 | 
							bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
 | 
				
			||||||
			jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
 | 
						bat_priv->bla.bcast_duplist_curr = 0;
 | 
				
			||||||
	bat_priv->bcast_duplist_curr = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bat_priv->claim_hash)
 | 
						if (bat_priv->bla.claim_hash)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->claim_hash = batadv_hash_new(128);
 | 
						bat_priv->bla.claim_hash = batadv_hash_new(128);
 | 
				
			||||||
	bat_priv->backbone_hash = batadv_hash_new(32);
 | 
						bat_priv->bla.backbone_hash = batadv_hash_new(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!bat_priv->claim_hash || !bat_priv->backbone_hash)
 | 
						if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_hash_set_lock_class(bat_priv->claim_hash,
 | 
						batadv_hash_set_lock_class(bat_priv->bla.claim_hash,
 | 
				
			||||||
				   &batadv_claim_hash_lock_class_key);
 | 
									   &batadv_claim_hash_lock_class_key);
 | 
				
			||||||
	batadv_hash_set_lock_class(bat_priv->backbone_hash,
 | 
						batadv_hash_set_lock_class(bat_priv->bla.backbone_hash,
 | 
				
			||||||
				   &batadv_backbone_hash_lock_class_key);
 | 
									   &batadv_backbone_hash_lock_class_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
 | 
						batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
 | 
				
			||||||
| 
						 | 
					@ -1234,8 +1239,9 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 | 
				
			||||||
	crc = crc16(0, content, length);
 | 
						crc = crc16(0, content, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
 | 
						for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
 | 
				
			||||||
		curr = (bat_priv->bcast_duplist_curr + i) % BATADV_DUPLIST_SIZE;
 | 
							curr = (bat_priv->bla.bcast_duplist_curr + i);
 | 
				
			||||||
		entry = &bat_priv->bcast_duplist[curr];
 | 
							curr %= BATADV_DUPLIST_SIZE;
 | 
				
			||||||
 | 
							entry = &bat_priv->bla.bcast_duplist[curr];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* we can stop searching if the entry is too old ;
 | 
							/* we can stop searching if the entry is too old ;
 | 
				
			||||||
		 * later entries will be even older
 | 
							 * later entries will be even older
 | 
				
			||||||
| 
						 | 
					@ -1256,13 +1262,13 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* not found, add a new entry (overwrite the oldest entry) */
 | 
						/* not found, add a new entry (overwrite the oldest entry) */
 | 
				
			||||||
	curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
 | 
						curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
 | 
				
			||||||
	curr %= BATADV_DUPLIST_SIZE;
 | 
						curr %= BATADV_DUPLIST_SIZE;
 | 
				
			||||||
	entry = &bat_priv->bcast_duplist[curr];
 | 
						entry = &bat_priv->bla.bcast_duplist[curr];
 | 
				
			||||||
	entry->crc = crc;
 | 
						entry->crc = crc;
 | 
				
			||||||
	entry->entrytime = jiffies;
 | 
						entry->entrytime = jiffies;
 | 
				
			||||||
	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
 | 
						memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
 | 
				
			||||||
	bat_priv->bcast_duplist_curr = curr;
 | 
						bat_priv->bla.bcast_duplist_curr = curr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* allow it, its the first occurence. */
 | 
						/* allow it, its the first occurence. */
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1279,7 +1285,7 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
 | 
					int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->backbone_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct batadv_backbone_gw *backbone_gw;
 | 
						struct batadv_backbone_gw *backbone_gw;
 | 
				
			||||||
| 
						 | 
					@ -1339,8 +1345,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
 | 
				
			||||||
		if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr)))
 | 
							if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr)))
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		vhdr = (struct vlan_ethhdr *)(((uint8_t *)skb->data) +
 | 
							vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
 | 
				
			||||||
					      hdr_size);
 | 
					 | 
				
			||||||
		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
 | 
							vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1359,18 +1364,18 @@ void batadv_bla_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cancel_delayed_work_sync(&bat_priv->bla_work);
 | 
						cancel_delayed_work_sync(&bat_priv->bla.work);
 | 
				
			||||||
	primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
						primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bat_priv->claim_hash) {
 | 
						if (bat_priv->bla.claim_hash) {
 | 
				
			||||||
		batadv_bla_purge_claims(bat_priv, primary_if, 1);
 | 
							batadv_bla_purge_claims(bat_priv, primary_if, 1);
 | 
				
			||||||
		batadv_hash_destroy(bat_priv->claim_hash);
 | 
							batadv_hash_destroy(bat_priv->bla.claim_hash);
 | 
				
			||||||
		bat_priv->claim_hash = NULL;
 | 
							bat_priv->bla.claim_hash = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (bat_priv->backbone_hash) {
 | 
						if (bat_priv->bla.backbone_hash) {
 | 
				
			||||||
		batadv_bla_purge_backbone_gw(bat_priv, 1);
 | 
							batadv_bla_purge_backbone_gw(bat_priv, 1);
 | 
				
			||||||
		batadv_hash_destroy(bat_priv->backbone_hash);
 | 
							batadv_hash_destroy(bat_priv->bla.backbone_hash);
 | 
				
			||||||
		bat_priv->backbone_hash = NULL;
 | 
							bat_priv->bla.backbone_hash = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (primary_if)
 | 
						if (primary_if)
 | 
				
			||||||
		batadv_hardif_free_ref(primary_if);
 | 
							batadv_hardif_free_ref(primary_if);
 | 
				
			||||||
| 
						 | 
					@ -1409,7 +1414,7 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
 | 
				
			||||||
		goto allow;
 | 
							goto allow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
 | 
						if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
 | 
				
			||||||
		/* don't allow broadcasts while requests are in flight */
 | 
							/* don't allow broadcasts while requests are in flight */
 | 
				
			||||||
		if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
 | 
							if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
 | 
				
			||||||
			goto handled;
 | 
								goto handled;
 | 
				
			||||||
| 
						 | 
					@ -1508,7 +1513,7 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 | 
						ethhdr = (struct ethhdr *)skb_mac_header(skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
 | 
						if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
 | 
				
			||||||
		/* don't allow broadcasts while requests are in flight */
 | 
							/* don't allow broadcasts while requests are in flight */
 | 
				
			||||||
		if (is_multicast_ether_addr(ethhdr->h_dest))
 | 
							if (is_multicast_ether_addr(ethhdr->h_dest))
 | 
				
			||||||
			goto handled;
 | 
								goto handled;
 | 
				
			||||||
| 
						 | 
					@ -1564,7 +1569,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *net_dev = (struct net_device *)seq->private;
 | 
						struct net_device *net_dev = (struct net_device *)seq->private;
 | 
				
			||||||
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
						struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->claim_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
 | 
				
			||||||
	struct batadv_claim *claim;
 | 
						struct batadv_claim *claim;
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
| 
						 | 
					@ -1593,7 +1598,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
	seq_printf(seq,
 | 
						seq_printf(seq,
 | 
				
			||||||
		   "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
 | 
							   "Claims announced for the mesh %s (orig %pM, group id %04x)\n",
 | 
				
			||||||
		   net_dev->name, primary_addr,
 | 
							   net_dev->name, primary_addr,
 | 
				
			||||||
		   ntohs(bat_priv->claim_dest.group));
 | 
							   ntohs(bat_priv->bla.claim_dest.group));
 | 
				
			||||||
	seq_printf(seq, "   %-17s    %-5s    %-17s [o] (%-4s)\n",
 | 
						seq_printf(seq, "   %-17s    %-5s    %-17s [o] (%-4s)\n",
 | 
				
			||||||
		   "Client", "VID", "Originator", "CRC");
 | 
							   "Client", "VID", "Originator", "CRC");
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
| 
						 | 
					@ -1616,3 +1621,68 @@ out:
 | 
				
			||||||
		batadv_hardif_free_ref(primary_if);
 | 
							batadv_hardif_free_ref(primary_if);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct net_device *net_dev = (struct net_device *)seq->private;
 | 
				
			||||||
 | 
						struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
				
			||||||
 | 
						struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
 | 
				
			||||||
 | 
						struct batadv_backbone_gw *backbone_gw;
 | 
				
			||||||
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
 | 
						struct hlist_node *node;
 | 
				
			||||||
 | 
						struct hlist_head *head;
 | 
				
			||||||
 | 
						int secs, msecs;
 | 
				
			||||||
 | 
						uint32_t i;
 | 
				
			||||||
 | 
						bool is_own;
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
						uint8_t *primary_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
				
			||||||
 | 
						if (!primary_if) {
 | 
				
			||||||
 | 
							ret = seq_printf(seq,
 | 
				
			||||||
 | 
									 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
 | 
				
			||||||
 | 
									 net_dev->name);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (primary_if->if_status != BATADV_IF_ACTIVE) {
 | 
				
			||||||
 | 
							ret = seq_printf(seq,
 | 
				
			||||||
 | 
									 "BATMAN mesh %s disabled - primary interface not active\n",
 | 
				
			||||||
 | 
									 net_dev->name);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						primary_addr = primary_if->net_dev->dev_addr;
 | 
				
			||||||
 | 
						seq_printf(seq,
 | 
				
			||||||
 | 
							   "Backbones announced for the mesh %s (orig %pM, group id %04x)\n",
 | 
				
			||||||
 | 
							   net_dev->name, primary_addr,
 | 
				
			||||||
 | 
							   ntohs(bat_priv->bla.claim_dest.group));
 | 
				
			||||||
 | 
						seq_printf(seq, "   %-17s    %-5s %-9s (%-4s)\n",
 | 
				
			||||||
 | 
							   "Originator", "VID", "last seen", "CRC");
 | 
				
			||||||
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
 | 
							head = &hash->table[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rcu_read_lock();
 | 
				
			||||||
 | 
							hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) {
 | 
				
			||||||
 | 
								msecs = jiffies_to_msecs(jiffies -
 | 
				
			||||||
 | 
											 backbone_gw->lasttime);
 | 
				
			||||||
 | 
								secs = msecs / 1000;
 | 
				
			||||||
 | 
								msecs = msecs % 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								is_own = batadv_compare_eth(backbone_gw->orig,
 | 
				
			||||||
 | 
											    primary_addr);
 | 
				
			||||||
 | 
								if (is_own)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								seq_printf(seq,
 | 
				
			||||||
 | 
									   " * %pM on % 5d % 4i.%03is (%04x)\n",
 | 
				
			||||||
 | 
									   backbone_gw->orig, backbone_gw->vid,
 | 
				
			||||||
 | 
									   secs, msecs, backbone_gw->crc);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rcu_read_unlock();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						if (primary_if)
 | 
				
			||||||
 | 
							batadv_hardif_free_ref(primary_if);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,8 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid);
 | 
				
			||||||
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
 | 
					int batadv_bla_is_backbone_gw(struct sk_buff *skb,
 | 
				
			||||||
			      struct batadv_orig_node *orig_node, int hdr_size);
 | 
								      struct batadv_orig_node *orig_node, int hdr_size);
 | 
				
			||||||
int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
 | 
					int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
 | 
				
			||||||
 | 
					int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
 | 
				
			||||||
 | 
										     void *offset);
 | 
				
			||||||
int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
 | 
					int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
 | 
				
			||||||
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 | 
					int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 | 
				
			||||||
				   struct batadv_bcast_packet *bcast_packet,
 | 
									   struct batadv_bcast_packet *bcast_packet,
 | 
				
			||||||
| 
						 | 
					@ -41,8 +43,7 @@ void batadv_bla_free(struct batadv_priv *bat_priv);
 | 
				
			||||||
#else /* ifdef CONFIG_BATMAN_ADV_BLA */
 | 
					#else /* ifdef CONFIG_BATMAN_ADV_BLA */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
 | 
					static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
 | 
				
			||||||
				struct sk_buff *skb, short vid,
 | 
									struct sk_buff *skb, short vid, bool is_bcast)
 | 
				
			||||||
				bool is_bcast)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -66,6 +67,12 @@ static inline int batadv_bla_claim_table_seq_print_text(struct seq_file *seq,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
 | 
				
			||||||
 | 
												   void *offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
 | 
					static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
 | 
				
			||||||
						 uint8_t *orig)
 | 
											 uint8_t *orig)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -267,6 +267,15 @@ static int batadv_bla_claim_table_open(struct inode *inode, struct file *file)
 | 
				
			||||||
	return single_open(file, batadv_bla_claim_table_seq_print_text,
 | 
						return single_open(file, batadv_bla_claim_table_seq_print_text,
 | 
				
			||||||
			   net_dev);
 | 
								   net_dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int batadv_bla_backbone_table_open(struct inode *inode,
 | 
				
			||||||
 | 
										  struct file *file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct net_device *net_dev = (struct net_device *)inode->i_private;
 | 
				
			||||||
 | 
						return single_open(file, batadv_bla_backbone_table_seq_print_text,
 | 
				
			||||||
 | 
								   net_dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int batadv_transtable_local_open(struct inode *inode, struct file *file)
 | 
					static int batadv_transtable_local_open(struct inode *inode, struct file *file)
 | 
				
			||||||
| 
						 | 
					@ -305,6 +314,8 @@ static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
 | 
				
			||||||
			batadv_transtable_global_open);
 | 
								batadv_transtable_global_open);
 | 
				
			||||||
#ifdef CONFIG_BATMAN_ADV_BLA
 | 
					#ifdef CONFIG_BATMAN_ADV_BLA
 | 
				
			||||||
static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
 | 
					static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
 | 
				
			||||||
 | 
					static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
 | 
				
			||||||
 | 
								batadv_bla_backbone_table_open);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
 | 
					static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
 | 
				
			||||||
			batadv_transtable_local_open);
 | 
								batadv_transtable_local_open);
 | 
				
			||||||
| 
						 | 
					@ -316,6 +327,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 | 
				
			||||||
	&batadv_debuginfo_transtable_global,
 | 
						&batadv_debuginfo_transtable_global,
 | 
				
			||||||
#ifdef CONFIG_BATMAN_ADV_BLA
 | 
					#ifdef CONFIG_BATMAN_ADV_BLA
 | 
				
			||||||
	&batadv_debuginfo_bla_claim_table,
 | 
						&batadv_debuginfo_bla_claim_table,
 | 
				
			||||||
 | 
						&batadv_debuginfo_bla_backbone_table,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	&batadv_debuginfo_transtable_local,
 | 
						&batadv_debuginfo_transtable_local,
 | 
				
			||||||
	&batadv_debuginfo_vis_data,
 | 
						&batadv_debuginfo_vis_data,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv)
 | 
				
			||||||
	struct batadv_gw_node *gw_node;
 | 
						struct batadv_gw_node *gw_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	gw_node = rcu_dereference(bat_priv->curr_gw);
 | 
						gw_node = rcu_dereference(bat_priv->gw.curr_gw);
 | 
				
			||||||
	if (!gw_node)
 | 
						if (!gw_node)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,23 +91,23 @@ static void batadv_gw_select(struct batadv_priv *bat_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_gw_node *curr_gw_node;
 | 
						struct batadv_gw_node *curr_gw_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->gw_list_lock);
 | 
						spin_lock_bh(&bat_priv->gw.list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
 | 
						if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
 | 
				
			||||||
		new_gw_node = NULL;
 | 
							new_gw_node = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	curr_gw_node = rcu_dereference_protected(bat_priv->curr_gw, 1);
 | 
						curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1);
 | 
				
			||||||
	rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
 | 
						rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (curr_gw_node)
 | 
						if (curr_gw_node)
 | 
				
			||||||
		batadv_gw_node_free_ref(curr_gw_node);
 | 
							batadv_gw_node_free_ref(curr_gw_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->gw_list_lock);
 | 
						spin_unlock_bh(&bat_priv->gw.list_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void batadv_gw_deselect(struct batadv_priv *bat_priv)
 | 
					void batadv_gw_deselect(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	atomic_set(&bat_priv->gw_reselect, 1);
 | 
						atomic_set(&bat_priv->gw.reselect, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct batadv_gw_node *
 | 
					static struct batadv_gw_node *
 | 
				
			||||||
| 
						 | 
					@ -117,12 +117,17 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct batadv_gw_node *gw_node, *curr_gw = NULL;
 | 
						struct batadv_gw_node *gw_node, *curr_gw = NULL;
 | 
				
			||||||
	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
 | 
						uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
 | 
				
			||||||
 | 
						uint32_t gw_divisor;
 | 
				
			||||||
	uint8_t max_tq = 0;
 | 
						uint8_t max_tq = 0;
 | 
				
			||||||
	int down, up;
 | 
						int down, up;
 | 
				
			||||||
 | 
						uint8_t tq_avg;
 | 
				
			||||||
	struct batadv_orig_node *orig_node;
 | 
						struct batadv_orig_node *orig_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gw_divisor = BATADV_TQ_LOCAL_WINDOW_SIZE * BATADV_TQ_LOCAL_WINDOW_SIZE;
 | 
				
			||||||
 | 
						gw_divisor *= 64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
 | 
						hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) {
 | 
				
			||||||
		if (gw_node->deleted)
 | 
							if (gw_node->deleted)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -134,19 +139,19 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 | 
				
			||||||
		if (!atomic_inc_not_zero(&gw_node->refcount))
 | 
							if (!atomic_inc_not_zero(&gw_node->refcount))
 | 
				
			||||||
			goto next;
 | 
								goto next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tq_avg = router->tq_avg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (atomic_read(&bat_priv->gw_sel_class)) {
 | 
							switch (atomic_read(&bat_priv->gw_sel_class)) {
 | 
				
			||||||
		case 1: /* fast connection */
 | 
							case 1: /* fast connection */
 | 
				
			||||||
			batadv_gw_bandwidth_to_kbit(orig_node->gw_flags,
 | 
								batadv_gw_bandwidth_to_kbit(orig_node->gw_flags,
 | 
				
			||||||
						    &down, &up);
 | 
											    &down, &up);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			tmp_gw_factor = (router->tq_avg * router->tq_avg *
 | 
								tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100;
 | 
				
			||||||
					 down * 100 * 100) /
 | 
								tmp_gw_factor /= gw_divisor;
 | 
				
			||||||
					 (BATADV_TQ_LOCAL_WINDOW_SIZE *
 | 
					 | 
				
			||||||
					  BATADV_TQ_LOCAL_WINDOW_SIZE * 64);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((tmp_gw_factor > max_gw_factor) ||
 | 
								if ((tmp_gw_factor > max_gw_factor) ||
 | 
				
			||||||
			    ((tmp_gw_factor == max_gw_factor) &&
 | 
								    ((tmp_gw_factor == max_gw_factor) &&
 | 
				
			||||||
			     (router->tq_avg > max_tq))) {
 | 
								     (tq_avg > max_tq))) {
 | 
				
			||||||
				if (curr_gw)
 | 
									if (curr_gw)
 | 
				
			||||||
					batadv_gw_node_free_ref(curr_gw);
 | 
										batadv_gw_node_free_ref(curr_gw);
 | 
				
			||||||
				curr_gw = gw_node;
 | 
									curr_gw = gw_node;
 | 
				
			||||||
| 
						 | 
					@ -161,7 +166,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 | 
				
			||||||
			  *     soon as a better gateway appears which has
 | 
								  *     soon as a better gateway appears which has
 | 
				
			||||||
			  *     $routing_class more tq points)
 | 
								  *     $routing_class more tq points)
 | 
				
			||||||
			  */
 | 
								  */
 | 
				
			||||||
			if (router->tq_avg > max_tq) {
 | 
								if (tq_avg > max_tq) {
 | 
				
			||||||
				if (curr_gw)
 | 
									if (curr_gw)
 | 
				
			||||||
					batadv_gw_node_free_ref(curr_gw);
 | 
										batadv_gw_node_free_ref(curr_gw);
 | 
				
			||||||
				curr_gw = gw_node;
 | 
									curr_gw = gw_node;
 | 
				
			||||||
| 
						 | 
					@ -170,8 +175,8 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (router->tq_avg > max_tq)
 | 
							if (tq_avg > max_tq)
 | 
				
			||||||
			max_tq = router->tq_avg;
 | 
								max_tq = tq_avg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (tmp_gw_factor > max_gw_factor)
 | 
							if (tmp_gw_factor > max_gw_factor)
 | 
				
			||||||
			max_gw_factor = tmp_gw_factor;
 | 
								max_gw_factor = tmp_gw_factor;
 | 
				
			||||||
| 
						 | 
					@ -202,7 +207,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 | 
						curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect) && curr_gw)
 | 
						if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	next_gw = batadv_gw_get_best_gw_node(bat_priv);
 | 
						next_gw = batadv_gw_get_best_gw_node(bat_priv);
 | 
				
			||||||
| 
						 | 
					@ -321,9 +326,9 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
 | 
				
			||||||
	gw_node->orig_node = orig_node;
 | 
						gw_node->orig_node = orig_node;
 | 
				
			||||||
	atomic_set(&gw_node->refcount, 1);
 | 
						atomic_set(&gw_node->refcount, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->gw_list_lock);
 | 
						spin_lock_bh(&bat_priv->gw.list_lock);
 | 
				
			||||||
	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
 | 
						hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->gw_list_lock);
 | 
						spin_unlock_bh(&bat_priv->gw.list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up);
 | 
						batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up);
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 | 
						batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 | 
				
			||||||
| 
						 | 
					@ -350,7 +355,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
 | 
				
			||||||
	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 | 
						curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
 | 
						hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) {
 | 
				
			||||||
		if (gw_node->orig_node != orig_node)
 | 
							if (gw_node->orig_node != orig_node)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -404,10 +409,10 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 | 
						curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->gw_list_lock);
 | 
						spin_lock_bh(&bat_priv->gw.list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hlist_for_each_entry_safe(gw_node, node, node_tmp,
 | 
						hlist_for_each_entry_safe(gw_node, node, node_tmp,
 | 
				
			||||||
				  &bat_priv->gw_list, list) {
 | 
									  &bat_priv->gw.list, list) {
 | 
				
			||||||
		if (((!gw_node->deleted) ||
 | 
							if (((!gw_node->deleted) ||
 | 
				
			||||||
		     (time_before(jiffies, gw_node->deleted + timeout))) &&
 | 
							     (time_before(jiffies, gw_node->deleted + timeout))) &&
 | 
				
			||||||
		    atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE)
 | 
							    atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE)
 | 
				
			||||||
| 
						 | 
					@ -420,7 +425,7 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv)
 | 
				
			||||||
		batadv_gw_node_free_ref(gw_node);
 | 
							batadv_gw_node_free_ref(gw_node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->gw_list_lock);
 | 
						spin_unlock_bh(&bat_priv->gw.list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* gw_deselect() needs to acquire the gw_list_lock */
 | 
						/* gw_deselect() needs to acquire the gw_list_lock */
 | 
				
			||||||
	if (do_deselect)
 | 
						if (do_deselect)
 | 
				
			||||||
| 
						 | 
					@ -496,7 +501,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
		   primary_if->net_dev->dev_addr, net_dev->name);
 | 
							   primary_if->net_dev->dev_addr, net_dev->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
 | 
						hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) {
 | 
				
			||||||
		if (gw_node->deleted)
 | 
							if (gw_node->deleted)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,13 +103,14 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_vis_packet *vis_packet;
 | 
						struct batadv_vis_packet *vis_packet;
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
 | 
						struct sk_buff *skb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
						primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
				
			||||||
	if (!primary_if)
 | 
						if (!primary_if)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vis_packet = (struct batadv_vis_packet *)
 | 
						skb = bat_priv->vis.my_info->skb_packet;
 | 
				
			||||||
				bat_priv->my_vis_info->skb_packet->data;
 | 
						vis_packet = (struct batadv_vis_packet *)skb->data;
 | 
				
			||||||
	memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
 | 
						memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
 | 
				
			||||||
	memcpy(vis_packet->sender_orig,
 | 
						memcpy(vis_packet->sender_orig,
 | 
				
			||||||
	       primary_if->net_dev->dev_addr, ETH_ALEN);
 | 
						       primary_if->net_dev->dev_addr, ETH_ALEN);
 | 
				
			||||||
| 
						 | 
					@ -313,7 +314,13 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 | 
				
			||||||
	hard_iface->if_num = bat_priv->num_ifaces;
 | 
						hard_iface->if_num = bat_priv->num_ifaces;
 | 
				
			||||||
	bat_priv->num_ifaces++;
 | 
						bat_priv->num_ifaces++;
 | 
				
			||||||
	hard_iface->if_status = BATADV_IF_INACTIVE;
 | 
						hard_iface->if_status = BATADV_IF_INACTIVE;
 | 
				
			||||||
	batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
 | 
						ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
 | 
				
			||||||
 | 
							bat_priv->num_ifaces--;
 | 
				
			||||||
 | 
							hard_iface->if_status = BATADV_IF_NOT_IN_USE;
 | 
				
			||||||
 | 
							goto err_dev;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hard_iface->batman_adv_ptype.type = ethertype;
 | 
						hard_iface->batman_adv_ptype.type = ethertype;
 | 
				
			||||||
	hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv;
 | 
						hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,9 +58,6 @@ static int __init batadv_init(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_iv_init();
 | 
						batadv_iv_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the name should not be longer than 10 chars - see
 | 
					 | 
				
			||||||
	 * http://lwn.net/Articles/23634/
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	batadv_event_workqueue = create_singlethread_workqueue("bat_events");
 | 
						batadv_event_workqueue = create_singlethread_workqueue("bat_events");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!batadv_event_workqueue)
 | 
						if (!batadv_event_workqueue)
 | 
				
			||||||
| 
						 | 
					@ -97,20 +94,20 @@ int batadv_mesh_init(struct net_device *soft_iface)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_init(&bat_priv->forw_bat_list_lock);
 | 
						spin_lock_init(&bat_priv->forw_bat_list_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->forw_bcast_list_lock);
 | 
						spin_lock_init(&bat_priv->forw_bcast_list_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->tt_changes_list_lock);
 | 
						spin_lock_init(&bat_priv->tt.changes_list_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->tt_req_list_lock);
 | 
						spin_lock_init(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->tt_roam_list_lock);
 | 
						spin_lock_init(&bat_priv->tt.roam_list_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->tt_buff_lock);
 | 
						spin_lock_init(&bat_priv->tt.last_changeset_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->gw_list_lock);
 | 
						spin_lock_init(&bat_priv->gw.list_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->vis_hash_lock);
 | 
						spin_lock_init(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	spin_lock_init(&bat_priv->vis_list_lock);
 | 
						spin_lock_init(&bat_priv->vis.list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
 | 
						INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
 | 
				
			||||||
	INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
 | 
						INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
 | 
				
			||||||
	INIT_HLIST_HEAD(&bat_priv->gw_list);
 | 
						INIT_HLIST_HEAD(&bat_priv->gw.list);
 | 
				
			||||||
	INIT_LIST_HEAD(&bat_priv->tt_changes_list);
 | 
						INIT_LIST_HEAD(&bat_priv->tt.changes_list);
 | 
				
			||||||
	INIT_LIST_HEAD(&bat_priv->tt_req_list);
 | 
						INIT_LIST_HEAD(&bat_priv->tt.req_list);
 | 
				
			||||||
	INIT_LIST_HEAD(&bat_priv->tt_roam_list);
 | 
						INIT_LIST_HEAD(&bat_priv->tt.roam_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = batadv_originator_init(bat_priv);
 | 
						ret = batadv_originator_init(bat_priv);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
| 
						 | 
					@ -131,7 +128,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	atomic_set(&bat_priv->gw_reselect, 0);
 | 
						atomic_set(&bat_priv->gw.reselect, 0);
 | 
				
			||||||
	atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
 | 
						atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@
 | 
				
			||||||
#define BATADV_DRIVER_DEVICE "batman-adv"
 | 
					#define BATADV_DRIVER_DEVICE "batman-adv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef BATADV_SOURCE_VERSION
 | 
					#ifndef BATADV_SOURCE_VERSION
 | 
				
			||||||
#define BATADV_SOURCE_VERSION "2012.3.0"
 | 
					#define BATADV_SOURCE_VERSION "2012.4.0"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* B.A.T.M.A.N. parameters */
 | 
					/* B.A.T.M.A.N. parameters */
 | 
				
			||||||
| 
						 | 
					@ -41,13 +41,14 @@
 | 
				
			||||||
 * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE
 | 
					 * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */
 | 
					#define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */
 | 
				
			||||||
#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in miliseconds */
 | 
					#define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */
 | 
				
			||||||
#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in miliseconds */
 | 
					#define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */
 | 
				
			||||||
 | 
					#define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */
 | 
				
			||||||
/* sliding packet range of received originator messages in sequence numbers
 | 
					/* sliding packet range of received originator messages in sequence numbers
 | 
				
			||||||
 * (should be a multiple of our word size)
 | 
					 * (should be a multiple of our word size)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define BATADV_TQ_LOCAL_WINDOW_SIZE 64
 | 
					#define BATADV_TQ_LOCAL_WINDOW_SIZE 64
 | 
				
			||||||
/* miliseconds we have to keep pending tt_req */
 | 
					/* milliseconds we have to keep pending tt_req */
 | 
				
			||||||
#define BATADV_TT_REQUEST_TIMEOUT 3000
 | 
					#define BATADV_TT_REQUEST_TIMEOUT 3000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BATADV_TQ_GLOBAL_WINDOW_SIZE 5
 | 
					#define BATADV_TQ_GLOBAL_WINDOW_SIZE 5
 | 
				
			||||||
| 
						 | 
					@ -59,7 +60,7 @@
 | 
				
			||||||
#define BATADV_TT_OGM_APPEND_MAX 3
 | 
					#define BATADV_TT_OGM_APPEND_MAX 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Time in which a client can roam at most ROAMING_MAX_COUNT times in
 | 
					/* Time in which a client can roam at most ROAMING_MAX_COUNT times in
 | 
				
			||||||
 * miliseconds
 | 
					 * milliseconds
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define BATADV_ROAMING_MAX_TIME 20000
 | 
					#define BATADV_ROAMING_MAX_TIME 20000
 | 
				
			||||||
#define BATADV_ROAMING_MAX_COUNT 5
 | 
					#define BATADV_ROAMING_MAX_COUNT 5
 | 
				
			||||||
| 
						 | 
					@ -123,15 +124,6 @@ enum batadv_uev_type {
 | 
				
			||||||
/* Append 'batman-adv: ' before kernel messages */
 | 
					/* Append 'batman-adv: ' before kernel messages */
 | 
				
			||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | 
					#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* all messages related to routing / flooding / broadcasting / etc */
 | 
					 | 
				
			||||||
enum batadv_dbg_level {
 | 
					 | 
				
			||||||
	BATADV_DBG_BATMAN = 1 << 0,
 | 
					 | 
				
			||||||
	BATADV_DBG_ROUTES = 1 << 1, /* route added / changed / deleted */
 | 
					 | 
				
			||||||
	BATADV_DBG_TT	  = 1 << 2, /* translation table operations */
 | 
					 | 
				
			||||||
	BATADV_DBG_BLA    = 1 << 3, /* bridge loop avoidance */
 | 
					 | 
				
			||||||
	BATADV_DBG_ALL    = 15,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Kernel headers */
 | 
					/* Kernel headers */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/mutex.h>	/* mutex */
 | 
					#include <linux/mutex.h>	/* mutex */
 | 
				
			||||||
| 
						 | 
					@ -173,6 +165,15 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 | 
				
			||||||
int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 | 
					int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 | 
				
			||||||
int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
 | 
					int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* all messages related to routing / flooding / broadcasting / etc */
 | 
				
			||||||
 | 
					enum batadv_dbg_level {
 | 
				
			||||||
 | 
						BATADV_DBG_BATMAN = BIT(0),
 | 
				
			||||||
 | 
						BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */
 | 
				
			||||||
 | 
						BATADV_DBG_TT	  = BIT(2), /* translation table operations */
 | 
				
			||||||
 | 
						BATADV_DBG_BLA    = BIT(3), /* bridge loop avoidance */
 | 
				
			||||||
 | 
						BATADV_DBG_ALL    = 15,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_BATMAN_ADV_DEBUG
 | 
					#ifdef CONFIG_BATMAN_ADV_DEBUG
 | 
				
			||||||
int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
 | 
					int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
 | 
				
			||||||
__printf(2, 3);
 | 
					__printf(2, 3);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,10 +37,10 @@ enum batadv_packettype {
 | 
				
			||||||
#define BATADV_COMPAT_VERSION 14
 | 
					#define BATADV_COMPAT_VERSION 14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum batadv_iv_flags {
 | 
					enum batadv_iv_flags {
 | 
				
			||||||
	BATADV_NOT_BEST_NEXT_HOP   = 1 << 3,
 | 
						BATADV_NOT_BEST_NEXT_HOP   = BIT(3),
 | 
				
			||||||
	BATADV_PRIMARIES_FIRST_HOP = 1 << 4,
 | 
						BATADV_PRIMARIES_FIRST_HOP = BIT(4),
 | 
				
			||||||
	BATADV_VIS_SERVER	   = 1 << 5,
 | 
						BATADV_VIS_SERVER	   = BIT(5),
 | 
				
			||||||
	BATADV_DIRECTLINK	   = 1 << 6,
 | 
						BATADV_DIRECTLINK	   = BIT(6),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ICMP message types */
 | 
					/* ICMP message types */
 | 
				
			||||||
| 
						 | 
					@ -60,8 +60,8 @@ enum batadv_vis_packettype {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* fragmentation defines */
 | 
					/* fragmentation defines */
 | 
				
			||||||
enum batadv_unicast_frag_flags {
 | 
					enum batadv_unicast_frag_flags {
 | 
				
			||||||
	BATADV_UNI_FRAG_HEAD	  = 1 << 0,
 | 
						BATADV_UNI_FRAG_HEAD	  = BIT(0),
 | 
				
			||||||
	BATADV_UNI_FRAG_LARGETAIL = 1 << 1,
 | 
						BATADV_UNI_FRAG_LARGETAIL = BIT(1),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TT_QUERY subtypes */
 | 
					/* TT_QUERY subtypes */
 | 
				
			||||||
| 
						 | 
					@ -74,26 +74,27 @@ enum batadv_tt_query_packettype {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TT_QUERY flags */
 | 
					/* TT_QUERY flags */
 | 
				
			||||||
enum batadv_tt_query_flags {
 | 
					enum batadv_tt_query_flags {
 | 
				
			||||||
	BATADV_TT_FULL_TABLE = 1 << 2,
 | 
						BATADV_TT_FULL_TABLE = BIT(2),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* BATADV_TT_CLIENT flags.
 | 
					/* BATADV_TT_CLIENT flags.
 | 
				
			||||||
 * Flags from 1 to 1 << 7 are sent on the wire, while flags from 1 << 8 to
 | 
					 * Flags from BIT(0) to BIT(7) are sent on the wire, while flags from BIT(8) to
 | 
				
			||||||
 * 1 << 15 are used for local computation only
 | 
					 * BIT(15) are used for local computation only
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum batadv_tt_client_flags {
 | 
					enum batadv_tt_client_flags {
 | 
				
			||||||
	BATADV_TT_CLIENT_DEL     = 1 << 0,
 | 
						BATADV_TT_CLIENT_DEL     = BIT(0),
 | 
				
			||||||
	BATADV_TT_CLIENT_ROAM    = 1 << 1,
 | 
						BATADV_TT_CLIENT_ROAM    = BIT(1),
 | 
				
			||||||
	BATADV_TT_CLIENT_WIFI    = 1 << 2,
 | 
						BATADV_TT_CLIENT_WIFI    = BIT(2),
 | 
				
			||||||
	BATADV_TT_CLIENT_NOPURGE = 1 << 8,
 | 
						BATADV_TT_CLIENT_TEMP	 = BIT(3),
 | 
				
			||||||
	BATADV_TT_CLIENT_NEW     = 1 << 9,
 | 
						BATADV_TT_CLIENT_NOPURGE = BIT(8),
 | 
				
			||||||
	BATADV_TT_CLIENT_PENDING = 1 << 10,
 | 
						BATADV_TT_CLIENT_NEW     = BIT(9),
 | 
				
			||||||
 | 
						BATADV_TT_CLIENT_PENDING = BIT(10),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* claim frame types for the bridge loop avoidance */
 | 
					/* claim frame types for the bridge loop avoidance */
 | 
				
			||||||
enum batadv_bla_claimframe {
 | 
					enum batadv_bla_claimframe {
 | 
				
			||||||
	BATADV_CLAIM_TYPE_ADD		= 0x00,
 | 
						BATADV_CLAIM_TYPE_CLAIM		= 0x00,
 | 
				
			||||||
	BATADV_CLAIM_TYPE_DEL		= 0x01,
 | 
						BATADV_CLAIM_TYPE_UNCLAIM	= 0x01,
 | 
				
			||||||
	BATADV_CLAIM_TYPE_ANNOUNCE	= 0x02,
 | 
						BATADV_CLAIM_TYPE_ANNOUNCE	= 0x02,
 | 
				
			||||||
	BATADV_CLAIM_TYPE_REQUEST	= 0x03,
 | 
						BATADV_CLAIM_TYPE_REQUEST	= 0x03,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -579,32 +579,45 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
 | 
				
			||||||
	return router;
 | 
						return router;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
 | 
					static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 | 
					 | 
				
			||||||
	struct batadv_tt_query_packet *tt_query;
 | 
					 | 
				
			||||||
	uint16_t tt_size;
 | 
					 | 
				
			||||||
	struct ethhdr *ethhdr;
 | 
						struct ethhdr *ethhdr;
 | 
				
			||||||
	char tt_flag;
 | 
					 | 
				
			||||||
	size_t packet_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* drop packet if it has not necessary minimum size */
 | 
						/* drop packet if it has not necessary minimum size */
 | 
				
			||||||
	if (unlikely(!pskb_may_pull(skb,
 | 
						if (unlikely(!pskb_may_pull(skb, hdr_size)))
 | 
				
			||||||
				    sizeof(struct batadv_tt_query_packet))))
 | 
							return -1;
 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* I could need to modify it */
 | 
					 | 
				
			||||||
	if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 | 
						ethhdr = (struct ethhdr *)skb_mac_header(skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* packet with unicast indication but broadcast recipient */
 | 
						/* packet with unicast indication but broadcast recipient */
 | 
				
			||||||
	if (is_broadcast_ether_addr(ethhdr->h_dest))
 | 
						if (is_broadcast_ether_addr(ethhdr->h_dest))
 | 
				
			||||||
		goto out;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* packet with broadcast sender address */
 | 
						/* packet with broadcast sender address */
 | 
				
			||||||
	if (is_broadcast_ether_addr(ethhdr->h_source))
 | 
						if (is_broadcast_ether_addr(ethhdr->h_source))
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* not for me */
 | 
				
			||||||
 | 
						if (!batadv_is_my_mac(ethhdr->h_dest))
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 | 
				
			||||||
 | 
						struct batadv_tt_query_packet *tt_query;
 | 
				
			||||||
 | 
						uint16_t tt_size;
 | 
				
			||||||
 | 
						int hdr_size = sizeof(*tt_query);
 | 
				
			||||||
 | 
						char tt_flag;
 | 
				
			||||||
 | 
						size_t packet_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (batadv_check_unicast_packet(skb, hdr_size) < 0)
 | 
				
			||||||
 | 
							return NET_RX_DROP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* I could need to modify it */
 | 
				
			||||||
 | 
						if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tt_query = (struct batadv_tt_query_packet *)skb->data;
 | 
						tt_query = (struct batadv_tt_query_packet *)skb->data;
 | 
				
			||||||
| 
						 | 
					@ -721,7 +734,7 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
 | 
				
			||||||
	 * been incremented yet. This flag will make me check all the incoming
 | 
						 * been incremented yet. This flag will make me check all the incoming
 | 
				
			||||||
	 * packets for the correct destination.
 | 
						 * packets for the correct destination.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	bat_priv->tt_poss_change = true;
 | 
						bat_priv->tt.poss_change = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_orig_node_free_ref(orig_node);
 | 
						batadv_orig_node_free_ref(orig_node);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
| 
						 | 
					@ -819,31 +832,6 @@ err:
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ethhdr *ethhdr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* drop packet if it has not necessary minimum size */
 | 
					 | 
				
			||||||
	if (unlikely(!pskb_may_pull(skb, hdr_size)))
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* packet with unicast indication but broadcast recipient */
 | 
					 | 
				
			||||||
	if (is_broadcast_ether_addr(ethhdr->h_dest))
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* packet with broadcast sender address */
 | 
					 | 
				
			||||||
	if (is_broadcast_ether_addr(ethhdr->h_source))
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* not for me */
 | 
					 | 
				
			||||||
	if (!batadv_is_my_mac(ethhdr->h_dest))
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int batadv_route_unicast_packet(struct sk_buff *skb,
 | 
					static int batadv_route_unicast_packet(struct sk_buff *skb,
 | 
				
			||||||
				       struct batadv_hard_iface *recv_if)
 | 
									       struct batadv_hard_iface *recv_if)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -947,8 +935,8 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
 | 
				
			||||||
	unicast_packet = (struct batadv_unicast_packet *)skb->data;
 | 
						unicast_packet = (struct batadv_unicast_packet *)skb->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (batadv_is_my_mac(unicast_packet->dest)) {
 | 
						if (batadv_is_my_mac(unicast_packet->dest)) {
 | 
				
			||||||
		tt_poss_change = bat_priv->tt_poss_change;
 | 
							tt_poss_change = bat_priv->tt.poss_change;
 | 
				
			||||||
		curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
 | 
							curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		orig_node = batadv_orig_hash_find(bat_priv,
 | 
							orig_node = batadv_orig_hash_find(bat_priv,
 | 
				
			||||||
						  unicast_packet->dest);
 | 
											  unicast_packet->dest);
 | 
				
			||||||
| 
						 | 
					@ -993,8 +981,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			memcpy(unicast_packet->dest, orig_node->orig,
 | 
								memcpy(unicast_packet->dest, orig_node->orig,
 | 
				
			||||||
			       ETH_ALEN);
 | 
								       ETH_ALEN);
 | 
				
			||||||
			curr_ttvn = (uint8_t)
 | 
								curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
 | 
				
			||||||
				atomic_read(&orig_node->last_ttvn);
 | 
					 | 
				
			||||||
			batadv_orig_node_free_ref(orig_node);
 | 
								batadv_orig_node_free_ref(orig_node);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1025,8 +1012,9 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* packet for me */
 | 
						/* packet for me */
 | 
				
			||||||
	if (batadv_is_my_mac(unicast_packet->dest)) {
 | 
						if (batadv_is_my_mac(unicast_packet->dest)) {
 | 
				
			||||||
		batadv_interface_rx(recv_if->soft_iface, skb, recv_if,
 | 
							batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
 | 
				
			||||||
				    hdr_size);
 | 
									    NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return NET_RX_SUCCESS;
 | 
							return NET_RX_SUCCESS;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1063,7 +1051,7 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
 | 
				
			||||||
			return NET_RX_SUCCESS;
 | 
								return NET_RX_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
 | 
							batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
 | 
				
			||||||
				    sizeof(struct batadv_unicast_packet));
 | 
									    sizeof(struct batadv_unicast_packet), NULL);
 | 
				
			||||||
		return NET_RX_SUCCESS;
 | 
							return NET_RX_SUCCESS;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1150,7 +1138,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* broadcast for me */
 | 
						/* broadcast for me */
 | 
				
			||||||
	batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
 | 
						batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
 | 
				
			||||||
 | 
								    orig_node);
 | 
				
			||||||
	ret = NET_RX_SUCCESS;
 | 
						ret = NET_RX_SUCCESS;
 | 
				
			||||||
	goto out;
 | 
						goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,13 +190,13 @@ out:
 | 
				
			||||||
static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
 | 
					static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hard_iface *hard_iface;
 | 
						struct batadv_hard_iface *hard_iface;
 | 
				
			||||||
	struct delayed_work *delayed_work =
 | 
						struct delayed_work *delayed_work;
 | 
				
			||||||
		container_of(work, struct delayed_work, work);
 | 
					 | 
				
			||||||
	struct batadv_forw_packet *forw_packet;
 | 
						struct batadv_forw_packet *forw_packet;
 | 
				
			||||||
	struct sk_buff *skb1;
 | 
						struct sk_buff *skb1;
 | 
				
			||||||
	struct net_device *soft_iface;
 | 
						struct net_device *soft_iface;
 | 
				
			||||||
	struct batadv_priv *bat_priv;
 | 
						struct batadv_priv *bat_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delayed_work = container_of(work, struct delayed_work, work);
 | 
				
			||||||
	forw_packet = container_of(delayed_work, struct batadv_forw_packet,
 | 
						forw_packet = container_of(delayed_work, struct batadv_forw_packet,
 | 
				
			||||||
				   delayed_work);
 | 
									   delayed_work);
 | 
				
			||||||
	soft_iface = forw_packet->if_incoming->soft_iface;
 | 
						soft_iface = forw_packet->if_incoming->soft_iface;
 | 
				
			||||||
| 
						 | 
					@ -239,11 +239,11 @@ out:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work)
 | 
					void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct delayed_work *delayed_work =
 | 
						struct delayed_work *delayed_work;
 | 
				
			||||||
		container_of(work, struct delayed_work, work);
 | 
					 | 
				
			||||||
	struct batadv_forw_packet *forw_packet;
 | 
						struct batadv_forw_packet *forw_packet;
 | 
				
			||||||
	struct batadv_priv *bat_priv;
 | 
						struct batadv_priv *bat_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delayed_work = container_of(work, struct delayed_work, work);
 | 
				
			||||||
	forw_packet = container_of(delayed_work, struct batadv_forw_packet,
 | 
						forw_packet = container_of(delayed_work, struct batadv_forw_packet,
 | 
				
			||||||
				   delayed_work);
 | 
									   delayed_work);
 | 
				
			||||||
	bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
 | 
						bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,14 @@ static int batadv_interface_release(struct net_device *dev)
 | 
				
			||||||
static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
 | 
					static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_priv *bat_priv = netdev_priv(dev);
 | 
						struct batadv_priv *bat_priv = netdev_priv(dev);
 | 
				
			||||||
	return &bat_priv->stats;
 | 
						struct net_device_stats *stats = &bat_priv->stats;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stats->tx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_TX);
 | 
				
			||||||
 | 
						stats->tx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_TX_BYTES);
 | 
				
			||||||
 | 
						stats->tx_dropped = batadv_sum_counter(bat_priv, BATADV_CNT_TX_DROPPED);
 | 
				
			||||||
 | 
						stats->rx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_RX);
 | 
				
			||||||
 | 
						stats->rx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_RX_BYTES);
 | 
				
			||||||
 | 
						return stats;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
 | 
					static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
 | 
				
			||||||
| 
						 | 
					@ -142,6 +149,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
 | 
				
			||||||
	int data_len = skb->len, ret;
 | 
						int data_len = skb->len, ret;
 | 
				
			||||||
	short vid __maybe_unused = -1;
 | 
						short vid __maybe_unused = -1;
 | 
				
			||||||
	bool do_bcast = false;
 | 
						bool do_bcast = false;
 | 
				
			||||||
 | 
						uint32_t seqno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
 | 
						if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
 | 
				
			||||||
		goto dropped;
 | 
							goto dropped;
 | 
				
			||||||
| 
						 | 
					@ -223,8 +231,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
 | 
				
			||||||
		       primary_if->net_dev->dev_addr, ETH_ALEN);
 | 
							       primary_if->net_dev->dev_addr, ETH_ALEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* set broadcast sequence number */
 | 
							/* set broadcast sequence number */
 | 
				
			||||||
		bcast_packet->seqno =
 | 
							seqno = atomic_inc_return(&bat_priv->bcast_seqno);
 | 
				
			||||||
			htonl(atomic_inc_return(&bat_priv->bcast_seqno));
 | 
							bcast_packet->seqno = htonl(seqno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		batadv_add_bcast_packet_to_list(bat_priv, skb, 1);
 | 
							batadv_add_bcast_packet_to_list(bat_priv, skb, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -246,14 +254,14 @@ static int batadv_interface_tx(struct sk_buff *skb,
 | 
				
			||||||
			goto dropped_freed;
 | 
								goto dropped_freed;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->stats.tx_packets++;
 | 
						batadv_inc_counter(bat_priv, BATADV_CNT_TX);
 | 
				
			||||||
	bat_priv->stats.tx_bytes += data_len;
 | 
						batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len);
 | 
				
			||||||
	goto end;
 | 
						goto end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dropped:
 | 
					dropped:
 | 
				
			||||||
	kfree_skb(skb);
 | 
						kfree_skb(skb);
 | 
				
			||||||
dropped_freed:
 | 
					dropped_freed:
 | 
				
			||||||
	bat_priv->stats.tx_dropped++;
 | 
						batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED);
 | 
				
			||||||
end:
 | 
					end:
 | 
				
			||||||
	if (primary_if)
 | 
						if (primary_if)
 | 
				
			||||||
		batadv_hardif_free_ref(primary_if);
 | 
							batadv_hardif_free_ref(primary_if);
 | 
				
			||||||
| 
						 | 
					@ -262,7 +270,7 @@ end:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void batadv_interface_rx(struct net_device *soft_iface,
 | 
					void batadv_interface_rx(struct net_device *soft_iface,
 | 
				
			||||||
			 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
 | 
								 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
 | 
				
			||||||
			 int hdr_size)
 | 
								 int hdr_size, struct batadv_orig_node *orig_node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
 | 
						struct batadv_priv *bat_priv = netdev_priv(soft_iface);
 | 
				
			||||||
	struct ethhdr *ethhdr;
 | 
						struct ethhdr *ethhdr;
 | 
				
			||||||
| 
						 | 
					@ -308,11 +316,16 @@ void batadv_interface_rx(struct net_device *soft_iface,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* skb->ip_summed = CHECKSUM_UNNECESSARY; */
 | 
						/* skb->ip_summed = CHECKSUM_UNNECESSARY; */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->stats.rx_packets++;
 | 
						batadv_inc_counter(bat_priv, BATADV_CNT_RX);
 | 
				
			||||||
	bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
 | 
						batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
 | 
				
			||||||
 | 
								   skb->len + ETH_HLEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	soft_iface->last_rx = jiffies;
 | 
						soft_iface->last_rx = jiffies;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (orig_node)
 | 
				
			||||||
 | 
							batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
 | 
				
			||||||
 | 
											     ethhdr->h_source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
 | 
						if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
 | 
				
			||||||
		goto dropped;
 | 
							goto dropped;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -379,15 +392,22 @@ struct net_device *batadv_softif_create(const char *name)
 | 
				
			||||||
	if (!soft_iface)
 | 
						if (!soft_iface)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bat_priv = netdev_priv(soft_iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* batadv_interface_stats() needs to be available as soon as
 | 
				
			||||||
 | 
						 * register_netdevice() has been called
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
 | 
				
			||||||
 | 
						if (!bat_priv->bat_counters)
 | 
				
			||||||
 | 
							goto free_soft_iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = register_netdevice(soft_iface);
 | 
						ret = register_netdevice(soft_iface);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		pr_err("Unable to register the batman interface '%s': %i\n",
 | 
							pr_err("Unable to register the batman interface '%s': %i\n",
 | 
				
			||||||
		       name, ret);
 | 
							       name, ret);
 | 
				
			||||||
		goto free_soft_iface;
 | 
							goto free_bat_counters;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv = netdev_priv(soft_iface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	atomic_set(&bat_priv->aggregated_ogms, 1);
 | 
						atomic_set(&bat_priv->aggregated_ogms, 1);
 | 
				
			||||||
	atomic_set(&bat_priv->bonding, 0);
 | 
						atomic_set(&bat_priv->bonding, 0);
 | 
				
			||||||
	atomic_set(&bat_priv->bridge_loop_avoidance, 0);
 | 
						atomic_set(&bat_priv->bridge_loop_avoidance, 0);
 | 
				
			||||||
| 
						 | 
					@ -405,29 +425,26 @@ struct net_device *batadv_softif_create(const char *name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
 | 
						atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
 | 
				
			||||||
	atomic_set(&bat_priv->bcast_seqno, 1);
 | 
						atomic_set(&bat_priv->bcast_seqno, 1);
 | 
				
			||||||
	atomic_set(&bat_priv->ttvn, 0);
 | 
						atomic_set(&bat_priv->tt.vn, 0);
 | 
				
			||||||
	atomic_set(&bat_priv->tt_local_changes, 0);
 | 
						atomic_set(&bat_priv->tt.local_changes, 0);
 | 
				
			||||||
	atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
 | 
						atomic_set(&bat_priv->tt.ogm_append_cnt, 0);
 | 
				
			||||||
	atomic_set(&bat_priv->bla_num_requests, 0);
 | 
					#ifdef CONFIG_BATMAN_ADV_BLA
 | 
				
			||||||
 | 
						atomic_set(&bat_priv->bla.num_requests, 0);
 | 
				
			||||||
	bat_priv->tt_buff = NULL;
 | 
					#endif
 | 
				
			||||||
	bat_priv->tt_buff_len = 0;
 | 
						bat_priv->tt.last_changeset = NULL;
 | 
				
			||||||
	bat_priv->tt_poss_change = false;
 | 
						bat_priv->tt.last_changeset_len = 0;
 | 
				
			||||||
 | 
						bat_priv->tt.poss_change = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->primary_if = NULL;
 | 
						bat_priv->primary_if = NULL;
 | 
				
			||||||
	bat_priv->num_ifaces = 0;
 | 
						bat_priv->num_ifaces = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t));
 | 
					 | 
				
			||||||
	if (!bat_priv->bat_counters)
 | 
					 | 
				
			||||||
		goto unreg_soft_iface;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = batadv_algo_select(bat_priv, batadv_routing_algo);
 | 
						ret = batadv_algo_select(bat_priv, batadv_routing_algo);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto free_bat_counters;
 | 
							goto unreg_soft_iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = batadv_sysfs_add_meshif(soft_iface);
 | 
						ret = batadv_sysfs_add_meshif(soft_iface);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto free_bat_counters;
 | 
							goto unreg_soft_iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = batadv_debugfs_add_meshif(soft_iface);
 | 
						ret = batadv_debugfs_add_meshif(soft_iface);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
| 
						 | 
					@ -443,12 +460,13 @@ unreg_debugfs:
 | 
				
			||||||
	batadv_debugfs_del_meshif(soft_iface);
 | 
						batadv_debugfs_del_meshif(soft_iface);
 | 
				
			||||||
unreg_sysfs:
 | 
					unreg_sysfs:
 | 
				
			||||||
	batadv_sysfs_del_meshif(soft_iface);
 | 
						batadv_sysfs_del_meshif(soft_iface);
 | 
				
			||||||
free_bat_counters:
 | 
					 | 
				
			||||||
	free_percpu(bat_priv->bat_counters);
 | 
					 | 
				
			||||||
unreg_soft_iface:
 | 
					unreg_soft_iface:
 | 
				
			||||||
 | 
						free_percpu(bat_priv->bat_counters);
 | 
				
			||||||
	unregister_netdevice(soft_iface);
 | 
						unregister_netdevice(soft_iface);
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					free_bat_counters:
 | 
				
			||||||
 | 
						free_percpu(bat_priv->bat_counters);
 | 
				
			||||||
free_soft_iface:
 | 
					free_soft_iface:
 | 
				
			||||||
	free_netdev(soft_iface);
 | 
						free_netdev(soft_iface);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
| 
						 | 
					@ -518,6 +536,11 @@ static u32 batadv_get_link(struct net_device *dev)
 | 
				
			||||||
static const struct {
 | 
					static const struct {
 | 
				
			||||||
	const char name[ETH_GSTRING_LEN];
 | 
						const char name[ETH_GSTRING_LEN];
 | 
				
			||||||
} batadv_counters_strings[] = {
 | 
					} batadv_counters_strings[] = {
 | 
				
			||||||
 | 
						{ "tx" },
 | 
				
			||||||
 | 
						{ "tx_bytes" },
 | 
				
			||||||
 | 
						{ "tx_dropped" },
 | 
				
			||||||
 | 
						{ "rx" },
 | 
				
			||||||
 | 
						{ "rx_bytes" },
 | 
				
			||||||
	{ "forward" },
 | 
						{ "forward" },
 | 
				
			||||||
	{ "forward_bytes" },
 | 
						{ "forward_bytes" },
 | 
				
			||||||
	{ "mgmt_tx" },
 | 
						{ "mgmt_tx" },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,8 +21,9 @@
 | 
				
			||||||
#define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
 | 
					#define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int batadv_skb_head_push(struct sk_buff *skb, unsigned int len);
 | 
					int batadv_skb_head_push(struct sk_buff *skb, unsigned int len);
 | 
				
			||||||
void batadv_interface_rx(struct net_device *soft_iface, struct sk_buff *skb,
 | 
					void batadv_interface_rx(struct net_device *soft_iface,
 | 
				
			||||||
			 struct batadv_hard_iface *recv_if, int hdr_size);
 | 
								 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
 | 
				
			||||||
 | 
								 int hdr_size, struct batadv_orig_node *orig_node);
 | 
				
			||||||
struct net_device *batadv_softif_create(const char *name);
 | 
					struct net_device *batadv_softif_create(const char *name);
 | 
				
			||||||
void batadv_softif_destroy(struct net_device *soft_iface);
 | 
					void batadv_softif_destroy(struct net_device *soft_iface);
 | 
				
			||||||
int batadv_softif_is_valid(const struct net_device *net_dev);
 | 
					int batadv_softif_is_valid(const struct net_device *net_dev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,10 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
 | 
				
			||||||
static void batadv_tt_purge(struct work_struct *work);
 | 
					static void batadv_tt_purge(struct work_struct *work);
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
 | 
					batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
 | 
				
			||||||
 | 
					static void batadv_tt_global_del(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
									 struct batadv_orig_node *orig_node,
 | 
				
			||||||
 | 
									 const unsigned char *addr,
 | 
				
			||||||
 | 
									 const char *message, bool roaming);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* returns 1 if they are the same mac addr */
 | 
					/* returns 1 if they are the same mac addr */
 | 
				
			||||||
static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
 | 
					static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
 | 
				
			||||||
| 
						 | 
					@ -46,8 +50,8 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_tt_start_timer(struct batadv_priv *bat_priv)
 | 
					static void batadv_tt_start_timer(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	INIT_DELAYED_WORK(&bat_priv->tt_work, batadv_tt_purge);
 | 
						INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
 | 
				
			||||||
	queue_delayed_work(batadv_event_workqueue, &bat_priv->tt_work,
 | 
						queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
 | 
				
			||||||
			   msecs_to_jiffies(5000));
 | 
								   msecs_to_jiffies(5000));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +92,7 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data)
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common_entry;
 | 
						struct batadv_tt_common_entry *tt_common_entry;
 | 
				
			||||||
	struct batadv_tt_local_entry *tt_local_entry = NULL;
 | 
						struct batadv_tt_local_entry *tt_local_entry = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tt_common_entry = batadv_tt_hash_find(bat_priv->tt_local_hash, data);
 | 
						tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data);
 | 
				
			||||||
	if (tt_common_entry)
 | 
						if (tt_common_entry)
 | 
				
			||||||
		tt_local_entry = container_of(tt_common_entry,
 | 
							tt_local_entry = container_of(tt_common_entry,
 | 
				
			||||||
					      struct batadv_tt_local_entry,
 | 
										      struct batadv_tt_local_entry,
 | 
				
			||||||
| 
						 | 
					@ -102,7 +106,7 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data)
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common_entry;
 | 
						struct batadv_tt_common_entry *tt_common_entry;
 | 
				
			||||||
	struct batadv_tt_global_entry *tt_global_entry = NULL;
 | 
						struct batadv_tt_global_entry *tt_global_entry = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tt_common_entry = batadv_tt_hash_find(bat_priv->tt_global_hash, data);
 | 
						tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data);
 | 
				
			||||||
	if (tt_common_entry)
 | 
						if (tt_common_entry)
 | 
				
			||||||
		tt_global_entry = container_of(tt_common_entry,
 | 
							tt_global_entry = container_of(tt_common_entry,
 | 
				
			||||||
					       struct batadv_tt_global_entry,
 | 
										       struct batadv_tt_global_entry,
 | 
				
			||||||
| 
						 | 
					@ -152,6 +156,8 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
 | 
					batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!atomic_dec_and_test(&orig_entry->refcount))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	/* to avoid race conditions, immediately decrease the tt counter */
 | 
						/* to avoid race conditions, immediately decrease the tt counter */
 | 
				
			||||||
	atomic_dec(&orig_entry->orig_node->tt_size);
 | 
						atomic_dec(&orig_entry->orig_node->tt_size);
 | 
				
			||||||
	call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
 | 
						call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
 | 
				
			||||||
| 
						 | 
					@ -175,8 +181,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
 | 
				
			||||||
	del_op_requested = flags & BATADV_TT_CLIENT_DEL;
 | 
						del_op_requested = flags & BATADV_TT_CLIENT_DEL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* check for ADD+DEL or DEL+ADD events */
 | 
						/* check for ADD+DEL or DEL+ADD events */
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_changes_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.changes_list_lock);
 | 
				
			||||||
	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
 | 
						list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 | 
				
			||||||
				 list) {
 | 
									 list) {
 | 
				
			||||||
		if (!batadv_compare_eth(entry->change.addr, addr))
 | 
							if (!batadv_compare_eth(entry->change.addr, addr))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -203,15 +209,15 @@ del:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* track the change in the OGMinterval list */
 | 
						/* track the change in the OGMinterval list */
 | 
				
			||||||
	list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
 | 
						list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (event_removed)
 | 
						if (event_removed)
 | 
				
			||||||
		atomic_dec(&bat_priv->tt_local_changes);
 | 
							atomic_dec(&bat_priv->tt.local_changes);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		atomic_inc(&bat_priv->tt_local_changes);
 | 
							atomic_inc(&bat_priv->tt.local_changes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int batadv_tt_len(int changes_num)
 | 
					int batadv_tt_len(int changes_num)
 | 
				
			||||||
| 
						 | 
					@ -221,12 +227,12 @@ int batadv_tt_len(int changes_num)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int batadv_tt_local_init(struct batadv_priv *bat_priv)
 | 
					static int batadv_tt_local_init(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (bat_priv->tt_local_hash)
 | 
						if (bat_priv->tt.local_hash)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->tt_local_hash = batadv_hash_new(1024);
 | 
						bat_priv->tt.local_hash = batadv_hash_new(1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!bat_priv->tt_local_hash)
 | 
						if (!bat_priv->tt.local_hash)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -258,7 +264,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
						batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
				
			||||||
		   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
 | 
							   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
 | 
				
			||||||
		   (uint8_t)atomic_read(&bat_priv->ttvn));
 | 
							   (uint8_t)atomic_read(&bat_priv->tt.vn));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
 | 
						memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
 | 
				
			||||||
	tt_local_entry->common.flags = BATADV_NO_FLAGS;
 | 
						tt_local_entry->common.flags = BATADV_NO_FLAGS;
 | 
				
			||||||
| 
						 | 
					@ -266,6 +272,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 | 
				
			||||||
		tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI;
 | 
							tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI;
 | 
				
			||||||
	atomic_set(&tt_local_entry->common.refcount, 2);
 | 
						atomic_set(&tt_local_entry->common.refcount, 2);
 | 
				
			||||||
	tt_local_entry->last_seen = jiffies;
 | 
						tt_local_entry->last_seen = jiffies;
 | 
				
			||||||
 | 
						tt_local_entry->common.added_at = tt_local_entry->last_seen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the batman interface mac address should never be purged */
 | 
						/* the batman interface mac address should never be purged */
 | 
				
			||||||
	if (batadv_compare_eth(addr, soft_iface->dev_addr))
 | 
						if (batadv_compare_eth(addr, soft_iface->dev_addr))
 | 
				
			||||||
| 
						 | 
					@ -277,7 +284,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
 | 
						tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash_added = batadv_hash_add(bat_priv->tt_local_hash, batadv_compare_tt,
 | 
						hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
 | 
				
			||||||
				     batadv_choose_orig,
 | 
									     batadv_choose_orig,
 | 
				
			||||||
				     &tt_local_entry->common,
 | 
									     &tt_local_entry->common,
 | 
				
			||||||
				     &tt_local_entry->common.hash_entry);
 | 
									     &tt_local_entry->common.hash_entry);
 | 
				
			||||||
| 
						 | 
					@ -348,7 +355,7 @@ static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv,
 | 
				
			||||||
	primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
						primary_if = batadv_primary_if_get_selected(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req_len = min_packet_len;
 | 
						req_len = min_packet_len;
 | 
				
			||||||
	req_len += batadv_tt_len(atomic_read(&bat_priv->tt_local_changes));
 | 
						req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if we have too many changes for one packet don't send any
 | 
						/* if we have too many changes for one packet don't send any
 | 
				
			||||||
	 * and wait for the tt table request which will be fragmented
 | 
						 * and wait for the tt table request which will be fragmented
 | 
				
			||||||
| 
						 | 
					@ -381,10 +388,10 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
 | 
				
			||||||
	if (new_len > 0)
 | 
						if (new_len > 0)
 | 
				
			||||||
		tot_changes = new_len / batadv_tt_len(1);
 | 
							tot_changes = new_len / batadv_tt_len(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_changes_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.changes_list_lock);
 | 
				
			||||||
	atomic_set(&bat_priv->tt_local_changes, 0);
 | 
						atomic_set(&bat_priv->tt.local_changes, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
 | 
						list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 | 
				
			||||||
				 list) {
 | 
									 list) {
 | 
				
			||||||
		if (count < tot_changes) {
 | 
							if (count < tot_changes) {
 | 
				
			||||||
			memcpy(tt_buff + batadv_tt_len(count),
 | 
								memcpy(tt_buff + batadv_tt_len(count),
 | 
				
			||||||
| 
						 | 
					@ -394,25 +401,25 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
 | 
				
			||||||
		list_del(&entry->list);
 | 
							list_del(&entry->list);
 | 
				
			||||||
		kfree(entry);
 | 
							kfree(entry);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Keep the buffer for possible tt_request */
 | 
						/* Keep the buffer for possible tt_request */
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_buff_lock);
 | 
						spin_lock_bh(&bat_priv->tt.last_changeset_lock);
 | 
				
			||||||
	kfree(bat_priv->tt_buff);
 | 
						kfree(bat_priv->tt.last_changeset);
 | 
				
			||||||
	bat_priv->tt_buff_len = 0;
 | 
						bat_priv->tt.last_changeset_len = 0;
 | 
				
			||||||
	bat_priv->tt_buff = NULL;
 | 
						bat_priv->tt.last_changeset = NULL;
 | 
				
			||||||
	/* check whether this new OGM has no changes due to size problems */
 | 
						/* check whether this new OGM has no changes due to size problems */
 | 
				
			||||||
	if (new_len > 0) {
 | 
						if (new_len > 0) {
 | 
				
			||||||
		/* if kmalloc() fails we will reply with the full table
 | 
							/* if kmalloc() fails we will reply with the full table
 | 
				
			||||||
		 * instead of providing the diff
 | 
							 * instead of providing the diff
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC);
 | 
							bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC);
 | 
				
			||||||
		if (bat_priv->tt_buff) {
 | 
							if (bat_priv->tt.last_changeset) {
 | 
				
			||||||
			memcpy(bat_priv->tt_buff, tt_buff, new_len);
 | 
								memcpy(bat_priv->tt.last_changeset, tt_buff, new_len);
 | 
				
			||||||
			bat_priv->tt_buff_len = new_len;
 | 
								bat_priv->tt.last_changeset_len = new_len;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_buff_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -421,7 +428,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *net_dev = (struct net_device *)seq->private;
 | 
						struct net_device *net_dev = (struct net_device *)seq->private;
 | 
				
			||||||
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
						struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common_entry;
 | 
						struct batadv_tt_common_entry *tt_common_entry;
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
| 
						 | 
					@ -446,7 +453,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seq_printf(seq,
 | 
						seq_printf(seq,
 | 
				
			||||||
		   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
 | 
							   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
 | 
				
			||||||
		   net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
 | 
							   net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
		head = &hash->table[i];
 | 
							head = &hash->table[i];
 | 
				
			||||||
| 
						 | 
					@ -544,7 +551,7 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_tt_local_purge(struct batadv_priv *bat_priv)
 | 
					static void batadv_tt_local_purge(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	spinlock_t *list_lock; /* protects write access to the hash lists */
 | 
						spinlock_t *list_lock; /* protects write access to the hash lists */
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
| 
						 | 
					@ -570,10 +577,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!bat_priv->tt_local_hash)
 | 
						if (!bat_priv->tt.local_hash)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->tt_local_hash;
 | 
						hash = bat_priv->tt.local_hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
		head = &hash->table[i];
 | 
							head = &hash->table[i];
 | 
				
			||||||
| 
						 | 
					@ -593,17 +600,17 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_hash_destroy(hash);
 | 
						batadv_hash_destroy(hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->tt_local_hash = NULL;
 | 
						bat_priv->tt.local_hash = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int batadv_tt_global_init(struct batadv_priv *bat_priv)
 | 
					static int batadv_tt_global_init(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (bat_priv->tt_global_hash)
 | 
						if (bat_priv->tt.global_hash)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->tt_global_hash = batadv_hash_new(1024);
 | 
						bat_priv->tt.global_hash = batadv_hash_new(1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!bat_priv->tt_global_hash)
 | 
						if (!bat_priv->tt.global_hash)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -613,62 +620,99 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_change_node *entry, *safe;
 | 
						struct batadv_tt_change_node *entry, *safe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_changes_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.changes_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
 | 
						list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 | 
				
			||||||
				 list) {
 | 
									 list) {
 | 
				
			||||||
		list_del(&entry->list);
 | 
							list_del(&entry->list);
 | 
				
			||||||
		kfree(entry);
 | 
							kfree(entry);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	atomic_set(&bat_priv->tt_local_changes, 0);
 | 
						atomic_set(&bat_priv->tt.local_changes, 0);
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* retrieves the orig_tt_list_entry belonging to orig_node from the
 | 
				
			||||||
 | 
					 * batadv_tt_global_entry list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * returns it with an increased refcounter, NULL if not found
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct batadv_tt_orig_list_entry *
 | 
				
			||||||
 | 
					batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
 | 
				
			||||||
 | 
									 const struct batadv_orig_node *orig_node)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
 | 
				
			||||||
 | 
						const struct hlist_head *head;
 | 
				
			||||||
 | 
						struct hlist_node *node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
						head = &entry->orig_list;
 | 
				
			||||||
 | 
						hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) {
 | 
				
			||||||
 | 
							if (tmp_orig_entry->orig_node != orig_node)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (!atomic_inc_not_zero(&tmp_orig_entry->refcount))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							orig_entry = tmp_orig_entry;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return orig_entry;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* find out if an orig_node is already in the list of a tt_global_entry.
 | 
					/* find out if an orig_node is already in the list of a tt_global_entry.
 | 
				
			||||||
 * returns 1 if found, 0 otherwise
 | 
					 * returns true if found, false otherwise
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
 | 
					batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
 | 
				
			||||||
				const struct batadv_orig_node *orig_node)
 | 
									const struct batadv_orig_node *orig_node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_orig_list_entry *tmp_orig_entry;
 | 
						struct batadv_tt_orig_list_entry *orig_entry;
 | 
				
			||||||
	const struct hlist_head *head;
 | 
					 | 
				
			||||||
	struct hlist_node *node;
 | 
					 | 
				
			||||||
	bool found = false;
 | 
						bool found = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
 | 
				
			||||||
	head = &entry->orig_list;
 | 
						if (orig_entry) {
 | 
				
			||||||
	hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) {
 | 
					 | 
				
			||||||
		if (tmp_orig_entry->orig_node == orig_node) {
 | 
					 | 
				
			||||||
		found = true;
 | 
							found = true;
 | 
				
			||||||
			break;
 | 
							batadv_tt_orig_list_entry_free_ref(orig_entry);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	rcu_read_unlock();
 | 
					 | 
				
			||||||
	return found;
 | 
						return found;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
batadv_tt_global_add_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
 | 
					batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
 | 
				
			||||||
				struct batadv_orig_node *orig_node, int ttvn)
 | 
									struct batadv_orig_node *orig_node, int ttvn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_orig_list_entry *orig_entry;
 | 
						struct batadv_tt_orig_list_entry *orig_entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
 | 
				
			||||||
 | 
						if (orig_entry) {
 | 
				
			||||||
 | 
							/* refresh the ttvn: the current value could be a bogus one that
 | 
				
			||||||
 | 
							 * was added during a "temporary client detection"
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							orig_entry->ttvn = ttvn;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
 | 
						orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
 | 
				
			||||||
	if (!orig_entry)
 | 
						if (!orig_entry)
 | 
				
			||||||
		return;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_HLIST_NODE(&orig_entry->list);
 | 
						INIT_HLIST_NODE(&orig_entry->list);
 | 
				
			||||||
	atomic_inc(&orig_node->refcount);
 | 
						atomic_inc(&orig_node->refcount);
 | 
				
			||||||
	atomic_inc(&orig_node->tt_size);
 | 
						atomic_inc(&orig_node->tt_size);
 | 
				
			||||||
	orig_entry->orig_node = orig_node;
 | 
						orig_entry->orig_node = orig_node;
 | 
				
			||||||
	orig_entry->ttvn = ttvn;
 | 
						orig_entry->ttvn = ttvn;
 | 
				
			||||||
 | 
						atomic_set(&orig_entry->refcount, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&tt_global_entry->list_lock);
 | 
						spin_lock_bh(&tt_global->list_lock);
 | 
				
			||||||
	hlist_add_head_rcu(&orig_entry->list,
 | 
						hlist_add_head_rcu(&orig_entry->list,
 | 
				
			||||||
			   &tt_global_entry->orig_list);
 | 
								   &tt_global->orig_list);
 | 
				
			||||||
	spin_unlock_bh(&tt_global_entry->list_lock);
 | 
						spin_unlock_bh(&tt_global->list_lock);
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						if (orig_entry)
 | 
				
			||||||
 | 
							batadv_tt_orig_list_entry_free_ref(orig_entry);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* caller must hold orig_node refcount */
 | 
					/* caller must hold orig_node refcount */
 | 
				
			||||||
| 
						 | 
					@ -695,11 +739,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 | 
				
			||||||
		common->flags = flags;
 | 
							common->flags = flags;
 | 
				
			||||||
		tt_global_entry->roam_at = 0;
 | 
							tt_global_entry->roam_at = 0;
 | 
				
			||||||
		atomic_set(&common->refcount, 2);
 | 
							atomic_set(&common->refcount, 2);
 | 
				
			||||||
 | 
							common->added_at = jiffies;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		INIT_HLIST_HEAD(&tt_global_entry->orig_list);
 | 
							INIT_HLIST_HEAD(&tt_global_entry->orig_list);
 | 
				
			||||||
		spin_lock_init(&tt_global_entry->list_lock);
 | 
							spin_lock_init(&tt_global_entry->list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		hash_added = batadv_hash_add(bat_priv->tt_global_hash,
 | 
							hash_added = batadv_hash_add(bat_priv->tt.global_hash,
 | 
				
			||||||
					     batadv_compare_tt,
 | 
										     batadv_compare_tt,
 | 
				
			||||||
					     batadv_choose_orig, common,
 | 
										     batadv_choose_orig, common,
 | 
				
			||||||
					     &common->hash_entry);
 | 
										     &common->hash_entry);
 | 
				
			||||||
| 
						 | 
					@ -709,11 +754,20 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 | 
				
			||||||
			batadv_tt_global_entry_free_ref(tt_global_entry);
 | 
								batadv_tt_global_entry_free_ref(tt_global_entry);
 | 
				
			||||||
			goto out_remove;
 | 
								goto out_remove;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		batadv_tt_global_add_orig_entry(tt_global_entry, orig_node,
 | 
					 | 
				
			||||||
						ttvn);
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		/* there is already a global entry, use this one. */
 | 
							/* If there is already a global entry, we can use this one for
 | 
				
			||||||
 | 
							 * our processing.
 | 
				
			||||||
 | 
							 * But if we are trying to add a temporary client we can exit
 | 
				
			||||||
 | 
							 * directly because the temporary information should never
 | 
				
			||||||
 | 
							 * override any already known client state (whatever it is)
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (flags & BATADV_TT_CLIENT_TEMP)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* if the client was temporary added before receiving the first
 | 
				
			||||||
 | 
							 * OGM announcing it, we have to clear the TEMP flag
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
 | 
							/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
 | 
				
			||||||
		 * one originator left in the list and we previously received a
 | 
							 * one originator left in the list and we previously received a
 | 
				
			||||||
| 
						 | 
					@ -727,12 +781,9 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 | 
				
			||||||
			tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
 | 
								tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
 | 
				
			||||||
			tt_global_entry->roam_at = 0;
 | 
								tt_global_entry->roam_at = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!batadv_tt_global_entry_has_orig(tt_global_entry,
 | 
					 | 
				
			||||||
						     orig_node))
 | 
					 | 
				
			||||||
			batadv_tt_global_add_orig_entry(tt_global_entry,
 | 
					 | 
				
			||||||
							orig_node, ttvn);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						/* add the new orig_entry (if needed) or update it */
 | 
				
			||||||
 | 
						batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
						batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
				
			||||||
		   "Creating new global tt entry: %pM (via %pM)\n",
 | 
							   "Creating new global tt entry: %pM (via %pM)\n",
 | 
				
			||||||
| 
						 | 
					@ -771,11 +822,12 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
 | 
				
			||||||
	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
 | 
						hlist_for_each_entry_rcu(orig_entry, node, head, list) {
 | 
				
			||||||
		flags = tt_common_entry->flags;
 | 
							flags = tt_common_entry->flags;
 | 
				
			||||||
		last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
 | 
							last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
 | 
				
			||||||
		seq_printf(seq, " * %pM  (%3u) via %pM     (%3u)   [%c%c]\n",
 | 
							seq_printf(seq,	" * %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
 | 
				
			||||||
			   tt_global_entry->common.addr, orig_entry->ttvn,
 | 
								   tt_global_entry->common.addr, orig_entry->ttvn,
 | 
				
			||||||
			   orig_entry->orig_node->orig, last_ttvn,
 | 
								   orig_entry->orig_node->orig, last_ttvn,
 | 
				
			||||||
			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
 | 
								   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
 | 
				
			||||||
			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'));
 | 
								   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
 | 
				
			||||||
 | 
								   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -783,7 +835,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *net_dev = (struct net_device *)seq->private;
 | 
						struct net_device *net_dev = (struct net_device *)seq->private;
 | 
				
			||||||
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
						struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common_entry;
 | 
						struct batadv_tt_common_entry *tt_common_entry;
 | 
				
			||||||
	struct batadv_tt_global_entry *tt_global;
 | 
						struct batadv_tt_global_entry *tt_global;
 | 
				
			||||||
	struct batadv_hard_iface *primary_if;
 | 
						struct batadv_hard_iface *primary_if;
 | 
				
			||||||
| 
						 | 
					@ -884,7 +936,7 @@ batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
 | 
				
			||||||
		   "Deleting global tt entry %pM: %s\n",
 | 
							   "Deleting global tt entry %pM: %s\n",
 | 
				
			||||||
		   tt_global_entry->common.addr, message);
 | 
							   tt_global_entry->common.addr, message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_hash_remove(bat_priv->tt_global_hash, batadv_compare_tt,
 | 
						batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
 | 
				
			||||||
			   batadv_choose_orig, tt_global_entry->common.addr);
 | 
								   batadv_choose_orig, tt_global_entry->common.addr);
 | 
				
			||||||
	batadv_tt_global_entry_free_ref(tt_global_entry);
 | 
						batadv_tt_global_entry_free_ref(tt_global_entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -995,7 +1047,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
 | 
				
			||||||
	struct batadv_tt_global_entry *tt_global;
 | 
						struct batadv_tt_global_entry *tt_global;
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common_entry;
 | 
						struct batadv_tt_common_entry *tt_common_entry;
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 | 
				
			||||||
	struct hlist_node *node, *safe;
 | 
						struct hlist_node *node, *safe;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	spinlock_t *list_lock; /* protects write access to the hash lists */
 | 
						spinlock_t *list_lock; /* protects write access to the hash lists */
 | 
				
			||||||
| 
						 | 
					@ -1030,49 +1082,63 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
 | 
				
			||||||
	orig_node->tt_initialised = false;
 | 
						orig_node->tt_initialised = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_tt_global_roam_purge_list(struct batadv_priv *bat_priv,
 | 
					static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
 | 
				
			||||||
					     struct hlist_head *head)
 | 
									      char **msg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common_entry;
 | 
						bool purge = false;
 | 
				
			||||||
	struct batadv_tt_global_entry *tt_global_entry;
 | 
						unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
 | 
				
			||||||
	struct hlist_node *node, *node_tmp;
 | 
						unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head,
 | 
						if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
 | 
				
			||||||
				  hash_entry) {
 | 
						    batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
 | 
				
			||||||
		tt_global_entry = container_of(tt_common_entry,
 | 
							purge = true;
 | 
				
			||||||
					       struct batadv_tt_global_entry,
 | 
							*msg = "Roaming timeout\n";
 | 
				
			||||||
					       common);
 | 
					 | 
				
			||||||
		if (!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM))
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		if (!batadv_has_timed_out(tt_global_entry->roam_at,
 | 
					 | 
				
			||||||
					  BATADV_TT_CLIENT_ROAM_TIMEOUT))
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
					 | 
				
			||||||
			   "Deleting global tt entry (%pM): Roaming timeout\n",
 | 
					 | 
				
			||||||
			   tt_global_entry->common.addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		hlist_del_rcu(node);
 | 
					 | 
				
			||||||
		batadv_tt_global_entry_free_ref(tt_global_entry);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
 | 
				
			||||||
 | 
						    batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
 | 
				
			||||||
 | 
							purge = true;
 | 
				
			||||||
 | 
							*msg = "Temporary client timeout\n";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return purge;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_tt_global_roam_purge(struct batadv_priv *bat_priv)
 | 
					static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
 | 
						struct hlist_node *node, *node_tmp;
 | 
				
			||||||
	spinlock_t *list_lock; /* protects write access to the hash lists */
 | 
						spinlock_t *list_lock; /* protects write access to the hash lists */
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
						char *msg = NULL;
 | 
				
			||||||
 | 
						struct batadv_tt_common_entry *tt_common;
 | 
				
			||||||
 | 
						struct batadv_tt_global_entry *tt_global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
		head = &hash->table[i];
 | 
							head = &hash->table[i];
 | 
				
			||||||
		list_lock = &hash->list_locks[i];
 | 
							list_lock = &hash->list_locks[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spin_lock_bh(list_lock);
 | 
							spin_lock_bh(list_lock);
 | 
				
			||||||
		batadv_tt_global_roam_purge_list(bat_priv, head);
 | 
							hlist_for_each_entry_safe(tt_common, node, node_tmp, head,
 | 
				
			||||||
 | 
										  hash_entry) {
 | 
				
			||||||
 | 
								tt_global = container_of(tt_common,
 | 
				
			||||||
 | 
											 struct batadv_tt_global_entry,
 | 
				
			||||||
 | 
											 common);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!batadv_tt_global_to_purge(tt_global, &msg))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
				
			||||||
 | 
									   "Deleting global tt entry (%pM): %s\n",
 | 
				
			||||||
 | 
									   tt_global->common.addr, msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								hlist_del_rcu(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								batadv_tt_global_entry_free_ref(tt_global);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		spin_unlock_bh(list_lock);
 | 
							spin_unlock_bh(list_lock);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
 | 
					static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
| 
						 | 
					@ -1085,10 +1151,10 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!bat_priv->tt_global_hash)
 | 
						if (!bat_priv->tt.global_hash)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->tt_global_hash;
 | 
						hash = bat_priv->tt.global_hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
		head = &hash->table[i];
 | 
							head = &hash->table[i];
 | 
				
			||||||
| 
						 | 
					@ -1108,7 +1174,7 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_hash_destroy(hash);
 | 
						batadv_hash_destroy(hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->tt_global_hash = NULL;
 | 
						bat_priv->tt.global_hash = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool
 | 
					static bool
 | 
				
			||||||
| 
						 | 
					@ -1187,7 +1253,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
 | 
				
			||||||
				     struct batadv_orig_node *orig_node)
 | 
									     struct batadv_orig_node *orig_node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint16_t total = 0, total_one;
 | 
						uint16_t total = 0, total_one;
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_global_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.global_hash;
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common;
 | 
						struct batadv_tt_common_entry *tt_common;
 | 
				
			||||||
	struct batadv_tt_global_entry *tt_global;
 | 
						struct batadv_tt_global_entry *tt_global;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
| 
						 | 
					@ -1210,6 +1276,12 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
 | 
								if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
								/* Temporary clients have not been announced yet, so
 | 
				
			||||||
 | 
								 * they have to be skipped while computing the global
 | 
				
			||||||
 | 
								 * crc
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* find out if this global entry is announced by this
 | 
								/* find out if this global entry is announced by this
 | 
				
			||||||
			 * originator
 | 
								 * originator
 | 
				
			||||||
| 
						 | 
					@ -1234,7 +1306,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
 | 
				
			||||||
static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
 | 
					static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint16_t total = 0, total_one;
 | 
						uint16_t total = 0, total_one;
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common;
 | 
						struct batadv_tt_common_entry *tt_common;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
| 
						 | 
					@ -1267,14 +1339,14 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_req_node *node, *safe;
 | 
						struct batadv_tt_req_node *node, *safe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
 | 
						list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
 | 
				
			||||||
		list_del(&node->list);
 | 
							list_del(&node->list);
 | 
				
			||||||
		kfree(node);
 | 
							kfree(node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
 | 
					static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
 | 
				
			||||||
| 
						 | 
					@ -1304,15 +1376,15 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_req_node *node, *safe;
 | 
						struct batadv_tt_req_node *node, *safe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
 | 
						list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
 | 
				
			||||||
		if (batadv_has_timed_out(node->issued_at,
 | 
							if (batadv_has_timed_out(node->issued_at,
 | 
				
			||||||
					 BATADV_TT_REQUEST_TIMEOUT)) {
 | 
										 BATADV_TT_REQUEST_TIMEOUT)) {
 | 
				
			||||||
			list_del(&node->list);
 | 
								list_del(&node->list);
 | 
				
			||||||
			kfree(node);
 | 
								kfree(node);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* returns the pointer to the new tt_req_node struct if no request
 | 
					/* returns the pointer to the new tt_req_node struct if no request
 | 
				
			||||||
| 
						 | 
					@ -1324,8 +1396,8 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
 | 
						struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
	list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) {
 | 
						list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
 | 
				
			||||||
		if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
 | 
							if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
 | 
				
			||||||
		    !batadv_has_timed_out(tt_req_node_tmp->issued_at,
 | 
							    !batadv_has_timed_out(tt_req_node_tmp->issued_at,
 | 
				
			||||||
					  BATADV_TT_REQUEST_TIMEOUT))
 | 
										  BATADV_TT_REQUEST_TIMEOUT))
 | 
				
			||||||
| 
						 | 
					@ -1339,9 +1411,9 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv,
 | 
				
			||||||
	memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
 | 
						memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
 | 
				
			||||||
	tt_req_node->issued_at = jiffies;
 | 
						tt_req_node->issued_at = jiffies;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_add(&tt_req_node->list, &bat_priv->tt_req_list);
 | 
						list_add(&tt_req_node->list, &bat_priv->tt.req_list);
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
	return tt_req_node;
 | 
						return tt_req_node;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1363,7 +1435,8 @@ static int batadv_tt_global_valid(const void *entry_ptr,
 | 
				
			||||||
	const struct batadv_tt_global_entry *tt_global_entry;
 | 
						const struct batadv_tt_global_entry *tt_global_entry;
 | 
				
			||||||
	const struct batadv_orig_node *orig_node = data_ptr;
 | 
						const struct batadv_orig_node *orig_node = data_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM)
 | 
						if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
 | 
				
			||||||
 | 
						    tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tt_global_entry = container_of(tt_common_entry,
 | 
						tt_global_entry = container_of(tt_common_entry,
 | 
				
			||||||
| 
						 | 
					@ -1507,9 +1580,9 @@ out:
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		kfree_skb(skb);
 | 
							kfree_skb(skb);
 | 
				
			||||||
	if (ret && tt_req_node) {
 | 
						if (ret && tt_req_node) {
 | 
				
			||||||
		spin_lock_bh(&bat_priv->tt_req_list_lock);
 | 
							spin_lock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
		list_del(&tt_req_node->list);
 | 
							list_del(&tt_req_node->list);
 | 
				
			||||||
		spin_unlock_bh(&bat_priv->tt_req_list_lock);
 | 
							spin_unlock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
		kfree(tt_req_node);
 | 
							kfree(tt_req_node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -1530,6 +1603,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
	uint16_t tt_len, tt_tot;
 | 
						uint16_t tt_len, tt_tot;
 | 
				
			||||||
	struct sk_buff *skb = NULL;
 | 
						struct sk_buff *skb = NULL;
 | 
				
			||||||
	struct batadv_tt_query_packet *tt_response;
 | 
						struct batadv_tt_query_packet *tt_response;
 | 
				
			||||||
 | 
						uint8_t *packet_pos;
 | 
				
			||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
						batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
				
			||||||
| 
						 | 
					@ -1583,8 +1657,8 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
			goto unlock;
 | 
								goto unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		skb_reserve(skb, ETH_HLEN);
 | 
							skb_reserve(skb, ETH_HLEN);
 | 
				
			||||||
		tt_response = (struct batadv_tt_query_packet *)skb_put(skb,
 | 
							packet_pos = skb_put(skb, len);
 | 
				
			||||||
								       len);
 | 
							tt_response = (struct batadv_tt_query_packet *)packet_pos;
 | 
				
			||||||
		tt_response->ttvn = req_ttvn;
 | 
							tt_response->ttvn = req_ttvn;
 | 
				
			||||||
		tt_response->tt_data = htons(tt_tot);
 | 
							tt_response->tt_data = htons(tt_tot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1600,7 +1674,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
		ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
 | 
							ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		skb = batadv_tt_response_fill_table(tt_len, ttvn,
 | 
							skb = batadv_tt_response_fill_table(tt_len, ttvn,
 | 
				
			||||||
						    bat_priv->tt_global_hash,
 | 
											    bat_priv->tt.global_hash,
 | 
				
			||||||
						    primary_if,
 | 
											    primary_if,
 | 
				
			||||||
						    batadv_tt_global_valid,
 | 
											    batadv_tt_global_valid,
 | 
				
			||||||
						    req_dst_orig_node);
 | 
											    req_dst_orig_node);
 | 
				
			||||||
| 
						 | 
					@ -1663,6 +1737,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
	uint16_t tt_len, tt_tot;
 | 
						uint16_t tt_len, tt_tot;
 | 
				
			||||||
	struct sk_buff *skb = NULL;
 | 
						struct sk_buff *skb = NULL;
 | 
				
			||||||
	struct batadv_tt_query_packet *tt_response;
 | 
						struct batadv_tt_query_packet *tt_response;
 | 
				
			||||||
 | 
						uint8_t *packet_pos;
 | 
				
			||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
						batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
				
			||||||
| 
						 | 
					@ -1671,7 +1746,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
		   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
 | 
							   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
 | 
						my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
 | 
				
			||||||
	req_ttvn = tt_request->ttvn;
 | 
						req_ttvn = tt_request->ttvn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
 | 
						orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
 | 
				
			||||||
| 
						 | 
					@ -1690,7 +1765,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
	 * is too big send the whole local translation table
 | 
						 * is too big send the whole local translation table
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
 | 
						if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
 | 
				
			||||||
	    !bat_priv->tt_buff)
 | 
						    !bat_priv->tt.last_changeset)
 | 
				
			||||||
		full_table = true;
 | 
							full_table = true;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		full_table = false;
 | 
							full_table = false;
 | 
				
			||||||
| 
						 | 
					@ -1699,8 +1774,8 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
	 * I'll send only one packet with as much TT entries as I can
 | 
						 * I'll send only one packet with as much TT entries as I can
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!full_table) {
 | 
						if (!full_table) {
 | 
				
			||||||
		spin_lock_bh(&bat_priv->tt_buff_lock);
 | 
							spin_lock_bh(&bat_priv->tt.last_changeset_lock);
 | 
				
			||||||
		tt_len = bat_priv->tt_buff_len;
 | 
							tt_len = bat_priv->tt.last_changeset_len;
 | 
				
			||||||
		tt_tot = tt_len / sizeof(struct batadv_tt_change);
 | 
							tt_tot = tt_len / sizeof(struct batadv_tt_change);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		len = sizeof(*tt_response) + tt_len;
 | 
							len = sizeof(*tt_response) + tt_len;
 | 
				
			||||||
| 
						 | 
					@ -1709,22 +1784,22 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
			goto unlock;
 | 
								goto unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		skb_reserve(skb, ETH_HLEN);
 | 
							skb_reserve(skb, ETH_HLEN);
 | 
				
			||||||
		tt_response = (struct batadv_tt_query_packet *)skb_put(skb,
 | 
							packet_pos = skb_put(skb, len);
 | 
				
			||||||
								       len);
 | 
							tt_response = (struct batadv_tt_query_packet *)packet_pos;
 | 
				
			||||||
		tt_response->ttvn = req_ttvn;
 | 
							tt_response->ttvn = req_ttvn;
 | 
				
			||||||
		tt_response->tt_data = htons(tt_tot);
 | 
							tt_response->tt_data = htons(tt_tot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tt_buff = skb->data + sizeof(*tt_response);
 | 
							tt_buff = skb->data + sizeof(*tt_response);
 | 
				
			||||||
		memcpy(tt_buff, bat_priv->tt_buff,
 | 
							memcpy(tt_buff, bat_priv->tt.last_changeset,
 | 
				
			||||||
		       bat_priv->tt_buff_len);
 | 
							       bat_priv->tt.last_changeset_len);
 | 
				
			||||||
		spin_unlock_bh(&bat_priv->tt_buff_lock);
 | 
							spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt);
 | 
							tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
 | 
				
			||||||
		tt_len *= sizeof(struct batadv_tt_change);
 | 
							tt_len *= sizeof(struct batadv_tt_change);
 | 
				
			||||||
		ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
 | 
							ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		skb = batadv_tt_response_fill_table(tt_len, ttvn,
 | 
							skb = batadv_tt_response_fill_table(tt_len, ttvn,
 | 
				
			||||||
						    bat_priv->tt_local_hash,
 | 
											    bat_priv->tt.local_hash,
 | 
				
			||||||
						    primary_if,
 | 
											    primary_if,
 | 
				
			||||||
						    batadv_tt_local_valid_entry,
 | 
											    batadv_tt_local_valid_entry,
 | 
				
			||||||
						    NULL);
 | 
											    NULL);
 | 
				
			||||||
| 
						 | 
					@ -1756,7 +1831,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
	goto out;
 | 
						goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_buff_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	if (orig_node)
 | 
						if (orig_node)
 | 
				
			||||||
		batadv_orig_node_free_ref(orig_node);
 | 
							batadv_orig_node_free_ref(orig_node);
 | 
				
			||||||
| 
						 | 
					@ -1909,14 +1984,14 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Delete the tt_req_node from pending tt_requests list */
 | 
						/* Delete the tt_req_node from pending tt_requests list */
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
 | 
						list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
 | 
				
			||||||
		if (!batadv_compare_eth(node->addr, tt_response->src))
 | 
							if (!batadv_compare_eth(node->addr, tt_response->src))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		list_del(&node->list);
 | 
							list_del(&node->list);
 | 
				
			||||||
		kfree(node);
 | 
							kfree(node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_req_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.req_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Recalculate the CRC for this orig_node and store it */
 | 
						/* Recalculate the CRC for this orig_node and store it */
 | 
				
			||||||
	orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
 | 
						orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
 | 
				
			||||||
| 
						 | 
					@ -1950,22 +2025,22 @@ static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_roam_node *node, *safe;
 | 
						struct batadv_tt_roam_node *node, *safe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_roam_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.roam_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
 | 
						list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
 | 
				
			||||||
		list_del(&node->list);
 | 
							list_del(&node->list);
 | 
				
			||||||
		kfree(node);
 | 
							kfree(node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.roam_list_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
 | 
					static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_tt_roam_node *node, *safe;
 | 
						struct batadv_tt_roam_node *node, *safe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_roam_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.roam_list_lock);
 | 
				
			||||||
	list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
 | 
						list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
 | 
				
			||||||
		if (!batadv_has_timed_out(node->first_time,
 | 
							if (!batadv_has_timed_out(node->first_time,
 | 
				
			||||||
					  BATADV_ROAMING_MAX_TIME))
 | 
										  BATADV_ROAMING_MAX_TIME))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -1973,7 +2048,7 @@ static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
 | 
				
			||||||
		list_del(&node->list);
 | 
							list_del(&node->list);
 | 
				
			||||||
		kfree(node);
 | 
							kfree(node);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.roam_list_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This function checks whether the client already reached the
 | 
					/* This function checks whether the client already reached the
 | 
				
			||||||
| 
						 | 
					@ -1988,11 +2063,11 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
 | 
				
			||||||
	struct batadv_tt_roam_node *tt_roam_node;
 | 
						struct batadv_tt_roam_node *tt_roam_node;
 | 
				
			||||||
	bool ret = false;
 | 
						bool ret = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->tt_roam_list_lock);
 | 
						spin_lock_bh(&bat_priv->tt.roam_list_lock);
 | 
				
			||||||
	/* The new tt_req will be issued only if I'm not waiting for a
 | 
						/* The new tt_req will be issued only if I'm not waiting for a
 | 
				
			||||||
	 * reply from the same orig_node yet
 | 
						 * reply from the same orig_node yet
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) {
 | 
						list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
 | 
				
			||||||
		if (!batadv_compare_eth(tt_roam_node->addr, client))
 | 
							if (!batadv_compare_eth(tt_roam_node->addr, client))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2017,12 +2092,12 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
 | 
				
			||||||
			   BATADV_ROAMING_MAX_COUNT - 1);
 | 
								   BATADV_ROAMING_MAX_COUNT - 1);
 | 
				
			||||||
		memcpy(tt_roam_node->addr, client, ETH_ALEN);
 | 
							memcpy(tt_roam_node->addr, client, ETH_ALEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		list_add(&tt_roam_node->list, &bat_priv->tt_roam_list);
 | 
							list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
 | 
				
			||||||
		ret = true;
 | 
							ret = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
 | 
						spin_unlock_bh(&bat_priv->tt.roam_list_lock);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2086,13 +2161,15 @@ out:
 | 
				
			||||||
static void batadv_tt_purge(struct work_struct *work)
 | 
					static void batadv_tt_purge(struct work_struct *work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct delayed_work *delayed_work;
 | 
						struct delayed_work *delayed_work;
 | 
				
			||||||
 | 
						struct batadv_priv_tt *priv_tt;
 | 
				
			||||||
	struct batadv_priv *bat_priv;
 | 
						struct batadv_priv *bat_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	delayed_work = container_of(work, struct delayed_work, work);
 | 
						delayed_work = container_of(work, struct delayed_work, work);
 | 
				
			||||||
	bat_priv = container_of(delayed_work, struct batadv_priv, tt_work);
 | 
						priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
 | 
				
			||||||
 | 
						bat_priv = container_of(priv_tt, struct batadv_priv, tt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_tt_local_purge(bat_priv);
 | 
						batadv_tt_local_purge(bat_priv);
 | 
				
			||||||
	batadv_tt_global_roam_purge(bat_priv);
 | 
						batadv_tt_global_purge(bat_priv);
 | 
				
			||||||
	batadv_tt_req_purge(bat_priv);
 | 
						batadv_tt_req_purge(bat_priv);
 | 
				
			||||||
	batadv_tt_roam_purge(bat_priv);
 | 
						batadv_tt_roam_purge(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2101,7 +2178,7 @@ static void batadv_tt_purge(struct work_struct *work)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void batadv_tt_free(struct batadv_priv *bat_priv)
 | 
					void batadv_tt_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	cancel_delayed_work_sync(&bat_priv->tt_work);
 | 
						cancel_delayed_work_sync(&bat_priv->tt.work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	batadv_tt_local_table_free(bat_priv);
 | 
						batadv_tt_local_table_free(bat_priv);
 | 
				
			||||||
	batadv_tt_global_table_free(bat_priv);
 | 
						batadv_tt_global_table_free(bat_priv);
 | 
				
			||||||
| 
						 | 
					@ -2109,7 +2186,7 @@ void batadv_tt_free(struct batadv_priv *bat_priv)
 | 
				
			||||||
	batadv_tt_changes_list_free(bat_priv);
 | 
						batadv_tt_changes_list_free(bat_priv);
 | 
				
			||||||
	batadv_tt_roam_list_free(bat_priv);
 | 
						batadv_tt_roam_list_free(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kfree(bat_priv->tt_buff);
 | 
						kfree(bat_priv->tt.last_changeset);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This function will enable or disable the specified flags for all the entries
 | 
					/* This function will enable or disable the specified flags for all the entries
 | 
				
			||||||
| 
						 | 
					@ -2153,7 +2230,7 @@ out:
 | 
				
			||||||
/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
 | 
					/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
 | 
				
			||||||
static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
 | 
					static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->tt_local_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common;
 | 
						struct batadv_tt_common_entry *tt_common;
 | 
				
			||||||
	struct batadv_tt_local_entry *tt_local;
 | 
						struct batadv_tt_local_entry *tt_local;
 | 
				
			||||||
	struct hlist_node *node, *node_tmp;
 | 
						struct hlist_node *node, *node_tmp;
 | 
				
			||||||
| 
						 | 
					@ -2178,7 +2255,7 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
 | 
				
			||||||
				   "Deleting local tt entry (%pM): pending\n",
 | 
									   "Deleting local tt entry (%pM): pending\n",
 | 
				
			||||||
				   tt_common->addr);
 | 
									   tt_common->addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			atomic_dec(&bat_priv->num_local_tt);
 | 
								atomic_dec(&bat_priv->tt.local_entry_num);
 | 
				
			||||||
			hlist_del_rcu(node);
 | 
								hlist_del_rcu(node);
 | 
				
			||||||
			tt_local = container_of(tt_common,
 | 
								tt_local = container_of(tt_common,
 | 
				
			||||||
						struct batadv_tt_local_entry,
 | 
											struct batadv_tt_local_entry,
 | 
				
			||||||
| 
						 | 
					@ -2196,26 +2273,26 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint16_t changed_num = 0;
 | 
						uint16_t changed_num = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (atomic_read(&bat_priv->tt_local_changes) < 1)
 | 
						if (atomic_read(&bat_priv->tt.local_changes) < 1)
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	changed_num = batadv_tt_set_flags(bat_priv->tt_local_hash,
 | 
						changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
 | 
				
			||||||
					  BATADV_TT_CLIENT_NEW, false);
 | 
										  BATADV_TT_CLIENT_NEW, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* all reset entries have to be counted as local entries */
 | 
						/* all reset entries have to be counted as local entries */
 | 
				
			||||||
	atomic_add(changed_num, &bat_priv->num_local_tt);
 | 
						atomic_add(changed_num, &bat_priv->tt.local_entry_num);
 | 
				
			||||||
	batadv_tt_local_purge_pending_clients(bat_priv);
 | 
						batadv_tt_local_purge_pending_clients(bat_priv);
 | 
				
			||||||
	bat_priv->tt_crc = batadv_tt_local_crc(bat_priv);
 | 
						bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Increment the TTVN only once per OGM interval */
 | 
						/* Increment the TTVN only once per OGM interval */
 | 
				
			||||||
	atomic_inc(&bat_priv->ttvn);
 | 
						atomic_inc(&bat_priv->tt.vn);
 | 
				
			||||||
	batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
						batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
				
			||||||
		   "Local changes committed, updating to ttvn %u\n",
 | 
							   "Local changes committed, updating to ttvn %u\n",
 | 
				
			||||||
		   (uint8_t)atomic_read(&bat_priv->ttvn));
 | 
							   (uint8_t)atomic_read(&bat_priv->tt.vn));
 | 
				
			||||||
	bat_priv->tt_poss_change = false;
 | 
						bat_priv->tt.poss_change = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* reset the sending counter */
 | 
						/* reset the sending counter */
 | 
				
			||||||
	atomic_set(&bat_priv->tt_ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
 | 
						atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
 | 
						return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
 | 
				
			||||||
					   packet_buff_len, packet_min_len);
 | 
										   packet_buff_len, packet_min_len);
 | 
				
			||||||
| 
						 | 
					@ -2235,7 +2312,7 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if the changes have been sent often enough */
 | 
						/* if the changes have been sent often enough */
 | 
				
			||||||
	if ((tt_num_changes < 0) &&
 | 
						if ((tt_num_changes < 0) &&
 | 
				
			||||||
	    (!batadv_atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) {
 | 
						    (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) {
 | 
				
			||||||
		batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
 | 
							batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
 | 
				
			||||||
					      packet_min_len, packet_min_len);
 | 
										      packet_min_len, packet_min_len);
 | 
				
			||||||
		tt_num_changes = 0;
 | 
							tt_num_changes = 0;
 | 
				
			||||||
| 
						 | 
					@ -2366,3 +2443,22 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
										  struct batadv_orig_node *orig_node,
 | 
				
			||||||
 | 
										  const unsigned char *addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool ret = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!batadv_tt_global_add(bat_priv, orig_node, addr,
 | 
				
			||||||
 | 
									  BATADV_TT_CLIENT_TEMP,
 | 
				
			||||||
 | 
									  atomic_read(&orig_node->last_ttvn)))
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						batadv_dbg(BATADV_DBG_TT, bat_priv,
 | 
				
			||||||
 | 
							   "Added temporary global client (addr: %pM orig: %pM)\n",
 | 
				
			||||||
 | 
							   addr, orig_node->orig);
 | 
				
			||||||
 | 
						ret = true;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
 | 
				
			||||||
			  int packet_min_len);
 | 
								  int packet_min_len);
 | 
				
			||||||
bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
 | 
					bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
 | 
				
			||||||
					uint8_t *addr);
 | 
										uint8_t *addr);
 | 
				
			||||||
 | 
					bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
										  struct batadv_orig_node *orig_node,
 | 
				
			||||||
 | 
										  const unsigned char *addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
 | 
					#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,6 +145,11 @@ struct batadv_bcast_duplist_entry {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum batadv_counters {
 | 
					enum batadv_counters {
 | 
				
			||||||
 | 
						BATADV_CNT_TX,
 | 
				
			||||||
 | 
						BATADV_CNT_TX_BYTES,
 | 
				
			||||||
 | 
						BATADV_CNT_TX_DROPPED,
 | 
				
			||||||
 | 
						BATADV_CNT_RX,
 | 
				
			||||||
 | 
						BATADV_CNT_RX_BYTES,
 | 
				
			||||||
	BATADV_CNT_FORWARD,
 | 
						BATADV_CNT_FORWARD,
 | 
				
			||||||
	BATADV_CNT_FORWARD_BYTES,
 | 
						BATADV_CNT_FORWARD_BYTES,
 | 
				
			||||||
	BATADV_CNT_MGMT_TX,
 | 
						BATADV_CNT_MGMT_TX,
 | 
				
			||||||
| 
						 | 
					@ -160,6 +165,67 @@ enum batadv_counters {
 | 
				
			||||||
	BATADV_CNT_NUM,
 | 
						BATADV_CNT_NUM,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct batadv_priv_tt - per mesh interface translation table data
 | 
				
			||||||
 | 
					 * @vn: translation table version number
 | 
				
			||||||
 | 
					 * @local_changes: changes registered in an originator interval
 | 
				
			||||||
 | 
					 * @poss_change: Detect an ongoing roaming phase. If true, then this node
 | 
				
			||||||
 | 
					 *  received a roaming_adv and has to inspect every packet directed to it to
 | 
				
			||||||
 | 
					 *  check whether it still is the true destination or not. This flag will be
 | 
				
			||||||
 | 
					 *  reset to false as soon as the this node's ttvn is increased
 | 
				
			||||||
 | 
					 * @changes_list: tracks tt local changes within an originator interval
 | 
				
			||||||
 | 
					 * @req_list: list of pending tt_requests
 | 
				
			||||||
 | 
					 * @local_crc: Checksum of the local table, recomputed before sending a new OGM
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct batadv_priv_tt {
 | 
				
			||||||
 | 
						atomic_t vn;
 | 
				
			||||||
 | 
						atomic_t ogm_append_cnt;
 | 
				
			||||||
 | 
						atomic_t local_changes;
 | 
				
			||||||
 | 
						bool poss_change;
 | 
				
			||||||
 | 
						struct list_head changes_list;
 | 
				
			||||||
 | 
						struct batadv_hashtable *local_hash;
 | 
				
			||||||
 | 
						struct batadv_hashtable *global_hash;
 | 
				
			||||||
 | 
						struct list_head req_list;
 | 
				
			||||||
 | 
						struct list_head roam_list;
 | 
				
			||||||
 | 
						spinlock_t changes_list_lock; /* protects changes */
 | 
				
			||||||
 | 
						spinlock_t req_list_lock; /* protects req_list */
 | 
				
			||||||
 | 
						spinlock_t roam_list_lock; /* protects roam_list */
 | 
				
			||||||
 | 
						atomic_t local_entry_num;
 | 
				
			||||||
 | 
						uint16_t local_crc;
 | 
				
			||||||
 | 
						unsigned char *last_changeset;
 | 
				
			||||||
 | 
						int16_t last_changeset_len;
 | 
				
			||||||
 | 
						spinlock_t last_changeset_lock; /* protects last_changeset */
 | 
				
			||||||
 | 
						struct delayed_work work;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_BATMAN_ADV_BLA
 | 
				
			||||||
 | 
					struct batadv_priv_bla {
 | 
				
			||||||
 | 
						atomic_t num_requests; /* number of bla requests in flight */
 | 
				
			||||||
 | 
						struct batadv_hashtable *claim_hash;
 | 
				
			||||||
 | 
						struct batadv_hashtable *backbone_hash;
 | 
				
			||||||
 | 
						struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
 | 
				
			||||||
 | 
						int bcast_duplist_curr;
 | 
				
			||||||
 | 
						struct batadv_bla_claim_dst claim_dest;
 | 
				
			||||||
 | 
						struct delayed_work work;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct batadv_priv_gw {
 | 
				
			||||||
 | 
						struct hlist_head list;
 | 
				
			||||||
 | 
						spinlock_t list_lock; /* protects gw_list and curr_gw */
 | 
				
			||||||
 | 
						struct batadv_gw_node __rcu *curr_gw;  /* rcu protected pointer */
 | 
				
			||||||
 | 
						atomic_t reselect;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct batadv_priv_vis {
 | 
				
			||||||
 | 
						struct list_head send_list;
 | 
				
			||||||
 | 
						struct batadv_hashtable *hash;
 | 
				
			||||||
 | 
						spinlock_t hash_lock; /* protects hash */
 | 
				
			||||||
 | 
						spinlock_t list_lock; /* protects info::recv_list */
 | 
				
			||||||
 | 
						struct delayed_work work;
 | 
				
			||||||
 | 
						struct batadv_vis_info *my_info;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct batadv_priv {
 | 
					struct batadv_priv {
 | 
				
			||||||
	atomic_t mesh_state;
 | 
						atomic_t mesh_state;
 | 
				
			||||||
	struct net_device_stats stats;
 | 
						struct net_device_stats stats;
 | 
				
			||||||
| 
						 | 
					@ -179,64 +245,24 @@ struct batadv_priv {
 | 
				
			||||||
	atomic_t bcast_seqno;
 | 
						atomic_t bcast_seqno;
 | 
				
			||||||
	atomic_t bcast_queue_left;
 | 
						atomic_t bcast_queue_left;
 | 
				
			||||||
	atomic_t batman_queue_left;
 | 
						atomic_t batman_queue_left;
 | 
				
			||||||
	atomic_t ttvn; /* translation table version number */
 | 
					 | 
				
			||||||
	atomic_t tt_ogm_append_cnt;
 | 
					 | 
				
			||||||
	atomic_t tt_local_changes; /* changes registered in a OGM interval */
 | 
					 | 
				
			||||||
	atomic_t bla_num_requests; /* number of bla requests in flight */
 | 
					 | 
				
			||||||
	/* The tt_poss_change flag is used to detect an ongoing roaming phase.
 | 
					 | 
				
			||||||
	 * If true, then I received a Roaming_adv and I have to inspect every
 | 
					 | 
				
			||||||
	 * packet directed to me to check whether I am still the true
 | 
					 | 
				
			||||||
	 * destination or not. This flag will be reset to false as soon as I
 | 
					 | 
				
			||||||
	 * increase my TTVN
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	bool tt_poss_change;
 | 
					 | 
				
			||||||
	char num_ifaces;
 | 
						char num_ifaces;
 | 
				
			||||||
	struct batadv_debug_log *debug_log;
 | 
						struct batadv_debug_log *debug_log;
 | 
				
			||||||
	struct kobject *mesh_obj;
 | 
						struct kobject *mesh_obj;
 | 
				
			||||||
	struct dentry *debug_dir;
 | 
						struct dentry *debug_dir;
 | 
				
			||||||
	struct hlist_head forw_bat_list;
 | 
						struct hlist_head forw_bat_list;
 | 
				
			||||||
	struct hlist_head forw_bcast_list;
 | 
						struct hlist_head forw_bcast_list;
 | 
				
			||||||
	struct hlist_head gw_list;
 | 
					 | 
				
			||||||
	struct list_head tt_changes_list; /* tracks changes in a OGM int */
 | 
					 | 
				
			||||||
	struct list_head vis_send_list;
 | 
					 | 
				
			||||||
	struct batadv_hashtable *orig_hash;
 | 
						struct batadv_hashtable *orig_hash;
 | 
				
			||||||
	struct batadv_hashtable *tt_local_hash;
 | 
					 | 
				
			||||||
	struct batadv_hashtable *tt_global_hash;
 | 
					 | 
				
			||||||
#ifdef CONFIG_BATMAN_ADV_BLA
 | 
					 | 
				
			||||||
	struct batadv_hashtable *claim_hash;
 | 
					 | 
				
			||||||
	struct batadv_hashtable *backbone_hash;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	struct list_head tt_req_list; /* list of pending tt_requests */
 | 
					 | 
				
			||||||
	struct list_head tt_roam_list;
 | 
					 | 
				
			||||||
	struct batadv_hashtable *vis_hash;
 | 
					 | 
				
			||||||
#ifdef CONFIG_BATMAN_ADV_BLA
 | 
					 | 
				
			||||||
	struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
 | 
					 | 
				
			||||||
	int bcast_duplist_curr;
 | 
					 | 
				
			||||||
	struct batadv_bla_claim_dst claim_dest;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
 | 
						spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
 | 
				
			||||||
	spinlock_t forw_bcast_list_lock; /* protects  */
 | 
						spinlock_t forw_bcast_list_lock; /* protects  */
 | 
				
			||||||
	spinlock_t tt_changes_list_lock; /* protects tt_changes */
 | 
					 | 
				
			||||||
	spinlock_t tt_req_list_lock; /* protects tt_req_list */
 | 
					 | 
				
			||||||
	spinlock_t tt_roam_list_lock; /* protects tt_roam_list */
 | 
					 | 
				
			||||||
	spinlock_t gw_list_lock; /* protects gw_list and curr_gw */
 | 
					 | 
				
			||||||
	spinlock_t vis_hash_lock; /* protects vis_hash */
 | 
					 | 
				
			||||||
	spinlock_t vis_list_lock; /* protects vis_info::recv_list */
 | 
					 | 
				
			||||||
	atomic_t num_local_tt;
 | 
					 | 
				
			||||||
	/* Checksum of the local table, recomputed before sending a new OGM */
 | 
					 | 
				
			||||||
	uint16_t tt_crc;
 | 
					 | 
				
			||||||
	unsigned char *tt_buff;
 | 
					 | 
				
			||||||
	int16_t tt_buff_len;
 | 
					 | 
				
			||||||
	spinlock_t tt_buff_lock; /* protects tt_buff */
 | 
					 | 
				
			||||||
	struct delayed_work tt_work;
 | 
					 | 
				
			||||||
	struct delayed_work orig_work;
 | 
						struct delayed_work orig_work;
 | 
				
			||||||
	struct delayed_work vis_work;
 | 
					 | 
				
			||||||
	struct delayed_work bla_work;
 | 
					 | 
				
			||||||
	struct batadv_gw_node __rcu *curr_gw;  /* rcu protected pointer */
 | 
					 | 
				
			||||||
	atomic_t gw_reselect;
 | 
					 | 
				
			||||||
	struct batadv_hard_iface __rcu *primary_if;  /* rcu protected pointer */
 | 
						struct batadv_hard_iface __rcu *primary_if;  /* rcu protected pointer */
 | 
				
			||||||
	struct batadv_vis_info *my_vis_info;
 | 
					 | 
				
			||||||
	struct batadv_algo_ops *bat_algo_ops;
 | 
						struct batadv_algo_ops *bat_algo_ops;
 | 
				
			||||||
 | 
					#ifdef CONFIG_BATMAN_ADV_BLA
 | 
				
			||||||
 | 
						struct batadv_priv_bla bla;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						struct batadv_priv_gw gw;
 | 
				
			||||||
 | 
						struct batadv_priv_tt tt;
 | 
				
			||||||
 | 
						struct batadv_priv_vis vis;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct batadv_socket_client {
 | 
					struct batadv_socket_client {
 | 
				
			||||||
| 
						 | 
					@ -258,6 +284,7 @@ struct batadv_tt_common_entry {
 | 
				
			||||||
	uint8_t addr[ETH_ALEN];
 | 
						uint8_t addr[ETH_ALEN];
 | 
				
			||||||
	struct hlist_node hash_entry;
 | 
						struct hlist_node hash_entry;
 | 
				
			||||||
	uint16_t flags;
 | 
						uint16_t flags;
 | 
				
			||||||
 | 
						unsigned long added_at;
 | 
				
			||||||
	atomic_t refcount;
 | 
						atomic_t refcount;
 | 
				
			||||||
	struct rcu_head rcu;
 | 
						struct rcu_head rcu;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -277,6 +304,7 @@ struct batadv_tt_global_entry {
 | 
				
			||||||
struct batadv_tt_orig_list_entry {
 | 
					struct batadv_tt_orig_list_entry {
 | 
				
			||||||
	struct batadv_orig_node *orig_node;
 | 
						struct batadv_orig_node *orig_node;
 | 
				
			||||||
	uint8_t ttvn;
 | 
						uint8_t ttvn;
 | 
				
			||||||
 | 
						atomic_t refcount;
 | 
				
			||||||
	struct rcu_head rcu;
 | 
						struct rcu_head rcu;
 | 
				
			||||||
	struct hlist_node list;
 | 
						struct hlist_node list;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,7 @@ batadv_frag_merge_packet(struct list_head *head,
 | 
				
			||||||
	struct batadv_unicast_packet *unicast_packet;
 | 
						struct batadv_unicast_packet *unicast_packet;
 | 
				
			||||||
	int hdr_len = sizeof(*unicast_packet);
 | 
						int hdr_len = sizeof(*unicast_packet);
 | 
				
			||||||
	int uni_diff = sizeof(*up) - hdr_len;
 | 
						int uni_diff = sizeof(*up) - hdr_len;
 | 
				
			||||||
 | 
						uint8_t *packet_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	up = (struct batadv_unicast_frag_packet *)skb->data;
 | 
						up = (struct batadv_unicast_frag_packet *)skb->data;
 | 
				
			||||||
	/* set skb to the first part and tmp_skb to the second part */
 | 
						/* set skb to the first part and tmp_skb to the second part */
 | 
				
			||||||
| 
						 | 
					@ -65,8 +66,8 @@ batadv_frag_merge_packet(struct list_head *head,
 | 
				
			||||||
	kfree_skb(tmp_skb);
 | 
						kfree_skb(tmp_skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memmove(skb->data + uni_diff, skb->data, hdr_len);
 | 
						memmove(skb->data + uni_diff, skb->data, hdr_len);
 | 
				
			||||||
	unicast_packet = (struct batadv_unicast_packet *)skb_pull(skb,
 | 
						packet_pos = skb_pull(skb, uni_diff);
 | 
				
			||||||
								  uni_diff);
 | 
						unicast_packet = (struct batadv_unicast_packet *)packet_pos;
 | 
				
			||||||
	unicast_packet->header.packet_type = BATADV_UNICAST;
 | 
						unicast_packet->header.packet_type = BATADV_UNICAST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return skb;
 | 
						return skb;
 | 
				
			||||||
| 
						 | 
					@ -121,6 +122,7 @@ batadv_frag_search_packet(struct list_head *head,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_frag_packet_list_entry *tfp;
 | 
						struct batadv_frag_packet_list_entry *tfp;
 | 
				
			||||||
	struct batadv_unicast_frag_packet *tmp_up = NULL;
 | 
						struct batadv_unicast_frag_packet *tmp_up = NULL;
 | 
				
			||||||
 | 
						int is_head_tmp, is_head;
 | 
				
			||||||
	uint16_t search_seqno;
 | 
						uint16_t search_seqno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (up->flags & BATADV_UNI_FRAG_HEAD)
 | 
						if (up->flags & BATADV_UNI_FRAG_HEAD)
 | 
				
			||||||
| 
						 | 
					@ -128,6 +130,8 @@ batadv_frag_search_packet(struct list_head *head,
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		search_seqno = ntohs(up->seqno)-1;
 | 
							search_seqno = ntohs(up->seqno)-1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						is_head = !!(up->flags & BATADV_UNI_FRAG_HEAD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(tfp, head, list) {
 | 
						list_for_each_entry(tfp, head, list) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!tfp->skb)
 | 
							if (!tfp->skb)
 | 
				
			||||||
| 
						 | 
					@ -139,9 +143,8 @@ batadv_frag_search_packet(struct list_head *head,
 | 
				
			||||||
		tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data;
 | 
							tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (tfp->seqno == search_seqno) {
 | 
							if (tfp->seqno == search_seqno) {
 | 
				
			||||||
 | 
								is_head_tmp = !!(tmp_up->flags & BATADV_UNI_FRAG_HEAD);
 | 
				
			||||||
			if ((tmp_up->flags & BATADV_UNI_FRAG_HEAD) !=
 | 
								if (is_head_tmp != is_head)
 | 
				
			||||||
			    (up->flags & BATADV_UNI_FRAG_HEAD))
 | 
					 | 
				
			||||||
				return tfp;
 | 
									return tfp;
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				goto mov_tail;
 | 
									goto mov_tail;
 | 
				
			||||||
| 
						 | 
					@ -334,8 +337,7 @@ find_router:
 | 
				
			||||||
	/* copy the destination for faster routing */
 | 
						/* copy the destination for faster routing */
 | 
				
			||||||
	memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
 | 
						memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
 | 
				
			||||||
	/* set the destination tt version number */
 | 
						/* set the destination tt version number */
 | 
				
			||||||
	unicast_packet->ttvn =
 | 
						unicast_packet->ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
 | 
				
			||||||
		(uint8_t)atomic_read(&orig_node->last_ttvn);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* inform the destination node that we are still missing a correct route
 | 
						/* inform the destination node that we are still missing a correct route
 | 
				
			||||||
	 * for this client. The destination will receive this packet and will
 | 
						 * for this client. The destination will receive this packet and will
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,13 +41,13 @@ static void batadv_free_info(struct kref *ref)
 | 
				
			||||||
	bat_priv = info->bat_priv;
 | 
						bat_priv = info->bat_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_del_init(&info->send_list);
 | 
						list_del_init(&info->send_list);
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_list_lock);
 | 
						spin_lock_bh(&bat_priv->vis.list_lock);
 | 
				
			||||||
	list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
 | 
						list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
 | 
				
			||||||
		list_del(&entry->list);
 | 
							list_del(&entry->list);
 | 
				
			||||||
		kfree(entry);
 | 
							kfree(entry);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_list_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.list_lock);
 | 
				
			||||||
	kfree_skb(info->skb_packet);
 | 
						kfree_skb(info->skb_packet);
 | 
				
			||||||
	kfree(info);
 | 
						kfree(info);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -94,7 +94,7 @@ static uint32_t batadv_vis_info_choose(const void *data, uint32_t size)
 | 
				
			||||||
static struct batadv_vis_info *
 | 
					static struct batadv_vis_info *
 | 
				
			||||||
batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data)
 | 
					batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->vis_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->vis.hash;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct hlist_node *node;
 | 
						struct hlist_node *node;
 | 
				
			||||||
	struct batadv_vis_info *vis_info, *vis_info_tmp = NULL;
 | 
						struct batadv_vis_info *vis_info, *vis_info_tmp = NULL;
 | 
				
			||||||
| 
						 | 
					@ -252,7 +252,7 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct net_device *net_dev = (struct net_device *)seq->private;
 | 
						struct net_device *net_dev = (struct net_device *)seq->private;
 | 
				
			||||||
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
						struct batadv_priv *bat_priv = netdev_priv(net_dev);
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->vis_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->vis.hash;
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
	int vis_server = atomic_read(&bat_priv->vis_mode);
 | 
						int vis_server = atomic_read(&bat_priv->vis_mode);
 | 
				
			||||||
| 
						 | 
					@ -264,12 +264,12 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset)
 | 
				
			||||||
	if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE)
 | 
						if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_lock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
		head = &hash->table[i];
 | 
							head = &hash->table[i];
 | 
				
			||||||
		batadv_vis_seq_print_text_bucket(seq, head);
 | 
							batadv_vis_seq_print_text_bucket(seq, head);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	if (primary_if)
 | 
						if (primary_if)
 | 
				
			||||||
| 
						 | 
					@ -285,7 +285,7 @@ static void batadv_send_list_add(struct batadv_priv *bat_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (list_empty(&info->send_list)) {
 | 
						if (list_empty(&info->send_list)) {
 | 
				
			||||||
		kref_get(&info->refcount);
 | 
							kref_get(&info->refcount);
 | 
				
			||||||
		list_add_tail(&info->send_list, &bat_priv->vis_send_list);
 | 
							list_add_tail(&info->send_list, &bat_priv->vis.send_list);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,9 +311,9 @@ static void batadv_recv_list_add(struct batadv_priv *bat_priv,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(entry->mac, mac, ETH_ALEN);
 | 
						memcpy(entry->mac, mac, ETH_ALEN);
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_list_lock);
 | 
						spin_lock_bh(&bat_priv->vis.list_lock);
 | 
				
			||||||
	list_add_tail(&entry->list, recv_list);
 | 
						list_add_tail(&entry->list, recv_list);
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_list_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.list_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* returns 1 if this mac is in the recv_list */
 | 
					/* returns 1 if this mac is in the recv_list */
 | 
				
			||||||
| 
						 | 
					@ -323,14 +323,14 @@ static int batadv_recv_list_is_in(struct batadv_priv *bat_priv,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct batadv_recvlist_node *entry;
 | 
						const struct batadv_recvlist_node *entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_list_lock);
 | 
						spin_lock_bh(&bat_priv->vis.list_lock);
 | 
				
			||||||
	list_for_each_entry(entry, recv_list, list) {
 | 
						list_for_each_entry(entry, recv_list, list) {
 | 
				
			||||||
		if (batadv_compare_eth(entry->mac, mac)) {
 | 
							if (batadv_compare_eth(entry->mac, mac)) {
 | 
				
			||||||
			spin_unlock_bh(&bat_priv->vis_list_lock);
 | 
								spin_unlock_bh(&bat_priv->vis.list_lock);
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_list_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.list_lock);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -354,7 +354,7 @@ batadv_add_packet(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*is_new = 0;
 | 
						*is_new = 0;
 | 
				
			||||||
	/* sanity check */
 | 
						/* sanity check */
 | 
				
			||||||
	if (!bat_priv->vis_hash)
 | 
						if (!bat_priv->vis.hash)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* see if the packet is already in vis_hash */
 | 
						/* see if the packet is already in vis_hash */
 | 
				
			||||||
| 
						 | 
					@ -385,7 +385,7 @@ batadv_add_packet(struct batadv_priv *bat_priv,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* remove old entry */
 | 
							/* remove old entry */
 | 
				
			||||||
		batadv_hash_remove(bat_priv->vis_hash, batadv_vis_info_cmp,
 | 
							batadv_hash_remove(bat_priv->vis.hash, batadv_vis_info_cmp,
 | 
				
			||||||
				   batadv_vis_info_choose, old_info);
 | 
									   batadv_vis_info_choose, old_info);
 | 
				
			||||||
		batadv_send_list_del(old_info);
 | 
							batadv_send_list_del(old_info);
 | 
				
			||||||
		kref_put(&old_info->refcount, batadv_free_info);
 | 
							kref_put(&old_info->refcount, batadv_free_info);
 | 
				
			||||||
| 
						 | 
					@ -426,7 +426,7 @@ batadv_add_packet(struct batadv_priv *bat_priv,
 | 
				
			||||||
	batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
 | 
						batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* try to add it */
 | 
						/* try to add it */
 | 
				
			||||||
	hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp,
 | 
						hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
 | 
				
			||||||
				     batadv_vis_info_choose, info,
 | 
									     batadv_vis_info_choose, info,
 | 
				
			||||||
				     &info->hash_entry);
 | 
									     &info->hash_entry);
 | 
				
			||||||
	if (hash_added != 0) {
 | 
						if (hash_added != 0) {
 | 
				
			||||||
| 
						 | 
					@ -449,7 +449,7 @@ void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC);
 | 
						make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_lock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
 | 
						info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
 | 
				
			||||||
				 &is_new, make_broadcast);
 | 
									 &is_new, make_broadcast);
 | 
				
			||||||
	if (!info)
 | 
						if (!info)
 | 
				
			||||||
| 
						 | 
					@ -461,7 +461,7 @@ void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
 | 
				
			||||||
	if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new)
 | 
						if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new)
 | 
				
			||||||
		batadv_send_list_add(bat_priv, info);
 | 
							batadv_send_list_add(bat_priv, info);
 | 
				
			||||||
end:
 | 
					end:
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* handle an incoming client update packet and schedule forward if needed. */
 | 
					/* handle an incoming client update packet and schedule forward if needed. */
 | 
				
			||||||
| 
						 | 
					@ -484,7 +484,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
 | 
				
			||||||
	    batadv_is_my_mac(vis_packet->target_orig))
 | 
						    batadv_is_my_mac(vis_packet->target_orig))
 | 
				
			||||||
		are_target = 1;
 | 
							are_target = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_lock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
 | 
						info = batadv_add_packet(bat_priv, vis_packet, vis_info_len,
 | 
				
			||||||
				 &is_new, are_target);
 | 
									 &is_new, are_target);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -505,7 +505,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end:
 | 
					end:
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Walk the originators and find the VIS server with the best tq. Set the packet
 | 
					/* Walk the originators and find the VIS server with the best tq. Set the packet
 | 
				
			||||||
| 
						 | 
					@ -574,10 +574,11 @@ static int batadv_generate_vis_packet(struct batadv_priv *bat_priv)
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct batadv_orig_node *orig_node;
 | 
						struct batadv_orig_node *orig_node;
 | 
				
			||||||
	struct batadv_neigh_node *router;
 | 
						struct batadv_neigh_node *router;
 | 
				
			||||||
	struct batadv_vis_info *info = bat_priv->my_vis_info;
 | 
						struct batadv_vis_info *info = bat_priv->vis.my_info;
 | 
				
			||||||
	struct batadv_vis_packet *packet;
 | 
						struct batadv_vis_packet *packet;
 | 
				
			||||||
	struct batadv_vis_info_entry *entry;
 | 
						struct batadv_vis_info_entry *entry;
 | 
				
			||||||
	struct batadv_tt_common_entry *tt_common_entry;
 | 
						struct batadv_tt_common_entry *tt_common_entry;
 | 
				
			||||||
 | 
						uint8_t *packet_pos;
 | 
				
			||||||
	int best_tq = -1;
 | 
						int best_tq = -1;
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -618,8 +619,8 @@ static int batadv_generate_vis_packet(struct batadv_priv *bat_priv)
 | 
				
			||||||
				goto next;
 | 
									goto next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* fill one entry into buffer. */
 | 
								/* fill one entry into buffer. */
 | 
				
			||||||
			entry = (struct batadv_vis_info_entry *)
 | 
								packet_pos = skb_put(info->skb_packet, sizeof(*entry));
 | 
				
			||||||
				      skb_put(info->skb_packet, sizeof(*entry));
 | 
								entry = (struct batadv_vis_info_entry *)packet_pos;
 | 
				
			||||||
			memcpy(entry->src,
 | 
								memcpy(entry->src,
 | 
				
			||||||
			       router->if_incoming->net_dev->dev_addr,
 | 
								       router->if_incoming->net_dev->dev_addr,
 | 
				
			||||||
			       ETH_ALEN);
 | 
								       ETH_ALEN);
 | 
				
			||||||
| 
						 | 
					@ -636,7 +637,7 @@ next:
 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash = bat_priv->tt_local_hash;
 | 
						hash = bat_priv->tt.local_hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < hash->size; i++) {
 | 
						for (i = 0; i < hash->size; i++) {
 | 
				
			||||||
		head = &hash->table[i];
 | 
							head = &hash->table[i];
 | 
				
			||||||
| 
						 | 
					@ -644,9 +645,8 @@ next:
 | 
				
			||||||
		rcu_read_lock();
 | 
							rcu_read_lock();
 | 
				
			||||||
		hlist_for_each_entry_rcu(tt_common_entry, node, head,
 | 
							hlist_for_each_entry_rcu(tt_common_entry, node, head,
 | 
				
			||||||
					 hash_entry) {
 | 
										 hash_entry) {
 | 
				
			||||||
			entry = (struct batadv_vis_info_entry *)
 | 
								packet_pos = skb_put(info->skb_packet, sizeof(*entry));
 | 
				
			||||||
					skb_put(info->skb_packet,
 | 
								entry = (struct batadv_vis_info_entry *)packet_pos;
 | 
				
			||||||
						sizeof(*entry));
 | 
					 | 
				
			||||||
			memset(entry->src, 0, ETH_ALEN);
 | 
								memset(entry->src, 0, ETH_ALEN);
 | 
				
			||||||
			memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN);
 | 
								memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN);
 | 
				
			||||||
			entry->quality = 0; /* 0 means TT */
 | 
								entry->quality = 0; /* 0 means TT */
 | 
				
			||||||
| 
						 | 
					@ -671,7 +671,7 @@ unlock:
 | 
				
			||||||
static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
 | 
					static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
	struct batadv_hashtable *hash = bat_priv->vis_hash;
 | 
						struct batadv_hashtable *hash = bat_priv->vis.hash;
 | 
				
			||||||
	struct hlist_node *node, *node_tmp;
 | 
						struct hlist_node *node, *node_tmp;
 | 
				
			||||||
	struct hlist_head *head;
 | 
						struct hlist_head *head;
 | 
				
			||||||
	struct batadv_vis_info *info;
 | 
						struct batadv_vis_info *info;
 | 
				
			||||||
| 
						 | 
					@ -682,7 +682,7 @@ static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
 | 
				
			||||||
		hlist_for_each_entry_safe(info, node, node_tmp,
 | 
							hlist_for_each_entry_safe(info, node, node_tmp,
 | 
				
			||||||
					  head, hash_entry) {
 | 
										  head, hash_entry) {
 | 
				
			||||||
			/* never purge own data. */
 | 
								/* never purge own data. */
 | 
				
			||||||
			if (info == bat_priv->my_vis_info)
 | 
								if (info == bat_priv->vis.my_info)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (batadv_has_timed_out(info->first_seen,
 | 
								if (batadv_has_timed_out(info->first_seen,
 | 
				
			||||||
| 
						 | 
					@ -814,34 +814,36 @@ out:
 | 
				
			||||||
/* called from timer; send (and maybe generate) vis packet. */
 | 
					/* called from timer; send (and maybe generate) vis packet. */
 | 
				
			||||||
static void batadv_send_vis_packets(struct work_struct *work)
 | 
					static void batadv_send_vis_packets(struct work_struct *work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct delayed_work *delayed_work =
 | 
						struct delayed_work *delayed_work;
 | 
				
			||||||
		container_of(work, struct delayed_work, work);
 | 
					 | 
				
			||||||
	struct batadv_priv *bat_priv;
 | 
						struct batadv_priv *bat_priv;
 | 
				
			||||||
 | 
						struct batadv_priv_vis *priv_vis;
 | 
				
			||||||
	struct batadv_vis_info *info;
 | 
						struct batadv_vis_info *info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv = container_of(delayed_work, struct batadv_priv, vis_work);
 | 
						delayed_work = container_of(work, struct delayed_work, work);
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_hash_lock);
 | 
						priv_vis = container_of(delayed_work, struct batadv_priv_vis, work);
 | 
				
			||||||
 | 
						bat_priv = container_of(priv_vis, struct batadv_priv, vis);
 | 
				
			||||||
 | 
						spin_lock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	batadv_purge_vis_packets(bat_priv);
 | 
						batadv_purge_vis_packets(bat_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (batadv_generate_vis_packet(bat_priv) == 0) {
 | 
						if (batadv_generate_vis_packet(bat_priv) == 0) {
 | 
				
			||||||
		/* schedule if generation was successful */
 | 
							/* schedule if generation was successful */
 | 
				
			||||||
		batadv_send_list_add(bat_priv, bat_priv->my_vis_info);
 | 
							batadv_send_list_add(bat_priv, bat_priv->vis.my_info);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!list_empty(&bat_priv->vis_send_list)) {
 | 
						while (!list_empty(&bat_priv->vis.send_list)) {
 | 
				
			||||||
		info = list_first_entry(&bat_priv->vis_send_list,
 | 
							info = list_first_entry(&bat_priv->vis.send_list,
 | 
				
			||||||
					typeof(*info), send_list);
 | 
										typeof(*info), send_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		kref_get(&info->refcount);
 | 
							kref_get(&info->refcount);
 | 
				
			||||||
		spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
							spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		batadv_send_vis_packet(bat_priv, info);
 | 
							batadv_send_vis_packet(bat_priv, info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spin_lock_bh(&bat_priv->vis_hash_lock);
 | 
							spin_lock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
		batadv_send_list_del(info);
 | 
							batadv_send_list_del(info);
 | 
				
			||||||
		kref_put(&info->refcount, batadv_free_info);
 | 
							kref_put(&info->refcount, batadv_free_info);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	batadv_start_vis_timer(bat_priv);
 | 
						batadv_start_vis_timer(bat_priv);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -856,37 +858,37 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
 | 
				
			||||||
	unsigned long first_seen;
 | 
						unsigned long first_seen;
 | 
				
			||||||
	struct sk_buff *tmp_skb;
 | 
						struct sk_buff *tmp_skb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bat_priv->vis_hash)
 | 
						if (bat_priv->vis.hash)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_lock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->vis_hash = batadv_hash_new(256);
 | 
						bat_priv->vis.hash = batadv_hash_new(256);
 | 
				
			||||||
	if (!bat_priv->vis_hash) {
 | 
						if (!bat_priv->vis.hash) {
 | 
				
			||||||
		pr_err("Can't initialize vis_hash\n");
 | 
							pr_err("Can't initialize vis_hash\n");
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bat_priv->my_vis_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
 | 
						bat_priv->vis.my_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC);
 | 
				
			||||||
	if (!bat_priv->my_vis_info)
 | 
						if (!bat_priv->vis.my_info)
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
 | 
						len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
 | 
				
			||||||
	bat_priv->my_vis_info->skb_packet = dev_alloc_skb(len);
 | 
						bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
 | 
				
			||||||
	if (!bat_priv->my_vis_info->skb_packet)
 | 
						if (!bat_priv->vis.my_info->skb_packet)
 | 
				
			||||||
		goto free_info;
 | 
							goto free_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb_reserve(bat_priv->my_vis_info->skb_packet, ETH_HLEN);
 | 
						skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
 | 
				
			||||||
	tmp_skb = bat_priv->my_vis_info->skb_packet;
 | 
						tmp_skb = bat_priv->vis.my_info->skb_packet;
 | 
				
			||||||
	packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
 | 
						packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* prefill the vis info */
 | 
						/* prefill the vis info */
 | 
				
			||||||
	first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL);
 | 
						first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL);
 | 
				
			||||||
	bat_priv->my_vis_info->first_seen = first_seen;
 | 
						bat_priv->vis.my_info->first_seen = first_seen;
 | 
				
			||||||
	INIT_LIST_HEAD(&bat_priv->my_vis_info->recv_list);
 | 
						INIT_LIST_HEAD(&bat_priv->vis.my_info->recv_list);
 | 
				
			||||||
	INIT_LIST_HEAD(&bat_priv->my_vis_info->send_list);
 | 
						INIT_LIST_HEAD(&bat_priv->vis.my_info->send_list);
 | 
				
			||||||
	kref_init(&bat_priv->my_vis_info->refcount);
 | 
						kref_init(&bat_priv->vis.my_info->refcount);
 | 
				
			||||||
	bat_priv->my_vis_info->bat_priv = bat_priv;
 | 
						bat_priv->vis.my_info->bat_priv = bat_priv;
 | 
				
			||||||
	packet->header.version = BATADV_COMPAT_VERSION;
 | 
						packet->header.version = BATADV_COMPAT_VERSION;
 | 
				
			||||||
	packet->header.packet_type = BATADV_VIS;
 | 
						packet->header.packet_type = BATADV_VIS;
 | 
				
			||||||
	packet->header.ttl = BATADV_TTL;
 | 
						packet->header.ttl = BATADV_TTL;
 | 
				
			||||||
| 
						 | 
					@ -894,28 +896,28 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
 | 
				
			||||||
	packet->reserved = 0;
 | 
						packet->reserved = 0;
 | 
				
			||||||
	packet->entries = 0;
 | 
						packet->entries = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&bat_priv->vis_send_list);
 | 
						INIT_LIST_HEAD(&bat_priv->vis.send_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp,
 | 
						hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp,
 | 
				
			||||||
				     batadv_vis_info_choose,
 | 
									     batadv_vis_info_choose,
 | 
				
			||||||
				     bat_priv->my_vis_info,
 | 
									     bat_priv->vis.my_info,
 | 
				
			||||||
				     &bat_priv->my_vis_info->hash_entry);
 | 
									     &bat_priv->vis.my_info->hash_entry);
 | 
				
			||||||
	if (hash_added != 0) {
 | 
						if (hash_added != 0) {
 | 
				
			||||||
		pr_err("Can't add own vis packet into hash\n");
 | 
							pr_err("Can't add own vis packet into hash\n");
 | 
				
			||||||
		/* not in hash, need to remove it manually. */
 | 
							/* not in hash, need to remove it manually. */
 | 
				
			||||||
		kref_put(&bat_priv->my_vis_info->refcount, batadv_free_info);
 | 
							kref_put(&bat_priv->vis.my_info->refcount, batadv_free_info);
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	batadv_start_vis_timer(bat_priv);
 | 
						batadv_start_vis_timer(bat_priv);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
free_info:
 | 
					free_info:
 | 
				
			||||||
	kfree(bat_priv->my_vis_info);
 | 
						kfree(bat_priv->vis.my_info);
 | 
				
			||||||
	bat_priv->my_vis_info = NULL;
 | 
						bat_priv->vis.my_info = NULL;
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	batadv_vis_quit(bat_priv);
 | 
						batadv_vis_quit(bat_priv);
 | 
				
			||||||
	return -ENOMEM;
 | 
						return -ENOMEM;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -933,23 +935,23 @@ static void batadv_free_info_ref(struct hlist_node *node, void *arg)
 | 
				
			||||||
/* shutdown vis-server */
 | 
					/* shutdown vis-server */
 | 
				
			||||||
void batadv_vis_quit(struct batadv_priv *bat_priv)
 | 
					void batadv_vis_quit(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!bat_priv->vis_hash)
 | 
						if (!bat_priv->vis.hash)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cancel_delayed_work_sync(&bat_priv->vis_work);
 | 
						cancel_delayed_work_sync(&bat_priv->vis.work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_lock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
	/* properly remove, kill timers ... */
 | 
						/* properly remove, kill timers ... */
 | 
				
			||||||
	batadv_hash_delete(bat_priv->vis_hash, batadv_free_info_ref, NULL);
 | 
						batadv_hash_delete(bat_priv->vis.hash, batadv_free_info_ref, NULL);
 | 
				
			||||||
	bat_priv->vis_hash = NULL;
 | 
						bat_priv->vis.hash = NULL;
 | 
				
			||||||
	bat_priv->my_vis_info = NULL;
 | 
						bat_priv->vis.my_info = NULL;
 | 
				
			||||||
	spin_unlock_bh(&bat_priv->vis_hash_lock);
 | 
						spin_unlock_bh(&bat_priv->vis.hash_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* schedule packets for (re)transmission */
 | 
					/* schedule packets for (re)transmission */
 | 
				
			||||||
static void batadv_start_vis_timer(struct batadv_priv *bat_priv)
 | 
					static void batadv_start_vis_timer(struct batadv_priv *bat_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	INIT_DELAYED_WORK(&bat_priv->vis_work, batadv_send_vis_packets);
 | 
						INIT_DELAYED_WORK(&bat_priv->vis.work, batadv_send_vis_packets);
 | 
				
			||||||
	queue_delayed_work(batadv_event_workqueue, &bat_priv->vis_work,
 | 
						queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work,
 | 
				
			||||||
			   msecs_to_jiffies(BATADV_VIS_INTERVAL));
 | 
								   msecs_to_jiffies(BATADV_VIS_INTERVAL));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@
 | 
				
			||||||
#ifndef _NET_BATMAN_ADV_VIS_H_
 | 
					#ifndef _NET_BATMAN_ADV_VIS_H_
 | 
				
			||||||
#define _NET_BATMAN_ADV_VIS_H_
 | 
					#define _NET_BATMAN_ADV_VIS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* timeout of vis packets in miliseconds */
 | 
					/* timeout of vis packets in milliseconds */
 | 
				
			||||||
#define BATADV_VIS_TIMEOUT		200000
 | 
					#define BATADV_VIS_TIMEOUT		200000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int batadv_vis_seq_print_text(struct seq_file *seq, void *offset);
 | 
					int batadv_vis_seq_print_text(struct seq_file *seq, void *offset);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue