[][openwrt][mt7988][crypto][EIP197 Alpha Release]
[Description]
Add alpha version of EIP197 package(crypto-eip)
[Release-log]
N/A
Change-Id: Ib90915f531aa238b90bd0fecc81e2ec3bf6016cc
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7908928
diff --git a/package-21.02/kernel/crypto-eip/src/xfrm-offload.c b/package-21.02/kernel/crypto-eip/src/xfrm-offload.c
new file mode 100644
index 0000000..bd79147
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/xfrm-offload.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ * Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#include <linux/bitops.h>
+
+#include <mtk_eth_soc.h>
+#include <mtk_hnat/hnat.h>
+#include <mtk_hnat/nf_hnat_mtk.h>
+
+#include <pce/cdrt.h>
+#include <pce/cls.h>
+#include <pce/netsys.h>
+
+#include <crypto-eip/ddk/configs/cs_hwpal_ext.h>
+#include <crypto-eip/ddk/kit/iotoken/iotoken.h>
+#include <crypto-eip/ddk/kit/iotoken/iotoken_ext.h>
+
+#include "crypto-eip/crypto-eip.h"
+#include "crypto-eip/ddk-wrapper.h"
+#include "crypto-eip/internal.h"
+
+static LIST_HEAD(xfrm_params_head);
+
+static void mtk_xfrm_offload_cdrt_tear_down(struct mtk_xfrm_params *xfrm_params)
+{
+ memset(&xfrm_params->cdrt->desc, 0, sizeof(struct cdrt_desc));
+
+ mtk_pce_cdrt_entry_write(xfrm_params->cdrt);
+}
+
+static int mtk_xfrm_offload_cdrt_setup(struct mtk_xfrm_params *xfrm_params)
+{
+ struct cdrt_desc *cdesc = &xfrm_params->cdrt->desc;
+
+ cdesc->desc1.common.type = 3;
+ cdesc->desc1.token_len = 48;
+ cdesc->desc1.p_tr[0] = __pa(xfrm_params->p_tr) | 2;
+
+ cdesc->desc2.hw_srv = 2;
+ cdesc->desc2.allow_pad = 1;
+ cdesc->desc2.strip_pad = 1;
+
+ return mtk_pce_cdrt_entry_write(xfrm_params->cdrt);
+}
+
+static int mtk_xfrm_offload_cls_entry_setup(struct mtk_xfrm_params *xfrm_params)
+{
+ struct cls_entry esp_cls_entry = {
+ .entry = xfrm_params->cdrt->idx + 10, /* TODO: need update */
+ .cdesc = {
+ .fport = 0x3,
+ .tport_idx = 0x2,
+ .cdrt_idx = xfrm_params->cdrt->idx,
+
+ .l4_udp_hdr_nez_m = 0x1,
+ .l4_udp_hdr_nez = 0x1,
+ .l4_hdr_usr_data_m = 0xffffffff,
+ .l4_hdr_usr_data = be32_to_cpu(xfrm_params->xs->id.spi),
+ .l4_valid_m = 0x3,
+ .l4_valid = 0x3,
+ .l4_dport_m = 0x0,
+ .l4_dport = 0x0,
+ .tag_m = 0x3,
+ .tag = 0x1,
+ .dip_match_m = 0x0,
+ .dip_match = 0x0,
+ .l4_type_m = 0xff,
+ .l4_type = 0x32,
+ },
+ };
+
+ return mtk_pce_cls_entry_register(&esp_cls_entry);
+}
+
+static void mtk_xfrm_offload_context_tear_down(struct mtk_xfrm_params *xfrm_params)
+{
+ mtk_xfrm_offload_cdrt_tear_down(xfrm_params);
+
+ /* TODO: free context */
+ devm_kfree(crypto_dev, xfrm_params->p_tr);
+
+ /* TODO: transform record tear down */
+}
+
+static int mtk_xfrm_offload_context_setup(struct mtk_xfrm_params *xfrm_params)
+{
+ u32 *tr;
+ int ret;
+
+ xfrm_params->p_tr = devm_kcalloc(crypto_dev, sizeof(u32),
+ TRANSFORM_RECORD_LEN, GFP_KERNEL);
+ if (unlikely(!xfrm_params->p_tr))
+ return -ENOMEM;
+
+ switch (xfrm_params->xs->outer_mode.encap) {
+ case XFRM_MODE_TUNNEL:
+ tr = mtk_ddk_tr_ipsec_build(xfrm_params, SAB_IPSEC_TUNNEL);
+ break;
+ case XFRM_MODE_TRANSPORT:
+ tr = mtk_ddk_tr_ipsec_build(xfrm_params, SAB_IPSEC_TRANSPORT);
+ break;
+ default:
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ if (!tr) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ memcpy(xfrm_params->p_tr, tr, sizeof(u32) * TRANSFORM_RECORD_LEN);
+
+ /* TODO: free tr */
+
+ return mtk_xfrm_offload_cdrt_setup(xfrm_params);
+
+err_out:
+ devm_kfree(crypto_dev, xfrm_params->p_tr);
+
+ return ret;
+}
+
+static int mtk_xfrm_offload_state_add_outbound(struct xfrm_state *xs,
+ struct mtk_xfrm_params *xfrm_params)
+{
+ int ret;
+
+ xfrm_params->cdrt = mtk_pce_cdrt_entry_alloc(CDRT_ENCRYPT);
+ if (IS_ERR(xfrm_params->cdrt))
+ return PTR_ERR(xfrm_params->cdrt);
+
+ xfrm_params->dir = SAB_DIRECTION_OUTBOUND;
+
+ ret = mtk_xfrm_offload_context_setup(xfrm_params);
+ if (ret)
+ goto free_cdrt;
+
+ return ret;
+
+free_cdrt:
+ mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+ return ret;
+}
+
+static int mtk_xfrm_offload_state_add_inbound(struct xfrm_state *xs,
+ struct mtk_xfrm_params *xfrm_params)
+{
+ int ret;
+
+ xfrm_params->cdrt = mtk_pce_cdrt_entry_alloc(CDRT_DECRYPT);
+ if (IS_ERR(xfrm_params->cdrt))
+ return PTR_ERR(xfrm_params->cdrt);
+
+ xfrm_params->dir = SAB_DIRECTION_INBOUND;
+
+ ret = mtk_xfrm_offload_context_setup(xfrm_params);
+ if (ret)
+ goto free_cdrt;
+
+ ret = mtk_xfrm_offload_cls_entry_setup(xfrm_params);
+ if (ret)
+ goto tear_down_context;
+
+ return ret;
+
+tear_down_context:
+ mtk_xfrm_offload_context_tear_down(xfrm_params);
+
+free_cdrt:
+ mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+ return ret;
+}
+
+int mtk_xfrm_offload_state_add(struct xfrm_state *xs)
+{
+ struct mtk_xfrm_params *xfrm_params;
+ int ret = 0;
+
+ /* TODO: maybe support IPv6 in the future? */
+ if (xs->props.family != AF_INET) {
+ CRYPTO_NOTICE("Only IPv4 xfrm states may be offloaded\n");
+ return -EINVAL;
+ }
+
+ /* only support ESP right now */
+ if (xs->id.proto != IPPROTO_ESP) {
+ CRYPTO_NOTICE("Unsupported protocol 0x%04x\n", xs->id.proto);
+ return -EINVAL;
+ }
+
+ /* only support tunnel mode or transport mode */
+ if (!(xs->outer_mode.encap == XFRM_MODE_TUNNEL
+ || xs->outer_mode.encap == XFRM_MODE_TRANSPORT))
+ return -EINVAL;
+
+ xfrm_params = devm_kzalloc(crypto_dev,
+ sizeof(struct mtk_xfrm_params),
+ GFP_KERNEL);
+ if (!xfrm_params)
+ return -ENOMEM;
+
+ xfrm_params->xs = xs;
+ INIT_LIST_HEAD(&xfrm_params->node);
+
+ if (xs->xso.flags & XFRM_OFFLOAD_INBOUND)
+ /* rx path */
+ ret = mtk_xfrm_offload_state_add_inbound(xs, xfrm_params);
+ else
+ /* tx path */
+ ret = mtk_xfrm_offload_state_add_outbound(xs, xfrm_params);
+
+ if (ret) {
+ devm_kfree(crypto_dev, xfrm_params);
+ goto out;
+ }
+
+ xs->xso.offload_handle = (unsigned long)xfrm_params;
+ list_add_tail(&xfrm_params->node, &xfrm_params_head);
+out:
+ return ret;
+}
+
+void mtk_xfrm_offload_state_delete(struct xfrm_state *xs)
+{
+}
+
+void mtk_xfrm_offload_state_free(struct xfrm_state *xs)
+{
+ struct mtk_xfrm_params *xfrm_params;
+
+ if (!xs->xso.offload_handle)
+ return;
+
+ xfrm_params = (struct mtk_xfrm_params *)xs->xso.offload_handle;
+
+ list_del(&xfrm_params->node);
+
+ if (xs->xso.flags & XFRM_OFFLOAD_INBOUND)
+ mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+ mtk_xfrm_offload_context_tear_down(xfrm_params);
+
+ mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+ devm_kfree(crypto_dev, xfrm_params);
+}
+
+void mtk_xfrm_offload_state_tear_down(void)
+{
+ struct mtk_xfrm_params *xfrm_params, *tmp;
+
+ list_for_each_entry_safe(xfrm_params, tmp, &xfrm_params_head, node)
+ mtk_xfrm_offload_state_free(xfrm_params->xs);
+}
+
+int mtk_xfrm_offload_policy_add(struct xfrm_policy *xp)
+{
+ return 0;
+}
+
+bool mtk_xfrm_offload_ok(struct sk_buff *skb,
+ struct xfrm_state *xs)
+{
+ struct mtk_xfrm_params *xfrm_params;
+
+ xfrm_params = (struct mtk_xfrm_params *)xs->xso.offload_handle;
+ skb_hnat_cdrt(skb) = xfrm_params->cdrt->idx;
+
+ return false;
+}