Basic Multicast Optimizations
This is the seventh revision of the basic multicast optimization patches.
It adds the style changes as suggested by Marek via eMail.
It also adds various suggestion from IRC (for instance adding kerneldoc for the functions touched in translation-table.c, making the counter an atomic one to be on the safe side for some "exotic" targets).
PATCHv7 4/4 is a new one and the result of a longer discussion on IRC:
Whether to add some support for some IPv4 addresses already for the cost of a slightly larger complexity both code and documentation wise
- for a case which is uncommon for most mesh networks anyway: a mesh with no bridges on any node involved.
So the fourth patch is sort of an RFC patch one, too (although the consense/ tendency on IRC so far was to add and support this case).
If everyone is fine with that concept, then I can also easily merge it into patches 2/4 and 3/4 (if that is desired).
Cheers, Linus
PATCH v7 1/4 batman-adv: Multicast Listener Announcements via Translation Table
With this patch a node which has no bridge interface on top of its soft interface announces its local multicast listeners via the translation table.
--- Makefile | 2 + Makefile.kbuild | 1 + compat.h | 20 ++++- gen-compat-autoconf.sh | 1 + main.c | 6 ++ main.h | 1 + multicast.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++ multicast.h | 43 +++++++++++ soft-interface.c | 3 + sysfs-class-net-mesh | 9 +++ sysfs.c | 6 ++ translation-table.c | 22 +++++- types.h | 22 ++++++ 13 files changed, 330 insertions(+), 5 deletions(-) create mode 100644 multicast.c create mode 100644 multicast.h
net/batman-adv/Makefile +2 -0
@@ -27,6 +27,8 @@ export CONFIG_BATMAN_ADV_BLA=y export CONFIG_BATMAN_ADV_DAT=y # B.A.T.M.A.N network coding (catwoman): export CONFIG_BATMAN_ADV_NC=n +# B.A.T.M.A.N. multicast optimizations: +export CONFIG_BATMAN_ADV_MCAST=y PWD:=$(shell pwd) KERNELPATH ?= /lib/modules/$(shell uname -r)/build
net/batman-adv/Makefile.kbuild +1 -0
@@ -38,3 +38,4 @@ batman-adv-y += send.o batman-adv-y += soft-interface.o batman-adv-y += sysfs.o batman-adv-y += translation-table.o +batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o
net/batman-adv/compat.h +19 -1
@@ -103,13 +103,31 @@ static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,#define pr_warn pr_warning +#undef netdev_for_each_mc_addr +#define netdev_for_each_mc_addr (mclist, dev) \ + for (mclist = (struct bat_dev_addr_list *)dev->mc_list; mclist; \ + mclist = (struct bat_dev_addr_list *)mclist->next) + +/* Note, that this breaks the usage of the normal 'struct netdev_hw_addr' +* for kernels < 2.6.35 in batman-adv! +*/ +#define netdev_hw_addr batadv_dev_addr_list +struct batadv_dev_addr_list { +struct dev_addr_list *next; +u8 addr[MAX_ADDR_LEN ]; +u8 da_addrlen; +u8 da_synced; +int da_users; +int da_gusers; +}; +#endif /* < KERNEL_VERSION(2, 6, 35) */ #if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,6 ,36 )#define __rcu -#define IFF_BRIDGE_PORT 0 || (hard_iface->net_dev->br_port ? 1 : 0) +#define IFF_BRIDGE_PORT 0 || (soft_iface->br_port ? 1 : 0) struct kernel_param_ops {/* Returns 0, or -errno. arg is in kp->arg. */
net/batman-adv/gen-compat-autoconf.sh +1 -0
@@ -39,6 +39,7 @@ gen_config() { gen_config 'CONFIG_BATMAN_ADV_DEBUG' ${CONFIG_BATMAN_ADV_DEBUG:="n"} >> "${TMP}" gen_config 'CONFIG_BATMAN_ADV_BLA' ${CONFIG_BATMAN_ADV_BLA:="y"} >> "${TMP}" gen_config 'CONFIG_BATMAN_ADV_DAT' ${CONFIG_BATMAN_ADV_DAT:="y"} >> "${TMP}" +gen_config 'CONFIG_BATMAN_ADV_MCAST' ${CONFIG_BATMAN_ADV_MCAST:="y"} >> "${TMP}" gen_config 'CONFIG_BATMAN_ADV_NC' ${CONFIG_BATMAN_ADV_NC:="n"} >> "${TMP}" # only regenerate compat-autoconf.h when config was changed
net/batman-adv/main.c +6 -0
@@ -33,6 +33,7 @@#include "gateway_client.h" #include "bridge_loop_avoidance.h" #include "distributed-arp-table.h" +#include "multicast.h" #include "gateway_common.h" #include "hash.h" #include "bat_algo.h"
@@ -117,6 +118,9 @@ int batadv_mesh_init(struct net_device *soft_iface)INIT_LIST_HEAD (&bat_priv->tt.changes_list);INIT_LIST_HEAD (&bat_priv->tt.req_list);INIT_LIST_HEAD (&bat_priv->tt.roam_list); +#ifdef CONFIG_BATMAN_ADV_MCAST +INIT_HLIST_HEAD (&bat_priv->mcast.mla_list); +#endif INIT_HLIST_HEAD (&bat_priv->tvlv.container_list);INIT_HLIST_HEAD (&bat_priv->tvlv.handler_list);INIT_HLIST_HEAD (&bat_priv->softif_vlan_list);
@@ -168,6 +172,8 @@ void batadv_mesh_free(struct net_device *soft_iface)batadv_dat_free (bat_priv);batadv_bla_free (bat_priv); +batadv_mcast_free (bat_priv); +/* Free the TT and the originator tables only after having terminated * all the other depending components which may use these structures for * their purposes.
net/batman-adv/main.h +1 -0
@@ -164,6 +164,7 @@ enum batadv_uev_type {#include <linux/percpu.h> #include <linux/slab.h> #include <net/sock.h> /* struct sock */ +#include <net/addrconf.h> /* ipv6 address stuff */ #include <net/rtnetlink.h> #include <linux/jiffies.h> #include <linux/seq_file.h>
net/batman-adv/multicast.c new file +199 -0
199 lines not on this page · raw message
net/batman-adv/multicast.h new file +43 -0
43 lines not on this page · raw message
net/batman-adv/soft-interface.c +3 -0
@@ -646,6 +646,9 @@ static int batadv_softif_init_late(struct net_device *dev)#ifdef CONFIG_BATMAN_ADV_DAT atomic_set (&bat_priv->distributed_arp_table,1 );#endif +#ifdef CONFIG_BATMAN_ADV_MCAST +atomic_set (&bat_priv->multicast_mode,1 ); +#endif atomic_set (&bat_priv->gw_mode,BATADV_GW_MODE_OFF );atomic_set (&bat_priv->gw_sel_class,20 );atomic_set (&bat_priv->gw.bandwidth_down,100 );
net/batman-adv/sysfs-class-net-mesh +9 -0
@@ -68,6 +68,15 @@ Description: Defines the penalty which will be applied to an originator message's tq-field on every hop. +What: /sys/class/net/<mesh_iface>/mesh/multicast_mode +Date: June 2013 +Contact: Linus Lüssing <[email protected]> +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 <[email protected]>
net/batman-adv/sysfs.c +6 -0
@@ -460,6 +460,9 @@ BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE, batadv_post_gw_deselect); static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, batadv_store_gw_bwidth); +#ifdef CONFIG_BATMAN_ADV_MCAST +BATADV_ATTR_SIF_BOOL (multicast_mode,S_IRUGO |S_IWUSR ,NULL ); +#endif #ifdef CONFIG_BATMAN_ADV_DEBUG BATADV_ATTR_SIF_UINT (log_level,S_IRUGO |S_IWUSR ,0 ,BATADV_DBG_ALL ,NULL );#endif
@@ -477,6 +480,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {#ifdef CONFIG_BATMAN_ADV_DAT &batadv_attr_distributed_arp_table,#endif +#ifdef CONFIG_BATMAN_ADV_MCAST + &batadv_attr_multicast_mode, +#endif &batadv_attr_fragmentation, &batadv_attr_routing_algo, &batadv_attr_gw_mode,
net/batman-adv/translation-table.c +18 -4
@@ -26,6 +26,7 @@#include "originator.h" #include "routing.h" #include "bridge_loop_avoidance.h" +#include "multicast.h" #include <linux/crc32c.h>
@@ -351,14 +352,16 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, {struct batadv_priv *bat_priv =netdev_priv (soft_iface);struct batadv_tt_local_entry *tt_local; -struct batadv_tt_global_entry *tt_global; +struct batadv_tt_global_entry *tt_global =NULL ;struct hlist_head *head;struct batadv_tt_orig_list_entry *orig_entry;int hash_added;bool roamed_back = false; tt_local =batadv_tt_local_hash_find (bat_priv, addr, vid); - tt_global =batadv_tt_global_hash_find (bat_priv, addr, vid); + +if (!is_multicast_ether_addr (addr)) + tt_global =batadv_tt_global_hash_find (bat_priv, addr, vid);if (tt_local) { tt_local->last_seen = jiffies;
@@ -412,8 +415,11 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, tt_local->last_seen = jiffies; tt_local->common.added_at = tt_local->last_seen; -/* the batman interface mac address should never be purged */ -if (batadv_compare_eth (addr, soft_iface->dev_addr)) +/* the batman interface mac and multicast addresses should never be +* purged +*/ +if (batadv_compare_eth (addr, soft_iface->dev_addr) || +is_multicast_ether_addr (addr)) tt_local->common.flags |=BATADV_TT_CLIENT_NOPURGE ; hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
@@ -1007,6 +1013,11 @@ add_orig_entry: ret = true; out_remove: +/* Do not remove multicast addresses from the local hash on +* global additions +*/ +if (is_multicast_ether_addr (tt_addr)) + goto out;/* remove address from local hash if present */ local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
@@ -2532,6 +2543,9 @@ void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv) {uint16_t changed_num =0 ; +/* Update multicast addresses in local translation table */ +batadv_mcast_mla_tt_update (bat_priv); +if (atomic_read (&bat_priv->tt.local_changes) <1 ) {if (!batadv_atomic_dec_not_zero (&bat_priv->tt.ogm_append_cnt))batadv_tt_tvlv_container_update (bat_priv);
net/batman-adv/types.h +22 -0
@@ -501,6 +501,12 @@ struct batadv_priv_dat { };#endif +#ifdef CONFIG_BATMAN_ADV_MCAST +struct batadv_priv_mcast { +struct hlist_head mla_list; +}; +#endif +/** * struct batadv_priv_nc - per mesh interface network coding private data * @work: work queue callback item for cleanup
@@ -610,6 +616,9 @@ struct batadv_priv {#ifdef CONFIG_BATMAN_ADV_DAT atomic_t distributed_arp_table;#endif +#ifdef CONFIG_BATMAN_ADV_MCAST +atomic_t multicast_mode; +#endif atomic_t gw_mode;atomic_t gw_sel_class;atomic_t orig_interval;
@@ -646,6 +655,9 @@ struct batadv_priv {#ifdef CONFIG_BATMAN_ADV_DAT struct batadv_priv_dat dat;#endif +#ifdef CONFIG_BATMAN_ADV_MCAST +struct batadv_priv_mcast mcast; +#endif #ifdef CONFIG_BATMAN_ADV_NC atomic_t network_coding;struct batadv_priv_nc nc;
@@ -971,6 +983,16 @@ struct batadv_dat_entry { };/** +* struct batadv_hw_addr - a list entry for a MAC address +* @list: list node for the linking of entries +* @addr: the MAC address of this list entry +*/ +struct batadv_hw_addr { +struct hlist_node list; +unsigned char addr[ETH_ALEN ]; +}; + +/** * struct batadv_dat_candidate - candidate destination for DAT operations * @type: the type of the selected candidate. It can one of the following: * - BATADV_DAT_CANDIDATE_NOT_FOUND
Signature · 1 line
1.7.10.4
PATCH v7 2/4 batman-adv: Announce new capability via multicast TVLV
In reply to Linus LüssingIf the soft interface of a node is not part of a bridge then a node announces a new multicast TVLV: The according flag (BATADV_MCAST_LISTENER_ANNOUNCEMENT) signalizes that this node is announcing all of its multicast listeners via the translation table infrastructure. More precisely, all multicast listeners of scope greater than link-local for IPv4 and of scope greater
or equal to link-local for IPv6.
--- main.c | 4 +++ main.h | 1 + multicast.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++- multicast.h | 14 +++++++++++ originator.c | 6 +++++ packet.h | 7 ++++++ soft-interface.c | 1 + types.h | 4 +++ 8 files changed, 110 insertions(+), 1 deletion(-)
net/batman-adv/main.c +4 -0
@@ -145,6 +145,10 @@ int batadv_mesh_init(struct net_device *soft_iface)if (ret <0 ) goto err; + ret =batadv_mcast_init (bat_priv); +if (ret <0 ) + goto err; + ret =batadv_gw_init (bat_priv);if (ret <0 ) goto err;
net/batman-adv/main.h +1 -0
@@ -68,6 +68,7 @@#define BATADV_ROAMING_MAX_TIME 20000#define BATADV_ROAMING_MAX_COUNT 5 +#define BATADV_UNINIT_FLAGS -1#define BATADV_NO_FLAGS 0#define BATADV_NULL_IFINDEX 0/* dummy ifindex used to avoid iface checks */
net/batman-adv/multicast.c +73 -1
96 lines not on this page · raw message
net/batman-adv/multicast.h +14 -0
@@ -24,8 +24,12 @@void batadv_mcast_mla_tt_update (struct batadv_priv *bat_priv); +int batadv_mcast_init (struct batadv_priv *bat_priv); +void batadv_mcast_free (struct batadv_priv *bat_priv); +void batadv_mcast_purge_orig (struct batadv_orig_node *orig_node); +#else static inline void batadv_mcast_mla_tt_update (struct batadv_priv *bat_priv)
@@ -33,11 +37,21 @@ static inline void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)return ; } +static inline int batadv_mcast_init (struct batadv_priv *bat_priv) +{ +return 0 ; +} +static inline void batadv_mcast_free (struct batadv_priv *bat_priv) {return ; } +static inline void batadv_mcast_purge_orig (struct batadv_orig_node *orig_node) +{ +return ; +} +#endif /* CONFIG_BATMAN_ADV_MCAST */ #endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
net/batman-adv/originator.c +6 -0
@@ -29,6 +29,7 @@#include "bridge_loop_avoidance.h" #include "network-coding.h" #include "fragmentation.h" +#include "multicast.h" /* hash class keys */ static struct lock_class_key batadv_orig_hash_lock_class_key;
@@ -143,6 +144,8 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)spin_unlock_bh (&orig_node->neigh_list_lock); +batadv_mcast_purge_orig (orig_node); +/* Free nc_nodes */ batadv_nc_purge_orig (orig_node->bat_priv, orig_node,NULL );
@@ -258,6 +261,9 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, reset_time = jiffies -1 -msecs_to_jiffies (BATADV_RESET_PROTECTION_MS ); orig_node->bcast_seqno_reset = reset_time; orig_node->batman_seqno_reset = reset_time; +#ifdef CONFIG_BATMAN_ADV_MCAST + orig_node->mcast_flags =BATADV_UNINIT_FLAGS ; +#endif atomic_set (&orig_node->bond_candidates,0 );
net/batman-adv/packet.h +7 -0
@@ -91,6 +91,11 @@ enum batadv_icmp_packettype { BATADV_PARAMETER_PROBLEM = 12, }; +/* multicast capabilities */ +enum batadv_mcast_flags { +BATADV_MCAST_LISTENER_ANNOUNCEMENT =BIT (0 ), +}; +/* tt data subtypes */ #define BATADV_TT_DATA_TYPE_MASK 0x0F
@@ -145,6 +150,7 @@ enum batadv_bla_claimframe {* @BATADV_TVLV_NC: network coding tvlv * @BATADV_TVLV_TT: translation table tvlv * @BATADV_TVLV_ROAM: roaming advertisement tvlv +* @BATADV_TVLV_MCAST: multicast capability tvlv */ enum batadv_tvlv_type {BATADV_TVLV_GW =0x01 ,
@@ -152,6 +158,7 @@ enum batadv_tvlv_type {BATADV_TVLV_NC =0x03 ,BATADV_TVLV_TT =0x04 ,BATADV_TVLV_ROAM =0x05 , + BATADV_TVLV_MCAST = 0x06, };/* the destination hardware field in the ARP frame is used to
net/batman-adv/soft-interface.c +1 -0
@@ -648,6 +648,7 @@ static int batadv_softif_init_late(struct net_device *dev)#endif #ifdef CONFIG_BATMAN_ADV_MCAST atomic_set (&bat_priv->multicast_mode,1 ); +atomic_set (&bat_priv->mcast.num_no_mla,0 );#endif atomic_set (&bat_priv->gw_mode,BATADV_GW_MODE_OFF );atomic_set (&bat_priv->gw_sel_class,20 );
net/batman-adv/types.h +4 -0
@@ -163,6 +163,9 @@ struct batadv_orig_node {unsigned long last_seen;unsigned long bcast_seqno_reset;unsigned long batman_seqno_reset; +#ifdef CONFIG_BATMAN_ADV_MCAST +int mcast_flags; +#endif uint8_t capabilities;atomic_t last_ttvn;uint32_t tt_crc;
@@ -504,6 +507,7 @@ struct batadv_priv_dat {#ifdef CONFIG_BATMAN_ADV_MCAST struct batadv_priv_mcast {struct hlist_head mla_list; +atomic_t num_no_mla; };#endif
Signature · 1 line
1.7.10.4
Re: [B.A.T.M.A.N.] [PATCHv7 2/4] batman-adv: Announce new capability via multicast TVLV
Quoted 26 lines · On Thursday, July 04, 2013 06:03:20 Linus Lüssing wrote:
net/batman-adv/multicast.c +10
-1@@ -169,13 +169,30 @@ void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv) struct net_device *soft_iface = bat_priv->soft_iface;struct hlist_head mcast_list =HLIST_HEAD_INIT ;int ret; +static bool enabled; +uint8_t mcast_flags;/* Avoid attaching MLAs, if multicast optimization is disabled * or there is a bridge on top of our soft interface (TODO) */ if (!atomic_read (&bat_priv->multicast_mode) || - bat_priv->soft_iface->priv_flags &IFF_BRIDGE_PORT ) + bat_priv->soft_iface->priv_flags &IFF_BRIDGE_PORT ) { +if (enabled) { +batadv_tvlv_container_unregister (bat_priv, +BATADV_TVLV_MCAST ,1 ); + enabled = false; + } + goto update; + } +
net/batman-adv/multicast.c void batadv_mcast_mla_tt_update(struct batadv_priv · line 198
Quoted 10 lines
net/batman-adv/multicast.c +6
-0+if (!enabled) { + mcast_flags =BATADV_MCAST_LISTENER_ANNOUNCEMENT ; +batadv_tvlv_container_register (bat_priv,BATADV_TVLV_MCAST ,1 , + &mcast_flags, +sizeof (mcast_flags)); + enabled = true; + } ret =batadv_mcast_mla_softif_get (soft_iface, &mcast_list);if (ret <0 )
Is there no better way than using a static variable ? Apart from bad readibility this totally breaks when using several batX interfaces with different settings.
net/batman-adv/multicast.c
Quoted 4 lines
net/batman-adv/multicast.c +4
-0+/* multicast capabilities */ +enum batadv_mcast_flags { +BATADV_MCAST_LISTENER_ANNOUNCEMENT =BIT (0 ), +};
Didn't we discuss that using feature names is better ? We talked about things like UNICAST, TRACKER, etc ?
Cheers,
Marek
Re: [B.A.T.M.A.N.] [PATCHv7 2/4] batman-adv: Announce new capability via multicast TVLV
Quoted 35 lines · Marek Lindner
Quoted 34 lines · On Thursday, July 04, 2013 06:03:20 Linus Lüssing wrote:
net/batman-adv/multicast.c +16
-1@@ -169,13 +169,30 @@ void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv) struct net_device *soft_iface = bat_priv->soft_iface;struct hlist_head mcast_list =HLIST_HEAD_INIT ;int ret; +static bool enabled; +uint8_t mcast_flags;/* Avoid attaching MLAs, if multicast optimization is disabled * or there is a bridge on top of our soft interface (TODO) */ if (!atomic_read (&bat_priv->multicast_mode) || - bat_priv->soft_iface->priv_flags &IFF_BRIDGE_PORT ) + bat_priv->soft_iface->priv_flags &IFF_BRIDGE_PORT ) { +if (enabled) { +batadv_tvlv_container_unregister (bat_priv, +BATADV_TVLV_MCAST ,1 ); + enabled = false; + } + goto update; + } + +if (!enabled) { + mcast_flags =BATADV_MCAST_LISTENER_ANNOUNCEMENT ; +batadv_tvlv_container_register (bat_priv,BATADV_TVLV_MCAST ,1 , + &mcast_flags, +sizeof (mcast_flags)); + enabled = true; + }
Quoted 6 lines
Quoted 2 lines
ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list); if (ret < 0)Is there no better way than using a static variable ? Apart from bad readibility this totally breaks when using several batX interfaces with different settings.
Ah, right, didn't think of multiple batX interfaces, that's a bug indeed. I'm going to fix that.
What do you think about adding new tvlv API like:
---
bool batadv_tvlv_container_is_registered(struct batadv_priv *bat_priv,
uint8_t type, uint8_t version)
{
struct batadv_tvlv_container *tvlv;
bool ret;
spin_lock_bh(&bat_priv->tvlv.container_list_lock);
tvlv = batadv_tvlv_container_get(bat_priv, type, version);
ret = tvlv ? true : false;
batadv_tvlv_container_free_ref(tvlv);
spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
return ret;
}----
The disadvantage is that this is a little heavier as it will perform a list lookup and holds a spin-lock.
If we were going to use something like bat_priv->mcast.tvlv_container_enabled instead, that would be lighter but less readable.
Quoted 9 lines
net/batman-adv/multicast.c
Quoted 6 lines
net/batman-adv/multicast.c +4
-0+/* multicast capabilities */ +enum batadv_mcast_flags { +BATADV_MCAST_LISTENER_ANNOUNCEMENT =BIT (0 ), +};Didn't we discuss that using feature names is better ? We talked about things like UNICAST, TRACKER, etc ?
Hm, I only remember discussing the name for sysfs. For the flags I thought we were only using UNICAST, TRACKER, etc. as abbreviations for the current names in our IRC discussion, I didn't interpret that as a suggestion to change these names.
Anyways, let's discuss a renaming of the flags then. I don't like a change like:
BATADV_MCAST_LISTENER_ANNOUNCEMENT -> BATADV_MCAST_UNICAST
Because for one thing, it isn't up to the node announcing this flag to deceide whether another, sending node is able use unicast. Whether unicast can be used depends on a lot more factors.
For another thing this flag is not only adding a unicast feature if all these factors are met, but also adds the dropping feature introduced by this patchset.
I'd rather keep the naming for the multicast flags to reflect the capabilities and settings of the local, announcing node.
Cheers, Linus
PATCH v7 3/4 batman-adv: Modified forwarding behaviour for multicast packets
In reply to Linus LüssingWith this patch a multicast packet is not always simply flooded anymore, the bevahiour 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 (BATADV_MCAST_LISTENER_ANNOUNCEMENT) then an IPv6 multicast packet with a destination of IPv6 link-local scope 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.
--- multicast.c | 60 +++++++++++++++++++++++++++++++++++ multicast.h | 23 ++++++++++++++ soft-interface.c | 18 +++++++++-- translation-table.c | 86 +++++++++++++++++++++++++++++++++++++++++---------- translation-table.h | 2 ++ types.h | 2 ++ 6 files changed, 173 insertions(+), 18 deletions(-)
net/batman-adv/multicast.c +60 -0
@@ -21,6 +21,7 @@#include "originator.h" #include "hard-interface.h" #include "translation-table.h" +#include "multicast.h" /** * batadv_mcast_mla_softif_get - get softif multicast listeners
@@ -207,6 +208,61 @@ out: }/** +* batadv_mcast_forw_mode - check on how to forward a multicast packet +* @skb: The multicast packet to check +* @bat_priv: the bat priv with all the soft interface information +* +* Return the forwarding mode as enum batadv_forw_mode. +*/ +enum batadv_forw_mode +batadv_mcast_forw_mode (struct sk_buff *skb,struct batadv_priv *bat_priv) +{ +struct ethhdr *ethhdr = (struct ethhdr *)(skb->data); +struct ipv6hdr *ip6hdr; +int count; + +if (!atomic_read (&bat_priv->multicast_mode)) +return BATADV_FORW_ALL ; + +if (atomic_read (&bat_priv->mcast.num_no_mla)) +return BATADV_FORW_ALL ; + +if (ntohs (ethhdr->h_proto) !=ETH_P_IPV6 ) +return BATADV_FORW_ALL ; + +/* We might fail due to out-of-memory -> drop it */ +if (!pskb_may_pull (skb,sizeof (*ethhdr) +sizeof (*ip6hdr))) +return BATADV_FORW_NONE ; + + ip6hdr =ipv6_hdr (skb); + +/* TODO: Implement Multicast Router Discovery, then add +* scope >= IPV6_ADDR_SCOPE_LINKLOCAL, too +*/ +if (IPV6_ADDR_MC_SCOPE (&ip6hdr->daddr) != +IPV6_ADDR_SCOPE_LINKLOCAL ) +return BATADV_FORW_ALL ; + +/* We cannot snoop and therefore cannot optimize the +* all-nodes-multicast address +*/ +if (ipv6_addr_is_ll_all_nodes (&ip6hdr->daddr)) +return BATADV_FORW_ALL ; + + count =batadv_tt_global_hash_count (bat_priv, ethhdr->h_dest, +BATADV_NO_FLAGS ); + +switch (count) { +case 0 : +return BATADV_FORW_NONE ; +case 1 : +return BATADV_FORW_SINGLE ; +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 * @orig: the orig_node of the ogm
@@ -264,6 +320,10 @@ void batadv_mcast_free(struct batadv_priv *bat_priv)batadv_mcast_mla_tt_clean (bat_priv,NULL ); } +/** +* batadv_mcast_purge_orig - reset originator global mcast state modifications +* @orig_node: the originator which is going to get purged +*/ void batadv_mcast_purge_orig (struct batadv_orig_node *orig_node) {if (!(orig_node->mcast_flags &BATADV_MCAST_LISTENER_ANNOUNCEMENT ))
net/batman-adv/multicast.h +23 -0
@@ -20,10 +20,27 @@#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_IV 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_tt_update (struct batadv_priv *bat_priv); +enum batadv_forw_mode +batadv_mcast_forw_mode (struct sk_buff *skb,struct batadv_priv *bat_priv); +int batadv_mcast_init (struct batadv_priv *bat_priv);void batadv_mcast_free (struct batadv_priv *bat_priv);
@@ -37,6 +54,12 @@ static inline void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)return ; } +static inline enum batadv_forw_mode +batadv_mcast_forw_mode (struct sk_buff *skb,struct batadv_priv *bat_priv) +{ +return BATADV_FORW_ALL ; +} +static inline int batadv_mcast_init (struct batadv_priv *bat_priv) {return 0 ;
net/batman-adv/soft-interface.c +16 -2
@@ -34,6 +34,7 @@#include <linux/ethtool.h> #include <linux/etherdevice.h> #include <linux/if_vlan.h> +#include "multicast.h" #include "bridge_loop_avoidance.h" #include "network-coding.h"
@@ -169,6 +170,8 @@ static int batadv_interface_tx(struct sk_buff *skb,bool do_bcast = false;unsigned short vid;uint32_t seqno; +enum batadv_forw_mode mode; +bool forw_to_gw = false;if (atomic_read (&bat_priv->mesh_state) !=BATADV_MESH_ACTIVE ) goto dropped;
@@ -226,13 +229,24 @@ static int batadv_interface_tx(struct sk_buff *skb,* via unicast to their gateway */ ret =batadv_gw_is_dhcp_target (skb, &header_len); -if (ret) +if (ret) { do_bcast = false; + forw_to_gw = true; + }break ;case BATADV_GW_MODE_OFF :default :break ; } + +if (do_bcast && !is_broadcast_ether_addr (ethhdr->h_dest)) { + mode =batadv_mcast_forw_mode (skb, bat_priv); +if (mode ==BATADV_FORW_NONE ) + goto dropped; + +if (mode ==BATADV_FORW_SINGLE ) + do_bcast = false; + } }/* ethernet packet should be broadcasted */
@@ -289,7 +303,7 @@ static int batadv_interface_tx(struct sk_buff *skb,batadv_dat_snoop_outgoing_arp_reply (bat_priv, skb); -if (is_multicast_ether_addr (ethhdr->h_dest)) +if (forw_to_gw) ret =batadv_send_skb_via_gw (bat_priv, skb, vid);else ret =batadv_send_skb_via_tt (bat_priv, skb, vid);
net/batman-adv/translation-table.c +70 -16
144 lines not on this page · raw message
net/batman-adv/translation-table.h +2 -0
@@ -31,6 +31,8 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);void batadv_tt_global_del_orig (struct batadv_priv *bat_priv,struct batadv_orig_node *orig_node,const char *message); +int batadv_tt_global_hash_count (struct batadv_priv *bat_priv, +const uint8_t *addr,unsigned short vid); struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, const uint8_t *src, const uint8_t *addr,
net/batman-adv/types.h +2 -0
@@ -784,12 +784,14 @@ struct batadv_tt_local_entry {* struct batadv_tt_global_entry - translation table global entry data * @common: general translation table data * @orig_list: list of orig nodes announcing this non-mesh client +* @orig_list_count: number of items in the orig_list * @list_lock: lock protecting orig_list * @roam_at: time at which TT_GLOBAL_ROAM was set */ struct batadv_tt_global_entry {struct batadv_tt_common_entry common;struct hlist_head orig_list; +atomic_t orig_list_count;spinlock_t list_lock;/* protects orig_list */ unsigned long roam_at; };
Signature · 1 line
1.7.10.4
PATCH v7 4/4 batman-adv: Add IPv4 link-local/IPv6-ll-all-nodes multicast support
In reply to Linus LüssingWith this patch a node may additionally perform the dropping or unicasting behaviour for a link-local IPv4 and link-local-all-nodes IPv6 multicast packet, too.
The extra counter and BATADV_MCAST_HAS_NO_BRIDGE flag is needed because with a future bridge snooping support integration a node with a bridge on top of its soft interface is not able to reliably detect its multicast listeners for IPv4 link-local and the IPv6 link-local-all-nodes addresses anymore (see RFC4541, section 2.1.2.2 and section 3).
Even though this new flag and the BATADV_MCAST_LISTENER_ANNOUNCEMENT flag are currently set and unset at the same time, so even though this new flag does make "no difference" now, it'll ensure a seamless integration of multicast bridge support without needing to break compatibility later.
Also note, that even with multicast bridge support it will need only one node with a bridge to disable optimizations for link-local IPv4 and IPv6-link-local-all-nodes multicast, resulting in flooding all these packets again. So the 224.0.0.x address range and the ff02::1 address will never be a safe choice for multicast streaming etc. if you do not control every node.
--- main.h | 1 + multicast.c | 170 ++++++++++++++++++++++++++++++++++++++++++++---------- packet.h | 1 + soft-interface.c | 1 + types.h | 1 + 5 files changed, 143 insertions(+), 31 deletions(-)
net/batman-adv/main.h +1 -0
@@ -166,6 +166,7 @@ enum batadv_uev_type {#include <linux/slab.h> #include <net/sock.h> /* struct sock */ #include <net/addrconf.h> /* ipv6 address stuff */ +#include <linux/ip.h> #include <net/rtnetlink.h> #include <linux/jiffies.h> #include <linux/seq_file.h>
net/batman-adv/multicast.c +139 -31
207 lines not on this page · raw message
net/batman-adv/packet.h +1 -0
@@ -94,6 +94,7 @@ enum batadv_icmp_packettype {/* multicast capabilities */ enum batadv_mcast_flags {BATADV_MCAST_LISTENER_ANNOUNCEMENT =BIT (0 ), +BATADV_MCAST_HAS_NO_BRIDGE =BIT (1 ), };/* tt data subtypes */
net/batman-adv/soft-interface.c +1 -0
@@ -663,6 +663,7 @@ static int batadv_softif_init_late(struct net_device *dev)#ifdef CONFIG_BATMAN_ADV_MCAST atomic_set (&bat_priv->multicast_mode,1 );atomic_set (&bat_priv->mcast.num_no_mla,0 ); +atomic_set (&bat_priv->mcast.num_has_bridge,0 );#endif atomic_set (&bat_priv->gw_mode,BATADV_GW_MODE_OFF );atomic_set (&bat_priv->gw_sel_class,20 );
net/batman-adv/types.h +1 -0
@@ -508,6 +508,7 @@ struct batadv_priv_dat {struct batadv_priv_mcast {struct hlist_head mla_list;atomic_t num_no_mla; +atomic_t num_has_bridge; };#endif
Signature · 1 line
1.7.10.4
Re: [B.A.T.M.A.N.] [PATCHv7 4/4] batman-adv: Add IPv4 link-local/IPv6-ll-all-nodes multicast support
net/batman-adv/multicast.c batadv_mcast_forw_mode(struct sk_buff *skb, struct batadv_priv *bat_priv) · line 334
Quoted 11 lines · Linus Lüssing
[...]
net/batman-adv/multicast.c +10
-0+enum batadv_forw_mode +batadv_mcast_forw_mode (struct sk_buff *skb,struct batadv_priv *bat_priv) +{ +struct ethhdr *ethhdr = (struct ethhdr *)(skb->data); +int ret; + + ret =batadv_mcast_forw_mode_check (skb, bat_priv); +if (ret == -ENOMEM ) +return BATADV_FORW_NONE ; +else if (ret == -EINVAL )
Shouldn't this better be "ret < 0", in case you add more error cases later?
Quoted 18 lines
net/batman-adv/multicast.c +5
-2return BATADV_FORW_ALL ; - count =batadv_tt_global_hash_count (bat_priv, ethhdr->h_dest, + ret =batadv_tt_global_hash_count (bat_priv, ethhdr->h_dest,BATADV_NO_FLAGS ); -switch (count) { +switch (ret) {case 0 :return BATADV_FORW_NONE ;case 1 :@@ -263,6 +348,28 @@ batadv_mcast_forw_mode(struct sk_buff *skb, struct batadv_priv *bat_priv) }/** +* batadv_mcast_tvlv_update_flag_counter - update the counter of a flag +* @flag: the flag we want to update counters for +* @flag_counter: the counter we might update
net/batman-adv/multicast.c batadv_mcast_forw_mode(struct sk_buff *skb, struct batadv_priv *bat_priv) · line 363
Quoted 10 lines
net/batman-adv/multicast.c +10
-0+* @new_flags: the new capability bitset of a node +* @old_flags: the current, to be updated bitset of a node +* +* Update the given flag_counter with the help of the new flag information +* of a node to reflect how many nodes have the given flag unset. +*/ +static void batadv_mcast_tvlv_update_flag_counter (uint8_t flag, +atomic_t *flag_counter, +uint8_t new_flags, +int old_flags)
Why are parts of the bitsets uint8_t, some int?
Also, this function should go into one of the previous patches, this has nothing to do with IPv4 but is just a refactoring.
Quoted 21 lines
net/batman-adv/multicast.c +9
-5+{ +if (!(new_flags & flag) && + (old_flags & flag || old_flags &BATADV_UNINIT_FLAGS )) +atomic_inc (flag_counter); +else if (new_flags & flag && !(old_flags & flag)) +atomic_dec (flag_counter); +} + +/** * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container * @bat_priv: the bat priv with all the soft interface information * @orig: the orig_node of the ogm @@ -285,13 +392,14 @@ static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, (tvlv_value) && (tvlv_value_len == sizeof(mcast_flags))) mcast_flags = *(uint8_t *)tvlv_value; -if (!(mcast_flags &BATADV_MCAST_LISTENER_ANNOUNCEMENT ) && - (orig->mcast_flags &BATADV_MCAST_LISTENER_ANNOUNCEMENT || - orig->mcast_flags &BATADV_UNINIT_FLAGS )) -atomic_inc (&bat_priv->mcast.num_no_mla); - else if (mcast_flags & BATADV_MCAST_LISTENER_ANNOUNCEMENT &&
net/batman-adv/multicast.c static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, · line 402
Quoted 10 lines
net/batman-adv/multicast.c +8
-2- !(orig->mcast_flags & BATADV_MCAST_LISTENER_ANNOUNCEMENT)) -atomic_dec (&bat_priv->mcast.num_no_mla); +batadv_mcast_tvlv_update_flag_counter ( +BATADV_MCAST_LISTENER_ANNOUNCEMENT , + &bat_priv->mcast.num_no_mla, + mcast_flags, orig->mcast_flags); +batadv_mcast_tvlv_update_flag_counter ( +BATADV_MCAST_HAS_NO_BRIDGE , + &bat_priv->mcast.num_has_bridge, + mcast_flags, orig->mcast_flags);
You should find a shorter name, the alignment looks really ugly. :)
Cheers,
Simon
Re: [B.A.T.M.A.N.] [PATCHv7 4/4] batman-adv: Add IPv4 link-local/IPv6-ll-all-nodes multicast support
Quoted 14 lines · Simon Wunderlich
net/batman-adv/multicast.c batadv_mcast_forw_mode(struct sk_buff *skb, struct batadv_priv *bat_priv) · line 334
Quoted 11 lines · Linus Lüssing
[...]
net/batman-adv/multicast.c +10
-0+enum batadv_forw_mode +batadv_mcast_forw_mode (struct sk_buff *skb,struct batadv_priv *bat_priv) +{ +struct ethhdr *ethhdr = (struct ethhdr *)(skb->data); +int ret; + + ret =batadv_mcast_forw_mode_check (skb, bat_priv); +if (ret == -ENOMEM ) +return BATADV_FORW_NONE ; +else if (ret == -EINVAL )Shouldn't this better be "ret < 0", in case you add more error cases later?
Good idea! Looks better, I'm adding that.
Quoted 15 lines
Quoted 15 lines
net/batman-adv/multicast.c +2
-2return BATADV_FORW_ALL ; - count =batadv_tt_global_hash_count (bat_priv, ethhdr->h_dest, + ret =batadv_tt_global_hash_count (bat_priv, ethhdr->h_dest,BATADV_NO_FLAGS ); -switch (count) { +switch (ret) {case 0 :return BATADV_FORW_NONE ;case 1 :@@ -263,6 +348,28 @@ batadv_mcast_forw_mode(struct sk_buff *skb, struct batadv_priv *bat_priv) }
Quoted 16 lines
Quoted 4 lines
net/batman-adv/multicast.c +3
-0/** +* batadv_mcast_tvlv_update_flag_counter - update the counter of a flag +* @flag: the flag we want to update counters for +* @flag_counter: the counter we might update net/batman-adv/multicast.c batadv_mcast_forw_mode(struct sk_buff *skb, struct batadv_priv *bat_priv) · line 363
Quoted 10 lines
net/batman-adv/multicast.c +10
-0+* @new_flags: the new capability bitset of a node +* @old_flags: the current, to be updated bitset of a node +* +* Update the given flag_counter with the help of the new flag information +* of a node to reflect how many nodes have the given flag unset. +*/ +static void batadv_mcast_tvlv_update_flag_counter (uint8_t flag, +atomic_t *flag_counter, +uint8_t new_flags, +int old_flags)Why are parts of the bitsets
uint8_t, some int?
Because the locally stored mcast_flags variable is bigger than the tvlv mcast_flags (because of the BATADV_UNINIT_FLAGS).
Quoted 3 lines
Also, this function should go into one of the previous patches, this has nothing to do with IPv4 but is just a refactoring.
Hm, it's just moving some code to a new function because the original function got too long for my taste now. Anyways, ok, I'm going to introduce that function in the previous patch already.
Quoted 26 lines
Quoted 26 lines
net/batman-adv/multicast.c +11
-7+{ +if (!(new_flags & flag) && + (old_flags & flag || old_flags &BATADV_UNINIT_FLAGS )) +atomic_inc (flag_counter); +else if (new_flags & flag && !(old_flags & flag)) +atomic_dec (flag_counter); +} + +/** * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container * @bat_priv: the bat priv with all the soft interface information * @orig: the orig_node of the ogm @@ -285,13 +392,14 @@ static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, (tvlv_value) && (tvlv_value_len == sizeof(mcast_flags))) mcast_flags = *(uint8_t *)tvlv_value; -if (!(mcast_flags &BATADV_MCAST_LISTENER_ANNOUNCEMENT ) && - (orig->mcast_flags &BATADV_MCAST_LISTENER_ANNOUNCEMENT || - orig->mcast_flags &BATADV_UNINIT_FLAGS )) -atomic_inc (&bat_priv->mcast.num_no_mla); -else if (mcast_flags &BATADV_MCAST_LISTENER_ANNOUNCEMENT && - !(orig->mcast_flags &BATADV_MCAST_LISTENER_ANNOUNCEMENT )) -atomic_dec (&bat_priv->mcast.num_no_mla); + batadv_mcast_tvlv_update_flag_counter( + BATADV_MCAST_LISTENER_ANNOUNCEMENT,
Quoted 8 lines
net/batman-adv/multicast.c static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, · line 402
Quoted 6 lines
net/batman-adv/multicast.c +6
-0+ &bat_priv->mcast.num_no_mla, + mcast_flags, orig->mcast_flags); +batadv_mcast_tvlv_update_flag_counter ( +BATADV_MCAST_HAS_NO_BRIDGE , + &bat_priv->mcast.num_has_bridge, + mcast_flags, orig->mcast_flags);You should find a shorter name, the alignment looks really ugly. :)
Oki doki, fair point :).
Quoted 3 lines
Cheers,
Simon
Cheers, Linus
And the sysfs file 'mcast_group_awareness' got renamed to 'multicast_mode'. The missing ABI documentation for this file was added, too.
Quoted 22 lines · Linus Lüssing
This is the seventh revision of the basic multicast optimization patches.
It adds the style changes as suggested by Marek via eMail.
It also adds various suggestion from IRC (for instance adding kerneldoc for the functions touched in
translation-table.c, making the counter an atomic one to be on the safe side for some "exotic" targets).PATCHv7 4/4 is a new one and the result of a longer discussion on IRC:
Whether to add some support for some IPv4 addresses already for the cost of a slightly larger complexity both code and documentation wise
- for a case which is uncommon for most mesh networks anyway: a mesh with no bridges on any node involved.So the fourth patch is sort of an RFC patch one, too (although the consense/ tendency on IRC so far was to add and support this case).
If everyone is fine with that concept, then I can also easily merge it into patches 2/4 and 3/4 (if that is desired).
Cheers, Linus