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

Merge tag 'batadv-net-for-davem-20200918' of git://git.open-mesh.org/linux-merge



Simon Wunderlich says:

====================
Here are some batman-adv bugfixes:

 - fix wrong type use in backbone_gw hash, by Linus Luessing

 - disable TT re-routing for multicast packets, by Linus Luessing

 - Add missing include for in_interrupt(), by Sven Eckelmann

 - fix BLA/multicast issues for packets sent via unicast,
   by Linus Luessing (3 patches)
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a1285927 2369e827
Loading
Loading
Loading
Loading
+117 −28
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/lockdep.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/preempt.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/seq_file.h>
@@ -83,11 +84,12 @@ static inline u32 batadv_choose_claim(const void *data, u32 size)
 */
static inline u32 batadv_choose_backbone_gw(const void *data, u32 size)
{
	const struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data;
	const struct batadv_bla_backbone_gw *gw;
	u32 hash = 0;

	hash = jhash(&claim->addr, sizeof(claim->addr), hash);
	hash = jhash(&claim->vid, sizeof(claim->vid), hash);
	gw = (struct batadv_bla_backbone_gw *)data;
	hash = jhash(&gw->orig, sizeof(gw->orig), hash);
	hash = jhash(&gw->vid, sizeof(gw->vid), hash);

	return hash % size;
}
@@ -1579,13 +1581,16 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
}

/**
 * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
 * batadv_bla_check_duplist() - Check if a frame is in the broadcast dup.
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: contains the bcast_packet to be checked
 * @skb: contains the multicast packet to be checked
 * @payload_ptr: pointer to position inside the head buffer of the skb
 *  marking the start of the data to be CRC'ed
 * @orig: originator mac address, NULL if unknown
 *
 * check if it is on our broadcast list. Another gateway might
 * have sent the same packet because it is connected to the same backbone,
 * so we have to remove this duplicate.
 * Check if it is on our broadcast list. Another gateway might have sent the
 * same packet because it is connected to the same backbone, so we have to
 * remove this duplicate.
 *
 * This is performed by checking the CRC, which will tell us
 * with a good chance that it is the same packet. If it is furthermore
@@ -1594,19 +1599,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 *
 * Return: true if a packet is in the duplicate list, false otherwise.
 */
bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
				    struct sk_buff *skb)
static bool batadv_bla_check_duplist(struct batadv_priv *bat_priv,
				     struct sk_buff *skb, u8 *payload_ptr,
				     const u8 *orig)
{
	int i, curr;
	__be32 crc;
	struct batadv_bcast_packet *bcast_packet;
	struct batadv_bcast_duplist_entry *entry;
	bool ret = false;

	bcast_packet = (struct batadv_bcast_packet *)skb->data;
	int i, curr;
	__be32 crc;

	/* calculate the crc ... */
	crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
	crc = batadv_skb_crc32(skb, payload_ptr);

	spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);

@@ -1625,8 +1628,21 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
		if (entry->crc != crc)
			continue;

		if (batadv_compare_eth(entry->orig, bcast_packet->orig))
		/* are the originators both known and not anonymous? */
		if (orig && !is_zero_ether_addr(orig) &&
		    !is_zero_ether_addr(entry->orig)) {
			/* If known, check if the new frame came from
			 * the same originator:
			 * We are safe to take identical frames from the
			 * same orig, if known, as multiplications in
			 * the mesh are detected via the (orig, seqno) pair.
			 * So we can be a bit more liberal here and allow
			 * identical frames from the same orig which the source
			 * host might have sent multiple times on purpose.
			 */
			if (batadv_compare_eth(entry->orig, orig))
				continue;
		}

		/* this entry seems to match: same crc, not too old,
		 * and from another gw. therefore return true to forbid it.
@@ -1642,7 +1658,14 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
	entry = &bat_priv->bla.bcast_duplist[curr];
	entry->crc = crc;
	entry->entrytime = jiffies;
	ether_addr_copy(entry->orig, bcast_packet->orig);

	/* known originator */
	if (orig)
		ether_addr_copy(entry->orig, orig);
	/* anonymous originator */
	else
		eth_zero_addr(entry->orig);

	bat_priv->bla.bcast_duplist_curr = curr;

out:
@@ -1651,6 +1674,48 @@ out:
	return ret;
}

/**
 * batadv_bla_check_ucast_duplist() - Check if a frame is in the broadcast dup.
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: contains the multicast packet to be checked, decapsulated from a
 *  unicast_packet
 *
 * Check if it is on our broadcast list. Another gateway might have sent the
 * same packet because it is connected to the same backbone, so we have to
 * remove this duplicate.
 *
 * Return: true if a packet is in the duplicate list, false otherwise.
 */
static bool batadv_bla_check_ucast_duplist(struct batadv_priv *bat_priv,
					   struct sk_buff *skb)
{
	return batadv_bla_check_duplist(bat_priv, skb, (u8 *)skb->data, NULL);
}

/**
 * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: contains the bcast_packet to be checked
 *
 * Check if it is on our broadcast list. Another gateway might have sent the
 * same packet because it is connected to the same backbone, so we have to
 * remove this duplicate.
 *
 * Return: true if a packet is in the duplicate list, false otherwise.
 */
bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
				    struct sk_buff *skb)
{
	struct batadv_bcast_packet *bcast_packet;
	u8 *payload_ptr;

	bcast_packet = (struct batadv_bcast_packet *)skb->data;
	payload_ptr = (u8 *)(bcast_packet + 1);

	return batadv_bla_check_duplist(bat_priv, skb, payload_ptr,
					bcast_packet->orig);
}

/**
 * batadv_bla_is_backbone_gw_orig() - Check if the originator is a gateway for
 *  the VLAN identified by vid.
@@ -1812,7 +1877,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: the frame to be checked
 * @vid: the VLAN ID of the frame
 * @is_bcast: the packet came in a broadcast packet type.
 * @packet_type: the batman packet type this frame came in
 *
 * batadv_bla_rx avoidance checks if:
 *  * we have to race for a claim
@@ -1824,7 +1889,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
 * further process the skb.
 */
bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
		   unsigned short vid, bool is_bcast)
		   unsigned short vid, int packet_type)
{
	struct batadv_bla_backbone_gw *backbone_gw;
	struct ethhdr *ethhdr;
@@ -1846,8 +1911,31 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
		goto handled;

	if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
		/* don't allow broadcasts while requests are in flight */
		if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
		/* don't allow multicast packets while requests are in flight */
		if (is_multicast_ether_addr(ethhdr->h_dest))
			/* Both broadcast flooding or multicast-via-unicasts
			 * delivery might send to multiple backbone gateways
			 * sharing the same LAN and therefore need to coordinate
			 * which backbone gateway forwards into the LAN,
			 * by claiming the payload source address.
			 *
			 * Broadcast flooding and multicast-via-unicasts
			 * delivery use the following two batman packet types.
			 * Note: explicitly exclude BATADV_UNICAST_4ADDR,
			 * as the DHCP gateway feature will send explicitly
			 * to only one BLA gateway, so the claiming process
			 * should be avoided there.
			 */
			if (packet_type == BATADV_BCAST ||
			    packet_type == BATADV_UNICAST)
				goto handled;

	/* potential duplicates from foreign BLA backbone gateways via
	 * multicast-in-unicast packets
	 */
	if (is_multicast_ether_addr(ethhdr->h_dest) &&
	    packet_type == BATADV_UNICAST &&
	    batadv_bla_check_ucast_duplist(bat_priv, skb))
		goto handled;

	ether_addr_copy(search_claim.addr, ethhdr->h_source);
@@ -1883,13 +1971,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
		goto allow;
	}

	/* if it is a broadcast ... */
	if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
	/* if it is a multicast ... */
	if (is_multicast_ether_addr(ethhdr->h_dest) &&
	    (packet_type == BATADV_BCAST || packet_type == BATADV_UNICAST)) {
		/* ... drop it. the responsible gateway is in charge.
		 *
		 * We need to check is_bcast because with the gateway
		 * We need to check packet type because with the gateway
		 * feature, broadcasts (like DHCP requests) may be sent
		 * using a unicast packet type.
		 * using a unicast 4 address packet type. See comment above.
		 */
		goto handled;
	} else {
+2 −2
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ static inline bool batadv_bla_is_loopdetect_mac(const uint8_t *mac)

#ifdef CONFIG_BATMAN_ADV_BLA
bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
		   unsigned short vid, bool is_bcast);
		   unsigned short vid, int packet_type);
bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
		   unsigned short vid);
bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
@@ -66,7 +66,7 @@ bool batadv_bla_check_claim(struct batadv_priv *bat_priv, u8 *addr,

static inline bool batadv_bla_rx(struct batadv_priv *bat_priv,
				 struct sk_buff *skb, unsigned short vid,
				 bool is_bcast)
				 int packet_type)
{
	return false;
}
+36 −10
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@
#include <uapi/linux/batadv_packet.h>
#include <uapi/linux/batman_adv.h>

#include "bridge_loop_avoidance.h"
#include "hard-interface.h"
#include "hash.h"
#include "log.h"
@@ -1434,6 +1435,35 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
	return BATADV_FORW_ALL;
}

/**
 * batadv_mcast_forw_send_orig() - send a multicast packet to an originator
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: the multicast packet to send
 * @vid: the vlan identifier
 * @orig_node: the originator to send the packet to
 *
 * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
 */
int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
				struct sk_buff *skb,
				unsigned short vid,
				struct batadv_orig_node *orig_node)
{
	/* Avoid sending multicast-in-unicast packets to other BLA
	 * gateways - they already got the frame from the LAN side
	 * we share with them.
	 * TODO: Refactor to take BLA into account earlier, to avoid
	 * reducing the mcast_fanout count.
	 */
	if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid)) {
		dev_kfree_skb(skb);
		return NET_XMIT_SUCCESS;
	}

	return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0,
				       orig_node, vid);
}

/**
 * batadv_mcast_forw_tt() - forwards a packet to multicast listeners
 * @bat_priv: the bat priv with all the soft interface information
@@ -1471,8 +1501,8 @@ batadv_mcast_forw_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
			break;
		}

		batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
					orig_entry->orig_node, vid);
		batadv_mcast_forw_send_orig(bat_priv, newskb, vid,
					    orig_entry->orig_node);
	}
	rcu_read_unlock();

@@ -1513,8 +1543,7 @@ batadv_mcast_forw_want_all_ipv4(struct batadv_priv *bat_priv,
			break;
		}

		batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
					orig_node, vid);
		batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
	}
	rcu_read_unlock();
	return ret;
@@ -1551,8 +1580,7 @@ batadv_mcast_forw_want_all_ipv6(struct batadv_priv *bat_priv,
			break;
		}

		batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
					orig_node, vid);
		batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
	}
	rcu_read_unlock();
	return ret;
@@ -1618,8 +1646,7 @@ batadv_mcast_forw_want_all_rtr4(struct batadv_priv *bat_priv,
			break;
		}

		batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
					orig_node, vid);
		batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
	}
	rcu_read_unlock();
	return ret;
@@ -1656,8 +1683,7 @@ batadv_mcast_forw_want_all_rtr6(struct batadv_priv *bat_priv,
			break;
		}

		batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
					orig_node, vid);
		batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
	}
	rcu_read_unlock();
	return ret;
+15 −0
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ enum batadv_forw_mode
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
		       struct batadv_orig_node **mcast_single_orig);

int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
				struct sk_buff *skb,
				unsigned short vid,
				struct batadv_orig_node *orig_node);

int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
			   unsigned short vid);

@@ -71,6 +76,16 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
	return BATADV_FORW_ALL;
}

static inline int
batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
			    struct sk_buff *skb,
			    unsigned short vid,
			    struct batadv_orig_node *orig_node)
{
	kfree_skb(skb);
	return NET_XMIT_DROP;
}

static inline int
batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
		       unsigned short vid)
+4 −0
Original line number Diff line number Diff line
@@ -826,6 +826,10 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
	vid = batadv_get_vid(skb, hdr_len);
	ethhdr = (struct ethhdr *)(skb->data + hdr_len);

	/* do not reroute multicast frames in a unicast header */
	if (is_multicast_ether_addr(ethhdr->h_dest))
		return true;

	/* check if the destination client was served by this node and it is now
	 * roaming. In this case, it means that the node has got a ROAM_ADV
	 * message and that it knows the new destination in the mesh to re-route
Loading