Skip to content

Commit fbe450b

Browse files
author
Herton R. Krzesinski
committed
Merge: net: Enable HSR and PRP
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/2590 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2177256 Enable hsr as a module to support the protocols HSR and PRP. Also add relevant patches that were added since the release of kernel 5.14 upstream. The code required to use it is already in iproute. Signed-off-by: Felix Maurer <fmaurer@redhat.com> Approved-by: Hangbin Liu <haliu@redhat.com> Approved-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
2 parents 62f30b9 + 53b0857 commit fbe450b

File tree

13 files changed

+499
-116
lines changed

13 files changed

+499
-116
lines changed

include/linux/if_hsr.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ enum hsr_version {
99
PRP_V1,
1010
};
1111

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+
1228
#if IS_ENABLED(CONFIG_HSR)
1329
extern bool is_hsr_master(struct net_device *dev);
1430
extern int hsr_get_version(struct net_device *dev, enum hsr_version *ver);

net/core/flow_dissector.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/ppp_defs.h>
2323
#include <linux/stddef.h>
2424
#include <linux/if_ether.h>
25+
#include <linux/if_hsr.h>
2526
#include <linux/mpls.h>
2627
#include <linux/tcp.h>
2728
#include <linux/ptp_classify.h>
@@ -1370,6 +1371,23 @@ bool __skb_flow_dissect(const struct net *net,
13701371
break;
13711372
}
13721373

1374+
case htons(ETH_P_PRP):
1375+
case htons(ETH_P_HSR): {
1376+
struct hsr_tag *hdr, _hdr;
1377+
1378+
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen,
1379+
&_hdr);
1380+
if (!hdr) {
1381+
fdret = FLOW_DISSECT_RET_OUT_BAD;
1382+
break;
1383+
}
1384+
1385+
proto = hdr->encap_proto;
1386+
nhoff += HSR_HLEN;
1387+
fdret = FLOW_DISSECT_RET_PROTO_AGAIN;
1388+
break;
1389+
}
1390+
13731391
default:
13741392
fdret = FLOW_DISSECT_RET_OUT_BAD;
13751393
break;

net/hsr/hsr_device.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
219219
skb->dev = master->dev;
220220
skb_reset_mac_header(skb);
221221
skb_reset_mac_len(skb);
222+
spin_lock_bh(&hsr->seqnr_lock);
222223
hsr_forward_skb(skb, master);
224+
spin_unlock_bh(&hsr->seqnr_lock);
223225
} else {
224226
dev_core_stats_tx_dropped_inc(dev);
225227
dev_kfree_skb_any(skb);
@@ -278,7 +280,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
278280
__u8 type = HSR_TLV_LIFE_CHECK;
279281
struct hsr_sup_payload *hsr_sp;
280282
struct hsr_sup_tag *hsr_stag;
281-
unsigned long irqflags;
282283
struct sk_buff *skb;
283284

284285
*interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
@@ -299,30 +300,31 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
299300
set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version);
300301

301302
/* From HSRv1 on we have separate supervision sequence numbers. */
302-
spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags);
303+
spin_lock_bh(&hsr->seqnr_lock);
303304
if (hsr->prot_version > 0) {
304305
hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr);
305306
hsr->sup_sequence_nr++;
306307
} else {
307308
hsr_stag->sequence_nr = htons(hsr->sequence_nr);
308309
hsr->sequence_nr++;
309310
}
310-
spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags);
311311

312-
hsr_stag->HSR_TLV_type = type;
312+
hsr_stag->tlv.HSR_TLV_type = type;
313313
/* TODO: Why 12 in HSRv0? */
314-
hsr_stag->HSR_TLV_length = hsr->prot_version ?
314+
hsr_stag->tlv.HSR_TLV_length = hsr->prot_version ?
315315
sizeof(struct hsr_sup_payload) : 12;
316316

317317
/* Payload: MacAddressA */
318318
hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload));
319319
ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr);
320320

321-
if (skb_put_padto(skb, ETH_ZLEN))
321+
if (skb_put_padto(skb, ETH_ZLEN)) {
322+
spin_unlock_bh(&hsr->seqnr_lock);
322323
return;
324+
}
323325

324326
hsr_forward_skb(skb, master);
325-
327+
spin_unlock_bh(&hsr->seqnr_lock);
326328
return;
327329
}
328330

