bridge loop avoidance (v3)
Hi,
the received comments motivated me to reword the commit messages to outline that the loop is caused by bridging the payload traffic and not by the LAN itself. Furthermore, the locking has been cleaned up and the neighbor list is purged when the module is unloaded.
Let me know if you have additional questions,
Marek
PATCH v3 1/2 batman-adv: softif bridge loop avoidance
By connecting multiple batman-adv mesh nodes to the same ethernet segment a loop can be created when the soft-interface is bridged into that ethernet segment. A simple visualization of the loop involving the most common case - a LAN as ethernet segment:
node1 <-- LAN --> node2
| | wifi <-- mesh --> wifi
Packets from the LAN (e.g. ARP broadcasts) will circle forever from node1 or node2 over the mesh back into the LAN.
This patch adds the functionality to detect other batman-adv nodes connected to the LAN and select a 'gateway' to talk to the non-batman-adv devices on this LAN. All traffic from and to the mesh will be handled by this gateway to avoid the loop. OGMs received via the soft-interface are interpreted as 'port announcements' to locate potential batman-adv nodes. The patch can also deal with vlans on top of batX and offers a list of LAN neighbors via debugfs.
--- batman-adv/bat_debugfs.c | 9 ++ batman-adv/main.c | 4 + batman-adv/main.h | 2 + batman-adv/originator.c | 3 + batman-adv/routing.c | 12 +- batman-adv/routing.h | 2 + batman-adv/soft-interface.c | 308 +++++++++++++++++++++++++++++++++++++++++-- batman-adv/soft-interface.h | 5 +- batman-adv/types.h | 12 ++ 9 files changed, 340 insertions(+), 17 deletions(-)
batman-adv/bat_debugfs.c +9 -0
@@ -29,6 +29,7 @@#include "hard-interface.h" #include "gateway_common.h" #include "gateway_client.h" +#include "soft-interface.h" #include "vis.h" #include "icmp_socket.h" #include "compat.h"
@@ -236,6 +237,12 @@ static int gateways_open(struct inode *inode, struct file *file)return single_open (file, gw_client_seq_print_text, net_dev); } +static int softif_neigh_open (struct inode *inode,struct file *file) +{ +struct net_device *net_dev = (struct net_device *)inode->i_private; +return single_open (file, softif_neigh_seq_print_text, net_dev); +} +static int transtable_global_open (struct inode *inode,struct file *file) {struct net_device *net_dev = (struct net_device *)inode->i_private;
@@ -273,6 +280,7 @@ struct bat_debuginfo bat_debuginfo_##_name = { \ static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); +static BAT_DEBUGINFO(softif_neigh, S_IRUGO, softif_neigh_open); static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open); static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open);
@@ -280,6 +288,7 @@ static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open);static struct bat_debuginfo *mesh_debuginfos[] = { &bat_debuginfo_originators, &bat_debuginfo_gateways, + &bat_debuginfo_softif_neigh, &bat_debuginfo_transtable_global, &bat_debuginfo_transtable_local, &bat_debuginfo_vis_data,
batman-adv/main.c +4 -0
@@ -89,10 +89,12 @@ int mesh_init(struct net_device *soft_iface)spin_lock_init (&bat_priv->gw_list_lock);spin_lock_init (&bat_priv->vis_hash_lock);spin_lock_init (&bat_priv->vis_list_lock); +spin_lock_init (&bat_priv->softif_neigh_lock);INIT_HLIST_HEAD (&bat_priv->forw_bat_list);INIT_HLIST_HEAD (&bat_priv->forw_bcast_list);INIT_HLIST_HEAD (&bat_priv->gw_list); +INIT_HLIST_HEAD (&bat_priv->softif_neigh_list);if (originator_init (bat_priv) <1 ) goto err;
@@ -137,6 +139,8 @@ void mesh_free(struct net_device *soft_iface)hna_local_free (bat_priv);hna_global_free (bat_priv); +softif_neigh_purge (bat_priv); +atomic_set (&bat_priv->mesh_state,MESH_INACTIVE ); }
batman-adv/main.h +2 -0
@@ -72,6 +72,8 @@* forw_packet->direct_link_flags */ #define MAX_AGGREGATION_MS 100 +#define SOFTIF_NEIGH_TIMEOUT 180000/* 3 minutes */ +#define RESET_PROTECTION_MS 30000#define EXPECTED_SEQNO_RANGE 65536/* don't reset again within 30 seconds */
batman-adv/originator.c +3 -0
@@ -30,6 +30,7 @@#include "gateway_client.h" #include "hard-interface.h" #include "unicast.h" +#include "soft-interface.h" static void purge_orig (struct work_struct *work);
@@ -292,6 +293,8 @@ static void _purge_orig(struct bat_priv *bat_priv)gw_node_purge_deleted (bat_priv);gw_election (bat_priv); + +softif_neigh_purge (bat_priv); }static void purge_orig (struct work_struct *work)
batman-adv/routing.c +6 -6
@@ -1133,8 +1133,8 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size)return 0 ; } -static int route_unicast_packet (struct sk_buff *skb, -struct batman_if *recv_if,int hdr_size) +int route_unicast_packet (struct sk_buff *skb,struct batman_if *recv_if, +int hdr_size) {struct bat_priv *bat_priv =netdev_priv (recv_if->soft_iface);struct orig_node *orig_node;
@@ -1202,7 +1202,7 @@ static int route_unicast_packet(struct sk_buff *skb,return NET_RX_SUCCESS ; skb = new_skb; - unicast_packet = (struct unicast_packet *) skb->data; + unicast_packet = (struct unicast_packet *)skb->data; }/* decrement ttl */
@@ -1226,7 +1226,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)/* packet for me */ if (is_my_mac (unicast_packet->dest)) { -interface_rx (recv_if->soft_iface, skb, hdr_size); +interface_rx (recv_if->soft_iface, skb, recv_if, hdr_size);return NET_RX_SUCCESS ; }
@@ -1258,7 +1258,7 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)if (!new_skb)return NET_RX_SUCCESS ; -interface_rx (recv_if->soft_iface, new_skb, +interface_rx (recv_if->soft_iface, new_skb, recv_if,sizeof (struct unicast_packet ));return NET_RX_SUCCESS ; }
@@ -1340,7 +1340,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)add_bcast_packet_to_list (bat_priv, skb);/* broadcast for me */ -interface_rx (recv_if->soft_iface, skb, hdr_size); +interface_rx (recv_if->soft_iface, skb, recv_if, hdr_size);return NET_RX_SUCCESS ; }
batman-adv/routing.h +2 -0
@@ -32,6 +32,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,void update_routes (struct bat_priv *bat_priv,struct orig_node *orig_node,struct neigh_node *neigh_node,unsigned char *hna_buff,int hna_buff_len); +int route_unicast_packet (struct sk_buff *skb,struct batman_if *recv_if, +int hdr_size);int recv_icmp_packet (struct sk_buff *skb,struct batman_if *recv_if);int recv_unicast_packet (struct sk_buff *skb,struct batman_if *recv_if);int recv_ucast_frag_packet (struct sk_buff *skb,struct batman_if *recv_if);
batman-adv/soft-interface.c +298 -10
367 lines not on this page · raw message
batman-adv/soft-interface.h +4 -1
@@ -23,9 +23,12 @@#define _NET_BATMAN_ADV_SOFT_INTERFACE_H_int my_skb_head_push (struct sk_buff *skb,unsigned int len); +int softif_neigh_seq_print_text (struct seq_file *seq,void *offset); +void softif_neigh_purge (struct bat_priv *bat_priv);int interface_tx (struct sk_buff *skb,struct net_device *soft_iface);void interface_rx (struct net_device *soft_iface, -struct sk_buff *skb,int hdr_size); +struct sk_buff *skb,struct batman_if *recv_if, +int hdr_size);struct net_device *softif_create (char *name);void softif_destroy (struct net_device *soft_iface);
batman-adv/types.h +12 -0
@@ -134,6 +134,8 @@ struct bat_priv {atomic_t bcast_queue_left;atomic_t batman_queue_left;char num_ifaces; +struct hlist_head softif_neigh_list; +struct softif_neigh *softif_neigh;struct debug_log *debug_log;struct batman_if *primary_if;struct kobject *mesh_obj;
@@ -154,6 +156,7 @@ struct bat_priv {spinlock_t gw_list_lock;/* protects gw_list */ spinlock_t vis_hash_lock;/* protects vis_hash */ spinlock_t vis_list_lock;/* protects vis_info::recv_list */ +spinlock_t softif_neigh_lock;/* protects soft-interface neigh list */ int16_t num_local_hna;atomic_t hna_local_changed;struct delayed_work hna_work;
@@ -253,4 +256,13 @@ struct recvlist_node { uint8_t mac[ETH_ALEN]; }; +struct softif_neigh { +struct hlist_node list; +uint8_t addr[ETH_ALEN ]; +unsigned long last_seen; +short vid; +struct kref refcount; +struct rcu_head rcu; +}; +#endif /* _NET_BATMAN_ADV_TYPES_H_ */
Signature · 1 line
1.7.1
PATCH v3 2/2 batctl: display soft-interface neighbor table
In reply to Marek Lindner--- batctl/debug.c | 9 +++++++++ batctl/debug.h | 2 ++ batctl/main.c | 6 ++++++ batctl/man/batctl.8 | 3 +++ 4 files changed, 20 insertions(+), 0 deletions(-)
batctl/debug.c +9 -0
@@ -61,6 +61,15 @@ void trans_global_usage(void)printf (" \t -w [interval] watch mode - refresh the global translation table continuously\n" ); } +void softif_neigh_usage (void ) +{ +printf ("Usage: batctl [options] softif_neigh \n" ); +printf ("options:\n" ); +printf (" \t -h print this help\n" ); +printf (" \t -n don't replace mac addresses with bat-host names\n" ); +printf (" \t -w [interval] watch mode - refresh the soft-interface neighbor table continuously\n" ); +} +void gateways_usage (void ) {printf ("Usage: batctl [options] gateways \n" );
batctl/debug.h +2 -0
@@ -24,6 +24,7 @@#define DEBUG_ORIGINATORS "originators"#define DEBUG_TRANSTABLE_LOCAL "transtable_local"#define DEBUG_TRANSTABLE_GLOBAL "transtable_global" +#define DEBUG_SOFTIF_NEIGH "softif_neigh"#define DEBUG_GATEWAYS "gateways"#define DEBUG_VIS_DATA "vis_data"#define DEBUG_LOG "log"
@@ -31,6 +32,7 @@void originators_usage (void );void trans_local_usage (void );void trans_global_usage (void ); +void softif_neigh_usage (void );void gateways_usage (void );int handle_debug_table (char *mesh_iface,int argc,char **argv,char *file_path,void table_usage (void ));
batctl/main.c +6 -0
@@ -52,6 +52,7 @@ void print_usage(void) {printf (" \tgateways|gwl \tdisplay the gateway server list\n" );printf (" \ttranslocal|tl \tdisplay the local translation table\n" );printf (" \ttransglobal|tg \tdisplay the global translation table\n" ); +printf (" \tsoftif_neigh|sn \tdisplay the soft-interface neighbor table\n" );printf (" \tvis_mode|vm [mode] \tdisplay or modify the status of the VIS server\n" );printf (" \tvis_data|vd [dot|JSON] \tdisplay the VIS data in dot or JSON format\n" );printf (" \taggregation|ag [0|1] \tdisplay or modify the packet aggregation setting\n" );
@@ -136,6 +137,11 @@ int main(int argc, char **argv) ret =handle_debug_table (mesh_iface, argc -1 , argv +1 ,DEBUG_TRANSTABLE_GLOBAL , trans_global_usage); + }else if ((strcmp (argv[1 ],"softif_neigh" ) ==0 ) || (strcmp (argv[1 ],"sn" ) ==0 )) { + + ret =handle_debug_table (mesh_iface, argc -1 , argv +1 , +DEBUG_SOFTIF_NEIGH , softif_neigh_usage); + }else if ((strcmp (argv[1 ],"loglevel" ) ==0 ) || (strcmp (argv[1 ],"ll" ) ==0 )) { ret =handle_loglevel (mesh_iface, argc -1 , argv +1 );
batctl/man/batctl.8 +3 -0
@@ -121,6 +121,9 @@ Display the local translation table. batctl will refresh the list every second i .IP "\fBtransglobal\fP|\fBtg\fP [\fB\-w\fP [\fI\interval\fP]][\fB\-n\fP]" Display the global translation table. batctl will refresh the list every second if the "\-w" option was given or add a number to let it refresh at a custom interval in seconds (with optional decimal places). Use "\-n" to let batctl not replace the MAC addresses with bat\-host names in the output. .br +.IP "\fBsoftif_neigh\fP|\fBsn\fP [\fB\-w\fP [\fI\interval\fP]][\fB\-n\fP]" +Display the soft\-interface neighbor table. batctl will refresh the list every second if the "\-w" option was given or add a number to let it refresh at a custom interval in seconds (with optional decimal places). Use "\-n" to let batctl not replace the MAC addresses with bat\-host names in the output. +.br .IP "\fBvis_mode|vm\fP [\fBmode\fP]\fP" If no parameter is given the current vis mode is displayed otherwise the parameter is used to set the vis mode. .br
Signature · 1 line
1.7.1
Quoted 4 lines · On Wednesday 29 September 2010 15:20:13 Marek Lindner wrote:
the received comments motivated me to reword the commit messages to outline that the loop is caused by bridging the payload traffic and not by the LAN itself. Furthermore, the locking has been cleaned up and the neighbor list is purged when the module is unloaded.
Since no more new questions came up I merged the patches into trunk (revision 1816-1817).
Regards,
Marek