summaryrefslogtreecommitdiffstats
path: root/net/hsr/hsr_slave.c
diff options
context:
space:
mode:
authorMurali Karicheri <m-karicheri2@ti.com>2020-07-22 10:40:21 -0400
committerDavid S. Miller <davem@davemloft.net>2020-07-27 12:20:40 -0700
commit451d8123f89791bb628277c0bdb4cae34a3563e6 (patch)
tree73021c2bce5b0a2b3939694a385e9c1407d740e9 /net/hsr/hsr_slave.c
parentfa4dc89531360de760359bf94086b04dada98d4e (diff)
downloadlinux-451d8123f89791bb628277c0bdb4cae34a3563e6.tar.gz
linux-451d8123f89791bb628277c0bdb4cae34a3563e6.tar.bz2
linux-451d8123f89791bb628277c0bdb4cae34a3563e6.zip
net: prp: add packet handling support
DAN-P (Dual Attached Nodes PRP) nodes are expected to receive traditional IP packets as well as PRP (Parallel Redundancy Protocol) tagged (trailer) packets. PRP trailer is 6 bytes of PRP protocol unit called RCT, Redundancy Control Trailer (RCT) similar to HSR tag. PRP network can have traditional devices such as bridges/switches or PC attached to it and should be able to communicate. Regular Ethernet devices treat the RCT as pads. This patch adds logic to format L2 frames from network stack to add a trailer (RCT) and send it as duplicates over the slave interfaces when the protocol is PRP as per IEC 62439-3. At the ingress, it strips the trailer, do duplicate detection and rejection and forward a stripped frame up the network stack. PRP device should accept frames from Singly Attached Nodes (SAN) and thus the driver mark the link where the frame came from in the node table. Signed-off-by: Murali Karicheri <m-karicheri2@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/hsr/hsr_slave.c')
-rw-r--r--net/hsr/hsr_slave.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index b5c0834de338..36d5fcf09c61 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -16,12 +16,22 @@
#include "hsr_forward.h"
#include "hsr_framereg.h"
+bool hsr_invalid_dan_ingress_frame(__be16 protocol)
+{
+ return (protocol != htons(ETH_P_PRP) && protocol != htons(ETH_P_HSR));
+}
+
static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct hsr_port *port;
+ struct hsr_priv *hsr;
__be16 protocol;
+ /* Packets from dev_loopback_xmit() do not have L2 header, bail out */
+ if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+ return RX_HANDLER_PASS;
+
if (!skb_mac_header_was_set(skb)) {
WARN_ONCE(1, "%s: skb invalid", __func__);
return RX_HANDLER_PASS;
@@ -30,6 +40,7 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
port = hsr_port_get_rcu(skb->dev);
if (!port)
goto finish_pass;
+ hsr = port->hsr;
if (hsr_addr_is_self(port->hsr, eth_hdr(skb)->h_source)) {
/* Directly kill frames sent by ourselves */
@@ -37,12 +48,23 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
goto finish_consume;
}
+ /* For HSR, only tagged frames are expected, but for PRP
+ * there could be non tagged frames as well from Single
+ * attached nodes (SANs).
+ */
protocol = eth_hdr(skb)->h_proto;
- if (protocol != htons(ETH_P_PRP) && protocol != htons(ETH_P_HSR))
+ if (hsr->proto_ops->invalid_dan_ingress_frame &&
+ hsr->proto_ops->invalid_dan_ingress_frame(protocol))
goto finish_pass;
skb_push(skb, ETH_HLEN);
+ if (skb_mac_header(skb) != skb->data) {
+ WARN_ONCE(1, "%s:%d: Malformed frame at source port %s)\n",
+ __func__, __LINE__, port->dev->name);
+ goto finish_consume;
+ }
+
hsr_forward_skb(skb, port);
finish_consume: