@@ -37,6 +37,22 @@ static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb)
return (struct ethhdr *)skb_inner_mac_header(skb);
}
+/* This determines the ethertype incoded into the skb data without
+ * relying on skb->protocol which is not always identical.
+ */
+static inline u16 skb_eth_raw_ethertype(struct sk_buff *skb)
+{
+ struct ethhdr *hdr;
+
+ /* If we can't extract a header, return invalid type */
+ if (!pskb_may_pull(skb, ETH_HLEN))
+ return 0x0000U;
+
+ hdr = skb_eth_hdr(skb);
+
+ return ntohs(hdr->h_proto);
+}
+
int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
There are circumstances where the skb->protocol can not be trusted, such as when using DSA switches that add a custom ethertype to the ethernet packet, which is later on supposed to be stripped by the switch hardware connected to the conduit ethernet interface. Since ethernet drivers transmitting such frames with alien ethertypes can have hardware that will get confused by custom ethertypes they need a way to retrieve and act on any such type. The new eth_skb_raw_ethertype() helper will extract the ethertype directly from the skb->data using the ethernet and (if necessary) VLAN helper functions, and return the ethertype actually found inside the raw buffer. Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Suggested-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- include/linux/if_ether.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)