flow_dissector: Parse batman-adv unicast headers

Message ID 20171127123341.11365-1-sven.eckelmann@openmesh.com (mailing list archive)
State RFC, archived
Delegated to: Simon Wunderlich
Headers
Series flow_dissector: Parse batman-adv unicast headers |

Commit Message

Sven Eckelmann Nov. 27, 2017, 12:33 p.m. UTC
  The batman-adv unicast packets contain a full layer 2 frame in encapsulated
form. The flow dissector must therefore be able to parse the batman-adv
unicast header to reach the layer 2+3 information to allow RPS to schedule
the flow to different cores.

Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
---

I've played around with the RPS+XPS to better distribute traffic to
different cores on modern SoCs. It was observed that the batman-adv unicast
traffic stayed at one core and this limited the overall throughput.

The test was done between a modern PC which was running iperf over
batman-adv. Another PC was also running iperf was just transmitting the
traffic over ethernet. A QCA Dakota (IPQ4018) based device was in the
middle and received the ethernet traffic on one port, encapsulated it as
batman-adv unicast and transferred the resulting packet via ethernet to the
modern PC.

    $ iperf -c 192.168.23.2 -t 30 -i 1  -P16

It was observed that only the receive processing was affected. Adding this
relative simple patch allowed me to increase the ethernet throughput from
689 Mbits/sec (with one core doing the interrupt processing and 1 core
completely busy with the other processing) to 910 Mbits/sec (one core doing
the interrupt processing and the other 3 cores were sharing the load). In
theory, the device with the patch could have handled a lot more traffic
than 910 Mbit/sec - at least the RPS cores were not even near 100% load.

This should bring a lot more when testing with good 802.11ac WiFi links
because the wifi stack/driver are usually stressing the CPU a lot more than
normal ethernet drivers.

The change itself is not really invasive but could be a lot cleaner when
the packet header information would be available under include/... . And I
don't know yet whether it would make sense to add a new flow dissector key
with the batman-adv destination address. This is also the reason why I only
post this to the b.a.t.m.a.n@lists.open-mesh.org mailing list.

Anyway, maybe some other people ran into the same problem and want to test
it.
---
 net/core/flow_dissector.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
  

Comments

Sven Eckelmann Nov. 27, 2017, 12:36 p.m. UTC | #1
On Montag, 27. November 2017 13:33:41 CET Sven Eckelmann wrote:
> The batman-adv unicast packets contain a full layer 2 frame in encapsulated
> form. The flow dissector must therefore be able to parse the batman-adv
> unicast header to reach the layer 2+3 information to allow RPS to schedule
> the flow to different cores.
> 
> Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
> ---
[...]

Arghh, this should have been an RFC. I will mark it this way in patchwork but 
please don't be confused on the mailing list about the subject.

Kind regards,
	Sven
  

Patch

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 0a977373d003..bbf894fff3fc 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -595,6 +595,39 @@  bool __skb_flow_dissect(const struct sk_buff *skb,
 
 		break;
 	}
+	case htons(ETH_P_BATMAN): {
+		/* TODO provide struct in include/uapi/... header */
+		struct batadv_unicast_packet {
+			u8 packet_type;
+			u8 version;
+			u8 ttl;
+			u8 ttvn;
+			u8 dest[ETH_ALEN];
+		};
+
+		struct {
+			struct batadv_unicast_packet batadv_unicast;
+			struct ethhdr eth;
+		} *hdr, _hdr;
+
+		hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen,
+					   &_hdr);
+		if (!hdr)
+			goto out_bad;
+
+		if (hdr->batadv_unicast.version != 15)
+			break;
+
+		if (hdr->batadv_unicast.packet_type != 0x40)
+			break;
+
+		/* TODO set batman-adv dest address as flow key? */
+
+		proto = hdr->eth.h_proto;
+		nhoff += sizeof(*hdr);
+
+		goto again;
+	}
 	case htons(ETH_P_8021AD):
 	case htons(ETH_P_8021Q): {
 		const struct vlan_hdr *vlan;