diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2020-08-11 13:11:08 +0200 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2020-08-24 18:53:59 +0200 |
commit | 8735997686a360545f5f1c6cb54d48e85dda7707 (patch) | |
tree | 96436a1af47dd4c6993a48e9a99da2a5712aa97c /target/linux/generic/backport-5.4/757-v5.8-net-dsa-tag_rtl4_a-Implement-Realtek-4-byte-A-tag.patch | |
parent | e742a31f07f66700ae43141bd6a733718a2ad501 (diff) | |
download | upstream-8735997686a360545f5f1c6cb54d48e85dda7707.tar.gz upstream-8735997686a360545f5f1c6cb54d48e85dda7707.tar.bz2 upstream-8735997686a360545f5f1c6cb54d48e85dda7707.zip |
kernel: backport RTL8366RB patches
These upstream patches makes the RTL8366RB DSA switch work
properly with OpenWrt, the D-Link DIR-685 gets network and
can be used as a router, and the same should be applicable
for any other device that want to enable the RTL8366RB
through Device Tree.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'target/linux/generic/backport-5.4/757-v5.8-net-dsa-tag_rtl4_a-Implement-Realtek-4-byte-A-tag.patch')
-rw-r--r-- | target/linux/generic/backport-5.4/757-v5.8-net-dsa-tag_rtl4_a-Implement-Realtek-4-byte-A-tag.patch | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.4/757-v5.8-net-dsa-tag_rtl4_a-Implement-Realtek-4-byte-A-tag.patch b/target/linux/generic/backport-5.4/757-v5.8-net-dsa-tag_rtl4_a-Implement-Realtek-4-byte-A-tag.patch new file mode 100644 index 0000000000..70d7000ba1 --- /dev/null +++ b/target/linux/generic/backport-5.4/757-v5.8-net-dsa-tag_rtl4_a-Implement-Realtek-4-byte-A-tag.patch @@ -0,0 +1,232 @@ +From 078ced30af696b52a450a016a16eb47499d68117 Mon Sep 17 00:00:00 2001 +From: Linus Walleij <linus.walleij@linaro.org> +Date: Wed, 8 Jul 2020 14:25:36 +0200 +Subject: [PATCH 2/5] net: dsa: tag_rtl4_a: Implement Realtek 4 byte A tag + +This implements the known parts of the Realtek 4 byte +tag protocol version 0xA, as found in the RTL8366RB +DSA switch. + +It is designated as protocol version 0xA as a +different Realtek 4 byte tag format with protocol +version 0x9 is known to exist in the Realtek RTL8306 +chips. + +The tag and switch chip lacks public documentation, so +the tag format has been reverse-engineered from +packet dumps. As only ingress traffic has been available +for analysis an egress tag has not been possible to +develop (even using educated guesses about bit fields) +so this is as far as it gets. It is not known if the +switch even supports egress tagging. + +Excessive attempts to figure out the egress tag format +was made. When nothing else worked, I just tried all bit +combinations with 0xannp where a is protocol and p is +port. I looped through all values several times trying +to get a response from ping, without any positive +result. + +Using just these ingress tags however, the switch +functionality is vastly improved and the packets find +their way into the destination port without any +tricky VLAN configuration. On the D-Link DIR-685 the +LAN ports now come up and respond to ping without +any command line configuration so this is a real +improvement for users. + +Egress packets need to be restricted to the proper +target ports using VLAN, which the RTL8366RB DSA +switch driver already sets up. + +Cc: DENG Qingfang <dqfext@gmail.com> +Cc: Mauri Sandberg <sandberg@mailfence.com> +Reviewed-by: Andrew Lunn <andrew@lunn.ch> +Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + include/net/dsa.h | 2 + + net/dsa/Kconfig | 7 +++ + net/dsa/Makefile | 1 + + net/dsa/tag_rtl4_a.c | 130 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 140 insertions(+) + create mode 100644 net/dsa/tag_rtl4_a.c + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -42,6 +42,7 @@ struct phylink_link_state; + #define DSA_TAG_PROTO_8021Q_VALUE 12 + #define DSA_TAG_PROTO_SJA1105_VALUE 13 + #define DSA_TAG_PROTO_KSZ8795_VALUE 14 ++#define DSA_TAG_PROTO_RTL4_A_VALUE 17 + + enum dsa_tag_protocol { + DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, +@@ -59,6 +60,7 @@ enum dsa_tag_protocol { + DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE, + DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE, + DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE, ++ DSA_TAG_PROTO_RTL4_A = DSA_TAG_PROTO_RTL4_A_VALUE, + }; + + struct packet_type; +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -80,6 +80,13 @@ config NET_DSA_TAG_KSZ + Say Y if you want to enable support for tagging frames for the + Microchip 8795/9477/9893 families of switches. + ++config NET_DSA_TAG_RTL4_A ++ tristate "Tag driver for Realtek 4 byte protocol A tags" ++ help ++ Say Y or M if you want to enable support for tagging frames for the ++ Realtek switches with 4 byte protocol A tags, sich as found in ++ the Realtek RTL8366RB. ++ + config NET_DSA_TAG_QCA + tristate "Tag driver for Qualcomm Atheros QCA8K switches" + help +--- a/net/dsa/Makefile ++++ b/net/dsa/Makefile +@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa + obj-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o + obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o + obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o ++obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o + obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o + obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o + obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o +--- /dev/null ++++ b/net/dsa/tag_rtl4_a.c +@@ -0,0 +1,130 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Handler for Realtek 4 byte DSA switch tags ++ * Currently only supports protocol "A" found in RTL8366RB ++ * Copyright (c) 2020 Linus Walleij <linus.walleij@linaro.org> ++ * ++ * This "proprietary tag" header looks like so: ++ * ++ * ------------------------------------------------- ++ * | MAC DA | MAC SA | 0x8899 | 2 bytes tag | Type | ++ * ------------------------------------------------- ++ * ++ * The 2 bytes tag form a 16 bit big endian word. The exact ++ * meaning has been guessed from packet dumps from ingress ++ * frames, as no working egress traffic has been available ++ * we do not know the format of the egress tags or if they ++ * are even supported. ++ */ ++ ++#include <linux/etherdevice.h> ++#include <linux/bits.h> ++ ++#include "dsa_priv.h" ++ ++#define RTL4_A_HDR_LEN 4 ++#define RTL4_A_ETHERTYPE 0x8899 ++#define RTL4_A_PROTOCOL_SHIFT 12 ++/* ++ * 0x1 = Realtek Remote Control protocol (RRCP) ++ * 0x2/0x3 seems to be used for loopback testing ++ * 0x9 = RTL8306 DSA protocol ++ * 0xa = RTL8366RB DSA protocol ++ */ ++#define RTL4_A_PROTOCOL_RTL8366RB 0xa ++ ++static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ /* ++ * Just let it pass thru, we don't know if it is possible ++ * to tag a frame with the 0x8899 ethertype and direct it ++ * to a specific port, all attempts at reverse-engineering have ++ * ended up with the frames getting dropped. ++ * ++ * The VLAN set-up needs to restrict the frames to the right port. ++ * ++ * If you have documentation on the tagging format for RTL8366RB ++ * (tag type A) then please contribute. ++ */ ++ return skb; ++} ++ ++static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb, ++ struct net_device *dev, ++ struct packet_type *pt) ++{ ++ u16 protport; ++ __be16 *p; ++ u16 etype; ++ u8 *tag; ++ u8 prot; ++ u8 port; ++ ++ if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN))) ++ return NULL; ++ ++ /* The RTL4 header has its own custom Ethertype 0x8899 and that ++ * starts right at the beginning of the packet, after the src ++ * ethernet addr. Apparantly skb->data always points 2 bytes in, ++ * behind the Ethertype. ++ */ ++ tag = skb->data - 2; ++ p = (__be16 *)tag; ++ etype = ntohs(*p); ++ if (etype != RTL4_A_ETHERTYPE) { ++ /* Not custom, just pass through */ ++ netdev_dbg(dev, "non-realtek ethertype 0x%04x\n", etype); ++ return skb; ++ } ++ p = (__be16 *)(tag + 2); ++ protport = ntohs(*p); ++ /* The 4 upper bits are the protocol */ ++ prot = (protport >> RTL4_A_PROTOCOL_SHIFT) & 0x0f; ++ if (prot != RTL4_A_PROTOCOL_RTL8366RB) { ++ netdev_err(dev, "unknown realtek protocol 0x%01x\n", prot); ++ return NULL; ++ } ++ port = protport & 0xff; ++ ++ skb->dev = dsa_master_find_slave(dev, 0, port); ++ if (!skb->dev) { ++ netdev_dbg(dev, "could not find slave for port %d\n", port); ++ return NULL; ++ } ++ ++ /* Remove RTL4 tag and recalculate checksum */ ++ skb_pull_rcsum(skb, RTL4_A_HDR_LEN); ++ ++ /* Move ethernet DA and SA in front of the data */ ++ memmove(skb->data - ETH_HLEN, ++ skb->data - ETH_HLEN - RTL4_A_HDR_LEN, ++ 2 * ETH_ALEN); ++ ++ skb->offload_fwd_mark = 1; ++ ++ return skb; ++} ++ ++static int rtl4a_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto, ++ int *offset) ++{ ++ *offset = RTL4_A_HDR_LEN; ++ /* Skip past the tag and fetch the encapsulated Ethertype */ ++ *proto = ((__be16 *)skb->data)[1]; ++ ++ return 0; ++} ++ ++static const struct dsa_device_ops rtl4a_netdev_ops = { ++ .name = "rtl4a", ++ .proto = DSA_TAG_PROTO_RTL4_A, ++ .xmit = rtl4a_tag_xmit, ++ .rcv = rtl4a_tag_rcv, ++ .flow_dissect = rtl4a_tag_flow_dissect, ++ .overhead = RTL4_A_HDR_LEN, ++}; ++module_dsa_tag_driver(rtl4a_netdev_ops); ++ ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_RTL4_A); |