[][Add macsec HW offload backport from kernel 5.18]
[Description]
Add macsec HW offload backport from kernel 5.18.
[Release-log]
N/A
Change-Id: I5b143fe620ec4bcae4075d1d85db5e41c8d48717
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5981730
diff --git a/target/linux/mediatek/patches-5.4/999-1756-06-v5.18-net-macsec-add-nla-support-for-changing-the-offloading-selection.patch b/target/linux/mediatek/patches-5.4/999-1756-06-v5.18-net-macsec-add-nla-support-for-changing-the-offloading-selection.patch
new file mode 100644
index 0000000..849d2cd
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/999-1756-06-v5.18-net-macsec-add-nla-support-for-changing-the-offloading-selection.patch
@@ -0,0 +1,253 @@
+From dcb780fb279514f268826f2e9f4df3bc75610703 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@bootlin.com>
+Date: Mon, 13 Jan 2020 23:31:44 +0100
+Subject: net: macsec: add nla support for changing the offloading selection
+
+MACsec offloading to underlying hardware devices is disabled by default
+(the software implementation is used). This patch adds support for
+changing this setting through the MACsec netlink interface. Many checks
+are done when enabling offloading on a given MACsec interface as there
+are limitations (it must be supported by the hardware, only a single
+interface can be offloaded on a given physical device at a time, rules
+can't be moved for now).
+
+Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/macsec.c | 145 ++++++++++++++++++++++++++++++++++++++++-
+ include/uapi/linux/if_macsec.h | 11 ++++
+ 2 files changed, 153 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index 36b0416381bf1..e515919e8687f 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -1484,6 +1484,7 @@ static const struct nla_policy macsec_genl_policy[NUM_MACSEC_ATTR] = {
+ [MACSEC_ATTR_IFINDEX] = { .type = NLA_U32 },
+ [MACSEC_ATTR_RXSC_CONFIG] = { .type = NLA_NESTED },
+ [MACSEC_ATTR_SA_CONFIG] = { .type = NLA_NESTED },
++ [MACSEC_ATTR_OFFLOAD] = { .type = NLA_NESTED },
+ };
+
+ static const struct nla_policy macsec_genl_rxsc_policy[NUM_MACSEC_RXSC_ATTR] = {
+@@ -1501,6 +1502,10 @@ static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = {
+ .len = MACSEC_MAX_KEY_LEN, },
+ };
+
++static const struct nla_policy macsec_genl_offload_policy[NUM_MACSEC_OFFLOAD_ATTR] = {
++ [MACSEC_OFFLOAD_ATTR_TYPE] = { .type = NLA_U8 },
++};
++
+ /* Offloads an operation to a device driver */
+ static int macsec_offload(int (* const func)(struct macsec_context *),
+ struct macsec_context *ctx)
+@@ -2329,6 +2334,126 @@ cleanup:
+ return ret;
+ }
+
++static bool macsec_is_configured(struct macsec_dev *macsec)
++{
++ struct macsec_secy *secy = &macsec->secy;
++ struct macsec_tx_sc *tx_sc = &secy->tx_sc;
++ int i;
++
++ if (secy->n_rx_sc > 0)
++ return true;
++
++ for (i = 0; i < MACSEC_NUM_AN; i++)
++ if (tx_sc->sa[i])
++ return true;
++
++ return false;
++}
++
++static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)
++{
++ struct nlattr *tb_offload[MACSEC_OFFLOAD_ATTR_MAX + 1];
++ enum macsec_offload offload, prev_offload;
++ int (*func)(struct macsec_context *ctx);
++ struct nlattr **attrs = info->attrs;
++ struct net_device *dev, *loop_dev;
++ const struct macsec_ops *ops;
++ struct macsec_context ctx;
++ struct macsec_dev *macsec;
++ struct net *loop_net;
++ int ret;
++
++ if (!attrs[MACSEC_ATTR_IFINDEX])
++ return -EINVAL;
++
++ if (!attrs[MACSEC_ATTR_OFFLOAD])
++ return -EINVAL;
++
++ if (nla_parse_nested_deprecated(tb_offload, MACSEC_OFFLOAD_ATTR_MAX,
++ attrs[MACSEC_ATTR_OFFLOAD],
++ macsec_genl_offload_policy, NULL))
++ return -EINVAL;
++
++ dev = get_dev_from_nl(genl_info_net(info), attrs);
++ if (IS_ERR(dev))
++ return PTR_ERR(dev);
++ macsec = macsec_priv(dev);
++
++ offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]);
++ if (macsec->offload == offload)
++ return 0;
++
++ /* Check if the offloading mode is supported by the underlying layers */
++ if (offload != MACSEC_OFFLOAD_OFF &&
++ !macsec_check_offload(offload, macsec))
++ return -EOPNOTSUPP;
++
++ if (offload == MACSEC_OFFLOAD_OFF)
++ goto skip_limitation;
++
++ /* Check the physical interface isn't offloading another interface
++ * first.
++ */
++ for_each_net(loop_net) {
++ for_each_netdev(loop_net, loop_dev) {
++ struct macsec_dev *priv;
++
++ if (!netif_is_macsec(loop_dev))
++ continue;
++
++ priv = macsec_priv(loop_dev);
++
++ if (priv->real_dev == macsec->real_dev &&
++ priv->offload != MACSEC_OFFLOAD_OFF)
++ return -EBUSY;
++ }
++ }
++
++skip_limitation:
++ /* Check if the net device is busy. */
++ if (netif_running(dev))
++ return -EBUSY;
++
++ rtnl_lock();
++
++ prev_offload = macsec->offload;
++ macsec->offload = offload;
++
++ /* Check if the device already has rules configured: we do not support
++ * rules migration.
++ */
++ if (macsec_is_configured(macsec)) {
++ ret = -EBUSY;
++ goto rollback;
++ }
++
++ ops = __macsec_get_ops(offload == MACSEC_OFFLOAD_OFF ? prev_offload : offload,
++ macsec, &ctx);
++ if (!ops) {
++ ret = -EOPNOTSUPP;
++ goto rollback;
++ }
++
++ if (prev_offload == MACSEC_OFFLOAD_OFF)
++ func = ops->mdo_add_secy;
++ else
++ func = ops->mdo_del_secy;
++
++ ctx.secy = &macsec->secy;
++ ret = macsec_offload(func, &ctx);
++ if (ret)
++ goto rollback;
++
++ rtnl_unlock();
++ return 0;
++
++rollback:
++ macsec->offload = prev_offload;
++
++ rtnl_unlock();
++ return ret;
++}
++
+ static int copy_tx_sa_stats(struct sk_buff *skb,
+ struct macsec_tx_sa_stats __percpu *pstats)
+ {
+@@ -2590,12 +2715,13 @@ static noinline_for_stack int
+ dump_secy(struct macsec_secy *secy, struct net_device *dev,
+ struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct macsec_rx_sc *rx_sc;
++ struct macsec_dev *macsec = netdev_priv(dev);
+ struct macsec_tx_sc *tx_sc = &secy->tx_sc;
+ struct nlattr *txsa_list, *rxsc_list;
+- int i, j;
+- void *hdr;
++ struct macsec_rx_sc *rx_sc;
+ struct nlattr *attr;
++ void *hdr;
++ int i, j;
+
+ hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
+ &macsec_fam, NLM_F_MULTI, MACSEC_CMD_GET_TXSC);
+@@ -2607,6 +2733,13 @@ dump_secy(struct macsec_secy *secy, struct net_device *dev,
+ if (nla_put_u32(skb, MACSEC_ATTR_IFINDEX, dev->ifindex))
+ goto nla_put_failure;
+
++ attr = nla_nest_start_noflag(skb, MACSEC_ATTR_OFFLOAD);
++ if (!attr)
++ goto nla_put_failure;
++ if (nla_put_u8(skb, MACSEC_OFFLOAD_ATTR_TYPE, macsec->offload))
++ goto nla_put_failure;
++ nla_nest_end(skb, attr);
++
+ if (nla_put_secy(secy, skb))
+ goto nla_put_failure;
+
+@@ -2872,6 +3005,12 @@ static const struct genl_ops macsec_genl_ops[] = {
+ .doit = macsec_upd_rxsa,
+ .flags = GENL_ADMIN_PERM,
+ },
++ {
++ .cmd = MACSEC_CMD_UPD_OFFLOAD,
++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
++ .doit = macsec_upd_offload,
++ .flags = GENL_ADMIN_PERM,
++ },
+ };
+
+ static struct genl_family macsec_fam __ro_after_init = {
+diff --git a/include/uapi/linux/if_macsec.h b/include/uapi/linux/if_macsec.h
+index 98e4d5d7c45ca..1d63c43c38cca 100644
+--- a/include/uapi/linux/if_macsec.h
++++ b/include/uapi/linux/if_macsec.h
+@@ -45,6 +45,7 @@ enum macsec_attrs {
+ MACSEC_ATTR_RXSC_LIST, /* dump, nested, macsec_rxsc_attrs for each RXSC */
+ MACSEC_ATTR_TXSC_STATS, /* dump, nested, macsec_txsc_stats_attr */
+ MACSEC_ATTR_SECY_STATS, /* dump, nested, macsec_secy_stats_attr */
++ MACSEC_ATTR_OFFLOAD, /* config, nested, macsec_offload_attrs */
+ __MACSEC_ATTR_END,
+ NUM_MACSEC_ATTR = __MACSEC_ATTR_END,
+ MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1,
+@@ -97,6 +98,15 @@ enum macsec_sa_attrs {
+ MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1,
+ };
+
++enum macsec_offload_attrs {
++ MACSEC_OFFLOAD_ATTR_UNSPEC,
++ MACSEC_OFFLOAD_ATTR_TYPE, /* config/dump, u8 0..2 */
++ MACSEC_OFFLOAD_ATTR_PAD,
++ __MACSEC_OFFLOAD_ATTR_END,
++ NUM_MACSEC_OFFLOAD_ATTR = __MACSEC_OFFLOAD_ATTR_END,
++ MACSEC_OFFLOAD_ATTR_MAX = __MACSEC_OFFLOAD_ATTR_END - 1,
++};
++
+ enum macsec_nl_commands {
+ MACSEC_CMD_GET_TXSC,
+ MACSEC_CMD_ADD_RXSC,
+@@ -108,6 +118,7 @@ enum macsec_nl_commands {
+ MACSEC_CMD_ADD_RXSA,
+ MACSEC_CMD_DEL_RXSA,
+ MACSEC_CMD_UPD_RXSA,
++ MACSEC_CMD_UPD_OFFLOAD,
+ };
+
+ /* u64 per-RXSC stats */
+--
+cgit 1.2.3-1.el7
+