Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

flow_dissector: Add support for HSR

Network drivers such as igb or igc call eth_get_headlen() to determine the
header length for their to be constructed skbs in receive path.

When running HSR on top of these drivers, it results in triggering BUG_ON() in
skb_pull(). The reason is the skb headlen is not sufficient for HSR to work
correctly. skb_pull() notices that.

For instance, eth_get_headlen() returns 14 bytes for TCP traffic over HSR which
is not correct. The problem is, the flow dissection code does not take HSR into
account. Therefore, add support for it.

Reported-by: Anthony Harivel <anthony.harivel@linutronix.de>
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
Link: https://lore.kernel.org/r/20220228195856.88187-1-kurt@linutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kurt Kanzenbach and committed by
Jakub Kicinski
bf08824a 00202885

+33 -16
+16
include/linux/if_hsr.h
··· 9 9 PRP_V1, 10 10 }; 11 11 12 + /* HSR Tag. 13 + * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB, 14 + * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest, 15 + * h_source, h_proto = 0x88FB }, and add { path, LSDU_size, sequence Nr, 16 + * encapsulated protocol } instead. 17 + * 18 + * Field names as defined in the IEC:2010 standard for HSR. 19 + */ 20 + struct hsr_tag { 21 + __be16 path_and_LSDU_size; 22 + __be16 sequence_nr; 23 + __be16 encap_proto; 24 + } __packed; 25 + 26 + #define HSR_HLEN 6 27 + 12 28 #if IS_ENABLED(CONFIG_HSR) 13 29 extern bool is_hsr_master(struct net_device *dev); 14 30 extern int hsr_get_version(struct net_device *dev, enum hsr_version *ver);
+17
net/core/flow_dissector.c
··· 22 22 #include <linux/ppp_defs.h> 23 23 #include <linux/stddef.h> 24 24 #include <linux/if_ether.h> 25 + #include <linux/if_hsr.h> 25 26 #include <linux/mpls.h> 26 27 #include <linux/tcp.h> 27 28 #include <linux/ptp_classify.h> ··· 1280 1279 1281 1280 nhoff += ntohs(hdr->message_length); 1282 1281 fdret = FLOW_DISSECT_RET_OUT_GOOD; 1282 + break; 1283 + } 1284 + 1285 + case htons(ETH_P_HSR): { 1286 + struct hsr_tag *hdr, _hdr; 1287 + 1288 + hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, 1289 + &_hdr); 1290 + if (!hdr) { 1291 + fdret = FLOW_DISSECT_RET_OUT_BAD; 1292 + break; 1293 + } 1294 + 1295 + proto = hdr->encap_proto; 1296 + nhoff += HSR_HLEN; 1297 + fdret = FLOW_DISSECT_RET_PROTO_AGAIN; 1283 1298 break; 1284 1299 } 1285 1300
-16
net/hsr/hsr_main.h
··· 45 45 /* PRP V1 life redundancy box MAC address */ 46 46 #define PRP_TLV_REDBOX_MAC 30 47 47 48 - /* HSR Tag. 49 - * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB, 50 - * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest, 51 - * h_source, h_proto = 0x88FB }, and add { path, LSDU_size, sequence Nr, 52 - * encapsulated protocol } instead. 53 - * 54 - * Field names as defined in the IEC:2010 standard for HSR. 55 - */ 56 - struct hsr_tag { 57 - __be16 path_and_LSDU_size; 58 - __be16 sequence_nr; 59 - __be16 encap_proto; 60 - } __packed; 61 - 62 - #define HSR_HLEN 6 63 - 64 48 #define HSR_V1_SUP_LSDUSIZE 52 65 49 66 50 #define HSR_HSIZE_SHIFT 8