123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- 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,
- @@ -722,6 +774,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;
|