Commit 39620a35 authored by David S. Miller's avatar David S. Miller

Merge tag 'batadv-next-pullrequest-20231115' of git://git.open-mesh.org/linux-merge

This feature/cleanup patchset includes the following patches:

 - bump version strings, by Simon Wunderlich

 - Implement new multicast packet type, including its transmission,
   forwarding and parsing, by Linus Lüssing (3 patches)

 - Switch to new headers for sprintf and array size,
   by Sven Eckelmann (2 patches)
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 72a813a4 c3ed16a6
...@@ -116,6 +116,9 @@ enum batadv_icmp_packettype { ...@@ -116,6 +116,9 @@ enum batadv_icmp_packettype {
* only need routable IPv4 multicast packets we signed up for explicitly * only need routable IPv4 multicast packets we signed up for explicitly
* @BATADV_MCAST_WANT_NO_RTR6: we have no IPv6 multicast router and therefore * @BATADV_MCAST_WANT_NO_RTR6: we have no IPv6 multicast router and therefore
* only need routable IPv6 multicast packets we signed up for explicitly * only need routable IPv6 multicast packets we signed up for explicitly
* @BATADV_MCAST_HAVE_MC_PTYPE_CAPA: we can parse, receive and forward
* batman-adv multicast packets with a multicast tracker TVLV. And all our
* hard interfaces have an MTU of at least 1280 bytes.
*/ */
enum batadv_mcast_flags { enum batadv_mcast_flags {
BATADV_MCAST_WANT_ALL_UNSNOOPABLES = 1UL << 0, BATADV_MCAST_WANT_ALL_UNSNOOPABLES = 1UL << 0,
...@@ -123,6 +126,7 @@ enum batadv_mcast_flags { ...@@ -123,6 +126,7 @@ enum batadv_mcast_flags {
BATADV_MCAST_WANT_ALL_IPV6 = 1UL << 2, BATADV_MCAST_WANT_ALL_IPV6 = 1UL << 2,
BATADV_MCAST_WANT_NO_RTR4 = 1UL << 3, BATADV_MCAST_WANT_NO_RTR4 = 1UL << 3,
BATADV_MCAST_WANT_NO_RTR6 = 1UL << 4, BATADV_MCAST_WANT_NO_RTR6 = 1UL << 4,
BATADV_MCAST_HAVE_MC_PTYPE_CAPA = 1UL << 5,
}; };
/* tt data subtypes */ /* tt data subtypes */
...@@ -174,14 +178,16 @@ enum batadv_bla_claimframe { ...@@ -174,14 +178,16 @@ enum batadv_bla_claimframe {
* @BATADV_TVLV_TT: translation table tvlv * @BATADV_TVLV_TT: translation table tvlv
* @BATADV_TVLV_ROAM: roaming advertisement tvlv * @BATADV_TVLV_ROAM: roaming advertisement tvlv
* @BATADV_TVLV_MCAST: multicast capability tvlv * @BATADV_TVLV_MCAST: multicast capability tvlv
* @BATADV_TVLV_MCAST_TRACKER: multicast tracker tvlv
*/ */
enum batadv_tvlv_type { enum batadv_tvlv_type {
BATADV_TVLV_GW = 0x01, BATADV_TVLV_GW = 0x01,
BATADV_TVLV_DAT = 0x02, BATADV_TVLV_DAT = 0x02,
BATADV_TVLV_NC = 0x03, BATADV_TVLV_NC = 0x03,
BATADV_TVLV_TT = 0x04, BATADV_TVLV_TT = 0x04,
BATADV_TVLV_ROAM = 0x05, BATADV_TVLV_ROAM = 0x05,
BATADV_TVLV_MCAST = 0x06, BATADV_TVLV_MCAST = 0x06,
BATADV_TVLV_MCAST_TRACKER = 0x07,
}; };
#pragma pack(2) #pragma pack(2)
...@@ -487,6 +493,25 @@ struct batadv_bcast_packet { ...@@ -487,6 +493,25 @@ struct batadv_bcast_packet {
*/ */
}; };
/**
* struct batadv_mcast_packet - multicast packet for network payload
* @packet_type: batman-adv packet type, part of the general header
* @version: batman-adv protocol version, part of the general header
* @ttl: time to live for this packet, part of the general header
* @reserved: reserved byte for alignment
* @tvlv_len: length of the appended tvlv buffer (in bytes)
*/
struct batadv_mcast_packet {
__u8 packet_type;
__u8 version;
__u8 ttl;
__u8 reserved;
__be16 tvlv_len;
/* "4 bytes boundary + 2 bytes" long to make the payload after the
* following ethernet header again 4 bytes boundary aligned
*/
};
/** /**
* struct batadv_coded_packet - network coded packet * struct batadv_coded_packet - network coded packet
* @packet_type: batman-adv packet type, part of the general header * @packet_type: batman-adv packet type, part of the general header
...@@ -628,6 +653,14 @@ struct batadv_tvlv_mcast_data { ...@@ -628,6 +653,14 @@ struct batadv_tvlv_mcast_data {
__u8 reserved[3]; __u8 reserved[3];
}; };
/**
* struct batadv_tvlv_mcast_tracker - payload of a multicast tracker tvlv
* @num_dests: number of subsequent destination originator MAC addresses
*/
struct batadv_tvlv_mcast_tracker {
__be16 num_dests;
};
#pragma pack() #pragma pack()
#endif /* _UAPI_LINUX_BATADV_PACKET_H_ */ #endif /* _UAPI_LINUX_BATADV_PACKET_H_ */
...@@ -20,6 +20,7 @@ batman-adv-y += hash.o ...@@ -20,6 +20,7 @@ batman-adv-y += hash.o
batman-adv-$(CONFIG_BATMAN_ADV_DEBUG) += log.o batman-adv-$(CONFIG_BATMAN_ADV_DEBUG) += log.o
batman-adv-y += main.o batman-adv-y += main.o
batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o
batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast_forw.o
batman-adv-y += netlink.o batman-adv-y += netlink.o
batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o
batman-adv-y += originator.o batman-adv-y += originator.o
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/jhash.h> #include <linux/jhash.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
...@@ -31,6 +30,7 @@ ...@@ -31,6 +30,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/sprintf.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "hard-interface.h" #include "hard-interface.h"
#include "originator.h" #include "originator.h"
#include "routing.h"
#include "send.h" #include "send.h"
/** /**
...@@ -351,18 +350,14 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb, ...@@ -351,18 +350,14 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
struct batadv_orig_node *orig_node_src) struct batadv_orig_node *orig_node_src)
{ {
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_orig_node *orig_node_dst;
struct batadv_neigh_node *neigh_node = NULL; struct batadv_neigh_node *neigh_node = NULL;
struct batadv_frag_packet *packet; struct batadv_frag_packet *packet;
u16 total_size; u16 total_size;
bool ret = false; bool ret = false;
packet = (struct batadv_frag_packet *)skb->data; packet = (struct batadv_frag_packet *)skb->data;
orig_node_dst = batadv_orig_hash_find(bat_priv, packet->dest);
if (!orig_node_dst)
goto out;
neigh_node = batadv_find_router(bat_priv, orig_node_dst, recv_if); neigh_node = batadv_orig_to_router(bat_priv, packet->dest, recv_if);
if (!neigh_node) if (!neigh_node)
goto out; goto out;
...@@ -381,7 +376,6 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb, ...@@ -381,7 +376,6 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
} }
out: out:
batadv_orig_node_put(orig_node_dst);
batadv_neigh_node_put(neigh_node); batadv_neigh_node_put(neigh_node);
return ret; return ret;
} }
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/kernel.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
...@@ -29,6 +28,7 @@ ...@@ -29,6 +28,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/sprintf.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/udp.h> #include <linux/udp.h>
#include <net/sock.h> #include <net/sock.h>
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "main.h" #include "main.h"
#include <linux/array_size.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/build_bug.h> #include <linux/build_bug.h>
#include <linux/byteorder/generic.h> #include <linux/byteorder/generic.h>
...@@ -20,7 +21,6 @@ ...@@ -20,7 +21,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/kernel.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/sprintf.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
...@@ -532,6 +533,8 @@ static void batadv_recv_handler_init(void) ...@@ -532,6 +533,8 @@ static void batadv_recv_handler_init(void)
/* broadcast packet */ /* broadcast packet */
batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
/* multicast packet */
batadv_rx_handler[BATADV_MCAST] = batadv_recv_mcast_packet;
/* unicast packets ... */ /* unicast packets ... */
/* unicast with 4 addresses packet */ /* unicast with 4 addresses packet */
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,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 "2023.3" #define BATADV_SOURCE_VERSION "2024.0"
#endif #endif
/* B.A.T.M.A.N. parameters */ /* B.A.T.M.A.N. parameters */
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
...@@ -36,6 +35,7 @@ ...@@ -36,6 +35,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/sprintf.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -235,6 +235,37 @@ static u8 batadv_mcast_mla_rtr_flags_get(struct batadv_priv *bat_priv, ...@@ -235,6 +235,37 @@ static u8 batadv_mcast_mla_rtr_flags_get(struct batadv_priv *bat_priv,
return flags; return flags;
} }
/**
* batadv_mcast_mla_forw_flags_get() - get multicast forwarding flags
* @bat_priv: the bat priv with all the soft interface information
*
* Checks if all active hard interfaces have an MTU larger or equal to 1280
* bytes (IPv6 minimum MTU).
*
* Return: BATADV_MCAST_HAVE_MC_PTYPE_CAPA if yes, BATADV_NO_FLAGS otherwise.
*/
static u8 batadv_mcast_mla_forw_flags_get(struct batadv_priv *bat_priv)
{
const struct batadv_hard_iface *hard_iface;
rcu_read_lock();
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
if (hard_iface->if_status != BATADV_IF_ACTIVE)
continue;
if (hard_iface->soft_iface != bat_priv->soft_iface)
continue;
if (hard_iface->net_dev->mtu < IPV6_MIN_MTU) {
rcu_read_unlock();
return BATADV_NO_FLAGS;
}
}
rcu_read_unlock();
return BATADV_MCAST_HAVE_MC_PTYPE_CAPA;
}
/** /**
* batadv_mcast_mla_flags_get() - get the new multicast flags * batadv_mcast_mla_flags_get() - get the new multicast flags
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
...@@ -256,6 +287,7 @@ batadv_mcast_mla_flags_get(struct batadv_priv *bat_priv) ...@@ -256,6 +287,7 @@ batadv_mcast_mla_flags_get(struct batadv_priv *bat_priv)
mla_flags.enabled = 1; mla_flags.enabled = 1;
mla_flags.tvlv_flags |= batadv_mcast_mla_rtr_flags_get(bat_priv, mla_flags.tvlv_flags |= batadv_mcast_mla_rtr_flags_get(bat_priv,
bridge); bridge);
mla_flags.tvlv_flags |= batadv_mcast_mla_forw_flags_get(bat_priv);
if (!bridge) if (!bridge)
return mla_flags; return mla_flags;
...@@ -806,23 +838,25 @@ static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags) ...@@ -806,23 +838,25 @@ static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags)
{ {
bool old_enabled = bat_priv->mcast.mla_flags.enabled; bool old_enabled = bat_priv->mcast.mla_flags.enabled;
u8 old_flags = bat_priv->mcast.mla_flags.tvlv_flags; u8 old_flags = bat_priv->mcast.mla_flags.tvlv_flags;
char str_old_flags[] = "[.... . ]"; char str_old_flags[] = "[.... . .]";
sprintf(str_old_flags, "[%c%c%c%s%s]", sprintf(str_old_flags, "[%c%c%c%s%s%c]",
(old_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', (old_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
(old_flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', (old_flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
(old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.', (old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.',
!(old_flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ", !(old_flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ",
!(old_flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". "); !(old_flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". ",
!(old_flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA) ? 'P' : '.');
batadv_dbg(BATADV_DBG_MCAST, bat_priv, batadv_dbg(BATADV_DBG_MCAST, bat_priv,
"Changing multicast flags from '%s' to '[%c%c%c%s%s]'\n", "Changing multicast flags from '%s' to '[%c%c%c%s%s%c]'\n",
old_enabled ? str_old_flags : "<undefined>", old_enabled ? str_old_flags : "<undefined>",
(flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
(flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
(flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.', (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.',
!(flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ", !(flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ",
!(flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". "); !(flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". ",
!(flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA) ? 'P' : '.');
} }
/** /**
...@@ -1135,17 +1169,62 @@ static int batadv_mcast_forw_rtr_count(struct batadv_priv *bat_priv, ...@@ -1135,17 +1169,62 @@ static int batadv_mcast_forw_rtr_count(struct batadv_priv *bat_priv,
} }
} }
/**
* batadv_mcast_forw_mode_by_count() - get forwarding mode by count
* @bat_priv: the bat priv with all the soft interface information
* @skb: the multicast packet to check
* @vid: the vlan identifier
* @is_routable: stores whether the destination is routable
* @count: the number of originators the multicast packet need to be sent to
*
* For a multicast packet with multiple destination originators, checks which
* mode to use. For BATADV_FORW_MCAST it also encapsulates the packet with a
* complete batman-adv multicast header.
*
* Return:
* BATADV_FORW_MCAST: If all nodes have multicast packet routing
* capabilities and an MTU >= 1280 on all hard interfaces (including us)
* and the encapsulated multicast packet with all destination addresses
* would still fit into an 1280 bytes batman-adv multicast packet
* (excluding the outer ethernet frame) and we could successfully push
* the full batman-adv multicast packet header.
* BATADV_FORW_UCASTS: If the packet cannot be sent in a batman-adv
* multicast packet and the amount of batman-adv unicast packets needed
* is smaller or equal to the configured multicast fanout.
* BATADV_FORW_BCAST: Otherwise.
*/
static enum batadv_forw_mode
batadv_mcast_forw_mode_by_count(struct batadv_priv *bat_priv,
struct sk_buff *skb, unsigned short vid,
int is_routable, int count)
{
unsigned int mcast_hdrlen = batadv_mcast_forw_packet_hdrlen(count);
u8 own_tvlv_flags = bat_priv->mcast.mla_flags.tvlv_flags;
if (!atomic_read(&bat_priv->mcast.num_no_mc_ptype_capa) &&
own_tvlv_flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA &&
skb->len + mcast_hdrlen <= IPV6_MIN_MTU &&
batadv_mcast_forw_push(bat_priv, skb, vid, is_routable, count))
return BATADV_FORW_MCAST;
if (count <= atomic_read(&bat_priv->multicast_fanout))
return BATADV_FORW_UCASTS;
return BATADV_FORW_BCAST;
}
/** /**
* batadv_mcast_forw_mode() - check on how to forward a multicast packet * batadv_mcast_forw_mode() - check on how to forward a multicast packet
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
* @skb: the multicast packet to check * @skb: the multicast packet to check
* @vid: the vlan identifier
* @is_routable: stores whether the destination is routable * @is_routable: stores whether the destination is routable
* *
* Return: The forwarding mode as enum batadv_forw_mode. * Return: The forwarding mode as enum batadv_forw_mode.
*/ */
enum batadv_forw_mode 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,
int *is_routable) unsigned short vid, int *is_routable)
{ {
int ret, tt_count, ip_count, unsnoop_count, total_count; int ret, tt_count, ip_count, unsnoop_count, total_count;
bool is_unsnoopable = false; bool is_unsnoopable = false;
...@@ -1175,10 +1254,8 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -1175,10 +1254,8 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
else if (unsnoop_count) else if (unsnoop_count)
return BATADV_FORW_BCAST; return BATADV_FORW_BCAST;
if (total_count <= atomic_read(&bat_priv->multicast_fanout)) return batadv_mcast_forw_mode_by_count(bat_priv, skb, vid, *is_routable,
return BATADV_FORW_UCASTS; total_count);
return BATADV_FORW_BCAST;
} }
/** /**
...@@ -1738,6 +1815,31 @@ static void batadv_mcast_want_rtr6_update(struct batadv_priv *bat_priv, ...@@ -1738,6 +1815,31 @@ static void batadv_mcast_want_rtr6_update(struct batadv_priv *bat_priv,
} }
} }
/**
* batadv_mcast_have_mc_ptype_update() - update multicast packet type counter
* @bat_priv: the bat priv with all the soft interface information
* @orig: the orig_node which multicast state might have changed of
* @mcast_flags: flags indicating the new multicast state
*
* If the BATADV_MCAST_HAVE_MC_PTYPE_CAPA flag of this originator, orig, has
* toggled then this method updates the counter accordingly.
*/
static void batadv_mcast_have_mc_ptype_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
u8 mcast_flags)
{
lockdep_assert_held(&orig->mcast_handler_lock);
/* switched from flag set to unset */
if (!(mcast_flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA) &&
orig->mcast_flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA)
atomic_inc(&bat_priv->mcast.num_no_mc_ptype_capa);
/* switched from flag unset to set */
else if (mcast_flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA &&
!(orig->mcast_flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA))
atomic_dec(&bat_priv->mcast.num_no_mc_ptype_capa);
}
/** /**
* batadv_mcast_tvlv_flags_get() - get multicast flags from an OGM TVLV * batadv_mcast_tvlv_flags_get() - get multicast flags from an OGM TVLV
* @enabled: whether the originator has multicast TVLV support enabled * @enabled: whether the originator has multicast TVLV support enabled
...@@ -1806,6 +1908,7 @@ static void batadv_mcast_tvlv_ogm_handler(struct batadv_priv *bat_priv, ...@@ -1806,6 +1908,7 @@ static void batadv_mcast_tvlv_ogm_handler(struct batadv_priv *bat_priv,
batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags); batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags);
batadv_mcast_want_rtr4_update(bat_priv, orig, mcast_flags); batadv_mcast_want_rtr4_update(bat_priv, orig, mcast_flags);
batadv_mcast_want_rtr6_update(bat_priv, orig, mcast_flags); batadv_mcast_want_rtr6_update(bat_priv, orig, mcast_flags);
batadv_mcast_have_mc_ptype_update(bat_priv, orig, mcast_flags);
orig->mcast_flags = mcast_flags; orig->mcast_flags = mcast_flags;
spin_unlock_bh(&orig->mcast_handler_lock); spin_unlock_bh(&orig->mcast_handler_lock);
...@@ -1820,6 +1923,10 @@ void batadv_mcast_init(struct batadv_priv *bat_priv) ...@@ -1820,6 +1923,10 @@ void batadv_mcast_init(struct batadv_priv *bat_priv)
batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler, batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler,
NULL, NULL, BATADV_TVLV_MCAST, 2, NULL, NULL, BATADV_TVLV_MCAST, 2,
BATADV_TVLV_HANDLER_OGM_CIFNOTFND); BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
batadv_tvlv_handler_register(bat_priv, NULL, NULL,
batadv_mcast_forw_tracker_tvlv_handler,
BATADV_TVLV_MCAST_TRACKER, 1,
BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
INIT_DELAYED_WORK(&bat_priv->mcast.work, batadv_mcast_mla_update); INIT_DELAYED_WORK(&bat_priv->mcast.work, batadv_mcast_mla_update);
batadv_mcast_start_timer(bat_priv); batadv_mcast_start_timer(bat_priv);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/types.h>
/** /**
* enum batadv_forw_mode - the way a packet should be forwarded as * enum batadv_forw_mode - the way a packet should be forwarded as
...@@ -28,6 +29,12 @@ enum batadv_forw_mode { ...@@ -28,6 +29,12 @@ enum batadv_forw_mode {
*/ */
BATADV_FORW_UCASTS, BATADV_FORW_UCASTS,
/**
* @BATADV_FORW_MCAST: forward the packet to some nodes via a
* batman-adv multicast packet
*/
BATADV_FORW_MCAST,
/** @BATADV_FORW_NONE: don't forward, drop it */ /** @BATADV_FORW_NONE: don't forward, drop it */
BATADV_FORW_NONE, BATADV_FORW_NONE,
}; };
...@@ -36,7 +43,7 @@ enum batadv_forw_mode { ...@@ -36,7 +43,7 @@ enum batadv_forw_mode {
enum batadv_forw_mode 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,
int *is_routable); unsigned short vid, int *is_routable);
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, int is_routable); unsigned short vid, int is_routable);
...@@ -52,11 +59,23 @@ void batadv_mcast_free(struct batadv_priv *bat_priv); ...@@ -52,11 +59,23 @@ void batadv_mcast_free(struct batadv_priv *bat_priv);
void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node);
/* multicast_forw.c */
int batadv_mcast_forw_tracker_tvlv_handler(struct batadv_priv *bat_priv,
struct sk_buff *skb);
unsigned int batadv_mcast_forw_packet_hdrlen(unsigned int num_dests);
bool batadv_mcast_forw_push(struct batadv_priv *bat_priv, struct sk_buff *skb,
unsigned short vid, int is_routable, int count);
int batadv_mcast_forw_mcsend(struct batadv_priv *bat_priv, struct sk_buff *skb);
#else #else
static inline enum batadv_forw_mode static inline 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,
int *is_routable) unsigned short vid, int *is_routable)
{ {
return BATADV_FORW_BCAST; return BATADV_FORW_BCAST;
} }
...@@ -94,6 +113,13 @@ static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node) ...@@ -94,6 +113,13 @@ static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node)
{ {
} }
static inline int batadv_mcast_forw_mcsend(struct batadv_priv *bat_priv,
struct sk_buff *skb)
{
kfree_skb(skb);
return NET_XMIT_DROP;
}
#endif /* CONFIG_BATMAN_ADV_MCAST */ #endif /* CONFIG_BATMAN_ADV_MCAST */
#endif /* _NET_BATMAN_ADV_MULTICAST_H_ */ #endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
This diff is collapsed.
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "netlink.h" #include "netlink.h"
#include "main.h" #include "main.h"
#include <linux/array_size.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/bug.h> #include <linux/bug.h>
...@@ -20,7 +21,6 @@ ...@@ -20,7 +21,6 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/minmax.h> #include <linux/minmax.h>
......
...@@ -311,6 +311,33 @@ batadv_orig_router_get(struct batadv_orig_node *orig_node, ...@@ -311,6 +311,33 @@ batadv_orig_router_get(struct batadv_orig_node *orig_node,
return router; return router;
} }
/**
* batadv_orig_to_router() - get next hop neighbor to an orig address
* @bat_priv: the bat priv with all the soft interface information
* @orig_addr: the originator MAC address to search the best next hop router for
* @if_outgoing: the interface where the payload packet has been received or
* the OGM should be sent to
*
* Return: A neighbor node which is the best router towards the given originator
* address.
*/
struct batadv_neigh_node *
batadv_orig_to_router(struct batadv_priv *bat_priv, u8 *orig_addr,
struct batadv_hard_iface *if_outgoing)
{
struct batadv_neigh_node *neigh_node;
struct batadv_orig_node *orig_node;
orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
if (!orig_node)
return NULL;
neigh_node = batadv_find_router(bat_priv, orig_node, if_outgoing);
batadv_orig_node_put(orig_node);
return neigh_node;
}
/** /**
* batadv_orig_ifinfo_get() - find the ifinfo from an orig_node * batadv_orig_ifinfo_get() - find the ifinfo from an orig_node
* @orig_node: the orig node to be queried * @orig_node: the orig node to be queried
...@@ -942,6 +969,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, ...@@ -942,6 +969,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
#ifdef CONFIG_BATMAN_ADV_MCAST #ifdef CONFIG_BATMAN_ADV_MCAST
orig_node->mcast_flags = BATADV_MCAST_WANT_NO_RTR4; orig_node->mcast_flags = BATADV_MCAST_WANT_NO_RTR4;
orig_node->mcast_flags |= BATADV_MCAST_WANT_NO_RTR6; orig_node->mcast_flags |= BATADV_MCAST_WANT_NO_RTR6;
orig_node->mcast_flags |= BATADV_MCAST_HAVE_MC_PTYPE_CAPA;
INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node); INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node);
INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node); INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node);
INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node); INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node);
......
...@@ -36,6 +36,9 @@ void batadv_neigh_node_release(struct kref *ref); ...@@ -36,6 +36,9 @@ void batadv_neigh_node_release(struct kref *ref);
struct batadv_neigh_node * struct batadv_neigh_node *
batadv_orig_router_get(struct batadv_orig_node *orig_node, batadv_orig_router_get(struct batadv_orig_node *orig_node,
const struct batadv_hard_iface *if_outgoing); const struct batadv_hard_iface *if_outgoing);
struct batadv_neigh_node *
batadv_orig_to_router(struct batadv_priv *bat_priv, u8 *orig_addr,
struct batadv_hard_iface *if_outgoing);
struct batadv_neigh_ifinfo * struct batadv_neigh_ifinfo *
batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
struct batadv_hard_iface *if_outgoing); struct batadv_hard_iface *if_outgoing);
......
...@@ -1270,3 +1270,73 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, ...@@ -1270,3 +1270,73 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
batadv_orig_node_put(orig_node); batadv_orig_node_put(orig_node);
return ret; return ret;
} }
#ifdef CONFIG_BATMAN_ADV_MCAST
/**
* batadv_recv_mcast_packet() - process received batman-adv multicast packet
* @skb: the received batman-adv multicast packet
* @recv_if: interface that the skb is received on
*
* Parses the given, received batman-adv multicast packet. Depending on the
* contents of its TVLV forwards it and/or decapsulates it to hand it to the
* soft interface.
*
* Return: NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise.
*/
int batadv_recv_mcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_mcast_packet *mcast_packet;
int hdr_size = sizeof(*mcast_packet);
unsigned char *tvlv_buff;
int ret = NET_RX_DROP;
u16 tvlv_buff_len;
if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
goto free_skb;
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
goto free_skb;
/* packet needs to be linearized to access the tvlv content */
if (skb_linearize(skb) < 0)
goto free_skb;
mcast_packet = (struct batadv_mcast_packet *)skb->data;
if (mcast_packet->ttl-- < 2)
goto free_skb;
tvlv_buff = (unsigned char *)(skb->data + hdr_size);
tvlv_buff_len = ntohs(mcast_packet->tvlv_len);
if (tvlv_buff_len > skb->len - hdr_size)
goto free_skb;
ret = batadv_tvlv_containers_process(bat_priv, BATADV_MCAST, NULL, skb,
tvlv_buff, tvlv_buff_len);
if (ret >= 0) {
batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_RX);
batadv_add_counter(bat_priv, BATADV_CNT_MCAST_RX_BYTES,
skb->len + ETH_HLEN);
}
hdr_size += tvlv_buff_len;
if (ret == NET_RX_SUCCESS && (skb->len - hdr_size >= ETH_HLEN)) {
batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_RX_LOCAL);
batadv_add_counter(bat_priv, BATADV_CNT_MCAST_RX_LOCAL_BYTES,
skb->len - hdr_size);
batadv_interface_rx(bat_priv->soft_iface, skb, hdr_size, NULL);
/* skb was consumed */
skb = NULL;
}
free_skb:
kfree_skb(skb);
return ret;
}
#endif /* CONFIG_BATMAN_ADV_MCAST */
...@@ -27,6 +27,17 @@ int batadv_recv_frag_packet(struct sk_buff *skb, ...@@ -27,6 +27,17 @@ int batadv_recv_frag_packet(struct sk_buff *skb,
struct batadv_hard_iface *iface); struct batadv_hard_iface *iface);
int batadv_recv_bcast_packet(struct sk_buff *skb, int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if); struct batadv_hard_iface *recv_if);
#ifdef CONFIG_BATMAN_ADV_MCAST
int batadv_recv_mcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
#else
static inline int batadv_recv_mcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
kfree_skb(skb);
return NET_RX_DROP;
}
#endif
int batadv_recv_unicast_tvlv(struct sk_buff *skb, int batadv_recv_unicast_tvlv(struct sk_buff *skb,
struct batadv_hard_iface *recv_if); struct batadv_hard_iface *recv_if);
int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb, int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
......
...@@ -301,12 +301,13 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, ...@@ -301,12 +301,13 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
send: send:
if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) { if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) {
forw_mode = batadv_mcast_forw_mode(bat_priv, skb, forw_mode = batadv_mcast_forw_mode(bat_priv, skb, vid,
&mcast_is_routable); &mcast_is_routable);
switch (forw_mode) { switch (forw_mode) {
case BATADV_FORW_BCAST: case BATADV_FORW_BCAST:
break; break;
case BATADV_FORW_UCASTS: case BATADV_FORW_UCASTS:
case BATADV_FORW_MCAST:
do_bcast = false; do_bcast = false;
break; break;
case BATADV_FORW_NONE: case BATADV_FORW_NONE:
...@@ -365,6 +366,8 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, ...@@ -365,6 +366,8 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
} else if (forw_mode == BATADV_FORW_UCASTS) { } else if (forw_mode == BATADV_FORW_UCASTS) {
ret = batadv_mcast_forw_send(bat_priv, skb, vid, ret = batadv_mcast_forw_send(bat_priv, skb, vid,
mcast_is_routable); mcast_is_routable);
} else if (forw_mode == BATADV_FORW_MCAST) {
ret = batadv_mcast_forw_mcsend(bat_priv, skb);
} else { } else {
if (batadv_dat_snoop_outgoing_arp_request(bat_priv, if (batadv_dat_snoop_outgoing_arp_request(bat_priv,
skb)) skb))
...@@ -762,6 +765,7 @@ static int batadv_softif_init_late(struct net_device *dev) ...@@ -762,6 +765,7 @@ static int batadv_softif_init_late(struct net_device *dev)
atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0);
atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0);
atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0);
atomic_set(&bat_priv->mcast.num_no_mc_ptype_capa, 0);
#endif #endif
atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF); atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw.bandwidth_down, 100); atomic_set(&bat_priv->gw.bandwidth_down, 100);
...@@ -925,6 +929,18 @@ static const struct { ...@@ -925,6 +929,18 @@ static const struct {
{ "tt_response_rx" }, { "tt_response_rx" },
{ "tt_roam_adv_tx" }, { "tt_roam_adv_tx" },
{ "tt_roam_adv_rx" }, { "tt_roam_adv_rx" },
#ifdef CONFIG_BATMAN_ADV_MCAST
{ "mcast_tx" },
{ "mcast_tx_bytes" },
{ "mcast_tx_local" },
{ "mcast_tx_local_bytes" },
{ "mcast_rx" },
{ "mcast_rx_bytes" },
{ "mcast_rx_local" },
{ "mcast_rx_local_bytes" },
{ "mcast_fwd" },
{ "mcast_fwd_bytes" },
#endif
#ifdef CONFIG_BATMAN_ADV_DAT #ifdef CONFIG_BATMAN_ADV_DAT
{ "dat_get_tx" }, { "dat_get_tx" },
{ "dat_get_rx" }, { "dat_get_rx" },
......
...@@ -862,6 +862,70 @@ enum batadv_counters { ...@@ -862,6 +862,70 @@ enum batadv_counters {
*/ */
BATADV_CNT_TT_ROAM_ADV_RX, BATADV_CNT_TT_ROAM_ADV_RX,
#ifdef CONFIG_BATMAN_ADV_MCAST
/**
* @BATADV_CNT_MCAST_TX: transmitted batman-adv multicast packets
* counter
*/
BATADV_CNT_MCAST_TX,
/**
* @BATADV_CNT_MCAST_TX_BYTES: transmitted batman-adv multicast packets
* bytes counter
*/
BATADV_CNT_MCAST_TX_BYTES,
/**
* @BATADV_CNT_MCAST_TX_LOCAL: counter for multicast packets which
* were locally encapsulated and transmitted as batman-adv multicast
* packets
*/
BATADV_CNT_MCAST_TX_LOCAL,
/**
* @BATADV_CNT_MCAST_TX_LOCAL_BYTES: bytes counter for multicast packets
* which were locally encapsulated and transmitted as batman-adv
* multicast packets
*/
BATADV_CNT_MCAST_TX_LOCAL_BYTES,
/**
* @BATADV_CNT_MCAST_RX: received batman-adv multicast packet counter
*/
BATADV_CNT_MCAST_RX,
/**
* @BATADV_CNT_MCAST_RX_BYTES: received batman-adv multicast packet
* bytes counter
*/
BATADV_CNT_MCAST_RX_BYTES,
/**
* @BATADV_CNT_MCAST_RX_LOCAL: counter for received batman-adv multicast
* packets which were forwarded to the local soft interface
*/
BATADV_CNT_MCAST_RX_LOCAL,
/**
* @BATADV_CNT_MCAST_RX_LOCAL_BYTES: bytes counter for received
* batman-adv multicast packets which were forwarded to the local soft
* interface
*/
BATADV_CNT_MCAST_RX_LOCAL_BYTES,
/**
* @BATADV_CNT_MCAST_FWD: counter for received batman-adv multicast
* packets which were forwarded to other, neighboring nodes
*/
BATADV_CNT_MCAST_FWD,
/**
* @BATADV_CNT_MCAST_FWD_BYTES: bytes counter for received batman-adv
* multicast packets which were forwarded to other, neighboring nodes
*/
BATADV_CNT_MCAST_FWD_BYTES,
#endif
#ifdef CONFIG_BATMAN_ADV_DAT #ifdef CONFIG_BATMAN_ADV_DAT
/** /**
* @BATADV_CNT_DAT_GET_TX: transmitted dht GET traffic packet counter * @BATADV_CNT_DAT_GET_TX: transmitted dht GET traffic packet counter
...@@ -1278,6 +1342,12 @@ struct batadv_priv_mcast { ...@@ -1278,6 +1342,12 @@ struct batadv_priv_mcast {
/** @num_want_all_rtr6: counter for items in want_all_rtr6_list */ /** @num_want_all_rtr6: counter for items in want_all_rtr6_list */
atomic_t num_want_all_rtr6; atomic_t num_want_all_rtr6;
/**
* @num_no_mc_ptype_capa: counter for number of nodes without the
* BATADV_MCAST_HAVE_MC_PTYPE_CAPA flag
*/
atomic_t num_no_mc_ptype_capa;
/** /**
* @want_lists_lock: lock for protecting modifications to mcasts * @want_lists_lock: lock for protecting modifications to mcasts
* want_all_{unsnoopables,ipv4,ipv6}_list (traversals are rcu-locked) * want_all_{unsnoopables,ipv4,ipv6}_list (traversals are rcu-locked)
......
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