Commit 8f4c0e01 authored by Murali Karicheri's avatar Murali Karicheri Committed by David S. Miller

hsr: enhance netlink socket interface to support PRP

Parallel Redundancy Protocol (PRP) is another redundancy protocol
introduced by IEC 63439 standard. It is similar to HSR in many
aspects:-

 - Use a pair of Ethernet interfaces to created the PRP device
 - Use a 6 byte redundancy protocol part (RCT, Redundancy Check
   Trailer) similar to HSR Tag.
 - Has Link Redundancy Entity (LRE) that works with RCT to implement
   redundancy.

Key difference is that the protocol unit is a trailer instead of a
prefix as in HSR. That makes it inter-operable with tradition network
components such as bridges/switches which treat it as pad bytes,
whereas HSR nodes requires some kind of translators (Called redbox) to
talk to regular network devices. This features allows regular linux box
to be converted to a DAN-P box. DAN-P stands for Dual Attached Node - PRP
similar to DAN-H (Dual Attached Node - HSR).

Add a comment at the header/source code to explicitly state that the
driver files also handles PRP protocol as well.
Signed-off-by: default avatarMurali Karicheri <m-karicheri2@ti.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1775da47
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/* Generic Netlink HSR family definition /* Generic Netlink HSR family definition
*/ */
/* attributes */ /* attributes for HSR or PRP node */
enum { enum {
HSR_A_UNSPEC, HSR_A_UNSPEC,
HSR_A_NODE_ADDR, HSR_A_NODE_ADDR,
......
...@@ -907,7 +907,14 @@ enum { ...@@ -907,7 +907,14 @@ enum {
#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
/* HSR section */ /* HSR/PRP section, both uses same interface */
/* Different redundancy protocols for hsr device */
enum {
HSR_PROTOCOL_HSR,
HSR_PROTOCOL_PRP,
HSR_PROTOCOL_MAX,
};
enum { enum {
IFLA_HSR_UNSPEC, IFLA_HSR_UNSPEC,
...@@ -917,6 +924,9 @@ enum { ...@@ -917,6 +924,9 @@ enum {
IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */
IFLA_HSR_SEQ_NR, IFLA_HSR_SEQ_NR,
IFLA_HSR_VERSION, /* HSR version */ IFLA_HSR_VERSION, /* HSR version */
IFLA_HSR_PROTOCOL, /* Indicate different protocol than
* HSR. For example PRP.
*/
__IFLA_HSR_MAX, __IFLA_HSR_MAX,
}; };
......
...@@ -4,24 +4,35 @@ ...@@ -4,24 +4,35 @@
# #
config HSR config HSR
tristate "High-availability Seamless Redundancy (HSR)" tristate "High-availability Seamless Redundancy (HSR & PRP)"
help help
This enables IEC 62439 defined High-availability Seamless
Redundancy (HSR) and Parallel Redundancy Protocol (PRP).
If you say Y here, then your Linux box will be able to act as a If you say Y here, then your Linux box will be able to act as a
DANH ("Doubly attached node implementing HSR"). For this to work, DANH ("Doubly attached node implementing HSR") or DANP ("Doubly
your Linux box needs (at least) two physical Ethernet interfaces, attached node implementing PRP"). For this to work, your Linux box
and it must be connected as a node in a ring network together with needs (at least) two physical Ethernet interfaces.
other HSR capable nodes.
For DANH, it must be connected as a node in a ring network together
with other HSR capable nodes. All Ethernet frames sent over the HSR
device will be sent in both directions on the ring (over both slave
ports), giving a redundant, instant fail-over network. Each HSR node
in the ring acts like a bridge for HSR frames, but filters frames
that have been forwarded earlier.
All Ethernet frames sent over the hsr device will be sent in both For DANP, it must be connected as a node connecting to two
directions on the ring (over both slave ports), giving a redundant, separate networks over the two slave interfaces. Like HSR, Ethernet
instant fail-over network. Each HSR node in the ring acts like a frames sent over the PRP device will be sent to both networks giving
bridge for HSR frames, but filters frames that have been forwarded a redundant, instant fail-over network. Unlike HSR, PRP networks
earlier. can have Singly Attached Nodes (SAN) such as PC, printer, bridges
etc and will be able to communicate with DANP nodes.
This code is a "best effort" to comply with the HSR standard as This code is a "best effort" to comply with the HSR standard as
described in IEC 62439-3:2010 (HSRv0) and IEC 62439-3:2012 (HSRv1), described in IEC 62439-3:2010 (HSRv0) and IEC 62439-3:2012 (HSRv1),
but no compliancy tests have been made. Use iproute2 to select and PRP standard described in IEC 62439-4:2012 (PRP), but no
the version you desire. compliancy tests have been made. Use iproute2 to select the protocol
you would like to use.
You need to perform any and all necessary tests yourself before You need to perform any and all necessary tests yourself before
relying on this code in a safety critical system! relying on this code in a safety critical system!
......
/* /*
* hsr_debugfs code * debugfs code for HSR & PRP
* Copyright (C) 2019 Texas Instruments Incorporated * Copyright (C) 2019 Texas Instruments Incorporated
* *
* Author(s): * Author(s):
......
...@@ -3,9 +3,8 @@ ...@@ -3,9 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* This file contains device methods for creating, using and destroying * This file contains device methods for creating, using and destroying
* virtual HSR devices. * virtual HSR or PRP devices.
*/ */
#include <linux/netdevice.h> #include <linux/netdevice.h>
...@@ -427,6 +426,10 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], ...@@ -427,6 +426,10 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
ether_addr_copy(hsr_dev->dev_addr, slave[0]->dev_addr); ether_addr_copy(hsr_dev->dev_addr, slave[0]->dev_addr);
/* currently PRP is not supported */
if (protocol_version == PRP_V1)
return -EPROTONOSUPPORT;
/* Make sure we recognize frames from ourselves in hsr_rcv() */ /* Make sure we recognize frames from ourselves in hsr_rcv() */
res = hsr_create_self_node(hsr, hsr_dev->dev_addr, res = hsr_create_self_node(hsr, hsr_dev->dev_addr,
slave[1]->dev_addr); slave[1]->dev_addr);
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* include file for HSR and PRP.
*/ */
#ifndef __HSR_DEVICE_H #ifndef __HSR_DEVICE_H
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* Frame router for HSR and PRP.
*/ */
#include "hsr_forward.h" #include "hsr_forward.h"
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* include file for HSR and PRP.
*/ */
#ifndef __HSR_FORWARD_H #ifndef __HSR_FORWARD_H
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* interface. A frame is identified by its source MAC address and its HSR * interface. A frame is identified by its source MAC address and its HSR
* sequence number. This code keeps track of senders and their sequence numbers * sequence number. This code keeps track of senders and their sequence numbers
* to allow filtering of duplicate frames, and to detect HSR ring errors. * to allow filtering of duplicate frames, and to detect HSR ring errors.
* Same code handles filtering of duplicates for PRP as well.
*/ */
#include <linux/if_ether.h> #include <linux/if_ether.h>
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* include file for HSR and PRP.
*/ */
#ifndef __HSR_FRAMEREG_H #ifndef __HSR_FRAMEREG_H
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* Event handling for HSR and PRP devices.
*/ */
#include <linux/netdevice.h> #include <linux/netdevice.h>
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* include file for HSR and PRP.
*/ */
#ifndef __HSR_PRIVATE_H #ifndef __HSR_PRIVATE_H
...@@ -131,6 +133,13 @@ struct hsr_port { ...@@ -131,6 +133,13 @@ struct hsr_port {
enum hsr_port_type type; enum hsr_port_type type;
}; };
/* used by driver internally to differentiate various protocols */
enum hsr_version {
HSR_V0 = 0,
HSR_V1,
PRP_V1,
};
struct hsr_priv { struct hsr_priv {
struct rcu_head rcu_head; struct rcu_head rcu_head;
struct list_head ports; struct list_head ports;
...@@ -141,7 +150,7 @@ struct hsr_priv { ...@@ -141,7 +150,7 @@ struct hsr_priv {
int announce_count; int announce_count;
u16 sequence_nr; u16 sequence_nr;
u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */
u8 prot_version; /* Indicate if HSRv0 or HSRv1. */ enum hsr_version prot_version; /* Indicate if HSRv0, HSRv1 or PRPv1 */
spinlock_t seqnr_lock; /* locking for sequence_nr */ spinlock_t seqnr_lock; /* locking for sequence_nr */
spinlock_t list_lock; /* locking for node list */ spinlock_t list_lock; /* locking for node list */
unsigned char sup_multicast_addr[ETH_ALEN]; unsigned char sup_multicast_addr[ETH_ALEN];
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
* *
* Routines for handling Netlink messages for HSR. * Routines for handling Netlink messages for HSR and PRP.
*/ */
#include "hsr_netlink.h" #include "hsr_netlink.h"
...@@ -22,6 +22,7 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = { ...@@ -22,6 +22,7 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
[IFLA_HSR_VERSION] = { .type = NLA_U8 }, [IFLA_HSR_VERSION] = { .type = NLA_U8 },
[IFLA_HSR_SUPERVISION_ADDR] = { .len = ETH_ALEN }, [IFLA_HSR_SUPERVISION_ADDR] = { .len = ETH_ALEN },
[IFLA_HSR_SEQ_NR] = { .type = NLA_U16 }, [IFLA_HSR_SEQ_NR] = { .type = NLA_U16 },
[IFLA_HSR_PROTOCOL] = { .type = NLA_U8 },
}; };
/* Here, it seems a netdevice has already been allocated for us, and the /* Here, it seems a netdevice has already been allocated for us, and the
...@@ -31,8 +32,10 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, ...@@ -31,8 +32,10 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[], struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
enum hsr_version proto_version;
unsigned char multicast_spec;
u8 proto = HSR_PROTOCOL_HSR;
struct net_device *link[2]; struct net_device *link[2];
unsigned char multicast_spec, hsr_version;
if (!data) { if (!data) {
NL_SET_ERR_MSG_MOD(extack, "No slave devices specified"); NL_SET_ERR_MSG_MOD(extack, "No slave devices specified");
...@@ -69,18 +72,34 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, ...@@ -69,18 +72,34 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
else else
multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]); multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]);
if (data[IFLA_HSR_PROTOCOL])
proto = nla_get_u8(data[IFLA_HSR_PROTOCOL]);
if (proto >= HSR_PROTOCOL_MAX) {
NL_SET_ERR_MSG_MOD(extack, "Unsupported protocol\n");
return -EINVAL;
}
if (!data[IFLA_HSR_VERSION]) { if (!data[IFLA_HSR_VERSION]) {
hsr_version = 0; proto_version = HSR_V0;
} else { } else {
hsr_version = nla_get_u8(data[IFLA_HSR_VERSION]); if (proto == HSR_PROTOCOL_PRP) {
if (hsr_version > 1) { NL_SET_ERR_MSG_MOD(extack, "PRP version unsupported\n");
return -EINVAL;
}
proto_version = nla_get_u8(data[IFLA_HSR_VERSION]);
if (proto_version > HSR_V1) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"Only versions 0..1 are supported"); "Only HSR version 0/1 supported\n");
return -EINVAL; return -EINVAL;
} }
} }
return hsr_dev_finalize(dev, link, multicast_spec, hsr_version, extack); if (proto == HSR_PROTOCOL_PRP)
proto_version = PRP_V1;
return hsr_dev_finalize(dev, link, multicast_spec, proto_version, extack);
} }
static void hsr_dellink(struct net_device *dev, struct list_head *head) static void hsr_dellink(struct net_device *dev, struct list_head *head)
...@@ -102,6 +121,7 @@ static void hsr_dellink(struct net_device *dev, struct list_head *head) ...@@ -102,6 +121,7 @@ static void hsr_dellink(struct net_device *dev, struct list_head *head)
static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev) static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
{ {
struct hsr_priv *hsr = netdev_priv(dev); struct hsr_priv *hsr = netdev_priv(dev);
u8 proto = HSR_PROTOCOL_HSR;
struct hsr_port *port; struct hsr_port *port;
port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
...@@ -120,6 +140,10 @@ static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev) ...@@ -120,6 +140,10 @@ static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
hsr->sup_multicast_addr) || hsr->sup_multicast_addr) ||
nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr->sequence_nr)) nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr->sequence_nr))
goto nla_put_failure; goto nla_put_failure;
if (hsr->prot_version == PRP_V1)
proto = HSR_PROTOCOL_PRP;
if (nla_put_u8(skb, IFLA_HSR_PROTOCOL, proto))
goto nla_put_failure;
return 0; return 0;
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* include file for HSR and PRP.
*/ */
#ifndef __HSR_NETLINK_H #ifndef __HSR_NETLINK_H
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* Frame handler other utility functions for HSR and PRP.
*/ */
#include "hsr_slave.h" #include "hsr_slave.h"
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
* *
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*
* include file for HSR and PRP.
*/ */
#ifndef __HSR_SLAVE_H #ifndef __HSR_SLAVE_H
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment