new file mode 100644
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ * Copyright (C) 2022 Maxime Chevallier <maxime.chevallier@bootlin.com>
+ */
+
+#ifndef _NET_DSA_OOB_H
+#define _NET_DSA_OOB_H
+
+#include <linux/skbuff.h>
+
+struct dsa_oob_tag_info {
+ u16 proto;
+ u16 dp;
+};
+
+int dsa_oob_tag_push(struct sk_buff *skb, struct dsa_oob_tag_info *ti);
+int dsa_oob_tag_pop(struct sk_buff *skb, struct dsa_oob_tag_info *ti);
+#endif
@@ -4571,6 +4571,9 @@ enum skb_ext_id {
#endif
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
SKB_EXT_MCTP,
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB)
+ SKB_EXT_DSA_OOB,
#endif
SKB_EXT_NUM, /* must be last */
};
@@ -55,6 +55,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_RTL8_4T_VALUE 25
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26
#define DSA_TAG_PROTO_LAN937X_VALUE 27
+#define DSA_TAG_PROTO_OOB_VALUE 28
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
@@ -85,6 +86,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE,
DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
DSA_TAG_PROTO_LAN937X = DSA_TAG_PROTO_LAN937X_VALUE,
+ DSA_TAG_PROTO_OOB = DSA_TAG_PROTO_OOB_VALUE,
};
struct dsa_switch;
@@ -61,8 +61,12 @@
#include <linux/if_vlan.h>
#include <linux/mpls.h>
#include <linux/kcov.h>
+#ifdef CONFIG_NET_DSA_TAG_OOB
+#include <linux/dsa/oob.h>
+#endif
#include <net/protocol.h>
+#include <net/dsa.h>
#include <net/dst.h>
#include <net/sock.h>
#include <net/checksum.h>
@@ -4474,6 +4478,9 @@ static const u8 skb_ext_type_len[] = {
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
[SKB_EXT_MCTP] = SKB_EXT_CHUNKSIZEOF(struct mctp_flow),
#endif
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB)
+ [SKB_EXT_DSA_OOB] = SKB_EXT_CHUNKSIZEOF(struct dsa_oob_tag_info),
+#endif
};
static __always_inline unsigned int skb_ext_total_length(void)
@@ -4493,6 +4500,9 @@ static __always_inline unsigned int skb_ext_total_length(void)
#endif
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
skb_ext_type_len[SKB_EXT_MCTP] +
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB)
+ skb_ext_type_len[SKB_EXT_DSA_OOB] +
#endif
0;
}
@@ -57,6 +57,14 @@ config NET_DSA_TAG_HELLCREEK
Say Y or M if you want to enable support for tagging frames
for the Hirschmann Hellcreek TSN switches.
+config NET_DSA_TAG_OOB
+ select SKB_EXTENSIONS
+ tristate "Tag driver for Out-of-band tagging drivers"
+ help
+ Say Y or M if you want to enable support for tagging out-of-band. In
+ that case, the MAC driver becomes responsible for sending the tag to
+ the switch, outside the inband data.
+
config NET_DSA_TAG_GSWIP
tristate "Tag driver for Lantiq / Intel GSWIP switches"
help
@@ -17,6 +17,7 @@ obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o
obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o
obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o
+obj-$(CONFIG_NET_DSA_TAG_OOB) += tag_oob.o
obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
new file mode 100644
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/* Copyright (c) 2022, Maxime Chevallier <maxime.chevallier@bootlin.com> */
+
+#include <linux/bitfield.h>
+#include <linux/dsa/oob.h>
+#include <linux/skbuff.h>
+
+#include "dsa_priv.h"
+
+#define DSA_OOB_TAG_LEN 4
+
+int dsa_oob_tag_push(struct sk_buff *skb, struct dsa_oob_tag_info *ti)
+{
+ struct dsa_oob_tag_info *tag_info;
+
+ tag_info = skb_ext_add(skb, SKB_EXT_DSA_OOB);
+
+ tag_info->dp = ti->dp;
+
+ return 0;
+}
+EXPORT_SYMBOL(dsa_oob_tag_push);
+
+int dsa_oob_tag_pop(struct sk_buff *skb, struct dsa_oob_tag_info *ti)
+{
+ struct dsa_oob_tag_info *tag_info;
+
+ tag_info = skb_ext_find(skb, SKB_EXT_DSA_OOB);
+ if (!tag_info)
+ return -EINVAL;
+
+ ti->dp = tag_info->dp;
+
+ return 0;
+}
+EXPORT_SYMBOL(dsa_oob_tag_pop);
+
+static struct sk_buff *oob_tag_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct dsa_port *dp = dsa_slave_to_port(dev);
+ struct dsa_oob_tag_info tag_info;
+
+ tag_info.dp = dp->index;
+
+ if (dsa_oob_tag_push(skb, &tag_info))
+ return NULL;
+
+ return skb;
+}
+
+static struct sk_buff *oob_tag_rcv(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct dsa_oob_tag_info tag_info;
+
+ if (dsa_oob_tag_pop(skb, &tag_info))
+ return NULL;
+
+ skb->dev = dsa_master_find_slave(dev, 0, tag_info.dp);
+ if (!skb->dev)
+ return NULL;
+
+ return skb;
+}
+
+const struct dsa_device_ops oob_tag_dsa_ops = {
+ .name = "oob",
+ .proto = DSA_TAG_PROTO_OOB,
+ .xmit = oob_tag_xmit,
+ .rcv = oob_tag_rcv,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DSA tag driver for out-of-band tagging");
+MODULE_AUTHOR("Maxime Chevallier <maxime.chevallier@bootlin.com>");
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_OOB);
+
+module_dsa_tag_driver(oob_tag_dsa_ops);
This tagging protocol is designed for the situation where the link between the MAC and the Switch is designed such that the Destination Port, which is usually embedded in some part of the Ethernet Header, is sent out-of-band, and isn't present at all in the Ethernet frame. This can happen when the MAC and Switch are tightly integrated on an SoC, as is the case with the Qualcomm IPQ4019 for example, where the DSA tag is inserted directly into the DMA descriptors. In that case, the MAC driver is responsible for sending the tag to the switch using the out-of-band medium. To do so, the MAC driver needs to have the information of the destination port for that skb. Add a new tagging protocol based on SKB extensions to convey the information about the destination port to the MAC driver Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> --- V4->V5 - Use SKB extensions to convey the tag V3->V4 - No changes V3->V2: - No changes, as the discussion is ongoing V1->V2: - Reworked the tagging method, putting the tag at skb->head instead of putting it into skb->shinfo, as per Andrew, Florian and Vlad's reviews include/linux/dsa/oob.h | 17 +++++++++ include/linux/skbuff.h | 3 ++ include/net/dsa.h | 2 ++ net/core/skbuff.c | 10 ++++++ net/dsa/Kconfig | 8 +++++ net/dsa/Makefile | 1 + net/dsa/tag_oob.c | 80 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 121 insertions(+) create mode 100644 include/linux/dsa/oob.h create mode 100644 net/dsa/tag_oob.c