Commit 07afe1ba authored by Linus Lüssing's avatar Linus Lüssing Committed by Simon Wunderlich
Browse files

batman-adv: mcast: implement multicast packet reception and forwarding



Implement functionality to receive and forward a new TVLV capable
multicast packet type.

The new batman-adv multicast packet type allows to contain several
originator destination addresses within a TVLV. Routers on the way will
potentially split the batman-adv multicast packet and adjust its tracker
TVLV contents.

Routing decisions are still based on the selected BATMAN IV or BATMAN V
routing algorithm. So this new batman-adv multicast packet type retains
the same loop-free properties.

Also a new OGM multicast TVLV flag is introduced to signal to other
nodes that we are capable of handling a batman-adv multicast packet and
multicast tracker TVLV. And that all of our hard interfaces have an MTU
of at least 1280 bytes (IPv6 minimum MTU), as a simple solution for now
to avoid MTU issues while forwarding.

Signed-off-by: default avatarLinus Lüssing <linus.luessing@c0d3.blue>
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
parent e4679a1b
Loading
Loading
Loading
Loading
+39 −6
Original line number Diff line number Diff line
@@ -116,6 +116,9 @@ enum batadv_icmp_packettype {
 * only need routable IPv4 multicast packets we signed up for explicitly
 * @BATADV_MCAST_WANT_NO_RTR6: we have no IPv6 multicast router and therefore
 * 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 {
	BATADV_MCAST_WANT_ALL_UNSNOOPABLES	= 1UL << 0,
@@ -123,6 +126,7 @@ enum batadv_mcast_flags {
	BATADV_MCAST_WANT_ALL_IPV6		= 1UL << 2,
	BATADV_MCAST_WANT_NO_RTR4		= 1UL << 3,
	BATADV_MCAST_WANT_NO_RTR6		= 1UL << 4,
	BATADV_MCAST_HAVE_MC_PTYPE_CAPA		= 1UL << 5,
};

/* tt data subtypes */
@@ -174,6 +178,7 @@ enum batadv_bla_claimframe {
 * @BATADV_TVLV_TT: translation table tvlv
 * @BATADV_TVLV_ROAM: roaming advertisement tvlv
 * @BATADV_TVLV_MCAST: multicast capability tvlv
 * @BATADV_TVLV_MCAST_TRACKER: multicast tracker tvlv
 */
enum batadv_tvlv_type {
	BATADV_TVLV_GW			= 0x01,
@@ -182,6 +187,7 @@ enum batadv_tvlv_type {
	BATADV_TVLV_TT			= 0x04,
	BATADV_TVLV_ROAM		= 0x05,
	BATADV_TVLV_MCAST		= 0x06,
	BATADV_TVLV_MCAST_TRACKER	= 0x07,
};

#pragma pack(2)
@@ -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
 * @packet_type: batman-adv packet type, part of the general header
@@ -628,6 +653,14 @@ struct batadv_tvlv_mcast_data {
	__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()

#endif /* _UAPI_LINUX_BATADV_PACKET_H_ */
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ batman-adv-y += hash.o
batman-adv-$(CONFIG_BATMAN_ADV_DEBUG) += log.o
batman-adv-y += main.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-$(CONFIG_BATMAN_ADV_NC) += network-coding.o
batman-adv-y += originator.o
+1 −7
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@

#include "hard-interface.h"
#include "originator.h"
#include "routing.h"
#include "send.h"

/**
@@ -351,18 +350,14 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
			 struct batadv_orig_node *orig_node_src)
{
	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_frag_packet *packet;
	u16 total_size;
	bool ret = false;

	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)
		goto out;

@@ -381,7 +376,6 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
	}

out:
	batadv_orig_node_put(orig_node_dst);
	batadv_neigh_node_put(neigh_node);
	return ret;
}
+2 −0
Original line number Diff line number Diff line
@@ -532,6 +532,8 @@ static void batadv_recv_handler_init(void)

	/* broadcast packet */
	batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
	/* multicast packet */
	batadv_rx_handler[BATADV_MCAST] = batadv_recv_mcast_packet;

	/* unicast packets ... */
	/* unicast with 4 addresses packet */
+43 −5
Original line number Diff line number Diff line
@@ -235,6 +235,37 @@ static u8 batadv_mcast_mla_rtr_flags_get(struct batadv_priv *bat_priv,
	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
 * @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)
	mla_flags.enabled = 1;
	mla_flags.tvlv_flags |= batadv_mcast_mla_rtr_flags_get(bat_priv,
							       bridge);
	mla_flags.tvlv_flags |= batadv_mcast_mla_forw_flags_get(bat_priv);

	if (!bridge)
		return mla_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;
	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_IPV4) ? '4' : '.',
		(old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.',
		!(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,
		   "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>",
		   (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
		   (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
		   (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.',
		   !(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' : '.');
}

/**
@@ -1820,6 +1854,10 @@ void batadv_mcast_init(struct batadv_priv *bat_priv)
	batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler,
				     NULL, NULL, BATADV_TVLV_MCAST, 2,
				     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);
	batadv_mcast_start_timer(bat_priv);
Loading