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

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
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/preempt.h>
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -83,11 +84,12 @@ static inline u32 batadv_choose_claim(const void *data, u32 size) ...@@ -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) 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; u32 hash = 0;
hash = jhash(&claim->addr, sizeof(claim->addr), hash); gw = (struct batadv_bla_backbone_gw *)data;
hash = jhash(&claim->vid, sizeof(claim->vid), hash); hash = jhash(&gw->orig, sizeof(gw->orig), hash);
hash = jhash(&gw->vid, sizeof(gw->vid), hash);
return hash % size; return hash % size;
} }
...@@ -1579,13 +1581,16 @@ int batadv_bla_init(struct batadv_priv *bat_priv) ...@@ -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 * @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 * Check if it is on our broadcast list. Another gateway might have sent the
* have sent the same packet because it is connected to the same backbone, * same packet because it is connected to the same backbone, so we have to
* so we have to remove this duplicate. * remove this duplicate.
* *
* This is performed by checking the CRC, which will tell us * 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 * 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) ...@@ -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. * Return: true if a packet is in the duplicate list, false otherwise.
*/ */
bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, static bool batadv_bla_check_duplist(struct batadv_priv *bat_priv,
struct sk_buff *skb) 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; struct batadv_bcast_duplist_entry *entry;
bool ret = false; bool ret = false;
int i, curr;
bcast_packet = (struct batadv_bcast_packet *)skb->data; __be32 crc;
/* calculate the 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); spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
...@@ -1625,8 +1628,21 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, ...@@ -1625,8 +1628,21 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
if (entry->crc != crc) if (entry->crc != crc)
continue; continue;
if (batadv_compare_eth(entry->orig, bcast_packet->orig)) /* are the originators both known and not anonymous? */
continue; 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, /* this entry seems to match: same crc, not too old,
* and from another gw. therefore return true to forbid it. * 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, ...@@ -1642,7 +1658,14 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
entry = &bat_priv->bla.bcast_duplist[curr]; entry = &bat_priv->bla.bcast_duplist[curr];
entry->crc = crc; entry->crc = crc;
entry->entrytime = jiffies; 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; bat_priv->bla.bcast_duplist_curr = curr;
out: out:
...@@ -1651,6 +1674,48 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, ...@@ -1651,6 +1674,48 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
return ret; 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 * batadv_bla_is_backbone_gw_orig() - Check if the originator is a gateway for
* the VLAN identified by vid. * the VLAN identified by vid.
...@@ -1812,7 +1877,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -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 * @bat_priv: the bat priv with all the soft interface information
* @skb: the frame to be checked * @skb: the frame to be checked
* @vid: the VLAN ID of the frame * @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: * batadv_bla_rx avoidance checks if:
* * we have to race for a claim * * we have to race for a claim
...@@ -1824,7 +1889,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -1824,7 +1889,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
* further process the skb. * further process the skb.
*/ */
bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *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 batadv_bla_backbone_gw *backbone_gw;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
...@@ -1846,9 +1911,32 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -1846,9 +1911,32 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
goto handled; goto handled;
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 multicast packets while requests are in flight */
if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) if (is_multicast_ether_addr(ethhdr->h_dest))
goto handled; /* 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); ether_addr_copy(search_claim.addr, ethhdr->h_source);
search_claim.vid = vid; search_claim.vid = vid;
...@@ -1883,13 +1971,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -1883,13 +1971,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
goto allow; goto allow;
} }
/* if it is a broadcast ... */ /* if it is a multicast ... */
if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) { if (is_multicast_ether_addr(ethhdr->h_dest) &&
(packet_type == BATADV_BCAST || packet_type == BATADV_UNICAST)) {
/* ... drop it. the responsible gateway is in charge. /* ... 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 * 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; goto handled;
} else { } else {
......
...@@ -35,7 +35,7 @@ static inline bool batadv_bla_is_loopdetect_mac(const uint8_t *mac) ...@@ -35,7 +35,7 @@ static inline bool batadv_bla_is_loopdetect_mac(const uint8_t *mac)
#ifdef CONFIG_BATMAN_ADV_BLA #ifdef CONFIG_BATMAN_ADV_BLA
bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *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);
bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
unsigned short vid); unsigned short vid);
bool batadv_bla_is_backbone_gw(struct sk_buff *skb, 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, ...@@ -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, static inline bool batadv_bla_rx(struct batadv_priv *bat_priv,
struct sk_buff *skb, unsigned short vid, struct sk_buff *skb, unsigned short vid,
bool is_bcast) int packet_type)
{ {
return false; return false;
} }
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <uapi/linux/batadv_packet.h> #include <uapi/linux/batadv_packet.h>
#include <uapi/linux/batman_adv.h> #include <uapi/linux/batman_adv.h>
#include "bridge_loop_avoidance.h"
#include "hard-interface.h" #include "hard-interface.h"
#include "hash.h" #include "hash.h"
#include "log.h" #include "log.h"
...@@ -1434,6 +1435,35 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -1434,6 +1435,35 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
return BATADV_FORW_ALL; 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 * batadv_mcast_forw_tt() - forwards a packet to multicast listeners
* @bat_priv: the bat priv with all the soft interface information * @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, ...@@ -1471,8 +1501,8 @@ batadv_mcast_forw_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
break; break;
} }
batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, batadv_mcast_forw_send_orig(bat_priv, newskb, vid,
orig_entry->orig_node, vid); orig_entry->orig_node);
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -1513,8 +1543,7 @@ batadv_mcast_forw_want_all_ipv4(struct batadv_priv *bat_priv, ...@@ -1513,8 +1543,7 @@ batadv_mcast_forw_want_all_ipv4(struct batadv_priv *bat_priv,
break; break;
} }
batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
orig_node, vid);
} }
rcu_read_unlock(); rcu_read_unlock();
return ret; return ret;
...@@ -1551,8 +1580,7 @@ batadv_mcast_forw_want_all_ipv6(struct batadv_priv *bat_priv, ...@@ -1551,8 +1580,7 @@ batadv_mcast_forw_want_all_ipv6(struct batadv_priv *bat_priv,
break; break;
} }
batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
orig_node, vid);
} }
rcu_read_unlock(); rcu_read_unlock();
return ret; return ret;
...@@ -1618,8 +1646,7 @@ batadv_mcast_forw_want_all_rtr4(struct batadv_priv *bat_priv, ...@@ -1618,8 +1646,7 @@ batadv_mcast_forw_want_all_rtr4(struct batadv_priv *bat_priv,
break; break;
} }
batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
orig_node, vid);
} }
rcu_read_unlock(); rcu_read_unlock();
return ret; return ret;
...@@ -1656,8 +1683,7 @@ batadv_mcast_forw_want_all_rtr6(struct batadv_priv *bat_priv, ...@@ -1656,8 +1683,7 @@ batadv_mcast_forw_want_all_rtr6(struct batadv_priv *bat_priv,
break; break;
} }
batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0, batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
orig_node, vid);
} }
rcu_read_unlock(); rcu_read_unlock();
return ret; return ret;
......
...@@ -46,6 +46,11 @@ enum batadv_forw_mode ...@@ -46,6 +46,11 @@ enum batadv_forw_mode
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
struct batadv_orig_node **mcast_single_orig); 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, int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
unsigned short vid); unsigned short vid);
...@@ -71,6 +76,16 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -71,6 +76,16 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
return BATADV_FORW_ALL; 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 static inline int
batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
unsigned short vid) unsigned short vid)
......
...@@ -826,6 +826,10 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, ...@@ -826,6 +826,10 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
vid = batadv_get_vid(skb, hdr_len); vid = batadv_get_vid(skb, hdr_len);
ethhdr = (struct ethhdr *)(skb->data + 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 /* 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 * 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 * message and that it knows the new destination in the mesh to re-route
......
...@@ -364,9 +364,8 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, ...@@ -364,9 +364,8 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
goto dropped; goto dropped;
ret = batadv_send_skb_via_gw(bat_priv, skb, vid); ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
} else if (mcast_single_orig) { } else if (mcast_single_orig) {
ret = batadv_send_skb_unicast(bat_priv, skb, ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid,
BATADV_UNICAST, 0, mcast_single_orig);
mcast_single_orig, vid);
} else if (forw_mode == BATADV_FORW_SOME) { } else if (forw_mode == BATADV_FORW_SOME) {
ret = batadv_mcast_forw_send(bat_priv, skb, vid); ret = batadv_mcast_forw_send(bat_priv, skb, vid);
} else { } else {
...@@ -425,10 +424,10 @@ void batadv_interface_rx(struct net_device *soft_iface, ...@@ -425,10 +424,10 @@ void batadv_interface_rx(struct net_device *soft_iface,
struct vlan_ethhdr *vhdr; struct vlan_ethhdr *vhdr;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
unsigned short vid; unsigned short vid;
bool is_bcast; int packet_type;
batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data; batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST); packet_type = batadv_bcast_packet->packet_type;
skb_pull_rcsum(skb, hdr_size); skb_pull_rcsum(skb, hdr_size);
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
...@@ -471,7 +470,7 @@ void batadv_interface_rx(struct net_device *soft_iface, ...@@ -471,7 +470,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
/* Let the bridge loop avoidance check the packet. If will /* Let the bridge loop avoidance check the packet. If will
* not handle it, we can safely push it up. * not handle it, we can safely push it up.
*/ */
if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) if (batadv_bla_rx(bat_priv, skb, vid, packet_type))
goto out; goto out;
if (orig_node) if (orig_node)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment