|
|
|
From: Sven Eckelmann <sven.eckelmann@openmesh.com>
|
|
|
|
Date: Thu, 21 Dec 2017 10:17:42 +0100
|
|
|
|
Subject: [PATCH] flow_dissector: Parse batman-adv unicast headers
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
+--------------------+
|
|
|
|
| ip(v6)hdr |
|
|
|
|
+--------------------+
|
|
|
|
| inner ethhdr |
|
|
|
|
+--------------------+
|
|
|
|
| batadv unicast hdr |
|
|
|
|
+--------------------+
|
|
|
|
| outer ethhdr |
|
|
|
|
+--------------------+
|
|
|
|
|
|
|
|
The obtained information from the upper layer can then be used by RPS to
|
|
|
|
schedule the processing on separate cores. This allows better distribution
|
|
|
|
of multiple flows from the same neighbor to different cores.
|
|
|
|
|
|
|
|
Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
|
|
|
|
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
|
|
|
|
Acked-by: Willem de Bruijn <willemb@google.com>
|
|
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
|
---
|
|
|
|
|
|
|
|
--- a/net/core/flow_dissector.c
|
|
|
|
+++ b/net/core/flow_dissector.c
|
|
|
|
@@ -22,6 +22,7 @@
|
|
|
|
#include <linux/tcp.h>
|
|
|
|
#include <net/flow_dissector.h>
|
|
|
|
#include <scsi/fc/fc_fcoe.h>
|
|
|
|
+#include <uapi/linux/batadv_packet.h>
|
|
|
|
|
|
|
|
static void dissector_set_key(struct flow_dissector *flow_dissector,
|
|
|
|
enum flow_dissector_key_id key_id)
|
|
|
|
@@ -338,6 +339,57 @@ __skb_flow_dissect_gre(const struct sk_b
|
|
|
|
return FLOW_DISSECT_RET_PROTO_AGAIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * __skb_flow_dissect_batadv() - dissect batman-adv header
|
|
|
|
+ * @skb: sk_buff to with the batman-adv header
|
|
|
|
+ * @key_control: flow dissectors control key
|
|
|
|
+ * @data: raw buffer pointer to the packet, if NULL use skb->data
|
|
|
|
+ * @p_proto: pointer used to update the protocol to process next
|
|
|
|
+ * @p_nhoff: pointer used to update inner network header offset
|
|
|
|
+ * @hlen: packet header length
|
|
|
|
+ * @flags: any combination of FLOW_DISSECTOR_F_*
|
|
|
|
+ *
|
|
|
|
+ * ETH_P_BATMAN packets are tried to be dissected. Only
|
|
|
|
+ * &struct batadv_unicast packets are actually processed because they contain an
|
|
|
|
+ * inner ethernet header and are usually followed by actual network header. This
|
|
|
|
+ * allows the flow dissector to continue processing the packet.
|
|
|
|
+ *
|
|
|
|
+ * Return: FLOW_DISSECT_RET_PROTO_AGAIN when &struct batadv_unicast was found,
|
|
|
|
+ * FLOW_DISSECT_RET_OUT_GOOD when dissector should stop after encapsulation,
|
|
|
|
+ * otherwise FLOW_DISSECT_RET_OUT_BAD
|
|
|
|
+ */
|
|
|
|
+static enum flow_dissect_ret
|
|
|
|
+__skb_flow_dissect_batadv(const struct sk_buff *skb,
|
|
|
|
+ struct flow_dissector_key_control *key_control,
|
|
|
|
+ void *data, __be16 *p_proto, int *p_nhoff, int hlen,
|
|
|
|
+ unsigned int flags)
|
|
|
|
+{
|
|
|
|
+ struct {
|
|
|
|
+ struct batadv_unicast_packet batadv_unicast;
|
|
|
|
+ struct ethhdr eth;
|
|
|
|
+ } *hdr, _hdr;
|
|
|
|
+
|
|
|
|
+ hdr = __skb_header_pointer(skb, *p_nhoff, sizeof(_hdr), data, hlen,
|
|
|
|
+ &_hdr);
|
|
|
|
+ if (!hdr)
|
|
|
|
+ return FLOW_DISSECT_RET_OUT_BAD;
|
|
|
|
+
|
|
|
|
+ if (hdr->batadv_unicast.version != BATADV_COMPAT_VERSION)
|
|
|
|
+ return FLOW_DISSECT_RET_OUT_BAD;
|
|
|
|
+
|
|
|
|
+ if (hdr->batadv_unicast.packet_type != BATADV_UNICAST)
|
|
|
|
+ return FLOW_DISSECT_RET_OUT_BAD;
|
|
|
|
+
|
|
|
|
+ *p_proto = hdr->eth.h_proto;
|
|
|
|
+ *p_nhoff += sizeof(*hdr);
|
|
|
|
+
|
|
|
|
+ key_control->flags |= FLOW_DIS_ENCAPSULATION;
|
|
|
|
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
|
|
|
|
+ return FLOW_DISSECT_RET_OUT_GOOD;
|
|
|
|
+
|
|
|
|
+ return FLOW_DISSECT_RET_PROTO_AGAIN;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
__skb_flow_dissect_tcp(const struct sk_buff *skb,
|
|
|
|
struct flow_dissector *flow_dissector,
|
|
|
|
@@ -718,6 +770,11 @@ proto_again:
|
|
|
|
nhoff, hlen);
|
|
|
|
break;
|
|
|
|
|
|
|
|
+ case htons(ETH_P_BATMAN):
|
|
|
|
+ fdret = __skb_flow_dissect_batadv(skb, key_control, data,
|
|
|
|
+ &proto, &nhoff, hlen, flags);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
default:
|
|
|
|
fdret = FLOW_DISSECT_RET_OUT_BAD;
|
|
|
|
break;
|