@@ -332,7 +334,6 @@ static void send_prp_supervision_frame(struct hsr_port *master,
332334
struct hsr_priv *hsr = master->hsr;
333335
struct hsr_sup_payload *hsr_sp;
334336
struct hsr_sup_tag *hsr_stag;
335-
unsigned long irqflags;
336337
struct sk_buff *skb;
337338

338339
skb = hsr_init_skb(master);
@@ -347,24 +348,23 @@ static void send_prp_supervision_frame(struct hsr_port *master,
347348
set_hsr_stag_HSR_ver(hsr_stag, (hsr->prot_version ? 1 : 0));
348349

349350
/* From HSRv1 on we have separate supervision sequence numbers. */
350-
spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags);
351+
spin_lock_bh(&hsr->seqnr_lock);
351352
hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr);
352353
hsr->sup_sequence_nr++;
353-
hsr_stag->HSR_TLV_type = PRP_TLV_LIFE_CHECK_DD;
354-
hsr_stag->HSR_TLV_length = sizeof(struct hsr_sup_payload);
354+
hsr_stag->tlv.HSR_TLV_type = PRP_TLV_LIFE_CHECK_DD;
355+
hsr_stag->tlv.HSR_TLV_length = sizeof(struct hsr_sup_payload);
355356

356357
/* Payload: MacAddressA */
357358
hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload));
358359
ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr);
359360

360361
if (skb_put_padto(skb, ETH_ZLEN)) {
361-
spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags);
362+
spin_unlock_bh(&hsr->seqnr_lock);
362363
return;
363364
}
364365

365-
spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags);
366-
367366
hsr_forward_skb(skb, master);
367+
spin_unlock_bh(&hsr->seqnr_lock);
368368
}
369369

370370
/* Announce (supervision frame) timer function
@@ -444,7 +444,7 @@ void hsr_dev_setup(struct net_device *dev)
444444
dev->header_ops = &hsr_header_ops;
445445
dev->netdev_ops = &hsr_device_ops;
446446
SET_NETDEV_DEVTYPE(dev, &hsr_type);
447-
dev->priv_flags |= IFF_NO_QUEUE;
447+
dev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL;
448448

449449
dev->needs_free_netdev = true;
450450

@@ -490,7 +490,6 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
490490
hsr = netdev_priv(hsr_dev);
491491
INIT_LIST_HEAD(&hsr->ports);
492492
INIT_LIST_HEAD(&hsr->node_db);
493-
INIT_LIST_HEAD(&hsr->self_node_db);
494493
spin_lock_init(&hsr->list_lock);
495494

496495
eth_hw_addr_set(hsr_dev, slave[0]->dev_addr);

net/hsr/hsr_forward.c

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
3737
struct ethhdr *eth_hdr;
3838
struct hsr_sup_tag *hsr_sup_tag;
3939
struct hsrv1_ethhdr_sp *hsr_V1_hdr;
40+
struct hsr_sup_tlv *hsr_sup_tlv;
41+
u16 total_length = 0;
4042

4143
WARN_ON_ONCE(!skb_mac_header_was_set(skb));
4244
eth_hdr = (struct ethhdr *)skb_mac_header(skb);
@@ -53,23 +55,63 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
5355

5456
/* Get the supervision header from correct location. */
5557
if (eth_hdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */
58+
total_length = sizeof(struct hsrv1_ethhdr_sp);
59+
if (!pskb_may_pull(skb, total_length))
60+
return false;
61+
5662
hsr_V1_hdr = (struct hsrv1_ethhdr_sp *)skb_mac_header(skb);
5763
if (hsr_V1_hdr->hsr.encap_proto != htons(ETH_P_PRP))
5864
return false;
5965

6066
hsr_sup_tag = &hsr_V1_hdr->hsr_sup;
6167
} else {
68+
total_length = sizeof(struct hsrv0_ethhdr_sp);
69+
if (!pskb_may_pull(skb, total_length))
70+
return false;
71+
6272
hsr_sup_tag =
6373
&((struct hsrv0_ethhdr_sp *)skb_mac_header(skb))->hsr_sup;
6474
}
6575

