Skip to contentSkip to conversation

net/hsr: Added support for HSR v1

PATCH Applied Peter Heise 4 participants 5 messages Apr 13, 2016 – Apr 20, 2016 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 net/hsr: Added support for HSR v1

This patch adds support for the newer version 1 of the HSR networking standard. Version 0 is still default and the new version has to be selected via iproute2.

Main changes are in the supervision frame handling and its ethertype field.

---
 include/uapi/linux/if_ether.h |  1 +
 include/uapi/linux/if_link.h  |  1 +
 net/hsr/Kconfig               |  5 +--
 net/hsr/hsr_device.c          | 80 +++++++++++++++++++++++++------------------
 net/hsr/hsr_device.h          |  2 +-
 net/hsr/hsr_forward.c         | 43 +++++++++++++++++------
 net/hsr/hsr_framereg.c        | 30 ++++++++++------
 net/hsr/hsr_main.h            | 13 ++++++-
 net/hsr/hsr_netlink.c         | 10 ++++--
 net/hsr/hsr_slave.c           |  4 ++-
 10 files changed, 126 insertions(+), 63 deletions(-)
include/uapi/linux/if_ether.h +1 -0
index 4a93051..cec849a 100644
@@ -92,6 +92,7 @@
 #define ETH_P_TDLS	0x890D          /* TDLS */
 #define ETH_P_FIP	0x8914		/* FCoE Initialization Protocol */
 #define ETH_P_80221	0x8917		/* IEEE 802.21 Media Independent Handover Protocol */
+#define ETH_P_HSR	0x892F		/* IEC 62439-3 HSRv1	*/
 #define ETH_P_LOOPBACK	0x9000		/* Ethernet loopback packet, per IEEE 802.3 */
 #define ETH_P_QINQ1	0x9100		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ2	0x9200		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
include/uapi/linux/if_link.h +1 -0
index 9427f17..bb3a90b 100644
@@ -773,6 +773,7 @@ enum {
 	IFLA_HSR_SLAVE1,
 	IFLA_HSR_SLAVE2,
 	IFLA_HSR_MULTICAST_SPEC,	/* Last byte of supervision addr */
+	IFLA_HSR_VERSION,		/* HSR version */
 	IFLA_HSR_SUPERVISION_ADDR,	/* Supervision frame multicast addr */
 	IFLA_HSR_SEQ_NR,
 	__IFLA_HSR_MAX,
net/hsr/Kconfig +3 -2
index 0d3d709..4b683fd 100644
@@ -18,8 +18,9 @@ config HSR
 	  earlier.
 
 	  This code is a "best effort" to comply with the HSR standard as
-	  described in IEC 62439-3:2010 (HSRv0), but no compliancy tests have
-	  been made.
+	  described in IEC 62439-3:2010 (HSRv0) and IEC 62439-3:2012 (HSRv1),
+	  but no compliancy tests have been made. Use iproute2 to select
+	  the version you desire.
 
 	  You need to perform any and all necessary tests yourself before
 	  relying on this code in a safety critical system!
net/hsr/hsr_device.c +46 -34

154 lines not on this page · raw message

net/hsr/hsr_device.h +1 -1
index 108a5d5..9975e31 100644
@@ -17,7 +17,7 @@
 
 void hsr_dev_setup(struct net_device *dev);
 int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
-		     unsigned char multicast_spec);
+		     unsigned char multicast_spec, u8 protocol_version);
 void hsr_check_carrier_and_operstate(struct hsr_priv *hsr);
 bool is_hsr_master(struct net_device *dev);
 int hsr_get_max_mtu(struct hsr_priv *hsr);
net/hsr/hsr_forward.c +32 -11

81 lines not on this page · raw message

net/hsr/hsr_framereg.c +19 -11
index bace124..7ea9258 100644
@@ -177,17 +177,17 @@ struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb,
 			return node;
 	}
 
-	if (!is_sup)
-		return NULL; /* Only supervision frame may create node entry */
+	/* Everyone may create a node entry, connected node to a HSR device. */
 
-	if (ethhdr->h_proto == htons(ETH_P_PRP)) {
+	if (ethhdr->h_proto == htons(ETH_P_PRP)
+			|| ethhdr->h_proto == htons(ETH_P_HSR)) {
 		/* Use the existing sequence_nr from the tag as starting point
 		 * for filtering duplicate frames.
 		 */
 		seq_out = hsr_get_skb_sequence_nr(skb) - 1;
 	} else {
 		WARN_ONCE(1, "%s: Non-HSR frame\n", __func__);
-		seq_out = 0;
+		seq_out = HSR_SEQNR_START;
 	}
 
 	return hsr_add_node(node_db, ethhdr->h_source, seq_out);
@@ -200,17 +200,25 @@ struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb,
 void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
 			  struct hsr_port *port_rcv)
 {
+	struct ethhdr *ethhdr;
 	struct hsr_node *node_real;
 	struct hsr_sup_payload *hsr_sp;
 	struct list_head *node_db;
 	int i;
 
-	skb_pull(skb, sizeof(struct hsr_ethhdr_sp));
-	hsr_sp = (struct hsr_sup_payload *) skb->data;
+	ethhdr = (struct ethhdr *) skb_mac_header(skb);
 
-	if (ether_addr_equal(eth_hdr(skb)->h_source, hsr_sp->MacAddressA))
-		/* Not sent from MacAddressB of a PICS_SUBS capable node */
-		goto done;
+	/* Leave the ethernet header. */
+	skb_pull(skb, sizeof(struct ethhdr));
+
+	/* And leave the HSR tag. */
+	if (ethhdr->h_proto == htons(ETH_P_HSR))
+		skb_pull(skb, sizeof(struct hsr_tag));
+
+	/* And leave the HSR sup tag. */
+	skb_pull(skb, sizeof(struct hsr_sup_tag));
+
+	hsr_sp = (struct hsr_sup_payload *) skb->data;
 
 	/* Merge node_curr (registered on MacAddressB) into node_real */
 	node_db = &port_rcv->hsr->node_db;
@@ -225,7 +233,7 @@ void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
 		/* Node has already been merged */
 		goto done;
 
-	ether_addr_copy(node_real->MacAddressB, eth_hdr(skb)->h_source);
+	ether_addr_copy(node_real->MacAddressB, ethhdr->h_source);
 	for (i = 0; i < HSR_PT_PORTS; i++) {
 		if (!node_curr->time_in_stale[i] &&
 		    time_after(node_curr->time_in[i], node_real->time_in[i])) {
@@ -241,7 +249,7 @@ void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
 	kfree_rcu(node_curr, rcu_head);
 
 done:
-	skb_push(skb, sizeof(struct hsr_ethhdr_sp));
+	skb_push(skb, sizeof(struct hsrv1_ethhdr_sp));
 }
 
 
net/hsr/hsr_main.h +12 -1
index 5a9c699..9b9909e 100644
@@ -30,6 +30,7 @@
  */
 #define MAX_SLAVE_DIFF			 3000 /* ms */
 #define HSR_SEQNR_START			(USHRT_MAX - 1024)
+#define HSR_SUP_SEQNR_START		(HSR_SEQNR_START / 2)
 
 
 /* How often shall we check for broken ring and remove node entries older than
@@ -58,6 +59,8 @@ struct hsr_tag {
 
 #define HSR_HLEN	6
 
+#define HSR_V1_SUP_LSDUSIZE		52
+
 /* The helper functions below assumes that 'path' occupies the 4 most
  * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or
  * equivalently, the 4 most significant bits of HSR tag byte 14).
@@ -131,8 +134,14 @@ static inline void set_hsr_stag_HSR_Ver(struct hsr_sup_tag *hst, u16 HSR_Ver)
 	set_hsr_tag_LSDU_size((struct hsr_tag *) hst, HSR_Ver);
 }
 
-struct hsr_ethhdr_sp {
+struct hsrv0_ethhdr_sp {
+	struct ethhdr		ethhdr;
+	struct hsr_sup_tag	hsr_sup;
+} __packed;
+
+struct hsrv1_ethhdr_sp {
 	struct ethhdr		ethhdr;
+	struct hsr_tag		hsr;
 	struct hsr_sup_tag	hsr_sup;
 } __packed;
 
@@ -162,6 +171,8 @@ struct hsr_priv {
 	struct timer_list	prune_timer;
 	int announce_count;
 	u16 sequence_nr;
+	u16 sup_sequence_nr;			/* For HSRv1 separate seq_nr for supervision */
+	u8 protVersion;					/* Indicate if HSRv0 or HSRv1. */
 	spinlock_t seqnr_lock;			/* locking for sequence_nr */
 	unsigned char		sup_multicast_addr[ETH_ALEN];
 };
net/hsr/hsr_netlink.c +8 -2
index a2c7e4c..5425d87 100644
@@ -23,6 +23,7 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
 	[IFLA_HSR_SLAVE1]		= { .type = NLA_U32 },
 	[IFLA_HSR_SLAVE2]		= { .type = NLA_U32 },
 	[IFLA_HSR_MULTICAST_SPEC]	= { .type = NLA_U8 },
+	[IFLA_HSR_VERSION]	= { .type = NLA_U8 },
 	[IFLA_HSR_SUPERVISION_ADDR]	= { .type = NLA_BINARY, .len = ETH_ALEN },
 	[IFLA_HSR_SEQ_NR]		= { .type = NLA_U16 },
 };
