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

Commit 1d8ab8d3 authored by Linus Lüssing's avatar Linus Lüssing Committed by Antonio Quartulli
Browse files

batman-adv: Modified forwarding behaviour for multicast packets



With this patch a multicast packet is not always simply flooded anymore,
the behaviour for the following cases is changed to reduce
unnecessary overhead:

If all nodes within the horizon of a certain node have signalized
multicast listener announcement capability then an IPv6 multicast packet
with a destination of IPv6 link-local scope (excluding ff02::1) coming
from the upstream of this node...

* ...is dropped if there is no according multicast listener in the
  translation table,
* ...is forwarded via unicast if there is a single node with interested
  multicast listeners
* ...and otherwise still gets flooded.

Signed-off-by: default avatarLinus Lüssing <linus.luessing@web.de>
Signed-off-by: default avatarMarek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: default avatarAntonio Quartulli <antonio@meshcoding.com>
parent 60432d75
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -76,6 +76,15 @@ Description:
		is used to classify clients as "isolated" by the
		Extended Isolation feature.

What:           /sys/class/net/<mesh_iface>/mesh/multicast_mode
Date:           Feb 2014
Contact:        Linus Lüssing <linus.luessing@web.de>
Description:
                Indicates whether multicast optimizations are enabled
                or disabled. If set to zero then all nodes in the
                mesh are going to use classic flooding for any
                multicast packet with no optimizations.

What:           /sys/class/net/<mesh_iface>/mesh/network_coding
Date:           Nov 2012
Contact:        Martin Hundeboll <martin@hundeboll.net>
+126 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "originator.h"
#include "hard-interface.h"
#include "translation-table.h"
#include "multicast.h"

/**
 * batadv_mcast_mla_softif_get - get softif multicast listeners
@@ -246,6 +247,131 @@ out:
	batadv_mcast_mla_list_free(&mcast_list);
}

/**
 * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: the IPv6 packet to check
 *
 * Checks whether the given IPv6 packet has the potential to be forwarded with a
 * mode more optimal than classic flooding.
 *
 * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
 * of memory.
 */
static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv,
					     struct sk_buff *skb)
{
	struct ipv6hdr *ip6hdr;

	/* We might fail due to out-of-memory -> drop it */
	if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr)))
		return -ENOMEM;

	ip6hdr = ipv6_hdr(skb);

	/* TODO: Implement Multicast Router Discovery (RFC4286),
	 * then allow scope > link local, too
	 */
	if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != IPV6_ADDR_SCOPE_LINKLOCAL)
		return -EINVAL;

	/* link-local-all-nodes multicast listeners behind a bridge are
	 * not snoopable (see RFC4541, section 3, paragraph 3)
	 */
	if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr))
		return -EINVAL;

	return 0;
}

/**
 * batadv_mcast_forw_mode_check - check for optimized forwarding potential
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: the multicast frame to check
 *
 * Checks whether the given multicast ethernet frame has the potential to be
 * forwarded with a mode more optimal than classic flooding.
 *
 * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
 * of memory.
 */
static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
					struct sk_buff *skb)
{
	struct ethhdr *ethhdr = eth_hdr(skb);

	if (!atomic_read(&bat_priv->multicast_mode))
		return -EINVAL;

	if (atomic_read(&bat_priv->mcast.num_disabled))
		return -EINVAL;

	switch (ntohs(ethhdr->h_proto)) {
	case ETH_P_IPV6:
		return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb);
	default:
		return -EINVAL;
	}
}

/**
 * batadv_mcast_forw_tt_node_get - get a multicast tt node
 * @bat_priv: the bat priv with all the soft interface information
 * @ethhdr: the ether header containing the multicast destination
 *
 * Returns an orig_node matching the multicast address provided by ethhdr
 * via a translation table lookup. This increases the returned nodes refcount.
 */
static struct batadv_orig_node *
batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv,
			      struct ethhdr *ethhdr)
{
	return batadv_transtable_search(bat_priv, ethhdr->h_source,
					ethhdr->h_dest, BATADV_NO_FLAGS);
}

/**
 * batadv_mcast_forw_mode - check on how to forward a multicast packet
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: The multicast packet to check
 * @orig: an originator to be set to forward the skb to
 *
 * Returns the forwarding mode as enum batadv_forw_mode and in case of
 * BATADV_FORW_SINGLE set the orig to the single originator the skb
 * should be forwarded to.
 */
enum batadv_forw_mode
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
		       struct batadv_orig_node **orig)
{
	struct ethhdr *ethhdr;
	int ret, tt_count;

	ret = batadv_mcast_forw_mode_check(bat_priv, skb);
	if (ret == -ENOMEM)
		return BATADV_FORW_NONE;
	else if (ret < 0)
		return BATADV_FORW_ALL;

	ethhdr = eth_hdr(skb);

	tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest,
					       BATADV_NO_FLAGS);

	switch (tt_count) {
	case 1:
		*orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr);
		if (*orig)
			return BATADV_FORW_SINGLE;

		/* fall through */
	case 0:
		return BATADV_FORW_NONE;
	default:
		return BATADV_FORW_ALL;
	}
}

/**
 * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container
 * @bat_priv: the bat priv with all the soft interface information
+25 −0
Original line number Diff line number Diff line
@@ -18,10 +18,28 @@
#ifndef _NET_BATMAN_ADV_MULTICAST_H_
#define _NET_BATMAN_ADV_MULTICAST_H_

/**
 * batadv_forw_mode - the way a packet should be forwarded as
 * @BATADV_FORW_ALL: forward the packet to all nodes (currently via classic
 *  flooding)
 * @BATADV_FORW_SINGLE: forward the packet to a single node (currently via the
 *  BATMAN unicast routing protocol)
 * @BATADV_FORW_NONE: don't forward, drop it
 */
enum batadv_forw_mode {
	BATADV_FORW_ALL,
	BATADV_FORW_SINGLE,
	BATADV_FORW_NONE,
};

#ifdef CONFIG_BATMAN_ADV_MCAST

void batadv_mcast_mla_update(struct batadv_priv *bat_priv);

enum batadv_forw_mode
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
		       struct batadv_orig_node **mcast_single_orig);

void batadv_mcast_init(struct batadv_priv *bat_priv);

void batadv_mcast_free(struct batadv_priv *bat_priv);
@@ -35,6 +53,13 @@ static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
	return;
}

static inline enum batadv_forw_mode
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
		       struct batadv_orig_node **mcast_single_orig)
{
	return BATADV_FORW_ALL;
}

static inline int batadv_mcast_init(struct batadv_priv *bat_priv)
{
	return 0;
+5 −5
Original line number Diff line number Diff line
@@ -248,7 +248,7 @@ out:
 *
 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
 */
static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
			    struct sk_buff *skb, int packet_type,
			    int packet_subtype,
			    struct batadv_orig_node *orig_node,
+5 −0
Original line number Diff line number Diff line
@@ -36,6 +36,11 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
					   struct sk_buff *skb,
					   struct batadv_orig_node *orig_node,
					   int packet_subtype);
int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
			    struct sk_buff *skb, int packet_type,
			    int packet_subtype,
			    struct batadv_orig_node *orig_node,
			    unsigned short vid);
int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
				   struct sk_buff *skb, int packet_type,
				   int packet_subtype, uint8_t *dst_hint,
Loading