66-
if (hsr_sup_tag->HSR_TLV_type != HSR_TLV_ANNOUNCE &&
67-
hsr_sup_tag->HSR_TLV_type != HSR_TLV_LIFE_CHECK &&
68-
hsr_sup_tag->HSR_TLV_type != PRP_TLV_LIFE_CHECK_DD &&
69-
hsr_sup_tag->HSR_TLV_type != PRP_TLV_LIFE_CHECK_DA)
76+
if (hsr_sup_tag->tlv.HSR_TLV_type != HSR_TLV_ANNOUNCE &&
77+
hsr_sup_tag->tlv.HSR_TLV_type != HSR_TLV_LIFE_CHECK &&
78+
hsr_sup_tag->tlv.HSR_TLV_type != PRP_TLV_LIFE_CHECK_DD &&
79+
hsr_sup_tag->tlv.HSR_TLV_type != PRP_TLV_LIFE_CHECK_DA)
80+
return false;
81+
if (hsr_sup_tag->tlv.HSR_TLV_length != 12 &&
82+
hsr_sup_tag->tlv.HSR_TLV_length != sizeof(struct hsr_sup_payload))
7083
return false;
71-
if (hsr_sup_tag->HSR_TLV_length != 12 &&
72-
hsr_sup_tag->HSR_TLV_length != sizeof(struct hsr_sup_payload))
84+
85+
/* Get next tlv */
86+
total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tag->tlv.HSR_TLV_length;
87+
if (!pskb_may_pull(skb, total_length))
88+
return false;
89+
skb_pull(skb, total_length);
90+
hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
91+
skb_push(skb, total_length);
92+
93+
/* if this is a redbox supervision frame we need to verify
94+
* that more data is available
95+
*/
96+
if (hsr_sup_tlv->HSR_TLV_type == PRP_TLV_REDBOX_MAC) {
97+
/* tlv length must be a length of a mac address */
98+
if (hsr_sup_tlv->HSR_TLV_length != sizeof(struct hsr_sup_payload))
99+
return false;
100+
101+
/* make sure another tlv follows */
102+
total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length;
103+
if (!pskb_may_pull(skb, total_length))
104+
return false;
105+
106+
/* get next tlv */
107+
skb_pull(skb, total_length);
108+
hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
109+
skb_push(skb, total_length);
110+
}
111+
112+
/* end of tlvs must follow at the end */
113+
if (hsr_sup_tlv->HSR_TLV_type == HSR_TLV_EOT &&
114+
hsr_sup_tlv->HSR_TLV_length != 0)
73115
return false;
74116

75117
return true;
@@ -108,15 +150,15 @@ struct sk_buff *hsr_get_untagged_frame(struct hsr_frame_info *frame,
108150
struct hsr_port *port)
109151
{
110152
if (!frame->skb_std) {
111-
if (frame->skb_hsr) {
153+
if (frame->skb_hsr)
112154
frame->skb_std =
113155
create_stripped_skb_hsr(frame->skb_hsr, frame);
114-
} else {
115-
/* Unexpected */
116-
WARN_ONCE(1, "%s:%d: Unexpected frame received (port_src %s)\n",
117-
__FILE__, __LINE__, port->dev->name);
156+
else
157+
netdev_warn_once(port->dev,
158+
"Unexpected frame received in hsr_get_untagged_frame()\n");
159+
160+
if (!frame->skb_std)
118161
return NULL;
119-
}
120162
}
121163

122164
return skb_clone(frame->skb_std, GFP_ATOMIC);
@@ -309,17 +351,18 @@ static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev,
309351
struct hsr_node *node_src)
310352
{
311353
bool was_multicast_frame;
312-
int res;
354+
int res, recv_len;
313355

314356
was_multicast_frame = (skb->pkt_type == PACKET_MULTICAST);
315357
hsr_addr_subst_source(node_src, skb);
316358
skb_pull(skb, ETH_HLEN);
359+
recv_len = skb->len;
317360
res = netif_rx(skb);
318361
if (res == NET_RX_DROP) {
319362
dev->stats.rx_dropped++;
320363
} else {
321364
dev->stats.rx_packets++;
322-
dev->stats.rx_bytes += skb->len;
365+
dev->stats.rx_bytes += recv_len;
323366
if (was_multicast_frame)
324367
dev->stats.multicast++;
325368
}
@@ -457,7 +500,6 @@ static void handle_std_frame(struct sk_buff *skb,
457500
{
458501
struct hsr_port *port = frame->port_rcv;
459502
struct hsr_priv *hsr = port->hsr;
460-
unsigned long irqflags;
461503

462504
frame->skb_hsr = NULL;
463505
frame->skb_prp = NULL;
@@ -467,10 +509,9 @@ static void handle_std_frame(struct sk_buff *skb,
467509
frame->is_from_san = true;
468510
} else {
469511
/* Sequence nr for the master node */
470-
spin_lock_irqsave(&hsr->seqnr_lock, irqflags);
512+
lockdep_assert_held(&hsr->seqnr_lock);
471513
frame->sequence_nr = hsr->sequence_nr;
472514
hsr->sequence_nr++;
473-
spin_unlock_irqrestore(&hsr->seqnr_lock, irqflags);
474515
}
475516
}
476517

@@ -571,11 +612,13 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port)
571612
{
572613
struct hsr_frame_info frame;
573614

615+
rcu_read_lock();
574616
if (fill_frame_info(&frame, skb, port) < 0)
575617
goto out_drop;
576618

577619
hsr_register_frame_in(frame.node_src, port, frame.sequence_nr);
578620
hsr_forward_do(&frame);
621+
rcu_read_unlock();
579622
/* Gets called for ingress frames as well as egress from master port.
580623
* So check and increment stats for master port only here.
581624
*/
@@ -590,6 +633,7 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port)
590633
return;
591634

592635
out_drop:
636+
rcu_read_unlock();
593637
port->dev->stats.tx_dropped++;
594638
kfree_skb(skb);
595639
}

0 commit comments

Comments
 (0)