Message ID | 1462525107-19750-3-git-send-email-apape@phoenixcontact.com |
---|---|
State | Superseded, archived |
Delegated to: | Marek Lindner |
Headers | show |
On Friday 06 May 2016 10:58:23 Andreas Pape wrote: > diff --git a/net/batman-adv/soft-interface.c > b/net/batman-adv/soft-interface.c index 81665b1..1f1742a 100644 > --- a/net/batman-adv/soft-interface.c > +++ b/net/batman-adv/soft-interface.c > @@ -28,6 +28,7 @@ > #include <linux/fs.h> > #include <linux/if_ether.h> > #include <linux/if_vlan.h> > +#include <linux/ip.h> > #include <linux/jiffies.h> > #include <linux/kernel.h> > #include <linux/kref.h> Haven't really looked at your patchset but was just interested in this new function. But I didn't came to look at it because I saw this weird include. Doesn't seem to make sense here at all when you look at the rest of the changes in this file: > @@ -442,6 +443,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_type_trans(skb, soft_iface); Kind regards, Sven
Hi, just some ideas (maybe not all of them are good): [...] > + 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) > + break; Do we need to continue here when there is no vhdr? Maybe just return. > + if (ntohs(vhdr->h_vlan_encapsulated_proto) == ETH_P_IP) { Maybe the check here could be inverted to just return when this is not ETH_P_IP > + iphdr = skb_header_pointer(skb, sizeof(tmp_vhdr), > + sizeof(tmp_iphdr), > + &tmp_iphdr); > + } > + break; > + } > + > + if (iphdr) { You could just modify the check to: if (!iphdr) return; Kind regards, Sven
On Fri, May 06, 2016 at 10:58:23AM +0200, 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 <apape@phoenixcontact.com> > --- This patch looks interesting :). Currently we have quite some ARP-requests from gateways to clients left in Freifunk setups (had been asking Antonio about it just yesterday) and looks like this patch could help here. > +void batadv_dat_entry_check(struct batadv_priv *bat_priv, struct sk_buff *skb, > + unsigned short vid) > +{ [...] > + batadv_dat_entry_add(bat_priv, iphdr->saddr, > + ethhdr->h_source, vid); > + } > +} There is something in batadv_dat_entry_add() that makes me a little worried: ---- if (dat_entry) { if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr)) ether_addr_copy(dat_entry->mac_addr, mac_addr); ---- ether_addr_copy() isn't atomic, there is a race condition between the update and any such check - like the one just above it. This isn't really a bug of your patchset, but could make this race condition much more likely. In the worst case, a fast IP packet stream would create a constant rewrite and mostly broken dat_entry->mac_addr.
On Fri, May 06, 2016 at 10:58:23AM +0200, Andreas Pape wrote: > +void batadv_dat_entry_check(struct batadv_priv *bat_priv, struct sk_buff *skb, > + unsigned short vid) > +{ [...] > + if (iphdr) { > + 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); > + } Not sure whether it is necessary, or whether there is a check somewhere later within DAT. But should we exclude some iphdr->saddr or ethhdr->h_source addresses? For instance a DHCPDISCOVER usually has a zero-ip address.
> Not sure whether it is necessary, or whether there is a check > somewhere later within DAT. But should we exclude some > iphdr->saddr or ethhdr->h_source addresses? For instance a > DHCPDISCOVER usually has a zero-ip address. And speaking of DHCP, do you (or anyone else) know, whether a dhcp-server (or its kernel) sends an ARP request before sending a unicast DHCPOFFER? Or do dhcp-servers usually craft DHCPOFFERs in userspace within their daemon including the ethernet header? If the latter is the case, maybe we could/should dat-snoop the ethernet+IP destination of such DHCPOFFERs in interface_rx(), too?
On Thu, May 19, 2016 at 09:33:12PM +0200, Linus Lüssing wrote: > This isn't really a bug of your patchset, but could make this race > condition much more likely. In the worst case, a fast IP packet > stream would create a constant rewrite and mostly broken > dat_entry->mac_addr. Sorry, this was wrong of me. Assuming no address collision, then this would result to up to one unnecessary ether_addr_copy() on 32bit but no broken dat_entry->mac_addr. So shouldn't be an issue, sorry.
On Thu, May 19, 2016 at 10:30:49PM +0200, Linus Lüssing wrote: > > Not sure whether it is necessary, or whether there is a check > > somewhere later within DAT. But should we exclude some > > iphdr->saddr or ethhdr->h_source addresses? For instance a > > DHCPDISCOVER usually has a zero-ip address. > > And speaking of DHCP, do you (or anyone else) know, whether a > dhcp-server (or its kernel) sends an ARP request before sending > a unicast DHCPOFFER? Or do dhcp-servers usually craft DHCPOFFERs > in userspace within their daemon including the ethernet header? > > If the latter is the case, maybe we could/should dat-snoop the > ethernet+IP destination of such DHCPOFFERs in interface_rx(), > too? Did a quick try in VMs with two standard Debian unstable machines using isc-dhcp-client and -server. Also enabled "ping-check false" on the dhcp-server. Then I do not see any ARP messages, I just see four DHCP packets (see below). And "ip neigh" stays empty. So it seems that at least the isc-dhcp-server can assemble raw packets, including the ethernet frame (*). So the DHCPOFFER's ethernet and IP destinations on a batadv_interface_tx() (sorry, wrongly wrote _rx() above) would give us an even earlier opportunity to feed DAT from. Would that make sense to do so? (*): Though looking at the code of isc-dhcpd, there seem to be compile-time options for two more, different send_packet() functions which do not always do that. ----- tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 22:32:03.379281 02:04:64:a4:39:e2 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 342: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328) 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 02:04:64:a4:39:e2 (oui Unknown), length 300, xid 0x17feeb29, Flags [none] Client-Ethernet-Address 02:04:64:a4:39:e2 (oui Unknown) Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Discover Hostname Option 12, length 12: "Linus-Debian" Parameter-Request Option 55, length 13: Subnet-Mask, BR, Time-Zone, Default-Gateway Domain-Name, Domain-Name-Server, Option 119, Hostname Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route NTP 22:32:03.385454 02:04:64:a4:39:c3 (oui Unknown) > 02:04:64:a4:39:e2 (oui Unknown), ethertype IPv4 (0x0800), length 342: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328) 192.168.123.1.bootps > 192.168.123.50.bootpc: BOOTP/DHCP, Reply, length 300, xid 0x17feeb29, Flags [none] Your-IP 192.168.123.50 Client-Ethernet-Address 02:04:64:a4:39:e2 (oui Unknown) Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Offer Server-ID Option 54, length 4: 192.168.123.1 Lease-Time Option 51, length 4: 600 Subnet-Mask Option 1, length 4: 255.255.255.0 Default-Gateway Option 3, length 4: 192.168.123.1 Domain-Name-Server Option 6, length 4: 192.168.123.1 22:32:03.386571 02:04:64:a4:39:e2 (oui Unknown) > Broadcast, ethertype IPv4 (0x0800), length 342: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328) 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 02:04:64:a4:39:e2 (oui Unknown), length 300, xid 0x17feeb29, Flags [none] Client-Ethernet-Address 02:04:64:a4:39:e2 (oui Unknown) Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Request Server-ID Option 54, length 4: 192.168.123.1 Requested-IP Option 50, length 4: 192.168.123.50 Hostname Option 12, length 12: "Linus-Debian" Parameter-Request Option 55, length 13: Subnet-Mask, BR, Time-Zone, Default-Gateway Domain-Name, Domain-Name-Server, Option 119, Hostname Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route NTP 22:32:03.398683 02:04:64:a4:39:c3 (oui Unknown) > 02:04:64:a4:39:e2 (oui Unknown), ethertype IPv4 (0x0800), length 342: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328) 192.168.123.1.bootps > 192.168.123.50.bootpc: BOOTP/DHCP, Reply, length 300, xid 0x17feeb29, Flags [none] Your-IP 192.168.123.50 Client-Ethernet-Address 02:04:64:a4:39:e2 (oui Unknown) Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: ACK Server-ID Option 54, length 4: 192.168.123.1 Lease-Time Option 51, length 4: 600 Subnet-Mask Option 1, length 4: 255.255.255.0 Default-Gateway Option 3, length 4: 192.168.123.1 Domain-Name-Server Option 6, length 4: 192.168.123.1 -----
On Thu, May 19, 2016 at 10:30:49PM +0200, Linus Lüssing wrote: > Or do dhcp-servers usually craft DHCPOFFERs > in userspace within their daemon including the ethernet header? Just noticed, they have to. The dhcp-server has to fill in the ethernet destination as the kernel cannot provide it via ARP yet - because the dhcp-client has no IP address yet :).
"B.A.T.M.A.N" <b.a.t.m.a.n-bounces@lists.open-mesh.org> schrieb am 19.05.2016 21:45:53: > Von: Linus Lüssing <linus.luessing@c0d3.blue> > An: The list for a Better Approach To Mobile Ad-hoc Networking > <b.a.t.m.a.n@lists.open-mesh.org> > Datum: 19.05.2016 21:47 > Betreff: Re: [B.A.T.M.A.N.] [PATCHv3 2/6] batman-adv: speed up dat > by snooping received ip traffic > Gesendet von: "B.A.T.M.A.N" <b.a.t.m.a.n-bounces@lists.open-mesh.org> > > On Fri, May 06, 2016 at 10:58:23AM +0200, Andreas Pape wrote: > > +void batadv_dat_entry_check(struct batadv_priv *bat_priv, struct > sk_buff *skb, > > + unsigned short vid) > > +{ > [...] > > + if (iphdr) { > > + 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); > > + } > > Not sure whether it is necessary, or whether there is a check > somewhere later within DAT. But should we exclude some > iphdr->saddr or ethhdr->h_source addresses? For instance a > DHCPDISCOVER usually has a zero-ip address. I think you have a good point here. Excluding especially ip addresses like zero-ip address seems reasonable. Although I think that this isn't a problem as long as no one is sending arp requests for such ip addresses, filling the dat table with unreasonable entries isn't a smart idea either. I will add some additional tests here for reasonable ip addresses for the next version of the patchset. Thanks and regards, Andreas .................................................................. PHOENIX CONTACT ELECTRONICS GmbH Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont USt-Id-Nr.: DE811742156 Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528 Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
On Fri, May 20, 2016 at 01:32:35PM +0200, Andreas Pape wrote: > "B.A.T.M.A.N" <b.a.t.m.a.n-bounces@lists.open-mesh.org> schrieb am > 19.05.2016 21:45:53: > > > Von: Linus Lüssing <linus.luessing@c0d3.blue> > > An: The list for a Better Approach To Mobile Ad-hoc Networking > > <b.a.t.m.a.n@lists.open-mesh.org> > > Datum: 19.05.2016 21:47 > > Betreff: Re: [B.A.T.M.A.N.] [PATCHv3 2/6] batman-adv: speed up dat > > by snooping received ip traffic > > Gesendet von: "B.A.T.M.A.N" <b.a.t.m.a.n-bounces@lists.open-mesh.org> > > > > On Fri, May 06, 2016 at 10:58:23AM +0200, Andreas Pape wrote: > > > +void batadv_dat_entry_check(struct batadv_priv *bat_priv, struct > > sk_buff *skb, > > > + unsigned short vid) > > > +{ > > [...] > > > + if (iphdr) { > > > + 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); > > > + } > > > > Not sure whether it is necessary, or whether there is a check > > somewhere later within DAT. But should we exclude some > > iphdr->saddr or ethhdr->h_source addresses? For instance a > > DHCPDISCOVER usually has a zero-ip address. > > I think you have a good point here. Excluding especially > ip addresses like zero-ip address seems reasonable. Although > I think that this isn't a problem as long as no one is sending > arp requests for such ip addresses, filling the dat table with > unreasonable entries isn't a smart idea either. I will add some > additional tests here for reasonable ip addresses for the next > version of the patchset. We already have some checks in the snooping functions that are performed when calling batadv_arp_get_type(). Aren't those enough ? Cheers,
On Fri, May 06, 2016 at 10:58:23AM +0200, 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. Any IP packet can't be sent if an ARP "handshake" has not been performed. This means that when you are snooping an IP packet you have already snooped an ARP packet slightly before. In which case do we really win something ? On top of that, don't you think that snooping *every* packet will badly affect the performance ? Have you tried measuring the difference ? Cheers,
"B.A.T.M.A.N" <b.a.t.m.a.n-bounces@lists.open-mesh.org> schrieb am 20.05.2016 15:51:38: > Von: Antonio Quartulli <a@unstable.cc> > An: The list for a Better Approach To Mobile Ad-hoc Networking > <b.a.t.m.a.n@lists.open-mesh.org> > Datum: 20.05.2016 15:52 > Betreff: Re: [B.A.T.M.A.N.] [PATCHv3 2/6] batman-adv: speed up dat > by snooping received ip traffic > Gesendet von: "B.A.T.M.A.N" <b.a.t.m.a.n-bounces@lists.open-mesh.org> > > On Fri, May 06, 2016 at 10:58:23AM +0200, 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. > > Any IP packet can't be sent if an ARP "handshake" has not been performed. This > means that when you are snooping an IP packet you have already snooped an ARP > packet slightly before. In which case do we really win something ? > In case of a static mesh ("static" in terms of non-moving mesh nodes and when the mesh nodes almost always use the same backbone gateways for a common wired backbone) we gain nothing by snooping every packet. The idea came up when I started experimenting with more dynamic setups where the mesh nodes move around with several gateways into a common wired backbone. In this case routing becomes more dynamically and it is not assured that the traffic from/for a mesh node is always routed via the same gateway which has already snooped the arp traffic. > On top of that, don't you think that snooping *every* packet will badly affect > the performance ? Have you tried measuring the difference ? > I'm aware that this has an impact. I can try to measure the difference using my devices but these results of course are related to the hardware I use. I'm lacking experience if such results can be used to generalize a conclusion. On the other hand this "feature" was not the root cause to post this patchset. More important for me is the prevention of the "arp reply storms" and the temporary loops between backbone network and the mesh because this generates trouble in my application. If it increases the propability for acceptance I don't care to remove the ip source address snooping from the patchset. Best regards, Andreas .................................................................. PHOENIX CONTACT ELECTRONICS GmbH Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont USt-Id-Nr.: DE811742156 Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528 Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
Hi, On IRC, Matthias just pointed out another, conceptual issue with this patch: It snoops routed traffic, too. So we would end up with DAT entries for every internet host as well :(. Regards, Linus
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index c11f035..58cb488 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -27,6 +27,7 @@ #include <linux/if_arp.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> +#include <linux/ip.h> #include <linux/in.h> #include <linux/jiffies.h> #include <linux/kernel.h> @@ -362,6 +363,55 @@ 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) + break; + if (ntohs(vhdr->h_vlan_encapsulated_proto) == ETH_P_IP) { + iphdr = skb_header_pointer(skb, sizeof(tmp_vhdr), + sizeof(tmp_iphdr), + &tmp_iphdr); + } + break; + } + + if (iphdr) { + 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..1f1742a 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -28,6 +28,7 @@ #include <linux/fs.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> +#include <linux/ip.h> #include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/kref.h> @@ -442,6 +443,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_type_trans(skb, soft_iface);
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 <apape@phoenixcontact.com> --- net/batman-adv/distributed-arp-table.c | 50 ++++++++++++++++++++++++++++++++ net/batman-adv/distributed-arp-table.h | 9 +++++- net/batman-adv/soft-interface.c | 4 ++ 3 files changed, 62 insertions(+), 1 deletions(-) -- 1.7.0.4 .................................................................. PHOENIX CONTACT ELECTRONICS GmbH Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont USt-Id-Nr.: DE811742156 Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528 Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck