[RFC net-next v3 6/6] net: phy: nxp-c45-tja11xx: implement mdo_insert_tx_tag

From: Radu Pirea (NXP OSS)
Date: Wed Sep 06 2023 - 12:03:20 EST


Implement mdo_insert_tx_tag to insert the TLV header in the ethernet
frame.

If extscs parameter is set to 1, then the TLV header will contain the
TX SC that will be used to encrypt the frame, otherwise the TX SC will
be selected using the MAC source address.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@xxxxxxxxxxx>
---

Changes in V3:
- extscs parameter renamed to macsec_extscs and improved description

Changes in V2:
- added extscs parameter to choose the TX SC selection mechanism between
and MAC SA based selection and TLV header based selection

drivers/net/phy/nxp-c45-tja11xx-macsec.c | 72 ++++++++++++++++++++++++
1 file changed, 72 insertions(+)

diff --git a/drivers/net/phy/nxp-c45-tja11xx-macsec.c b/drivers/net/phy/nxp-c45-tja11xx-macsec.c
index ec827b2080d8..e2c7794a4a09 100644
--- a/drivers/net/phy/nxp-c45-tja11xx-macsec.c
+++ b/drivers/net/phy/nxp-c45-tja11xx-macsec.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/processor.h>
+#include <net/dst_metadata.h>
#include <net/macsec.h>

#include "nxp-c45-tja11xx.h"
@@ -23,6 +24,7 @@
#define VEND1_MACSEC_BASE 0x9000

#define MACSEC_CFG 0x0000
+#define MACSEC_CFG_EXTSCS BIT(26)
#define MACSEC_CFG_BYPASS BIT(1)
#define MACSEC_CFG_S0I BIT(0)

@@ -118,6 +120,8 @@
#define ADPTR_CNTRL 0x0F00
#define ADPTR_CNTRL_CONFIG_EN BIT(14)
#define ADPTR_CNTRL_ADPTR_EN BIT(12)
+#define ADPTR_TX_TAG_CNTRL 0x0F0C
+#define ADPTR_TX_TAG_CNTRL_ENA BIT(31)

#define TX_SC_FLT_BASE 0x800
#define TX_SC_FLT_SIZE 0x10
@@ -166,6 +170,18 @@
#define MACSEC_INPBTS 0x0638
#define MACSEC_IPSNFS 0x063C

+#define TJA11XX_TLV_TX_NEEDED_HEADROOM (32)
+#define TJA11XX_TLV_NEEDED_TAILROOM (0)
+
+#define MACSEC_TLV_CP BIT(0)
+#define MACSEC_TLV_SC_ID_OFF (2)
+
+#define ETH_P_TJA11XX_TLV (0x4e58)
+
+static bool macsec_extscs;
+module_param(macsec_extscs, bool, 0);
+MODULE_PARM_DESC(macsec_extscs, "Select the TX SC using TLV header information. PTP frames encryption cannot work when this feature is enabled");
+
enum nxp_c45_sa_type {
TX_SA,
RX_SA,
@@ -1523,6 +1539,48 @@ static int nxp_c45_mdo_get_rx_sa_stats(struct macsec_context *ctx)
return 0;
}

+struct tja11xx_tlv_header {
+ struct ethhdr eth;
+ u8 subtype;
+ u8 len;
+ u8 payload[28];
+};
+
+static int nxp_c45_mdo_insert_tx_tag(struct phy_device *phydev,
+ struct sk_buff *skb)
+{
+ struct nxp_c45_phy *priv = phydev->priv;
+ struct tja11xx_tlv_header *tlv;
+ struct nxp_c45_secy *phy_secy;
+ struct metadata_dst *md_dst;
+ struct ethhdr *eth;
+ sci_t sci;
+
+ eth = eth_hdr(skb);
+ tlv = skb_push(skb, TJA11XX_TLV_TX_NEEDED_HEADROOM);
+ memmove(tlv, eth, sizeof(*eth));
+ skb_reset_mac_header(skb);
+ tlv->eth.h_proto = htons(ETH_P_TJA11XX_TLV);
+ tlv->subtype = 1;
+ tlv->len = sizeof(tlv->payload);
+ memset(tlv->payload, 0, sizeof(tlv->payload));
+
+ if (!macsec_extscs)
+ return 0;
+
+ /* md_dst should be always set if MACsec is offloaded. */
+ md_dst = skb_metadata_dst(skb);
+ sci = md_dst->u.macsec_info.sci;
+ phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, sci);
+ if (IS_ERR(phy_secy))
+ return PTR_ERR(phy_secy);
+
+ tlv->payload[3] = phy_secy->secy_id << MACSEC_TLV_SC_ID_OFF |
+ MACSEC_TLV_CP;
+
+ return 0;
+}
+
static const struct macsec_ops nxp_c45_macsec_ops = {
.mdo_dev_open = nxp_c45_mdo_dev_open,
.mdo_dev_stop = nxp_c45_mdo_dev_stop,
@@ -1543,6 +1601,9 @@ static const struct macsec_ops nxp_c45_macsec_ops = {
.mdo_get_tx_sa_stats = nxp_c45_mdo_get_tx_sa_stats,
.mdo_get_rx_sc_stats = nxp_c45_mdo_get_rx_sc_stats,
.mdo_get_rx_sa_stats = nxp_c45_mdo_get_rx_sa_stats,
+ .mdo_insert_tx_tag = nxp_c45_mdo_insert_tx_tag,
+ .needed_headroom = TJA11XX_TLV_TX_NEEDED_HEADROOM,
+ .needed_tailroom = TJA11XX_TLV_NEEDED_TAILROOM,
};

int nxp_c45_macsec_config_init(struct phy_device *phydev)
@@ -1562,6 +1623,11 @@ int nxp_c45_macsec_config_init(struct phy_device *phydev)
if (ret)
return ret;

+ ret = nxp_c45_macsec_write(phydev, ADPTR_TX_TAG_CNTRL,
+ ADPTR_TX_TAG_CNTRL_ENA);
+ if (ret)
+ return ret;
+
ret = nxp_c45_macsec_write(phydev, ADPTR_CNTRL, ADPTR_CNTRL_ADPTR_EN);
if (ret)
return ret;
@@ -1584,6 +1650,12 @@ int nxp_c45_macsec_config_init(struct phy_device *phydev)
return ret;

ret = nxp_c45_macsec_write(phydev, MACSEC_UPFR0R, MACSEC_UPFR_EN);
+ if (ret)
+ return ret;
+
+ if (macsec_extscs)
+ ret = nxp_c45_macsec_write(phydev, MACSEC_CFG,
+ MACSEC_CFG_EXTSCS);

return ret;
}
--
2.34.1