Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db0fe0b2 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge



Included fixes:
- Fix broadcast packet CRC calculation which can lead to ~80% broadcast packet
  loss
- Fix a race condition in duplicate broadcast packet check

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a3374c42 7dac7b76
Loading
Loading
Loading
Loading
+18 −9
Original line number Original line Diff line number Diff line
@@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
	uint16_t crc;
	uint16_t crc;
	unsigned long entrytime;
	unsigned long entrytime;


	spin_lock_init(&bat_priv->bla.bcast_duplist_lock);

	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 */
@@ -1210,8 +1212,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
/**
/**
 * batadv_bla_check_bcast_duplist
 * batadv_bla_check_bcast_duplist
 * @bat_priv: the bat priv with all the soft interface information
 * @bat_priv: the bat priv with all the soft interface information
 * @bcast_packet: originator mac address
 * @bcast_packet: encapsulated broadcast frame plus batman header
 * @hdr_size: maximum length of the frame
 * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
 *
 *
 * check if it is on our broadcast list. Another gateway might
 * check if it is on our broadcast list. Another gateway might
 * have sent the same packet because it is connected to the same backbone,
 * have sent the same packet because it is connected to the same backbone,
@@ -1224,20 +1226,22 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 */
 */
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,
				   int hdr_size)
				   int bcast_packet_len)
{
{
	int i, length, curr;
	int i, length, curr, ret = 0;
	uint8_t *content;
	uint8_t *content;
	uint16_t crc;
	uint16_t crc;
	struct batadv_bcast_duplist_entry *entry;
	struct batadv_bcast_duplist_entry *entry;


	length = hdr_size - sizeof(*bcast_packet);
	length = bcast_packet_len - sizeof(*bcast_packet);
	content = (uint8_t *)bcast_packet;
	content = (uint8_t *)bcast_packet;
	content += sizeof(*bcast_packet);
	content += sizeof(*bcast_packet);


	/* calculate the crc ... */
	/* calculate the crc ... */
	crc = crc16(0, content, length);
	crc = crc16(0, content, length);


	spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);

	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
		curr = (bat_priv->bla.bcast_duplist_curr + i);
		curr = (bat_priv->bla.bcast_duplist_curr + i);
		curr %= BATADV_DUPLIST_SIZE;
		curr %= BATADV_DUPLIST_SIZE;
@@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
		/* this entry seems to match: same crc, not too old,
		/* this entry seems to match: same crc, not too old,
		 * and from another gw. therefore return 1 to forbid it.
		 * and from another gw. therefore return 1 to forbid it.
		 */
		 */
		return 1;
		ret = 1;
		goto out;
	}
	}
	/* not found, add a new entry (overwrite the oldest entry) */
	/* not found, add a new entry (overwrite the oldest entry)
	 * and allow it, its the first occurence.
	 */
	curr = (bat_priv->bla.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->bla.bcast_duplist[curr];
	entry = &bat_priv->bla.bcast_duplist[curr];
@@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
	bat_priv->bla.bcast_duplist_curr = curr;
	bat_priv->bla.bcast_duplist_curr = curr;


	/* allow it, its the first occurence. */
out:
	return 0;
	spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);

	return ret;
}
}




+7 −1
Original line number Original line Diff line number Diff line
@@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,


	spin_unlock_bh(&orig_node->bcast_seqno_lock);
	spin_unlock_bh(&orig_node->bcast_seqno_lock);


	/* keep skb linear for crc calculation */
	if (skb_linearize(skb) < 0)
		goto out;

	bcast_packet = (struct batadv_bcast_packet *)skb->data;

	/* check whether this has been sent by another originator before */
	/* check whether this has been sent by another originator before */
	if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size))
	if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))
		goto out;
		goto out;


	/* rebroadcast packet */
	/* rebroadcast packet */
+2 −0
Original line number Original line Diff line number Diff line
@@ -205,6 +205,8 @@ struct batadv_priv_bla {
	struct batadv_hashtable *backbone_hash;
	struct batadv_hashtable *backbone_hash;
	struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
	struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
	int bcast_duplist_curr;
	int bcast_duplist_curr;
	/* protects bcast_duplist and bcast_duplist_curr */
	spinlock_t bcast_duplist_lock;
	struct batadv_bla_claim_dst claim_dest;
	struct batadv_bla_claim_dst claim_dest;
	struct delayed_work work;
	struct delayed_work work;
};
};