@@ -35,7 +36,7 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
 		       struct nlattr *tb[], struct nlattr *data[])
 {
 	struct net_device *link[2];
-	unsigned char multicast_spec;
+	unsigned char multicast_spec, hsr_version;
 
 	if (!data) {
 		netdev_info(dev, "HSR: No slave devices specified\n");
@@ -62,7 +63,12 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
 	else
 		multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]);
 
-	return hsr_dev_finalize(dev, link, multicast_spec);
+	if (!data[IFLA_HSR_VERSION])
+		hsr_version = 0;
+	else
+		hsr_version = nla_get_u8(data[IFLA_HSR_VERSION]);
+
+	return hsr_dev_finalize(dev, link, multicast_spec, hsr_version);
 }
 
 static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
net/hsr/hsr_slave.c +3 -1
index 7d37366..f5b6038 100644
@@ -22,6 +22,7 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
 {
 	struct sk_buff *skb = *pskb;
 	struct hsr_port *port;
+	u16 protocol;
 
 	if (!skb_mac_header_was_set(skb)) {
 		WARN_ONCE(1, "%s: skb invalid", __func__);
@@ -37,7 +38,8 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
 		goto finish_consume;
 	}
 
-	if (eth_hdr(skb)->h_proto != htons(ETH_P_PRP))
+	protocol = eth_hdr(skb)->h_proto;
+	if (protocol != htons(ETH_P_PRP) && protocol != htons(ETH_P_HSR))
 		goto finish_pass;
 
 	skb_push(skb, ETH_HLEN);
Signature · 1 line
2.5.0
maintainer Applied
#1 lore raw

From: Peter Heise <[email protected]>
Date: Wed, 13 Apr 2016 13:52:22 +0200

Quoted 8 lines

This patch adds support for the newer version 1 of the HSR networking standard. Version 0 is still default and the new version has to be selected via iproute2.

Main changes are in the supervision frame handling and its ethertype field.

Applied.

#2 lore raw
In reply to Peter Heise

include/uapi/linux/if_link.h enum { · line 778

Quoted 11 lines · On Wed, 13 Apr 2016 13:52:22 +0200 Peter Heise <[email protected]> wrote:
include/uapi/linux/if_link.h +1 -0
index 9427f17..bb3a90b 100644
@@ -773,6 +773,7 @@ enum {
 	IFLA_HSR_SLAVE1,
 	IFLA_HSR_SLAVE2,
 	IFLA_HSR_MULTICAST_SPEC,	/* Last byte of supervision addr */
+	IFLA_HSR_VERSION,		/* HSR version */
 	IFLA_HSR_SUPERVISION_ADDR,	/* Supervision frame multicast addr */
 	IFLA_HSR_SEQ_NR,

You added a new value into the middle of an enumeration field. This breaks kernel ABI. Older applications (like iproute) would see the wrong values.

Please submit a new change which moves HSR_VERSION to the end of the enum

maintainer
#3 lore raw

From: Stephen Hemminger <[email protected]>
Date: Tue, 19 Apr 2016 08:21:00 -0700

Quoted 19 lines

include/uapi/linux/if_link.h enum { · line 778

Quoted 11 lines · On Wed, 13 Apr 2016 13:52:22 +0200 Peter Heise <[email protected]> wrote:
include/uapi/linux/if_link.h +1 -0
index 9427f17..bb3a90b 100644
@@ -773,6 +773,7 @@ enum {
 	IFLA_HSR_SLAVE1,
 	IFLA_HSR_SLAVE2,
 	IFLA_HSR_MULTICAST_SPEC,	/* Last byte of supervision addr */
+	IFLA_HSR_VERSION,		/* HSR version */
 	IFLA_HSR_SUPERVISION_ADDR,	/* Supervision frame multicast addr */
 	IFLA_HSR_SEQ_NR,

You added a new value into the middle of an enumeration field. This breaks kernel ABI. Older applications (like iproute) would see the wrong values.

Quoted 1 line

Please submit a new change which moves HSR_VERSION to the end of the enum

Good catch, Stephen.

A message that is not in the archive (sent off-list or not yet received): 8104_1461082351_571658EF_8104_4642_1_20160419.121227.1437003570791513649.davem@davemloft.net

#5 lore raw

Thanks for the advice Stephen, new patch submitted!

-----Ursprüngliche Nachricht-----
Von: David Miller [mailto:[email protected]]
Gesendet: Dienstag, 19. April 2016 18:12
An: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Heise, Peter
Betreff: Re: [PATCH net-next] net/hsr: Added support for HSR v1

From: Stephen Hemminger <[email protected]>
Date: Tue, 19 Apr 2016 08:21:00 -0700

Quoted 19 lines

include/uapi/linux/if_link.h enum { · line 778

Quoted 11 lines · On Wed, 13 Apr 2016 13:52:22 +0200 Peter Heise <[email protected]> wrote:
(quoted diff) +0 -0

b/include/uapi/linux/if_link.h index 9427f17..bb3a90b 100644

include/uapi/linux/if_link.h +1 -0
@@ -773,6 +773,7 @@ enum {
 	IFLA_HSR_SLAVE1,
 	IFLA_HSR_SLAVE2,
 	IFLA_HSR_MULTICAST_SPEC,	/* Last byte of supervision addr */
+	IFLA_HSR_VERSION,		/* HSR version */
 	IFLA_HSR_SUPERVISION_ADDR,	/* Supervision frame multicast addr */
 	IFLA_HSR_SEQ_NR,

You added a new value into the middle of an enumeration field. This breaks kernel ABI. Older applications (like iproute) would see the wrong values.

Quoted 2 lines

Please submit a new change which moves HSR_VERSION to the end of the enum

Good catch, Stephen.

This mail has originated outside your organization, either from an external partner or the Global Internet. Keep this in mind if you answer this message.

The information in this e-mail is confidential. The contents may not be disclosed or used by anyone other than the addressee. Access to this e-mail by anyone else is unauthorised.
If you are not the intended recipient, please notify Airbus immediately and delete this e-mail.
Airbus cannot accept any responsibility for the accuracy or completeness of this e-mail as it has been sent over public networks. If you have any concerns over the content of this message or its Accuracy or Integrity, please contact Airbus immediately. All outgoing e-mails from Airbus are checked using regularly updated virus scanning software but you should take whatever measures you deem to be appropriate to ensure that this message and any attachments are virus free.