[B.A.T.M.A.N.] [PATCH 1/2] batman-adv: Add wrapper for ARP reply creation
Removing duplicate code. Signed-off-by: Linus Lüssing --- Changes in RFC -> non-RFC: * Added kerneldoc * Added Signed-off-by net/batman-adv/distributed-arp-table.c | 61 ++ 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index fa76465..66114af 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -948,6 +948,41 @@ static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size) } /** + * batadv_dat_arp_create_reply - create an ARP Reply + * @bat_priv: the bat priv with all the soft interface information + * @ip_src: ARP sender IP + * @ip_dst: ARP target IP + * @hw_src: Ethernet source and ARP sender MAC + * @hw_dst: Ethernet destination and ARP target MAC + * @vid: VLAN identifier (optional, set to zero otherwise) + * + * Creates an ARP Reply from the given values, optionally encapsulated in a + * VLAN header. + * + * Return: An skb containing an ARP Reply. + */ +static struct sk_buff * +batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src, + __be32 ip_dst, u8 *hw_src, u8 *hw_dst, + unsigned short vid) +{ + struct sk_buff *skb; + + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_dst, bat_priv->soft_iface, +ip_src, hw_dst, hw_src, hw_dst); + if (!skb) + return NULL; + + if (vid & BATADV_VLAN_HAS_TAG) + skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), + vid & VLAN_VID_MASK); + + skb_reset_mac_header(skb); + + return skb; +} + +/** * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to * answer using DAT * @bat_priv: the bat priv with all the soft interface information @@ -1005,17 +1040,12 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, goto out; } - skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, -bat_priv->soft_iface, ip_dst, hw_src, -dat_entry->mac_addr, hw_src); + skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src, + dat_entry->mac_addr, + hw_src, vid); if (!skb_new) goto out; - if (vid & BATADV_VLAN_HAS_TAG) - skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q), - vid & VLAN_VID_MASK); - - skb_reset_mac_header(skb_new); skb_new->protocol = eth_type_trans(skb_new, bat_priv->soft_iface); bat_priv->stats.rx_packets++; @@ -1079,22 +1109,11 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, if (!dat_entry) goto out; - skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, -bat_priv->soft_iface, ip_dst, hw_src, -dat_entry->mac_addr, hw_src); - + skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src, + dat_entry->mac_addr, hw_src, vid); if (!skb_new) goto out; - /* the rest of the TX path assumes that the mac_header offset pointing -* to the inner Ethernet header has been set, therefore reset it now. -*/ - skb_reset_mac_header(skb_new); - - if (vid & BATADV_VLAN_HAS_TAG) - skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q), - vid & VLAN_VID_MASK); - /* To preserve backwards compatibility, the node has choose the outgoing * format based on the incoming request packet type. The assumption is * that a node not using the 4addr packet format doesn't support it. -- 2.1.4
[B.A.T.M.A.N.] [PATCH 2/2] batman-adv: Snoop DHCPACKs for DAT
In a typical mesh network, when a new client connects then it will usually first try to grab an IPv4 address via DHCP. Afterwards in public mesh networks a client will try to contact the internet over the server. While the IPv4 address of the DHCP-Server is usually well propagated in the DHT, the IPv4 address of a newly joining client is not. This can lead to a considerable amount of ARP broadcasts not caught by DAT from the servers. In a 1000 nodes mesh network (Freifunk Hamburg) we can still see 30KBit/s of ARP traffic (equalling about 25% of all layer two specific overhead, remaining after some filtering) flooded through the mesh. These 30KBit/s are mainly ARP Requests from the gateways / DHCP servers. Through snooping DHCPACKs we can actually learn about MAC/IP address pairs without the need of any flooded ARP messages in advance. This allows servers to fill their local DAT cache with according entries before any communciation with a client can possibly have taken place. Signed-off-by: Linus Lüssing --- Changes in RFC -> non-RFC * Added kerneldoc * Added Signed-off-by * More IP Header checks (iph->hlen considered, ip version checked, ...) * Parsing & checking DHCP Message Type Option, only snooping DHCPACKs now * Moved ethernet protocol check from batadv_dat_check_dhcp to batadv_dat_check_dhcp_ipudp * Removed buffer-length parameter from batadv_dat_dhcp_get_{yiaddr,chaddr}() * Renamed batadv_dat_put() to batadv_dat_put_pairs() net/batman-adv/distributed-arp-table.c | 297 + net/batman-adv/distributed-arp-table.h | 4 + net/batman-adv/packet.h| 48 ++ net/batman-adv/soft-interface.c| 11 +- 4 files changed, 358 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 66114af..3a66d4b 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -40,8 +41,10 @@ #include #include #include +#include #include #include +#include #include "hard-interface.h" #include "hash.h" @@ -973,6 +976,8 @@ batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src, if (!skb) return NULL; + skb_set_network_header(skb, ETH_HLEN); + if (vid & BATADV_VLAN_HAS_TAG) skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), vid & VLAN_VID_MASK); @@ -1237,6 +1242,298 @@ out: } /** + * batadv_dat_check_dhcp_ipudp - check skb for IP+UDP headers valid for DHCP + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * + * Checks whether the given skb has an IP and UDP header valid for a DHCP + * message from a DHCP server. + * + * Return: True if valid, false otherwise. + */ +static bool batadv_dat_check_dhcp_ipudp(struct sk_buff *skb) +{ + struct iphdr *iphdr, _iphdr; + struct udphdr *udphdr, _udphdr; + unsigned int offset = skb_network_offset(skb); + + iphdr = skb_header_pointer(skb, offset, sizeof(_iphdr), &_iphdr); + if (!iphdr || iphdr->version != 4 || ip_hdrlen(skb) < sizeof(_iphdr)) + return false; + + if (iphdr->protocol != IPPROTO_UDP) + return false; + + offset += ip_hdrlen(skb); + skb_set_transport_header(skb, offset); + + udphdr = skb_header_pointer(skb, offset, sizeof(_udphdr), &_udphdr); + if (!udphdr || udphdr->source != htons(67)) + return false; + + return true; +} + +/** + * batadv_dat_check_dhcp - examine packet for valid DHCP message + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * + * Checks whether the given skb is a valid DHCP packet. + * + * Caller needs to ensure that the skb network header is set correctly. + * + * Return: If skb is a valid DHCP packet, then returns its op code + * (e.g. BOOTREPLY vs. BOOTREQUEST). Otherwise returns -EINVAL. + */ +static int batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto) +{ + u8 *op, _op; + u8 *htype, _htype; + u8 *hlen, _hlen; + __be32 *magic, _magic; + unsigned int dhcp_offset; + unsigned int offset; + + if (proto != htons(ETH_P_IP)) + return -EINVAL; + + if (!batadv_dat_check_dhcp_ipudp(skb)) + return -EINVAL; + + dhcp_offset = skb_transport_offset(skb) + sizeof(struct udphdr); + if (skb->len < dhcp_offset + sizeof(struct batadv_dhcp_packet)) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, op); + + op = skb_header_pointer(skb, offset, sizeof(_op), &_op); + if (!op) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, htype); + + htype = skb_header_pointer(skb, o
Re: [B.A.T.M.A.N.] pull request for net-next: batman-adv 2016-07-01
From: Simon Wunderlich Date: Fri, 1 Jul 2016 15:08:52 +0200 > we are a bit late to submit our feature patches, but I hope we make it in > time. > Antonio is taking a pause in his upstream work, so I'll be submitting our > batman-adv patches for now. It is my first time, so please bear with me. :) > > Please pull or let me know of any problem! Pulled, thanks.
Re: [B.A.T.M.A.N.] [PATCH 02/17] batman-adv: statically print gateway table header
On Fri, 2016-07-01 at 15:08 +0200, Simon Wunderlich wrote: > To make it easier to search through the code it is better to print static > strings directly instead of using format strings printing constants. It's also generally smaller object code and faster at runtime. $ size net/batman-adv/gateway_client.o* text data bss dec hex filename 4898 1 0 4899 1323 net/batman-adv/gateway_client.o.new 4951 1 0 4952 1358 net/batman-adv/gateway_client.o.old
Re: [B.A.T.M.A.N.] [PATCH v5 0/6] Optimizations for setups running dat and bla
On Monday 13 June 2016 11:01:54 Sven Eckelmann wrote: > On Monday 13 June 2016 10:06:55 Andreas Pape wrote: > > > Btw. there seems to be an "a" missing in "enabled" of the Subject > > > of the first patch :) > > > > Will be corrected as there's another version obviously necessary ...;-) > > Maybe there are other comments from Simon oder Antonio. But I think there > are still open questions from them as reply to the patches for v3 of the > patchset. At least I cannot find any replies on the mailing list. Hi Andreas, sorry for the late review. I think we are through from my end, your patches mostly require a rebase and some small change. I'd also drop one of the patches and submit them separately to get the other patches through. Thanks! Simon signature.asc Description: This is a digitally signed message part.
Re: [B.A.T.M.A.N.] [PATCH v5 3/6] batman-adv: prevent duplication of ARP replies when DAT is used
On Friday 10 June 2016 13:11:01 Andreas Pape wrote: > If none of the backbone gateways in a bla setup has already knowledge of > the mac address searched for in an incoming ARP request from the backbone > an address resolution via the DHT of DAT is started. The gateway can send > several ARP requests to different DHT nodes and therefore can get several > replies. This patch assures that not all of the possible ARP replies are > returned to the backbone by checking the local DAT cache of the gateway. > If there is an entry in the local cache the gateway has already learned > the requested address and there is no need to forward the additional reply > to the backbone. > Furthermore it is checked if this gateway has claimed the source of the ARP > reply and only forwards it to the backbone if it has claimed the source or > if there is no claim at all. Acked-by: Simon Wunderlich but one small style suggestion below: > > Signed-off-by: Andreas Pape > --- > net/batman-adv/distributed-arp-table.c | 32 > 1 files changed, 32 insertions(+), 0 > deletions(-) > > diff --git a/net/batman-adv/distributed-arp-table.c > b/net/batman-adv/distributed-arp-table.c index 998a4b8..e7b054a 100644 > --- a/net/batman-adv/distributed-arp-table.c > +++ b/net/batman-adv/distributed-arp-table.c > @@ -1244,6 +1244,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct > batadv_priv *bat_priv, __be32 ip_src, ip_dst; > u8 *hw_src, *hw_dst; > bool dropped = false; > + struct batadv_dat_entry *dat_entry = NULL; > unsigned short vid; > > if (!atomic_read(&bat_priv->distributed_arp_table)) > @@ -1263,12 +1264,41 @@ bool batadv_dat_snoop_incoming_arp_reply(struct > batadv_priv *bat_priv, hw_dst = batadv_arp_hw_dst(skb, hdr_size); > ip_dst = batadv_arp_ip_dst(skb, hdr_size); > > + /* If ip_dst is already in cache and has the right mac address, > + * drop this frame if this ARP reply is destined for us because it's > + * most probably an ARP reply generated by another node of the DHT. > + * We have most probably received already a reply earlier. Delivering > + * this frame would lead to doubled receive of an ARP reply. > + */ > + dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_src, vid); > + if ((dat_entry) && (batadv_compare_eth(hw_src, dat_entry->mac_addr))) { you can drop the braces for dat_entry and batadv_compare_eth here. Cheers, Simon signature.asc Description: This is a digitally signed message part.
Re: [B.A.T.M.A.N.] [PATCH v3 2/4] batman-adv: Fix non-atomic bla_claim::backbone_gw access
On Friday 01 July 2016 15:49:43 Sven Eckelmann wrote: > The pointer batadv_bla_claim::backbone_gw can be changed at any time. > Therefore, access to it must be protected to ensure that two function > accessing the same backbone_gw are actually accessing the same. This is > especially important when the crc_lock is used or when the backbone_gw of a > claim is exchanged. > > Not doing so leads to invalid memory access and/or reference leaks. > > Fixes: a9ce0dc43e2c ("batman-adv: add basic bridge loop avoidance code") > Fixes: b307e72d119f ("batman-adv: lock crc access in bridge loop avoidance") > Signed-off-by: Sven Eckelmann Acked-by: Simon Wunderlich Thanks, Simon signature.asc Description: This is a digitally signed message part.
Re: [B.A.T.M.A.N.] [PATCH v5 1/6] batman-adv: prevent multiple ARP replies sent by gateways if dat enbled
On Friday 10 June 2016 13:10:59 Andreas Pape wrote: > If dat is enabled it must be made sure that only the backbone gw which has > claimed the remote destination for the ARP request answers the ARP request > directly if the MAC address is known due to the local dat table. This > prevents multiple ARP replies in a common backbone if more than one > gateway already knows the remote mac searched for in the ARP request. > > Signed-off-by: Andreas Pape Acked-by: Simon Wunderlich Please add my Acked-by on resend. Thanks! Simon signature.asc Description: This is a digitally signed message part.
[B.A.T.M.A.N.] [PATCH v3 2/4] batman-adv: Fix non-atomic bla_claim::backbone_gw access
The pointer batadv_bla_claim::backbone_gw can be changed at any time. Therefore, access to it must be protected to ensure that two function accessing the same backbone_gw are actually accessing the same. This is especially important when the crc_lock is used or when the backbone_gw of a claim is exchanged. Not doing so leads to invalid memory access and/or reference leaks. Fixes: a9ce0dc43e2c ("batman-adv: add basic bridge loop avoidance code") Fixes: b307e72d119f ("batman-adv: lock crc access in bridge loop avoidance") Signed-off-by: Sven Eckelmann --- v3: - rename batadv_bla_claim_backbone_gw to batadv_bla_claim_get_backbone_gw v2: - Move backbone release of claim to batadv_claim_release - added kerneldoc for backbone_lock --- net/batman-adv/bridge_loop_avoidance.c | 111 ++--- net/batman-adv/types.h | 2 + 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 748a9ea..a796bde 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -177,10 +177,21 @@ static void batadv_backbone_gw_put(struct batadv_bla_backbone_gw *backbone_gw) static void batadv_claim_release(struct kref *ref) { struct batadv_bla_claim *claim; + struct batadv_bla_backbone_gw *old_backbone_gw; claim = container_of(ref, struct batadv_bla_claim, refcount); - batadv_backbone_gw_put(claim->backbone_gw); + spin_lock_bh(&claim->backbone_lock); + old_backbone_gw = claim->backbone_gw; + claim->backbone_gw = NULL; + spin_unlock_bh(&claim->backbone_lock); + + spin_lock_bh(&old_backbone_gw->crc_lock); + old_backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); + spin_unlock_bh(&old_backbone_gw->crc_lock); + + batadv_backbone_gw_put(old_backbone_gw); + kfree_rcu(claim, rcu); } @@ -674,8 +685,10 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, const u8 *mac, const unsigned short vid, struct batadv_bla_backbone_gw *backbone_gw) { + struct batadv_bla_backbone_gw *old_backbone_gw; struct batadv_bla_claim *claim; struct batadv_bla_claim search_claim; + bool remove_crc = false; int hash_added; ether_addr_copy(search_claim.addr, mac); @@ -689,8 +702,10 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, return; ether_addr_copy(claim->addr, mac); + spin_lock_init(&claim->backbone_lock); claim->vid = vid; claim->lasttime = jiffies; + kref_get(&backbone_gw->refcount); claim->backbone_gw = backbone_gw; kref_init(&claim->refcount); @@ -718,15 +733,26 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, "bla_add_claim(): changing ownership for %pM, vid %d\n", mac, BATADV_PRINT_VID(vid)); - spin_lock_bh(&claim->backbone_gw->crc_lock); - claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); - spin_unlock_bh(&claim->backbone_gw->crc_lock); - batadv_backbone_gw_put(claim->backbone_gw); + remove_crc = true; } - /* set (new) backbone gw */ + + /* replace backbone_gw atomically and adjust reference counters */ + spin_lock_bh(&claim->backbone_lock); + old_backbone_gw = claim->backbone_gw; kref_get(&backbone_gw->refcount); claim->backbone_gw = backbone_gw; + spin_unlock_bh(&claim->backbone_lock); + + if (remove_crc) { + /* remove claim address from old backbone_gw */ + spin_lock_bh(&old_backbone_gw->crc_lock); + old_backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); + spin_unlock_bh(&old_backbone_gw->crc_lock); + } + batadv_backbone_gw_put(old_backbone_gw); + + /* add claim address to new backbone_gw */ spin_lock_bh(&backbone_gw->crc_lock); backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); spin_unlock_bh(&backbone_gw->crc_lock); @@ -737,6 +763,26 @@ claim_free_ref: } /** + * batadv_bla_claim_get_backbone_gw - Get valid reference for backbone_gw of + * claim + * @claim: claim whose backbone_gw should be returned + * + * Return: valid reference to claim::backbone_gw + */ +static struct batadv_bla_backbone_gw * +batadv_bla_claim_get_backbone_gw(struct batadv_bla_claim *claim) +{ + struct batadv_bla_backbone_gw *backbone_gw; + + spin_lock_bh(&claim->backbone_lock); + backbone_gw = claim->backbone_gw; + kref_get(&backbone_gw->refcount); + spin_unlock_bh(&claim->backbone_lock); + + return backbone_gw; +} + +/** * batadv_bla_del_claim - delete a claim from the claim hash
Re: [B.A.T.M.A.N.] [PATCH v5 2/6] batman-adv: speed up dat by snooping received ip traffic
Hi Andreas, as suggested by yourself and according to the discussion, please drop this patch from the patchset on the next resend. It may be better to resend it separately when the concerns are cleared. Thanks! Simon On Friday 10 June 2016 13:11:00 Andreas Pape wrote: > Speeding up dat address lookup is achieved by snooping all incoming ip > traffic. This especially increases the propability in bla setups that > a gateway into a common backbone network already has a fitting dat entry > to answer incoming ARP requests directly coming from the backbone > network thus further reducing ARP traffic in the mesh. > > Signed-off-by: Andreas Pape > --- > net/batman-adv/distributed-arp-table.c | 55 > net/batman-adv/distributed-arp-table.h | > 9 +- > net/batman-adv/soft-interface.c|3 ++ > 3 files changed, 66 insertions(+), 1 deletions(-) > > diff --git a/net/batman-adv/distributed-arp-table.c > b/net/batman-adv/distributed-arp-table.c index b752f8d..998a4b8 100644 > --- a/net/batman-adv/distributed-arp-table.c > +++ b/net/batman-adv/distributed-arp-table.c > @@ -27,6 +27,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -362,6 +363,60 @@ out: > batadv_dat_entry_put(dat_entry); > } > > +/** > + * batadv_dat_entry_check - check and update a dat entry > + * @bat_priv: the bat priv with all the soft interface information > + * @skb: socket buffer > + * @vid: VLAN identifier > + * > + * snoops incoming socket buffer for dat cache updates, if dat is enabled. > + * Can be called from other modules. > + */ > +void batadv_dat_entry_check(struct batadv_priv *bat_priv, struct sk_buff > *skb, + unsigned short vid) > +{ > + struct vlan_ethhdr *vhdr = NULL, tmp_vhdr; > + struct ethhdr *ethhdr = NULL; > + struct iphdr *iphdr = NULL, tmp_iphdr; > + > + if (!atomic_read(&bat_priv->distributed_arp_table)) > + return; > + > + ethhdr = eth_hdr(skb); > + > + switch (ntohs(ethhdr->h_proto)) { > + case ETH_P_IP: > + iphdr = skb_header_pointer(skb, ETH_HLEN, sizeof(tmp_iphdr), > +&tmp_iphdr); > + break; > + case ETH_P_8021Q: > + vhdr = skb_header_pointer(skb, 0, sizeof(tmp_vhdr), > + &tmp_vhdr); > + if (!vhdr) > + return; > + if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_IP) > + return; > + iphdr = skb_header_pointer(skb, sizeof(tmp_vhdr), > +sizeof(tmp_iphdr), > +&tmp_iphdr); > + break; > + } > + > + if (!iphdr) > + return; > + /* don't add source address 0.0.0.0, which can occur during > + * dhcp discover or request. > + */ > + if (ntohl(iphdr->saddr) == 0) > + return; > + > + batadv_dbg(BATADV_DBG_DAT, bat_priv, > +"Snooped IP address: %pI4 %pM (vid: %d)\n", > +&iphdr->saddr, ethhdr->h_source, > +BATADV_PRINT_VID(vid)); > + batadv_dat_entry_add(bat_priv, iphdr->saddr, ethhdr->h_source, vid); > +} > + > #ifdef CONFIG_BATMAN_ADV_DEBUG > > /** > diff --git a/net/batman-adv/distributed-arp-table.h > b/net/batman-adv/distributed-arp-table.h index 813ecea..cf1b93c 100644 > --- a/net/batman-adv/distributed-arp-table.h > +++ b/net/batman-adv/distributed-arp-table.h > @@ -80,7 +80,8 @@ batadv_dat_init_own_addr(struct batadv_priv *bat_priv, > int batadv_dat_init(struct batadv_priv *bat_priv); > void batadv_dat_free(struct batadv_priv *bat_priv); > int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset); > - > +void batadv_dat_entry_check(struct batadv_priv *bat_priv, struct sk_buff > *skb, + unsigned short vid); > /** > * batadv_dat_inc_counter - increment the correct DAT packet counter > * @bat_priv: the bat priv with all the soft interface information > @@ -173,6 +174,12 @@ static inline void batadv_dat_inc_counter(struct > batadv_priv *bat_priv, { > } > > +static inline > +void batadv_dat_entry_check(struct batadv_priv *bat_priv, struct sk_buff > *skb, + unsigned short vid) > +{ > +} > + > #endif /* CONFIG_BATMAN_ADV_DAT */ > > #endif /* _NET_BATMAN_ADV_DISTRIBUTED_ARP_TABLE_H_ */ > diff --git a/net/batman-adv/soft-interface.c > b/net/batman-adv/soft-interface.c index 81665b1..a86748f 100644 > --- a/net/batman-adv/soft-interface.c > +++ b/net/batman-adv/soft-interface.c > @@ -442,6 +442,9 @@ void batadv_interface_rx(struct net_device *soft_iface, > goto dropped; > } > > + /* Snoop incoming traffic for dat update */ > + batadv_dat_entry_check(bat_priv, skb, vid); > + > /* skb->dev & skb->pkt_type are set here */ > skb->protocol = eth_
Re: [B.A.T.M.A.N.] [PATCH v5 4/6] batman-adv: drop unicast packets from other backbone gw
On Friday 10 June 2016 13:11:02 Andreas Pape wrote: > Additional dropping of unicast packets received from another backbone gw of > the same backbone network before being forwarded to the same backbone again > is necessary. It was observed in a test setup that in rare cases these > frames lead to looping unicast traffic backbone->mesh->backbone. > > Signed-off-by: Andreas Pape Acked-by: Simon Wunderlich I believe Svens previous concerns have been cleared. When you resend this patchset, please add my Acked-by into your commit message (unless you do major changes in the content ...) Thanks, Simon signature.asc Description: This is a digitally signed message part.
Re: [B.A.T.M.A.N.] [PATCH v2 2/3] batman-adv: Fix non-atomic bla_claim::backbone_gw access
On Thursday 30 June 2016 20:11:33 Sven Eckelmann wrote: > The pointer batadv_bla_claim::backbone_gw can be changed at any time. > Therefore, access to it must be protected to ensure that two function > accessing the same backbone_gw are actually accessing the same. This is > especially important when the crc_lock is used or when the backbone_gw of a > claim is exchanged. > > Not doing so leads to invalid memory access and/or reference leaks. > > Fixes: a9ce0dc43e2c ("batman-adv: add basic bridge loop avoidance code") > Fixes: b307e72d119f ("batman-adv: lock crc access in bridge loop avoidance") > Signed-off-by: Sven Eckelmann Technically, you can already add my "Acked-by". However I'd like to suggest one style change: Could you please rename batadv_bla_claim_backbone_gw into batadv_bla_claim_get_backbone_gw? I think this would make it clearer what the function does and also shows get/put pairs clearly in the code. Thanks! Simon signature.asc Description: This is a digitally signed message part.
Re: [B.A.T.M.A.N.] [PATCH v2 3/3] batman-adv: Fix reference leak in batadv_find_router
Acked-by: Simon Wunderlich Thanks, this also looks much cleaner now! Simon On Thursday 30 June 2016 20:11:34 Sven Eckelmann wrote: > The replacement of last_bonding_candidate in batadv_orig_node has to be an > atomic operation. Otherwise it is possible that the reference counter of a > batadv_orig_ifinfo is reduced which was no longer the > last_bonding_candidate when the new candidate is added. This can either > lead to an invalid memory access or to reference leaks which make it > impossible to an interface which was added to batman-adv. > > Fixes: 797edd9e87ac ("batman-adv: add bonding again") > Signed-off-by: Sven Eckelmann > --- > v2: > - get refcnt for new selected router before assigning it to returned >variable > - move refcnt cleanup of all remembered candidates/routers to central place > --- > net/batman-adv/routing.c | 52 > net/batman-adv/types.h | > 4 +++- > 2 files changed, 42 insertions(+), 14 deletions(-) > > diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c > index bba9276..a4253d4 100644 > --- a/net/batman-adv/routing.c > +++ b/net/batman-adv/routing.c > @@ -462,6 +462,29 @@ static int batadv_check_unicast_packet(struct > batadv_priv *bat_priv, } > > /** > + * batadv_last_bonding_replace - Replace last_bonding_candidate of > orig_node + * @orig_node: originator node whose bonding candidates should > be replaced + * @new_candidate: new bonding candidate or NULL > + */ > +static void > +batadv_last_bonding_replace(struct batadv_orig_node *orig_node, > + struct batadv_orig_ifinfo *new_candidate) > +{ > + struct batadv_orig_ifinfo *old_candidate; > + > + spin_lock_bh(&orig_node->neigh_list_lock); > + old_candidate = orig_node->last_bonding_candidate; > + > + if (new_candidate) > + kref_get(&new_candidate->refcount); > + orig_node->last_bonding_candidate = new_candidate; > + spin_unlock_bh(&orig_node->neigh_list_lock); > + > + if (old_candidate) > + batadv_orig_ifinfo_put(old_candidate); > +} > + > +/** > * batadv_find_router - find a suitable router for this originator > * @bat_priv: the bat priv with all the soft interface information > * @orig_node: the destination node > @@ -568,10 +591,6 @@ next: > } > rcu_read_unlock(); > > - /* last_bonding_candidate is reset below, remove the old reference. */ > - if (orig_node->last_bonding_candidate) > - batadv_orig_ifinfo_put(orig_node->last_bonding_candidate); > - > /* After finding candidates, handle the three cases: >* 1) there is a next candidate, use that >* 2) there is no next candidate, use the first of the list > @@ -580,21 +599,28 @@ next: > if (next_candidate) { > batadv_neigh_node_put(router); > > - /* remove references to first candidate, we don't need it. */ > - if (first_candidate) { > - batadv_neigh_node_put(first_candidate_router); > - batadv_orig_ifinfo_put(first_candidate); > - } > + kref_get(&next_candidate_router->refcount); > router = next_candidate_router; > - orig_node->last_bonding_candidate = next_candidate; > + batadv_last_bonding_replace(orig_node, next_candidate); > } else if (first_candidate) { > batadv_neigh_node_put(router); > > - /* refcounting has already been done in the loop above. */ > + kref_get(&first_candidate_router->refcount); > router = first_candidate_router; > - orig_node->last_bonding_candidate = first_candidate; > + batadv_last_bonding_replace(orig_node, first_candidate); > } else { > - orig_node->last_bonding_candidate = NULL; > + batadv_last_bonding_replace(orig_node, NULL); > + } > + > + /* cleanup of candidates */ > + if (first_candidate) { > + batadv_neigh_node_put(first_candidate_router); > + batadv_orig_ifinfo_put(first_candidate); > + } > + > + if (next_candidate) { > + batadv_neigh_node_put(next_candidate_router); > + batadv_orig_ifinfo_put(next_candidate); > } > > return router; > diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h > index d82f6b4..96af6da 100644 > --- a/net/batman-adv/types.h > +++ b/net/batman-adv/types.h > @@ -329,7 +329,9 @@ struct batadv_orig_node { > DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); > u32 last_bcast_seqno; > struct hlist_head neigh_list; > - /* neigh_list_lock protects: neigh_list and router */ > + /* neigh_list_lock protects: neigh_list, ifinfo_list, > + * last_bonding_candidate and router > + */ > spinlock_t neigh_list_lock; > struct hlist_node hash_entry; > struct batadv_priv *bat_priv; signature.asc Description: This is a digi
[B.A.T.M.A.N.] [PATCH 08/17] batman-adv: remove ogm_emit and ogm_schedule API calls
From: Antonio Quartulli The ogm_emit and ogm_schedule API calls were rather tight to the B.A.T.M.A.N. IV logic and therefore rather difficult to use with other algorithm implementations. Remove such calls and move the surrounding logic into the B.A.T.M.A.N. IV specific code. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/bat_iv_ogm.c | 69 ++--- net/batman-adv/bat_v.c | 10 -- net/batman-adv/hard-interface.c | 3 -- net/batman-adv/main.c | 2 -- net/batman-adv/send.c | 61 +--- net/batman-adv/send.h | 4 +-- net/batman-adv/types.h | 4 --- 7 files changed, 67 insertions(+), 86 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index aa11296..4815db9 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,8 @@ #include "send.h" #include "translation-table.h" +static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work); + /** * enum batadv_dup_status - duplicate status * @BATADV_NO_DUP: the packet is no duplicate @@ -731,7 +734,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, /* start timer for this packet */ INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, - batadv_send_outstanding_bat_ogm_packet); + batadv_iv_send_outstanding_bat_ogm_packet); queue_delayed_work(batadv_event_workqueue, &forw_packet_aggr->delayed_work, send_time - jiffies); @@ -938,6 +941,19 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) u16 tvlv_len = 0; unsigned long send_time; + if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) || + (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)) + return; + + /* the interface gets activated here to avoid race conditions between +* the moment of activating the interface in +* hardif_activate_interface() where the originator mac is set and +* outdated packets (especially uninitialized mac addresses) in the +* packet queue +*/ + if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED) + hard_iface->if_status = BATADV_IF_ACTIVE; + primary_if = batadv_primary_if_get_selected(bat_priv); if (hard_iface == primary_if) { @@ -1779,6 +1795,45 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, batadv_orig_node_put(orig_node); } +static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work) +{ + struct delayed_work *delayed_work; + struct batadv_forw_packet *forw_packet; + struct batadv_priv *bat_priv; + + delayed_work = to_delayed_work(work); + forw_packet = container_of(delayed_work, struct batadv_forw_packet, + delayed_work); + bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); + spin_lock_bh(&bat_priv->forw_bat_list_lock); + hlist_del(&forw_packet->list); + spin_unlock_bh(&bat_priv->forw_bat_list_lock); + + if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) + goto out; + + batadv_iv_ogm_emit(forw_packet); + + /* we have to have at least one packet in the queue to determine the +* queues wake up time unless we are shutting down. +* +* only re-schedule if this is the "original" copy, e.g. the OGM of the +* primary interface should only be rescheduled once per period, but +* this function will be called for the forw_packet instances of the +* other secondary interfaces as well. +*/ + if (forw_packet->own && + forw_packet->if_incoming == forw_packet->if_outgoing) + batadv_iv_ogm_schedule(forw_packet->if_incoming); + +out: + /* don't count own packet */ + if (!forw_packet->own) + atomic_inc(&bat_priv->batman_queue_left); + + batadv_forw_packet_free(forw_packet); +} + static int batadv_iv_ogm_receive(struct sk_buff *skb, struct batadv_hard_iface *if_incoming) { @@ -1795,7 +1850,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, /* did we receive a B.A.T.M.A.N. IV OGM packet on an interface * that does not have B.A.T.M.A.N. IV enabled ? */ - if (bat_priv->bat_algo_ops->bat_ogm_emit != batadv_iv_ogm_emit) + if (bat_priv->bat_algo_ops->bat_iface_enable != + batadv_iv_ogm_iface_enable) return NET_RX_DROP; batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX)
[B.A.T.M.A.N.] [PATCH 17/17] batman-adv: Add debugfs table for mcast flags
From: Linus Lüssing This patch adds a debugfs table with originators and their according multicast flags to help users figure out why multicast optimizations might be enabled or disabled for them. Tested-by: Simon Wunderlich Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/debugfs.c | 23 ++ net/batman-adv/multicast.c | 104 + net/batman-adv/multicast.h | 3 ++ 3 files changed, 130 insertions(+) diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 9529004..f187a8f 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@ -48,6 +48,7 @@ #include "distributed-arp-table.h" #include "gateway_client.h" #include "icmp_socket.h" +#include "multicast.h" #include "network-coding.h" #include "originator.h" #include "translation-table.h" @@ -363,6 +364,22 @@ static int batadv_nc_nodes_open(struct inode *inode, struct file *file) } #endif +#ifdef CONFIG_BATMAN_ADV_MCAST +/** + * batadv_mcast_flags_open - prepare file handler for reads from mcast_flags + * @inode: inode which was opened + * @file: file handle to be initialized + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_mcast_flags_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + + return single_open(file, batadv_mcast_flags_seq_print_text, net_dev); +} +#endif + #define BATADV_DEBUGINFO(_name, _mode, _open) \ struct batadv_debuginfo batadv_debuginfo_##_name = { \ .attr = { \ @@ -407,6 +424,9 @@ static BATADV_DEBUGINFO(transtable_local, S_IRUGO, #ifdef CONFIG_BATMAN_ADV_NC static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); #endif +#ifdef CONFIG_BATMAN_ADV_MCAST +static BATADV_DEBUGINFO(mcast_flags, S_IRUGO, batadv_mcast_flags_open); +#endif static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { &batadv_debuginfo_neighbors, @@ -424,6 +444,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { #ifdef CONFIG_BATMAN_ADV_NC &batadv_debuginfo_nc_nodes, #endif +#ifdef CONFIG_BATMAN_ADV_MCAST + &batadv_debuginfo_mcast_flags, +#endif NULL, }; diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 2d1a896..d3222db 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,8 @@ #include #include +#include "hard-interface.h" +#include "hash.h" #include "packet.h" #include "translation-table.h" @@ -1130,6 +1133,107 @@ void batadv_mcast_init(struct batadv_priv *bat_priv) } /** + * batadv_mcast_flags_print_header - print own mcast flags to debugfs table + * @bat_priv: the bat priv with all the soft interface information + * @seq: debugfs table seq_file struct + * + * Prints our own multicast flags including a more specific reason why + * they are set, that is prints the bridge and querier state too, to + * the debugfs table specified via @seq. + */ +static void batadv_mcast_flags_print_header(struct batadv_priv *bat_priv, + struct seq_file *seq) +{ + u8 flags = bat_priv->mcast.flags; + char querier4, querier6, shadowing4, shadowing6; + bool bridged = bat_priv->mcast.bridged; + + if (bridged) { + querier4 = bat_priv->mcast.querier_ipv4.exists ? '.' : '4'; + querier6 = bat_priv->mcast.querier_ipv6.exists ? '.' : '6'; + shadowing4 = bat_priv->mcast.querier_ipv4.shadowing ? '4' : '.'; + shadowing6 = bat_priv->mcast.querier_ipv6.shadowing ? '6' : '.'; + } else { + querier4 = '?'; + querier6 = '?'; + shadowing4 = '?'; + shadowing6 = '?'; + } + + seq_printf(seq, "Multicast flags (own flags: [%c%c%c])\n", + (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', + (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', + (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.'); + seq_printf(seq, "* Bridged [U]\t\t\t\t%c\n", bridged ? 'U' : '.'); + seq_printf(seq, "* No IGMP/MLD Querier [4/6]:\t\t%c/%c\n", + querier4, querier6); + seq_printf(seq, "* Shadowing IGMP/MLD Querier [4/6]:\t%c/%c\n", + shadowing4, shadowing6); + seq_puts(seq, "---\n"); + seq_printf(seq, " %-10s %s\n", "Originator", "Flags"); +} + +/** + * batadv_mcast_flags_seq_print_text - print the mcast flags of other nodes + * @seq: seq file to print on + * @offset: not used + * + * This prints a table of (primary) originators and their according + * multicast flags, including
[B.A.T.M.A.N.] [PATCH 16/17] batman-adv: Adding logging of mcast flag changes
From: Linus Lüssing With this patch changes relevant to a node's own multicast flags are printed to the 'mcast' log level. Tested-by: Simon Wunderlich Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/main.h | 4 +- net/batman-adv/multicast.c | 133 +++- net/batman-adv/soft-interface.c | 4 ++ net/batman-adv/types.h | 4 ++ 4 files changed, 142 insertions(+), 3 deletions(-) diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index c356d91..cd83e28 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -231,6 +231,7 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr); * @BATADV_DBG_BLA: bridge loop avoidance messages * @BATADV_DBG_DAT: ARP snooping and DAT related messages * @BATADV_DBG_NC: network coding related messages + * @BATADV_DBG_MCAST: multicast related messages * @BATADV_DBG_ALL: the union of all the above log levels */ enum batadv_dbg_level { @@ -240,7 +241,8 @@ enum batadv_dbg_level { BATADV_DBG_BLA= BIT(3), BATADV_DBG_DAT= BIT(4), BATADV_DBG_NC = BIT(5), - BATADV_DBG_ALL= 63, + BATADV_DBG_MCAST = BIT(6), + BATADV_DBG_ALL= 127, }; #ifdef CONFIG_BATMAN_ADV_DEBUG diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index eb30316..2d1a896 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -334,6 +335,122 @@ static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv) } /** + * batadv_mcast_querier_log - debug output regarding the querier status on link + * @bat_priv: the bat priv with all the soft interface information + * @str_proto: a string for the querier protocol (e.g. "IGMP" or "MLD") + * @old_state: the previous querier state on our link + * @new_state: the new querier state on our link + * + * Outputs debug messages to the logging facility with log level 'mcast' + * regarding changes to the querier status on the link which are relevant + * to our multicast optimizations. + * + * Usually this is about whether a querier appeared or vanished in + * our mesh or whether the querier is in the suboptimal position of being + * behind our local bridge segment: Snooping switches will directly + * forward listener reports to the querier, therefore batman-adv and + * the bridge will potentially not see these listeners - the querier is + * potentially shadowing listeners from us then. + * + * This is only interesting for nodes with a bridge on top of their + * soft interface. + */ +static void +batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto, +struct batadv_mcast_querier_state *old_state, +struct batadv_mcast_querier_state *new_state) +{ + if (!old_state->exists && new_state->exists) + batadv_info(bat_priv->soft_iface, "%s Querier appeared\n", + str_proto); + else if (old_state->exists && !new_state->exists) + batadv_info(bat_priv->soft_iface, + "%s Querier disappeared - multicast optimizations disabled\n", + str_proto); + else if (!bat_priv->mcast.bridged && !new_state->exists) + batadv_info(bat_priv->soft_iface, + "No %s Querier present - multicast optimizations disabled\n", + str_proto); + + if (new_state->exists) { + if ((!old_state->shadowing && new_state->shadowing) || + (!old_state->exists && new_state->shadowing)) + batadv_dbg(BATADV_DBG_MCAST, bat_priv, + "%s Querier is behind our bridged segment: Might shadow listeners\n", + str_proto); + else if (old_state->shadowing && !new_state->shadowing) + batadv_dbg(BATADV_DBG_MCAST, bat_priv, + "%s Querier is not behind our bridged segment\n", + str_proto); + } +} + +/** + * batadv_mcast_bridge_log - debug output for topology changes in bridged setups + * @bat_priv: the bat priv with all the soft interface information + * @bridged: a flag about whether the soft interface is currently bridged or not + * @querier_ipv4: (maybe) new status of a potential, selected IGMP querier + * @querier_ipv6: (maybe) new status of a potential, selected MLD querier + * + * If no bridges are ever used on this node, then this function does nothing. + * + * Otherwise this function outputs debug information to the 'mcast' log level + * which might be relevant to our multicast optimizations. + * + * More precisely, it outputs information when a bridge interface is added o
[B.A.T.M.A.N.] [PATCH 15/17] batman-adv: Add multicast optimization support for bridged setups
From: Linus Lüssing With this patch we are finally able to support multicast optimizations in bridged setups, too. So far, if a bridge was added on top of a soft-interface (e.g. bat0) the batman-adv multicast optimizations needed to be disabled to avoid packetloss. Current Linux bridge implementations and API can now provide us with the so far missing information about interested but "remote" multicast receivers behind bridge ports. The Linux bridge performs the detection of remote participants interested in multicast packets with its own and mature so called IGMP and MLD snooping code and stores that in its database. With the new API provided by the bridge batman-adv can now simply hook into this database. We then reliably announce the gathered multicast listeners to other nodes through the batman-adv translation table. Additionally, the Linux bridge provides us with the information about whether an IGMP/MLD querier exists. If there is none then we need to disable multicast optimizations as we cannot learn about multicast listeners on external, bridged-in host then. Tested-by: Simon Wunderlich Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/Kconfig | 2 +- net/batman-adv/multicast.c | 181 - net/batman-adv/types.h | 13 3 files changed, 177 insertions(+), 19 deletions(-) diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index b7ba97d..833bb14 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig @@ -66,7 +66,7 @@ config BATMAN_ADV_NC config BATMAN_ADV_MCAST bool "Multicast optimisation" - depends on BATMAN_ADV && INET + depends on BATMAN_ADV && INET && !(BRIDGE=m && BATMAN_ADV=y) default n help This option enables the multicast optimisation which aims to diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 4673328..eb30316 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -45,18 +47,53 @@ #include #include #include +#include +#include #include #include "packet.h" #include "translation-table.h" /** + * batadv_mcast_get_bridge - get the bridge on top of the softif if it exists + * @soft_iface: netdev struct of the mesh interface + * + * If the given soft interface has a bridge on top then the refcount + * of the according net device is increased. + * + * Return: NULL if no such bridge exists. Otherwise the net device of the + * bridge. + */ +static struct net_device *batadv_mcast_get_bridge(struct net_device *soft_iface) +{ + struct net_device *upper = soft_iface; + + rcu_read_lock(); + do { + upper = netdev_master_upper_dev_get_rcu(upper); + } while (upper && !(upper->priv_flags & IFF_EBRIDGE)); + + if (upper) + dev_hold(upper); + rcu_read_unlock(); + + return upper; +} + +/** * batadv_mcast_mla_softif_get - get softif multicast listeners * @dev: the device to collect multicast addresses from * @mcast_list: a list to put found addresses into * - * Collect multicast addresses of the local multicast listeners - * on the given soft interface, dev, in the given mcast_list. + * Collects multicast addresses of multicast listeners residing + * on this kernel on the given soft interface, dev, in + * the given mcast_list. In general, multicast listeners provided by + * your multicast receiving applications run directly on this node. + * + * If there is a bridge interface on top of dev, collects from that one + * instead. Just like with IP addresses and routes, multicast listeners + * will(/should) register to the bridge interface instead of an + * enslaved bat0. * * Return: -ENOMEM on memory allocation error or the number of * items added to the mcast_list otherwise. @@ -64,12 +101,13 @@ static int batadv_mcast_mla_softif_get(struct net_device *dev, struct hlist_head *mcast_list) { + struct net_device *bridge = batadv_mcast_get_bridge(dev); struct netdev_hw_addr *mc_list_entry; struct batadv_hw_addr *new; int ret = 0; - netif_addr_lock_bh(dev); - netdev_for_each_mc_addr(mc_list_entry, dev) { + netif_addr_lock_bh(bridge ? bridge : dev); + netdev_for_each_mc_addr(mc_list_entry, bridge ? bridge : dev) { new = kmalloc(sizeof(*new), GFP_ATOMIC); if (!new) { ret = -ENOMEM; @@ -80,7 +118,10 @@ static int batadv_mcast_mla_softif_get(struct net_device *dev, hlist_add_head(&new->list, mcast_list); ret++; } - netif_addr_unlock_bh(dev); + netif_addr_unlock_bh(
[B.A.T.M.A.N.] [PATCH 14/17] batman-adv: Always flood IGMP/MLD reports
From: Linus Lüssing With this patch IGMP or MLD reports are always flooded. This is necessary for the upcoming bridge integration to function without multicast packet loss. With the report handling so far bridges might miss interested multicast listeners, leading to wrongly excluding ports from multicast packet forwarding. Currently we are treating IGMP/MLD reports, the messages bridges use to learn about interested multicast listeners, just as any other multicast packet: We try to send them to nodes matching its multicast destination. Unfortunately, the destination address of reports of the older IGMPv2/MLDv1 protocol families do not strictly adhere to their own protocol: More precisely, the interested receiver, an IGMPv2 or MLDv1 querier, itself usually does not listen to the multicast destination address of any reports. Therefore with this patch we are simply excluding IGMP/MLD reports from the multicast forwarding code path and keep flooding them. By that any bridge receives them and can properly learn about listeners. To avoid compatibility issues with older nodes not yet implementing this report handling, we need to force them to flood reports: We do this by bumping the multicast TVLV version to 2, effectively disabling their multicast optimization. Tested-by: Simon Wunderlich Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/Kconfig | 2 +- net/batman-adv/multicast.c | 87 +++--- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index f66930e..b7ba97d 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig @@ -66,7 +66,7 @@ config BATMAN_ADV_NC config BATMAN_ADV_MCAST bool "Multicast optimisation" - depends on BATMAN_ADV + depends on BATMAN_ADV && INET default n help This option enables the multicast optimisation which aims to diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index c32f24f..4673328 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -25,9 +25,11 @@ #include #include #include +#include #include -#include +#include #include +#include #include #include #include @@ -236,7 +238,7 @@ static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) if (batadv_mcast_has_bridge(bat_priv)) { if (bat_priv->mcast.enabled) { batadv_tvlv_container_unregister(bat_priv, -BATADV_TVLV_MCAST, 1); +BATADV_TVLV_MCAST, 2); bat_priv->mcast.enabled = false; } @@ -245,7 +247,7 @@ static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) if (!bat_priv->mcast.enabled || mcast_data.flags != bat_priv->mcast.flags) { - batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1, + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 2, &mcast_data, sizeof(mcast_data)); bat_priv->mcast.flags = mcast_data.flags; bat_priv->mcast.enabled = true; @@ -283,6 +285,31 @@ out: } /** + * batadv_mcast_is_report_ipv4 - check for IGMP reports + * @skb: the ethernet frame destined for the mesh + * + * This call might reallocate skb data. + * + * Checks whether the given frame is a valid IGMP report. + * + * Return: If so then true, otherwise false. + */ +static bool batadv_mcast_is_report_ipv4(struct sk_buff *skb) +{ + if (ip_mc_check_igmp(skb, NULL) < 0) + return false; + + switch (igmp_hdr(skb)->type) { + case IGMP_HOST_MEMBERSHIP_REPORT: + case IGMPV2_HOST_MEMBERSHIP_REPORT: + case IGMPV3_HOST_MEMBERSHIP_REPORT: + return true; + } + + return false; +} + +/** * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential * @bat_priv: the bat priv with all the soft interface information * @skb: the IPv4 packet to check @@ -304,6 +331,9 @@ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr))) return -ENOMEM; + if (batadv_mcast_is_report_ipv4(skb)) + return -EINVAL; + iphdr = ip_hdr(skb); /* TODO: Implement Multicast Router Discovery (RFC4286), @@ -320,6 +350,31 @@ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, return 0; } +#if IS_ENABLED(CONFIG_IPV6) +/** + * batadv_mcast_is_report_ipv6 - check for MLD reports + * @skb: the ethernet frame destined for the mesh + * + * This call might reallocate skb data. + * + * Checks whether the given frame is a valid MLD report.
[B.A.T.M.A.N.] [PATCH 13/17] batman-adv: Include frame priority in fragment header
From: Andrew Lunn Unfragmented frames which traverse a node have their skb->priority set by looking at the IP ToS byte, or the 802.1p header. However for fragments this is not possible, only one of the fragments will contain the headers. Instead, place the priority into the fragment header and on receiving a fragment, use this information to set the skb->priority for when the fragment is forwarded. Signed-off-by: Andrew Lunn Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/fragmentation.c | 9 + net/batman-adv/packet.h| 7 +-- net/batman-adv/routing.c | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index a119b6a..9f41a0a 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -472,6 +472,15 @@ bool batadv_frag_send_packet(struct sk_buff *skb, frag_header.reserved = 0; frag_header.no = 0; frag_header.total_size = htons(skb->len); + + /* skb->priority values from 256->263 are magic values to +* directly indicate a specific 802.1d priority. This is used +* to allow 802.1d priority to be passed directly in from VLAN +* tags, etc. +*/ + if (skb->priority >= 256 && skb->priority <= 263) + frag_header.priority = skb->priority - 256; + ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr); ether_addr_copy(frag_header.dest, orig_node->orig); diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 372128d..7156779 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -420,6 +420,7 @@ struct batadv_unicast_4addr_packet { * @dest: final destination used when routing fragments * @orig: originator of the fragment used when merging the packet * @no: fragment number within this sequence + * @priority: priority of frame, from ToS IP precedence or 802.1p * @reserved: reserved byte for alignment * @seqno: sequence identification * @total_size: size of the merged packet @@ -430,9 +431,11 @@ struct batadv_frag_packet { u8 ttl; #if defined(__BIG_ENDIAN_BITFIELD) u8 no:4; - u8 reserved:4; + u8 priority:3; + u8 reserved:1; #elif defined(__LITTLE_ENDIAN_BITFIELD) - u8 reserved:4; + u8 reserved:1; + u8 priority:3; u8 no:4; #else #error "unknown bitfield endianness" diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f75091c..24fc753 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1006,6 +1006,8 @@ int batadv_recv_frag_packet(struct sk_buff *skb, if (!orig_node_src) goto out; + skb->priority = frag_packet->priority + 256; + /* Route the fragment if it is not for us and too big to be merged. */ if (!batadv_is_my_mac(bat_priv, frag_packet->dest) && batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) { -- 2.8.1
[B.A.T.M.A.N.] [PATCH 12/17] batman-adv: Set skb priority in fragments
From: Andrew Lunn BATMAN will set the skb->priority based on the IP precedence or 802.1q tag. However, if it needs to fragment the frame, it currently leaves the fragment skb with the default priority and actually overwrites the priority in the unfragmented frame. Fix this. Signed-off-by: Andrew Lunn Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/fragmentation.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 65536db..a119b6a 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -414,7 +413,7 @@ static struct sk_buff *batadv_frag_create(struct sk_buff *skb, if (!skb_fragment) goto err; - skb->priority = TC_PRIO_CONTROL; + skb_fragment->priority = skb->priority; /* Eat the last mtu-bytes of the skb */ skb_reserve(skb_fragment, header_size + ETH_HLEN); -- 2.8.1
[B.A.T.M.A.N.] [PATCH 11/17] batman-adv: init ELP tweaking options only once
From: Marek Lindner The ELP interval and throughput override interface settings are initialized with default settings on every time an interface is added to a mesh. This patch prevents this behavior by moving the configuration init to the interface detection routine which runs only once per interface. Signed-off-by: Marek Lindner [a...@unstable.cc: move initialization to batadv_v_hardif_init] Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/bat_algo.h | 7 ++- net/batman-adv/bat_v.c | 19 ++- net/batman-adv/bat_v_elp.c | 1 - net/batman-adv/hard-interface.c | 3 +++ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/net/batman-adv/bat_algo.h b/net/batman-adv/bat_algo.h index 03dafd3..3654296 100644 --- a/net/batman-adv/bat_algo.h +++ b/net/batman-adv/bat_algo.h @@ -18,13 +18,14 @@ #ifndef _NET_BATMAN_ADV_BAT_ALGO_H_ #define _NET_BATMAN_ADV_BAT_ALGO_H_ -struct batadv_priv; +#include "main.h" int batadv_iv_init(void); #ifdef CONFIG_BATMAN_ADV_BATMAN_V int batadv_v_init(void); +void batadv_v_hardif_init(struct batadv_hard_iface *hardif); int batadv_v_mesh_init(struct batadv_priv *bat_priv); void batadv_v_mesh_free(struct batadv_priv *bat_priv); @@ -35,6 +36,10 @@ static inline int batadv_v_init(void) return 0; } +static inline void batadv_v_hardif_init(struct batadv_hard_iface *hardif) +{ +} + static inline int batadv_v_mesh_init(struct batadv_priv *bat_priv) { return 0; diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index c16cd44..c2fea81 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c @@ -70,11 +70,6 @@ static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface) if (ret < 0) batadv_v_elp_iface_disable(hard_iface); - /* enable link throughput auto-detection by setting the throughput -* override to zero -*/ - atomic_set(&hard_iface->bat_v.throughput_override, 0); - return ret; } @@ -339,6 +334,20 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = { }; /** + * batadv_v_hardif_init - initialize the algorithm specific fields in the + * hard-interface object + * @hard_iface: the hard-interface to initialize + */ +void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface) +{ + /* enable link throughput auto-detection by setting the throughput +* override to zero +*/ + atomic_set(&hard_iface->bat_v.throughput_override, 0); + atomic_set(&hard_iface->bat_v.elp_interval, 500); +} + +/** * batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a * mesh * @bat_priv: the object representing the mesh interface to initialise diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index 8909d1e..cf0262b 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c @@ -344,7 +344,6 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface) /* randomize initial seqno to avoid collision */ get_random_bytes(&random_seqno, sizeof(random_seqno)); atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno); - atomic_set(&hard_iface->bat_v.elp_interval, 500); /* assume full-duplex by default */ hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX; diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index db2009d..3696929 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -37,6 +37,7 @@ #include #include +#include "bat_algo.h" #include "bridge_loop_avoidance.h" #include "debugfs.h" #include "distributed-arp-table.h" @@ -683,6 +684,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) if (batadv_is_wifi_netdev(net_dev)) hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; + batadv_v_hardif_init(hard_iface); + /* extra reference for return */ kref_init(&hard_iface->refcount); kref_get(&hard_iface->refcount); -- 2.8.1
[B.A.T.M.A.N.] [PATCH 09/17] batman-adv: remove useless inline attribute for sysfs helper function
From: Antonio Quartulli the compiler can optimize functions within the same C file and therefore there is no need to make it explicit. Remove the useless inline attribute for __batadv_store_uint_attr() Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/sysfs.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 414b207..ef5832f 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -389,12 +389,12 @@ static int batadv_store_uint_attr(const char *buff, size_t count, return count; } -static inline ssize_t -__batadv_store_uint_attr(const char *buff, size_t count, -int min, int max, -void (*post_func)(struct net_device *), -const struct attribute *attr, -atomic_t *attr_store, struct net_device *net_dev) +static ssize_t __batadv_store_uint_attr(const char *buff, size_t count, + int min, int max, + void (*post_func)(struct net_device *), + const struct attribute *attr, + atomic_t *attr_store, + struct net_device *net_dev) { int ret; -- 2.8.1
[B.A.T.M.A.N.] [PATCH 10/17] batman-adv: move GW mode and selection class to private data structure
From: Antonio Quartulli To reduce the field pollution in our main batadv_priv data structure we've already created some substructures so that we could group fields in a convenient manner. However gw_mode and gw_sel_class are still part of the main object. More both fields to the GW private substructure. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/gateway_client.c | 12 ++-- net/batman-adv/gateway_common.c | 6 +++--- net/batman-adv/soft-interface.c | 6 +++--- net/batman-adv/sysfs.c | 10 +- net/batman-adv/types.h | 8 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index b9d72e9..18c3715 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -192,7 +192,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) tq_avg = router_ifinfo->bat_iv.tq_avg; - switch (atomic_read(&bat_priv->gw_sel_class)) { + switch (atomic_read(&bat_priv->gw.sel_class)) { case 1: /* fast connection */ tmp_gw_factor = tq_avg * tq_avg; tmp_gw_factor *= gw_node->bandwidth_down; @@ -255,7 +255,7 @@ void batadv_gw_check_client_stop(struct batadv_priv *bat_priv) { struct batadv_gw_node *curr_gw; - if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) + if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT) return; curr_gw = batadv_gw_get_selected_gw_node(bat_priv); @@ -283,7 +283,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv) struct batadv_neigh_ifinfo *router_ifinfo = NULL; char gw_addr[18] = { '\0' }; - if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) + if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT) goto out; curr_gw = batadv_gw_get_selected_gw_node(bat_priv); @@ -402,8 +402,8 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, /* if the routing class is greater than 3 the value tells us how much * greater the TQ value of the new gateway must be */ - if ((atomic_read(&bat_priv->gw_sel_class) > 3) && - (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class))) + if ((atomic_read(&bat_priv->gw.sel_class) > 3) && + (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw.sel_class))) goto out; batadv_dbg(BATADV_DBG_BATMAN, bat_priv, @@ -820,7 +820,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, if (!gw_node) goto out; - switch (atomic_read(&bat_priv->gw_mode)) { + switch (atomic_read(&bat_priv->gw.mode)) { case BATADV_GW_MODE_SERVER: /* If we are a GW then we are our best GW. We can artificially * set the tq towards ourself as the maximum value diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 4423047..3c26945 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c @@ -144,7 +144,7 @@ void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) u32 down, up; char gw_mode; - gw_mode = atomic_read(&bat_priv->gw_mode); + gw_mode = atomic_read(&bat_priv->gw.mode); switch (gw_mode) { case BATADV_GW_MODE_OFF: @@ -241,8 +241,8 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, /* restart gateway selection if fast or late switching was enabled */ if ((gateway.bandwidth_down != 0) && - (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) && - (atomic_read(&bat_priv->gw_sel_class) > 2)) + (atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) && + (atomic_read(&bat_priv->gw.sel_class) > 2)) batadv_gw_check_election(bat_priv, orig); } diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 343d2c9..81665b1 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -255,7 +255,7 @@ static int batadv_interface_tx(struct sk_buff *skb, if (batadv_compare_eth(ethhdr->h_dest, ectp_addr)) goto dropped; - gw_mode = atomic_read(&bat_priv->gw_mode); + gw_mode = atomic_read(&bat_priv->gw.mode); if (is_multicast_ether_addr(ethhdr->h_dest)) { /* if gw mode is off, broadcast every packet */ if (gw_mode == BATADV_GW_MODE_OFF) { @@ -815,8 +815,8 @@ static int batadv_softif_init_late(struct net_device *dev) 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_O
[B.A.T.M.A.N.] [PATCH 07/17] batman-adv: remove unused callback from batadv_algo_ops struct
From: Marek Lindner Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/originator.c | 5 - net/batman-adv/types.h | 3 --- 2 files changed, 8 deletions(-) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index b0bad57..076d258 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -251,10 +251,8 @@ static void batadv_neigh_node_release(struct kref *ref) struct hlist_node *node_tmp; struct batadv_neigh_node *neigh_node; struct batadv_neigh_ifinfo *neigh_ifinfo; - struct batadv_algo_ops *bao; neigh_node = container_of(ref, struct batadv_neigh_node, refcount); - bao = neigh_node->orig_node->bat_priv->bat_algo_ops; hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, &neigh_node->ifinfo_list, list) { @@ -263,9 +261,6 @@ static void batadv_neigh_node_release(struct kref *ref) batadv_hardif_neigh_put(neigh_node->hardif_neigh); - if (bao->bat_neigh_free) - bao->bat_neigh_free(neigh_node); - batadv_hardif_put(neigh_node->if_incoming); kfree_rcu(neigh_node, rcu); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 6a577f4..114d150 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1278,8 +1278,6 @@ struct batadv_forw_packet { * better than neigh2 for their respective outgoing interface from the metric * prospective * @bat_neigh_print: print the single hop neighbor list (optional) - * @bat_neigh_free: free the resources allocated by the routing algorithm for a - * neigh_node object * @bat_orig_print: print the originator table (optional) * @bat_orig_free: free the resources allocated by the routing algorithm for an * orig_node object @@ -1310,7 +1308,6 @@ struct batadv_algo_ops { struct batadv_neigh_node *neigh2, struct batadv_hard_iface *if_outgoing2); void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); - void (*bat_neigh_free)(struct batadv_neigh_node *neigh); /* orig_node handling API */ void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, struct batadv_hard_iface *hard_iface); -- 2.8.1
[B.A.T.M.A.N.] [PATCH 06/17] batman-adv: refactor batadv_neigh_node_* functions to follow common style
From: Marek Lindner Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/bat_iv_ogm.c | 3 ++- net/batman-adv/bat_v_elp.c | 3 ++- net/batman-adv/bat_v_ogm.c | 4 ++-- net/batman-adv/originator.c | 35 +-- net/batman-adv/originator.h | 6 +++--- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index ce2f203..aa11296 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -336,7 +336,8 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, { struct batadv_neigh_node *neigh_node; - neigh_node = batadv_neigh_node_new(orig_node, hard_iface, neigh_addr); + neigh_node = batadv_neigh_node_get_or_create(orig_node, +hard_iface, neigh_addr); if (!neigh_node) goto out; diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index df42eb1..8909d1e 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c @@ -443,7 +443,8 @@ static void batadv_v_elp_neigh_update(struct batadv_priv *bat_priv, if (!orig_neigh) return; - neigh = batadv_neigh_node_new(orig_neigh, if_incoming, neigh_addr); + neigh = batadv_neigh_node_get_or_create(orig_neigh, + if_incoming, neigh_addr); if (!neigh) goto orig_free; diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index 473ebb9..23ea9bf 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@ -683,8 +683,8 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset, if (!orig_node) return; - neigh_node = batadv_neigh_node_new(orig_node, if_incoming, - ethhdr->h_source); + neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming, +ethhdr->h_source); if (!neigh_node) goto out; diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 7f51bc2..b0bad57 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -602,19 +602,19 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, } /** - * batadv_neigh_node_new - create and init a new neigh_node object + * batadv_neigh_node_create - create a neigh node object * @orig_node: originator object representing the neighbour * @hard_iface: the interface where the neighbour is connected to * @neigh_addr: the mac address of the neighbour interface * * Allocates a new neigh_node object and initialises all the generic fields. * - * Return: neighbor when found. Othwerwise NULL + * Return: the neighbour node if found or created or NULL otherwise. */ -struct batadv_neigh_node * -batadv_neigh_node_new(struct batadv_orig_node *orig_node, - struct batadv_hard_iface *hard_iface, - const u8 *neigh_addr) +static struct batadv_neigh_node * +batadv_neigh_node_create(struct batadv_orig_node *orig_node, +struct batadv_hard_iface *hard_iface, +const u8 *neigh_addr) { struct batadv_neigh_node *neigh_node; struct batadv_hardif_neigh_node *hardif_neigh = NULL; @@ -667,6 +667,29 @@ out: } /** + * batadv_neigh_node_get_or_create - retrieve or create a neigh node object + * @orig_node: originator object representing the neighbour + * @hard_iface: the interface where the neighbour is connected to + * @neigh_addr: the mac address of the neighbour interface + * + * Return: the neighbour node if found or created or NULL otherwise. + */ +struct batadv_neigh_node * +batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node, + struct batadv_hard_iface *hard_iface, + const u8 *neigh_addr) +{ + struct batadv_neigh_node *neigh_node = NULL; + + /* first check without locking to avoid the overhead */ + neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); + if (neigh_node) + return neigh_node; + + return batadv_neigh_node_create(orig_node, hard_iface, neigh_addr); +} + +/** * batadv_hardif_neigh_seq_print_text - print the single hop neighbour list * @seq: neighbour table seq_file struct * @offset: not used diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 64a8951..566306b 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -46,9 +46,9 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, void batadv_hardif_neigh_put(struct batadv_hardif_neigh_node *hardif_neigh); struct batadv_neigh_node * -batadv_neigh_node_new(struct batadv_orig_node *orig_no
[B.A.T.M.A.N.] [PATCH 04/17] batman-adv: document sysfs files in alphabetical order
From: Marek Lindner Also update obsolete email address. Signed-off-by: Marek Lindner Acked-by: Antonio Quartulli Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- Documentation/ABI/testing/sysfs-class-net-batman-adv | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-class-net-batman-adv b/Documentation/ABI/testing/sysfs-class-net-batman-adv index 518f6a1..77d3083 100644 --- a/Documentation/ABI/testing/sysfs-class-net-batman-adv +++ b/Documentation/ABI/testing/sysfs-class-net-batman-adv @@ -1,13 +1,4 @@ -What: /sys/class/net//batman-adv/throughput_override -Date: Feb 2014 -Contact: Antonio Quartulli -description: - Defines the throughput value to be used by B.A.T.M.A.N. V - when estimating the link throughput using this interface. - If the value is set to 0 then batman-adv will try to - estimate the throughput by itself. - What: /sys/class/net//batman-adv/elp_interval Date: Feb 2014 Contact:Linus Lüssing @@ -28,3 +19,12 @@ Description: The /sys/class/net//batman-adv/mesh_iface file displays the batman mesh interface this currently is associated with. + +What: /sys/class/net//batman-adv/throughput_override +Date: Feb 2014 +Contact:Antonio Quartulli +description: +Defines the throughput value to be used by B.A.T.M.A.N. V +when estimating the link throughput using this interface. +If the value is set to 0 then batman-adv will try to +estimate the throughput by itself. -- 2.8.1
[B.A.T.M.A.N.] [PATCH 05/17] batman-adv: update elp interval documentation
From: Marek Lindner Signed-off-by: Marek Lindner Acked-by: Antonio Quartulli Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- Documentation/ABI/testing/sysfs-class-net-batman-adv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-class-net-batman-adv b/Documentation/ABI/testing/sysfs-class-net-batman-adv index 77d3083..8981068 100644 --- a/Documentation/ABI/testing/sysfs-class-net-batman-adv +++ b/Documentation/ABI/testing/sysfs-class-net-batman-adv @@ -4,7 +4,7 @@ Date: Feb 2014 Contact:Linus Lüssing Description: Defines the interval in milliseconds in which batman -sends its probing packets for link quality measurements. +emits probing packets for neighbor sensing (ELP). What: /sys/class/net//batman-adv/iface_status Date: May 2010 -- 2.8.1
[B.A.T.M.A.N.] [PATCH 03/17] batman-adv: remove unused vid local variable in tt seq print
Signed-off-by: Simon Wunderlich Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner --- net/batman-adv/translation-table.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index feaf492b..87bb203 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -995,7 +995,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) struct batadv_tt_local_entry *tt_local; struct batadv_hard_iface *primary_if; struct hlist_head *head; - unsigned short vid; u32 i; int last_seen_secs; int last_seen_msecs; @@ -1022,7 +1021,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) tt_local = container_of(tt_common_entry, struct batadv_tt_local_entry, common); - vid = tt_common_entry->vid; last_seen_jiffies = jiffies - tt_local->last_seen; last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); last_seen_secs = last_seen_msecs / 1000; -- 2.8.1
[B.A.T.M.A.N.] [PATCH 02/17] batman-adv: statically print gateway table header
From: Antonio Quartulli To make it easier to search through the code it is better to print static strings directly instead of using format strings printing constants. This was addressed in a previous patch, but the Gateway table header was not updated accordingly. Signed-off-by: Antonio Quartulli Reviewed-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Simon Wunderlich --- net/batman-adv/gateway_client.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 5839c56..b9d72e9 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -638,8 +638,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) goto out; seq_printf(seq, - " %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", - "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", + " Gateway (#/255) Nexthop [outgoingIF]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", BATADV_SOURCE_VERSION, primary_if->net_dev->name, primary_if->net_dev->dev_addr, net_dev->name); -- 2.8.1
[B.A.T.M.A.N.] [PATCH 01/17] batman-adv: Start new development cycle
Signed-off-by: Simon Wunderlich Signed-off-by: Sven Eckelmann --- net/batman-adv/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 76925266..c356d91 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -24,7 +24,7 @@ #define BATADV_DRIVER_DEVICE "batman-adv" #ifndef BATADV_SOURCE_VERSION -#define BATADV_SOURCE_VERSION "2016.2" +#define BATADV_SOURCE_VERSION "2016.3" #endif /* B.A.T.M.A.N. parameters */ -- 2.8.1
[B.A.T.M.A.N.] pull request for net-next: batman-adv 2016-07-01
Hi David, we are a bit late to submit our feature patches, but I hope we make it in time. Antonio is taking a pause in his upstream work, so I'll be submitting our batman-adv patches for now. It is my first time, so please bear with me. :) Please pull or let me know of any problem! Thank you, Simon The following changes since commit 99860208bc62d8ebd5c57495b84856506fe075bc: sched: remove NET_XMIT_POLICED (2016-06-12 22:02:11 -0400) are available in the git repository at: git://git.open-mesh.org/linux-merge.git tags/batadv-next-for-davem-20160701 for you to fetch changes up to 4e3e823b5a503235630921287f130e1d8d22d200: batman-adv: Add debugfs table for mcast flags (2016-06-30 10:29:43 +0200) This feature patchset includes the following changes: - two patches with minimal clean up work by Antonio Quartulli and Simon Wunderlich - eight patches of B.A.T.M.A.N. V, API and documentation clean up work, by Antonio Quartulli and Marek Lindner - Andrew Lunn fixed the skb priority adoption when forwarding fragmented packets (two patches) - Multicast optimization support is now enabled for bridges which comes with some protocol updates, by Linus Luessing Andrew Lunn (2): batman-adv: Set skb priority in fragments batman-adv: Include frame priority in fragment header Antonio Quartulli (4): batman-adv: statically print gateway table header batman-adv: remove ogm_emit and ogm_schedule API calls batman-adv: remove useless inline attribute for sysfs helper function batman-adv: move GW mode and selection class to private data structure Linus Lüssing (4): batman-adv: Always flood IGMP/MLD reports batman-adv: Add multicast optimization support for bridged setups batman-adv: Adding logging of mcast flag changes batman-adv: Add debugfs table for mcast flags Marek Lindner (5): batman-adv: document sysfs files in alphabetical order batman-adv: update elp interval documentation batman-adv: refactor batadv_neigh_node_* functions to follow common style batman-adv: remove unused callback from batadv_algo_ops struct batman-adv: init ELP tweaking options only once Simon Wunderlich (2): batman-adv: Start new development cycle batman-adv: remove unused vid local variable in tt seq print .../ABI/testing/sysfs-class-net-batman-adv | 20 +- net/batman-adv/Kconfig | 2 +- net/batman-adv/bat_algo.h | 7 +- net/batman-adv/bat_iv_ogm.c| 72 ++- net/batman-adv/bat_v.c | 29 +- net/batman-adv/bat_v_elp.c | 4 +- net/batman-adv/bat_v_ogm.c | 4 +- net/batman-adv/debugfs.c | 23 + net/batman-adv/fragmentation.c | 12 +- net/batman-adv/gateway_client.c| 15 +- net/batman-adv/gateway_common.c| 6 +- net/batman-adv/hard-interface.c| 6 +- net/batman-adv/main.c | 2 - net/batman-adv/main.h | 6 +- net/batman-adv/multicast.c | 499 +++-- net/batman-adv/multicast.h | 3 + net/batman-adv/originator.c| 40 +- net/batman-adv/originator.h| 6 +- net/batman-adv/packet.h| 7 +- net/batman-adv/routing.c | 2 + net/batman-adv/send.c | 61 +-- net/batman-adv/send.h | 4 +- net/batman-adv/soft-interface.c| 10 +- net/batman-adv/sysfs.c | 22 +- net/batman-adv/translation-table.c | 2 - net/batman-adv/types.h | 32 +- 26 files changed, 704 insertions(+), 192 deletions(-) -- 2.8.1
Re: [B.A.T.M.A.N.] [PATCH 2/2] batman-adv: Use broadcast as fallback for gateway replies
[] > Hm, I'm wondering what kind of overhead implications this could > have in larger mesh networks. > > Didn't TT support temporary entries? Could the gateway server > inject them into its global translation table after parsing an > incoming DHCP packet? Right now we have the problem that DHCP requests (broadcasts by the user) are encapsulated by the gateway code in the wrong type of packet [1,2,3]. These are the unicast packets (non-4addr) which cannot be used to create temporary TT entries. This should be addressed by the first patch. The second patch is currently only my bandaid (because I cannot patch all APs) and I would be more than happy when this patch is not required. So I would not object when this patch is rejected because it causes noise on the network. For example gluon already accepted the first patch [4] and thus will hopefully not require the second patch anymore with 2016.2.0 for clients doing their DHCP Discover as broadcast. Btw. the non-RFC version of the patch is here: https://patchwork.open-mesh.org/patch/16377/ I have taken the freedom to move the reply to this patch. Kind regards, Sven [1] https://patchwork.open-mesh.org/patch/16376/ [2] https://git.open-mesh.org/batman-adv.git/blob/a36b7a3b08f4cc7c41103aa4db176a11e965e068:/net/batman-adv/routing.c#l914 [3] https://git.open-mesh.org/batman-adv.git/blob/a36b7a3b08f4cc7c41103aa4db176a11e965e068:/net/batman-adv/soft-interface.c#l468 [4] https://github.com/freifunk-gluon/gluon/commit/93fe275000b65a4148d6a9713a030b0d30e6a9f1 signature.asc Description: This is a digitally signed message part.
Re: [B.A.T.M.A.N.] [RFC 2/2] batman-adv: Use broadcast as fallback for gateway replies
On Sat, Jun 11, 2016 at 10:27:53PM +0200, Sven Eckelmann wrote: > The replies from gateway server to gateway client are usually sent via > unicast packets. This only works when the destination address for the reply > is already known to the translation table. But usually the gateway replies > are in response to the first known contact from a device to the gateway > server. So it can happen that the TT entry was not yet created. > > The gateway server has therefore use broadcast as fallback when the entry > is not yet known. This makes the first responses from a DHCP server to a > DHCP client more robost. > > Signed-off-by: Sven Eckelmann > --- > This is completely untested. The RFC was submitted to better explain a > problem to Antonio. This problems was noticed in real world setups but > these patches were not yet tested in these setups. Hm, I'm wondering what kind of overhead implications this could have in larger mesh networks. Didn't TT support temporary entries? Could the gateway server inject them into its global translation table after parsing an incoming DHCP packet?