Basic Multicast Optimizations
v14 cover Basic Multicast Optimizations
This is the fourteenth revision of the basic multicast optimization patches.
Changes in v14 include:
* fixed compilation for CONFIG_BATMAN_ADV_MCAST=n (issue was introduced by v13)
* fixed potential null pointer exception (moved ethhdr assignment in batadv_mcast_forw_mode() to after the check methods / pskb_may_pull()s)
* removed flag-list-"helper" functions
* removed methods which were performing both counting and orig_node retrieval in batadv_mcast_forw_mode(), instead doing that in two logical, seperate sections in batadv_mcast_forw_mode()
Cheers, Linus
PATCH v14 1/6 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 | 37 ++++++++ gen-compat-autoconf.sh | 1 + main.c | 6 ++ main.h | 1 + multicast.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++ multicast.h | 38 ++++++++ translation-table.c | 22 ++++- types.h | 24 +++++ 10 files changed, 370 insertions(+), 4 deletions(-) create mode 100644 multicast.c create mode 100644 multicast.h
Makefile +2 -0
@@ -25,6 +25,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
Makefile.kbuild +1 -0
@@ -36,3 +36,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
compat.h +37 -0
@@ -103,6 +103,24 @@ 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 batadv_dev_addr_list *)dev->mc_list; mclist; \ + mclist = (struct batadv_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) */
@@ -143,6 +161,14 @@ static inline int batadv_param_set_copystring(const char *val,#define addr_assign_type ifindex#define NET_ADDR_RANDOM 0 +#define netdev_master_upper_dev_get_rcu (dev) \ + NULL; \ + if (dev->br_port ? 1 : 0) { \ + rcu_read_unlock(); \ + dev_hold(dev); \ + return dev; \ + } +#endif /* < KERNEL_VERSION(2, 6, 36) */ #if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,6 ,37 )
@@ -343,6 +369,17 @@ static int __batadv_interface_tx(struct sk_buff *skb, \ pos && ({ n = pos->member.next;1 ; }); \ pos = hlist_entry_safe(n, typeof(*pos), member)) +#ifndef netdev_master_upper_dev_get_rcu +#define netdev_master_upper_dev_get_rcu (dev) \ + NULL; \ + if (dev->priv_flags & IFF_BRIDGE_PORT) { \ + rcu_read_unlock(); \ + dev_hold(dev); \ + return dev; \ + } + +#endif /* netdev_master_upper_dev_get_rcu */ +#endif /* < KERNEL_VERSION(3, 9, 0) */ #if LINUX_VERSION_CODE <KERNEL_VERSION (3 ,10 ,0 )
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
main.c +6 -0
@@ -34,6 +34,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"
@@ -120,6 +121,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);
@@ -169,6 +173,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.
main.h +1 -0
@@ -176,6 +176,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>
multicast.c new file +242 -0
242 lines not on this page · raw message
multicast.h new file +38 -0
@@ -0,0 +1,38 @@ +/* Copyright (C) 2014 B.A.T.M.A.N. contributors: +* +* Linus Lüssing +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +*/ + +#ifndef _NET_BATMAN_ADV_MULTICAST_H_ +#define _NET_BATMAN_ADV_MULTICAST_H_ + +#ifdef CONFIG_BATMAN_ADV_MCAST + +void batadv_mcast_mla_update (struct batadv_priv *bat_priv); + +void batadv_mcast_free (struct batadv_priv *bat_priv); + +#else + +static inline void batadv_mcast_mla_update (struct batadv_priv *bat_priv) +{ +return ; +} + +static inline void batadv_mcast_free (struct batadv_priv *bat_priv) +{ +return ; +} + +#endif /* CONFIG_BATMAN_ADV_MCAST */ + +#endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
translation-table.c +18 -4
@@ -24,6 +24,7 @@#include "originator.h" #include "routing.h" #include "bridge_loop_avoidance.h" +#include "multicast.h" #include <linux/crc32c.h>
@@ -484,7 +485,7 @@ bool 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 net_device *in_dev =NULL ;struct hlist_head *head;struct batadv_tt_orig_list_entry *orig_entry;
@@ -497,7 +498,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, in_dev =dev_get_by_index (&init_net, ifindex); 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;
@@ -562,8 +565,11 @@ bool 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,
@@ -1361,6 +1367,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,
@@ -3120,6 +3131,9 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)*/ static void batadv_tt_local_commit_changes_nolock (struct batadv_priv *bat_priv) { +/* Update multicast addresses in local translation table */ +batadv_mcast_mla_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);
types.h +24 -0
@@ -607,6 +607,16 @@ struct batadv_priv_dat { };#endif +#ifdef CONFIG_BATMAN_ADV_MCAST +/** +* struct batadv_priv_mcast - per mesh interface mcast data +* @mla_list: list of multicast addresses we are currently announcing via TT +*/ +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
@@ -702,6 +712,7 @@ struct batadv_softif_vlan {* @tt: translation table data * @tvlv: type-version-length-value data * @dat: distributed arp table data +* @mcast: multicast data * @network_coding: bool indicating whether network coding is enabled * @batadv_priv_nc: network coding data */
@@ -759,6 +770,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;
@@ -1116,6 +1130,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
Marek Lindner
AppliedRe: [B.A.T.M.A.N.] [PATCHv14 1/6] batman-adv: Multicast Listener Announcements via Translation Table
Quoted 5 lines · On Saturday 15 February 2014 17:47:49 Linus Lüssing wrote:
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.
Signed-off-by Linus Lüssing <[email protected]>
Quoted 13 lines
--- Makefile | 2 + Makefile.kbuild | 1 + compat.h | 37 ++++++++ gen-compat-autoconf.sh | 1 + main.c | 6 ++ main.h | 1 + multicast.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++ multicast.h | 38 ++++++++ translation-table.c | 22 ++++- types.h | 24 +++++ 10 files changed, 370 insertions(+), 4 deletions(-)
Applied in revision e368857.
Thanks,
Marek
PATCH v14 2/6 batman-adv: introduce capability initialization bitfield
In reply to Linus LüssingThe new bitfield allows us to keep track whether capability subsets of an originator have gone through their initialization phase yet.
The translation table is the only user right now, but a new one will be added soon.
--- originator.c | 1 - translation-table.c | 12 +++++++----- types.h | 7 ++++--- 3 files changed, 11 insertions(+), 9 deletions(-)
originator.c +0 -1
@@ -664,7 +664,6 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,/* extra reference for return */ atomic_set (&orig_node->refcount,2 ); - orig_node->tt_initialised = false; orig_node->bat_priv = bat_priv;ether_addr_copy (orig_node->orig, addr);batadv_dat_init_orig_node_addr (orig_node);
translation-table.c +7 -5
@@ -1774,7 +1774,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, }spin_unlock_bh (list_lock); } - orig_node->tt_initialised = false; + orig_node->capa_initialized &= ~BATADV_ORIG_CAPA_HAS_TT ; } static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
@@ -2734,7 +2734,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,return ; } } - orig_node->tt_initialised = true; + orig_node->capa_initialized |=BATADV_ORIG_CAPA_HAS_TT ; } static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
@@ -3224,13 +3224,15 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,uint8_t orig_ttvn = (uint8_t )atomic_read (&orig_node->last_ttvn);struct batadv_tvlv_tt_vlan_data *tt_vlan;bool full_table = true; +bool has_tt_init; tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff; + has_tt_init = orig_node->capa_initialized &BATADV_ORIG_CAPA_HAS_TT ; +/* orig table not initialised AND first diff is in the OGM OR the ttvn * increased by one -> we can apply the attached changes */ -if ((!orig_node->tt_initialised && ttvn ==1 ) || - ttvn - orig_ttvn ==1 ) { +if ((!has_tt_init && ttvn ==1 ) || ttvn - orig_ttvn ==1 ) {/* the OGM could not contain the changes due to their size or * because they have already been sent BATADV_TT_OGM_APPEND_MAX * times.
@@ -3270,7 +3272,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,/* if we missed more than one change or our tables are not * in sync anymore -> request fresh tt data */ -if (!orig_node->tt_initialised || ttvn != orig_ttvn || +if (!has_tt_init || ttvn != orig_ttvn || !batadv_tt_global_check_crc (orig_node, tt_vlan, tt_num_vlan)) { request_table:
types.h +4 -3
@@ -205,13 +205,12 @@ struct batadv_orig_bat_iv {* @last_seen: time when last packet from this node was received * @bcast_seqno_reset: time when the broadcast seqno window was reset * @capabilities: announced capabilities of this originator +* @capa_initialized: bitfield to remember whether a capability was initialized * @last_ttvn: last seen translation table version number * @tt_buff: last tt changeset this node received from the orig node * @tt_buff_len: length of the last tt changeset this node received from the * orig node * @tt_buff_lock: lock that protects tt_buff and tt_buff_len -* @tt_initialised: bool keeping track of whether or not this node have received -* any translation table information from the orig node yet * @tt_lock: prevents from updating the table while reading it. Table update is * made up by two operations (data structure update and metdata -CRC/TTVN- * recalculation) and they have to be executed atomically in order to avoid
@@ -248,11 +247,11 @@ struct batadv_orig_node {unsigned long last_seen;unsigned long bcast_seqno_reset;uint8_t capabilities; +uint8_t capa_initialized;atomic_t last_ttvn;unsigned char *tt_buff;int16_t tt_buff_len;spinlock_t tt_buff_lock;/* protects tt_buff & tt_buff_len */ -bool tt_initialised;/* prevents from changing the table while reading it */ spinlock_t tt_lock;DECLARE_BITMAP (bcast_bits,BATADV_TQ_LOCAL_WINDOW_SIZE );
@@ -282,10 +281,12 @@ struct batadv_orig_node {* enum batadv_orig_capabilities - orig node capabilities * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled +* @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability */ enum batadv_orig_capabilities {BATADV_ORIG_CAPA_HAS_DAT =BIT (0 ),BATADV_ORIG_CAPA_HAS_NC =BIT (1 ), +BATADV_ORIG_CAPA_HAS_TT =BIT (2 ), };/**
Signature · 1 line
1.7.10.4
Marek Lindner
AppliedRe: [B.A.T.M.A.N.] [PATCHv14 2/6] batman-adv: introduce capability initialization bitfield
Quoted 6 lines · On Saturday 15 February 2014 17:47:50 Linus Lüssing wrote:
The new bitfield allows us to keep track whether capability subsets of an originator have gone through their initialization phase yet.
The translation table is the only user right now, but a new one will be added soon.
Quoted 6 lines
Signed-off-by Linus Lüssing <[email protected]>--- originator.c | 1 - translation-table.c | 12 +++++++----- types.h | 7 ++++--- 3 files changed, 11 insertions(+), 9 deletions(-)
Applied in revision 5d2121a.
Thanks,
Marek
PATCH v14 3/6 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 existence of this TVLV signalizes that this node is announcing all of its multicast listeners via the translation table infrastructure.
--- main.c | 1 + multicast.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++--- multicast.h | 14 +++++++ originator.c | 6 +++ packet.h | 12 ++++++ soft-interface.c | 4 ++ types.h | 13 ++++++ 7 files changed, 166 insertions(+), 5 deletions(-)
main.c +1 -0
@@ -149,6 +149,7 @@ int batadv_mesh_init(struct net_device *soft_iface) goto err;batadv_gw_init (bat_priv); +batadv_mcast_init (bat_priv);atomic_set (&bat_priv->gw.reselect,0 );atomic_set (&bat_priv->mesh_state,BATADV_MESH_ACTIVE );
multicast.c +116 -5
147 lines not on this page · raw message
multicast.h +14 -0
@@ -19,8 +19,12 @@void batadv_mcast_mla_update (struct batadv_priv *bat_priv); +void 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_update (struct batadv_priv *bat_priv)
@@ -28,11 +32,21 @@ static inline void batadv_mcast_mla_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_ */
originator.c +6 -0
@@ -27,6 +27,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;
@@ -557,6 +558,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 );
@@ -672,6 +675,9 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, orig_node->tt_buff_len =0 ; reset_time = jiffies -1 -msecs_to_jiffies (BATADV_RESET_PROTECTION_MS ); orig_node->bcast_seqno_reset = reset_time; +#ifdef CONFIG_BATMAN_ADV_MCAST + orig_node->mcast_flags =BATADV_NO_FLAGS ; +#endif /* create a vlan object for the "untagged" LAN */ vlan =batadv_orig_node_vlan_new (orig_node,BATADV_NO_FLAGS );
packet.h +12 -0
@@ -145,6 +145,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 +153,7 @@ enum batadv_tvlv_type {BATADV_TVLV_NC =0x03 ,BATADV_TVLV_TT =0x04 ,BATADV_TVLV_ROAM =0x05 , + BATADV_TVLV_MCAST = 0x06, };#pragma pack(2)
@@ -504,4 +506,14 @@ struct batadv_tvlv_roam_adv { __be16 vid; }; +/** +* struct batadv_tvlv_mcast_data - payload of a multicast tvlv +* @flags: multicast flags announced by the orig node +* @reserved: reserved field +*/ +struct batadv_tvlv_mcast_data { +uint8_t flags; +uint8_t reserved[3 ]; +}; +#endif /* _NET_BATMAN_ADV_PACKET_H_ */
soft-interface.c +4 -0
@@ -689,6 +689,10 @@ 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 + bat_priv->mcast.flags =BATADV_NO_FLAGS ; +atomic_set (&bat_priv->mcast.num_disabled,0 ); +#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 );
types.h +13 -0
@@ -204,6 +204,7 @@ struct batadv_orig_bat_iv {* @batadv_dat_addr_t: address of the orig node in the distributed hash * @last_seen: time when last packet from this node was received * @bcast_seqno_reset: time when the broadcast seqno window was reset +* @mcast_flags: multicast flags announced by the orig node * @capabilities: announced capabilities of this originator * @capa_initialized: bitfield to remember whether a capability was initialized * @last_ttvn: last seen translation table version number
@@ -246,6 +247,9 @@ struct batadv_orig_node {#endif unsigned long last_seen;unsigned long bcast_seqno_reset; +#ifdef CONFIG_BATMAN_ADV_MCAST +uint8_t mcast_flags; +#endif uint8_t capabilities;uint8_t capa_initialized;atomic_t last_ttvn;
@@ -282,11 +286,14 @@ struct batadv_orig_node {* @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled * @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability +* @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability +* (= orig node announces a tvlv of type BATADV_TVLV_MCAST) */ enum batadv_orig_capabilities {BATADV_ORIG_CAPA_HAS_DAT =BIT (0 ),BATADV_ORIG_CAPA_HAS_NC =BIT (1 ),BATADV_ORIG_CAPA_HAS_TT =BIT (2 ), +BATADV_ORIG_CAPA_HAS_MCAST =BIT (3 ), };/**
@@ -612,9 +619,15 @@ struct batadv_priv_dat {/** * struct batadv_priv_mcast - per mesh interface mcast data * @mla_list: list of multicast addresses we are currently announcing via TT +* @flags: the flags we have last sent in our mcast tvlv +* @enabled: whether the multicast tvlv is currently enabled +* @num_disabled: number of nodes that have no mcast tvlv */ struct batadv_priv_mcast {struct hlist_head mla_list; +uint8_t flags; +bool enabled; +atomic_t num_disabled; };#endif
Signature · 1 line
1.7.10.4
Marek Lindner
AppliedRe: [B.A.T.M.A.N.] [PATCHv14 3/6] batman-adv: Announce new capability via multicast TVLV
Quoted 6 lines · On Saturday 15 February 2014 17:47:51 Linus Lüssing wrote:
If the soft interface of a node is not part of a bridge then a node announces a new multicast TVLV: The existence of this TVLV signalizes that this node is announcing all of its multicast listeners via the translation table infrastructure.
Signed-off-by Linus Lüssing <[email protected]>
Quoted 10 lines
--- main.c | 1 + multicast.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++--- multicast.h | 14 +++++++ originator.c | 6 +++ packet.h | 12 ++++++ soft-interface.c | 4 ++ types.h | 13 ++++++ 7 files changed, 166 insertions(+), 5 deletions(-)
Applied in revision 77ec494.
Thanks,
Marek
PATCH v14 4/6 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 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.
--- multicast.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ multicast.h | 25 ++++++++++ send.c | 10 ++-- send.h | 5 ++ soft-interface.c | 20 +++++++- sysfs-class-net-mesh | 9 ++++ sysfs.c | 6 +++ translation-table.c | 92 ++++++++++++++++++++++++++++-------- translation-table.h | 2 + types.h | 7 +++ 10 files changed, 277 insertions(+), 26 deletions(-)
multicast.c +127 -0
@@ -17,6 +17,7 @@#include "originator.h" #include "hard-interface.h" #include "translation-table.h" +#include "multicast.h" /** * batadv_mcast_mla_softif_get - get softif multicast listeners
@@ -271,6 +272,132 @@ out: }/** +* 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 +* +* Check whether the given IPv6 packet has the potential to +* be forwarded with a mode more optimal than classic flooding. +* +* If so then return 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 +* +* Check whether the given multicast ethernet frame has the potential to +* be forwarded with a mode more optimal than classic flooding. +* +* If so then return 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 +* +* Return 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 +* +* Return 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 * @orig: the orig_node of the ogm
multicast.h +25 -0
@@ -15,10 +15,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);
@@ -32,6 +50,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 ;
send.c +5 -5
@@ -248,11 +248,11 @@ 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, -struct sk_buff *skb,int packet_type, -int packet_subtype, -struct batadv_orig_node *orig_node, -unsigned short vid) +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) {struct batadv_unicast_packet *unicast_packet;struct ethhdr *ethhdr;
send.h +5 -0
@@ -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,
soft-interface.c +19 -1
@@ -32,6 +32,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"
@@ -170,6 +171,8 @@ static int batadv_interface_tx(struct sk_buff *skb,unsigned short vid;uint32_t seqno;int gw_mode; +enum batadv_forw_mode forw_mode; +struct batadv_orig_node *mcast_single_orig =NULL ;if (atomic_read (&bat_priv->mesh_state) !=BATADV_MESH_ACTIVE ) goto dropped;
@@ -247,9 +250,19 @@ static int batadv_interface_tx(struct sk_buff *skb,* directed to a DHCP server */ goto dropped; - } send: +if (do_bcast && !is_broadcast_ether_addr (ethhdr->h_dest)) { + forw_mode =batadv_mcast_forw_mode (bat_priv, skb, + &mcast_single_orig); +if (forw_mode ==BATADV_FORW_NONE ) + goto dropped; + +if (forw_mode ==BATADV_FORW_SINGLE ) + do_bcast = false; + } + } +batadv_skb_set_priority (skb,0 );/* ethernet packet should be broadcasted */
@@ -301,6 +314,10 @@ send:if (ret) goto dropped; ret =batadv_send_skb_via_gw (bat_priv, skb, vid); + }else if (mcast_single_orig) { + ret =batadv_send_skb_unicast (bat_priv, skb, +BATADV_UNICAST ,0 , + mcast_single_orig, vid); }else {if (batadv_dat_snoop_outgoing_arp_request (bat_priv, skb))
@@ -691,6 +708,7 @@ static int batadv_softif_init_late(struct net_device *dev)#endif #ifdef CONFIG_BATMAN_ADV_MCAST bat_priv->mcast.flags =BATADV_NO_FLAGS ; +atomic_set (&bat_priv->multicast_mode,1 );atomic_set (&bat_priv->mcast.num_disabled,0 );#endif atomic_set (&bat_priv->gw_mode,BATADV_GW_MODE_OFF );
sysfs-class-net-mesh +9 -0
@@ -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: 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]>
sysfs.c +6 -0
@@ -539,6 +539,9 @@ BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect); 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
@@ -558,6 +561,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,
translation-table.c +72 -20
150 lines not on this page · raw message
translation-table.h +2 -0
@@ -29,6 +29,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,int32_t match_vid,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,
types.h +7 -0
@@ -696,6 +696,8 @@ struct batadv_softif_vlan {* enabled * @distributed_arp_table: bool indicating whether distributed ARP table is * enabled +* @multicast_mode: Enable or disable multicast optimizations on this node's +* sender/originating side * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) * @gw_sel_class: gateway selection class (applies if gw_mode client) * @orig_interval: OGM broadcast interval in milliseconds
@@ -746,6 +748,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;
@@ -909,12 +914,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
Marek Lindner
AppliedRe: [B.A.T.M.A.N.] [PATCHv14 4/6] batman-adv: Modified forwarding behaviour for multicast packets
Quoted 16 lines · On Saturday 15 February 2014 17:47:52 Linus Lüssing wrote:
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 Linus Lüssing <[email protected]>
Quoted 13 lines
--- multicast.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ multicast.h | 25 ++++++++++ send.c | 10 ++-- send.h | 5 ++ soft-interface.c | 20 +++++++- sysfs-class-net-mesh | 9 ++++ sysfs.c | 6 +++ translation-table.c | 92 ++++++++++++++++++++++++++++-------- translation-table.h | 2 + types.h | 7 +++ 10 files changed, 277 insertions(+), 26 deletions(-)
Applied in revision 405cc1e.
Thanks,
Marek
PATCH v14 5/6 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_WANT_ALL_UNSNOOPABLES 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 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 won't be possible to optimize 224.0.0.x and ff02::1 towards nodes with bridges, they will always receive these ranges.
--- main.c | 6 +++ main.h | 1 + multicast.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++---- packet.h | 9 ++++ soft-interface.c | 1 + types.h | 12 +++++ 6 files changed, 156 insertions(+), 8 deletions(-)
main.c +6 -0
@@ -111,6 +111,9 @@ int batadv_mesh_init(struct net_device *soft_iface)spin_lock_init (&bat_priv->tt.last_changeset_lock);spin_lock_init (&bat_priv->tt.commit_lock);spin_lock_init (&bat_priv->gw.list_lock); +#ifdef CONFIG_BATMAN_ADV_MCAST +spin_lock_init (&bat_priv->mcast.want_lists_lock); +#endif spin_lock_init (&bat_priv->tvlv.container_list_lock);spin_lock_init (&bat_priv->tvlv.handler_list_lock);spin_lock_init (&bat_priv->softif_vlan_list_lock);
@@ -118,6 +121,9 @@ int batadv_mesh_init(struct net_device *soft_iface)INIT_HLIST_HEAD (&bat_priv->forw_bat_list);INIT_HLIST_HEAD (&bat_priv->forw_bcast_list);INIT_HLIST_HEAD (&bat_priv->gw.list); +#ifdef CONFIG_BATMAN_ADV_MCAST +INIT_HLIST_HEAD (&bat_priv->mcast.want_all_unsnoopables_list); +#endif INIT_LIST_HEAD (&bat_priv->tt.changes_list);INIT_LIST_HEAD (&bat_priv->tt.req_list);INIT_LIST_HEAD (&bat_priv->tt.roam_list);
main.h +1 -0
@@ -177,6 +177,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>
multicast.c +127 -8
212 lines not on this page · raw message
packet.h +9 -0
@@ -89,6 +89,15 @@ enum batadv_icmp_packettype { BATADV_PARAMETER_PROBLEM = 12, }; +/** +* enum batadv_mcast_flags - flags for multicast capabilities and settings +* @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for +* 224.0.0.0/24 or ff02::1 +*/ +enum batadv_mcast_flags { +BATADV_MCAST_WANT_ALL_UNSNOOPABLES =BIT (0 ), +}; +/* tt data subtypes */ #define BATADV_TT_DATA_TYPE_MASK 0x0F
soft-interface.c +1 -0
@@ -710,6 +710,7 @@ static int batadv_softif_init_late(struct net_device *dev) bat_priv->mcast.flags =BATADV_NO_FLAGS ;atomic_set (&bat_priv->multicast_mode,1 );atomic_set (&bat_priv->mcast.num_disabled,0 ); +atomic_set (&bat_priv->mcast.num_want_all_unsnoopables,0 );#endif atomic_set (&bat_priv->gw_mode,BATADV_GW_MODE_OFF );atomic_set (&bat_priv->gw_sel_class,20 );
types.h +12 -0
@@ -205,6 +205,8 @@ struct batadv_orig_bat_iv {* @last_seen: time when last packet from this node was received * @bcast_seqno_reset: time when the broadcast seqno window was reset * @mcast_flags: multicast flags announced by the orig node +* @mcast_want_all_unsnoop_node: a list node for the +* mcast.want_all_unsnoopables list * @capabilities: announced capabilities of this originator * @capa_initialized: bitfield to remember whether a capability was initialized * @last_ttvn: last seen translation table version number
@@ -249,6 +251,7 @@ struct batadv_orig_node {unsigned long bcast_seqno_reset;#ifdef CONFIG_BATMAN_ADV_MCAST uint8_t mcast_flags; +struct hlist_node mcast_want_all_unsnoopables_node;#endif uint8_t capabilities;uint8_t capa_initialized;
@@ -619,15 +622,24 @@ struct batadv_priv_dat {/** * struct batadv_priv_mcast - per mesh interface mcast data * @mla_list: list of multicast addresses we are currently announcing via TT +* @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable +* multicast traffic * @flags: the flags we have last sent in our mcast tvlv * @enabled: whether the multicast tvlv is currently enabled * @num_disabled: number of nodes that have no mcast tvlv +* @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic +* @want_lists_lock: lock for protecting modifications to mcast want lists +* (traversals are rcu-locked) */ struct batadv_priv_mcast {struct hlist_head mla_list; +struct hlist_head want_all_unsnoopables_list;uint8_t flags;bool enabled;atomic_t num_disabled; +atomic_t num_want_all_unsnoopables; +/* protects want_all_unsnoopables_list */ +spinlock_t want_lists_lock; };#endif
Signature · 1 line
1.7.10.4
Marek Lindner
AppliedRe: [B.A.T.M.A.N.] [PATCHv14 5/6] batman-adv: Add IPv4 link-local/IPv6-ll-all-nodes multicast support
Quoted 20 lines · On Saturday 15 February 2014 17:47:53 Linus Lüssing wrote:
With 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_WANT_ALL_UNSNOOPABLESflag 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 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 won't be possible to optimize 224.0.0.x and ff02::1 towards nodes with bridges, they will always receive these ranges.
Signed-off-by Linus Lüssing <[email protected]>
Quoted 9 lines
--- main.c | 6 +++ main.h | 1 + multicast.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++---- packet.h | 9 ++++ soft-interface.c | 1 + types.h | 12 +++++ 6 files changed, 156 insertions(+), 8 deletions(-)
Applied in revision 1c09034.
Thanks,
Marek
Re: [B.A.T.M.A.N.] [PATCHv14 5/6] batman-adv: Add IPv4 link-local/IPv6-ll-all-nodes multicast support
In reply to Linus LüssingQuoted 12 lines · On Saturday 15 February 2014 17:47:53 Linus Lüssing wrote:
multicast.c +12
-0+static void batadv_mcast_want_unsnoop_update (struct batadv_priv *bat_priv, +struct batadv_orig_node *orig, +uint8_t mcast_flags) +{ +/* switched from flag unset to set */ +if (mcast_flags &BATADV_MCAST_WANT_ALL_UNSNOOPABLES && + !(orig->mcast_flags &BATADV_MCAST_WANT_ALL_UNSNOOPABLES )) { +atomic_inc (&bat_priv->mcast.num_want_all_unsnoopables); + +spin_lock_bh (&bat_priv->mcast.want_lists_lock); +hlist_add_head_rcu (&orig->mcast_want_all_unsnoopables_node, + &bat_priv->mcast.want_all_unsnoopables_list);
multicast.c batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, · line 512
Quoted 10 lines
multicast.c +10
-0+spin_unlock_bh (&bat_priv->mcast.want_lists_lock); +/* switched from flag set to unset */ + }else if (!(mcast_flags &BATADV_MCAST_WANT_ALL_UNSNOOPABLES ) && + orig->mcast_flags &BATADV_MCAST_WANT_ALL_UNSNOOPABLES ) { +atomic_dec (&bat_priv->mcast.num_want_all_unsnoopables); + +spin_lock_bh (&bat_priv->mcast.want_lists_lock); +hlist_del_rcu (&orig->mcast_want_all_unsnoopables_node); +spin_unlock_bh (&bat_priv->mcast.want_lists_lock); + }
Looks unsafe. How do you make sure that it is still in the list and not already already removed in the meantime? hlist_del_rcu does not re-initialize the pointers (only POISON them when CONFIG_DEBUG_LIST is activated). Thus calling hlist_del_rcu again on an object not in the list either kills other data structures or causes an Oops.
There are more *list_del* related problems of that type in your code. This is just one example I've picked.
See http://www.open-mesh.org/issues/217#note-5
Kind regards,
Sven
PATCH v14 6/6 batman-adv: Send multicast packets to nodes with a WANT_ALL flag
In reply to Linus LüssingWith this patch a node sends IPv4 multicast packets to nodes which have a BATADV_MCAST_WANT_ALL_IPV4 flag set and IPv6 multicast packets to nodes which have a BATADV_MCAST_WANT_ALL_IPV6 flag set, too.
Why is this needed? There are scenarios involving bridges where multicast report snooping and multicast TT announcements are not sufficient, which would lead to packet loss for some nodes otherwise:
MLDv1 and IGMPv1/IGMPv2 have a suppression mechanism
for multicast listener reports. When we have an MLDv1/IGMPv1/IGMPv2 querier behind a bridge then our snooping bridge is potentially not going to see any reports even though listeners exist because according to RFC4541 such reports are only forwarded to multicast routers:
-----------------------------------------------------------
---------------
{Querier}---|Snoop. Switch|----{Listener}
---------------
\ ^
-------
| br0 | < ???
-------
\
_-~---~_
_-~/ ~-_
~ batman-adv \-----{Sender}
\~_ cloud ~/
-~~__-__-~_/I) MLDv1 Query: {Querier} -> flooded
II) MLDv1 Report: {Listener} -> {Querier}-> br0 cannot detect the {Listener}
=> Packets from {Sender} need to be forwarded to all
detected listeners and MLDv1/IGMPv1/IGMPv2 queriers.
-----------------------------------------------------------
Note that we do not need to explicitly forward to MLDv2/IGMPv3 queriers, because these protocols have no report suppression: A bridge has no trouble detecting MLDv2/IGMPv3 listeners.
Even though we do not support bridges yet we need to provide the according infrastructure already to not break compatibility later.
--- main.c | 2 + multicast.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++- packet.h | 4 ++ send.c | 1 + soft-interface.c | 2 + types.h | 14 ++++- 6 files changed, 198 insertions(+), 3 deletions(-)
main.c +2 -0
@@ -123,6 +123,8 @@ int batadv_mesh_init(struct net_device *soft_iface)INIT_HLIST_HEAD (&bat_priv->gw.list);#ifdef CONFIG_BATMAN_ADV_MCAST INIT_HLIST_HEAD (&bat_priv->mcast.want_all_unsnoopables_list); +INIT_HLIST_HEAD (&bat_priv->mcast.want_all_ipv4_list); +INIT_HLIST_HEAD (&bat_priv->mcast.want_all_ipv6_list);#endif INIT_LIST_HEAD (&bat_priv->tt.changes_list);INIT_LIST_HEAD (&bat_priv->tt.req_list);
multicast.c +176 -2
226 lines not on this page · raw message
packet.h +4 -0
@@ -93,9 +93,13 @@ enum batadv_icmp_packettype {* enum batadv_mcast_flags - flags for multicast capabilities and settings * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for * 224.0.0.0/24 or ff02::1 +* @BATADV_MCAST_WANT_ALL_IPV4: we want all IPv4 multicast packets +* @BATADV_MCAST_WANT_ALL_IPV6: we want all IPv6 multicast packets */ enum batadv_mcast_flags {BATADV_MCAST_WANT_ALL_UNSNOOPABLES =BIT (0 ), +BATADV_MCAST_WANT_ALL_IPV4 =BIT (1 ), +BATADV_MCAST_WANT_ALL_IPV6 =BIT (2 ), };/* tt data subtypes */
send.c +1 -0
@@ -27,6 +27,7 @@#include "originator.h" #include "network-coding.h" #include "fragmentation.h" +#include "multicast.h" static void batadv_send_outstanding_bcast_packet (struct work_struct *work);
soft-interface.c +2 -0
@@ -711,6 +711,8 @@ static int batadv_softif_init_late(struct net_device *dev)atomic_set (&bat_priv->multicast_mode,1 );atomic_set (&bat_priv->mcast.num_disabled,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_ipv6,0 );#endif atomic_set (&bat_priv->gw_mode,BATADV_GW_MODE_OFF );atomic_set (&bat_priv->gw_sel_class,20 );
types.h +13 -1
@@ -207,6 +207,8 @@ struct batadv_orig_bat_iv {* @mcast_flags: multicast flags announced by the orig node * @mcast_want_all_unsnoop_node: a list node for the * mcast.want_all_unsnoopables list +* @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list +* @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list * @capabilities: announced capabilities of this originator * @capa_initialized: bitfield to remember whether a capability was initialized * @last_ttvn: last seen translation table version number
@@ -252,6 +254,8 @@ struct batadv_orig_node {#ifdef CONFIG_BATMAN_ADV_MCAST uint8_t mcast_flags;struct hlist_node mcast_want_all_unsnoopables_node; +struct hlist_node mcast_want_all_ipv4_node; +struct hlist_node mcast_want_all_ipv6_node;#endif uint8_t capabilities;uint8_t capa_initialized;
@@ -624,21 +628,29 @@ struct batadv_priv_dat {* @mla_list: list of multicast addresses we are currently announcing via TT * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable * multicast traffic +* @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic +* @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic * @flags: the flags we have last sent in our mcast tvlv * @enabled: whether the multicast tvlv is currently enabled * @num_disabled: number of nodes that have no mcast tvlv * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic +* @num_want_all_ipv4: counter for items in want_all_ipv4_list +* @num_want_all_ipv6: counter for items in want_all_ipv6_list * @want_lists_lock: lock for protecting modifications to mcast want lists * (traversals are rcu-locked) */ struct batadv_priv_mcast {struct hlist_head mla_list;struct hlist_head want_all_unsnoopables_list; +struct hlist_head want_all_ipv4_list; +struct hlist_head want_all_ipv6_list;uint8_t flags;bool enabled;atomic_t num_disabled;atomic_t num_want_all_unsnoopables; -/* protects want_all_unsnoopables_list */ +atomic_t num_want_all_ipv4; +atomic_t num_want_all_ipv6; +/* protects want_all_{unsnoopables,ipv4,ipv6}_list */ spinlock_t want_lists_lock; };#endif
Signature · 1 line
1.7.10.4
Marek Lindner
AppliedRe: [B.A.T.M.A.N.] [PATCHv14 6/6] batman-adv: Send multicast packets to nodes with a WANT_ALL flag
Quoted 46 lines · On Saturday 15 February 2014 17:47:54 Linus Lüssing wrote:
With this patch a node sends IPv4 multicast packets to nodes which have a
BATADV_MCAST_WANT_ALL_IPV4flag set and IPv6 multicast packets to nodes which have aBATADV_MCAST_WANT_ALL_IPV6flag set, too.Why is this needed? There are scenarios involving bridges where multicast report snooping and multicast TT announcements are not sufficient, which would lead to packet loss for some nodes otherwise:
MLDv1 and IGMPv1/IGMPv2 have a suppression mechanism
for multicast listener reports. When we have an MLDv1/IGMPv1/IGMPv2 querier behind a bridge then our snooping bridge is potentially not going to see any reports even though listeners exist because according to RFC4541 such reports are only forwarded to multicast routers:-----------------------------------------------------------
--------------- {Querier}---|Snoop. Switch|----{Listener} --------------- \ ^ ------- | br0 | < ??? ------- \ _-~---~_ _-~/ ~-_ ~ batman-adv \-----{Sender} \~_ cloud ~/ -~~__-__-~_/I) MLDv1 Query: {Querier} -> flooded II) MLDv1 Report: {Listener} -> {Querier}-> br0 cannot detect the {Listener}
=> Packets from {Sender} need to be forwarded to all
detected listeners and MLDv1/IGMPv1/IGMPv2 queriers.-----------------------------------------------------------
Note that we do not need to explicitly forward to MLDv2/IGMPv3 queriers, because these protocols have no report suppression: A bridge has no trouble detecting MLDv2/IGMPv3 listeners.
Even though we do not support bridges yet we need to provide the according infrastructure already to not break compatibility later.
Signed-off-by Linus Lüssing <[email protected]>
Quoted 9 lines
--- main.c | 2 + multicast.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++- packet.h | 4 ++ send.c | 1 + soft-interface.c | 2 + types.h | 14 ++++- 6 files changed, 198 insertions(+), 3 deletions(-)
Applied in revision 02705e4.
Thanks,
Marek