Got dpa_app working
This commit is contained in:
@@ -9,9 +9,9 @@ apk add alpine-base \
|
|||||||
|
|
||||||
# For diagnotics
|
# For diagnotics
|
||||||
apk add \
|
apk add \
|
||||||
iproute2 iproute2-ss curl bind-tools procps strace tcpdump lsof jq binutils \
|
iproute2 iproute2-ss curl bind-tools procps strace tcpdump lsof jq gdb binutils \
|
||||||
openssl conntrack-tools ethtool findmnt kmod coreutils util-linux zstd libcap-utils \
|
openssl conntrack-tools ethtool findmnt kmod coreutils util-linux zstd libcap-utils \
|
||||||
iotop sysstat
|
iotop sysstat dtc
|
||||||
echo '[ -x /bin/bash ] && exec /bin/bash -l' >> "/root/.profile"
|
echo '[ -x /bin/bash ] && exec /bin/bash -l' >> "/root/.profile"
|
||||||
|
|
||||||
# Compat layer for kubelet for now. Will look into building it myself later. If needed
|
# Compat layer for kubelet for now. Will look into building it myself later. If needed
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ RUN make -C "${ASK_DIR}/cmm" \
|
|||||||
PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \
|
PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \
|
||||||
make -C "${ASK_DIR}/dpa_app" \
|
make -C "${ASK_DIR}/dpa_app" \
|
||||||
CC="aarch64-linux-musl-gcc -static" \
|
CC="aarch64-linux-musl-gcc -static" \
|
||||||
CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \
|
CFLAGS="-DDPAA_DEBUG_ENABLE -DLS1043 -DNCSW_LINUX -D__STDC_LIMIT_MACROS \
|
||||||
-I/src/fmc/source \
|
-I/src/fmc/source \
|
||||||
-I${ASK_DIR}/cdx \
|
-I${ASK_DIR}/cdx \
|
||||||
-I/src/fmlib/include/fmd \
|
-I/src/fmlib/include/fmd \
|
||||||
@@ -265,8 +265,8 @@ RUN mkdir -p /out/ASK/dist && \
|
|||||||
mkdir -p /out/ASK/bin && \
|
mkdir -p /out/ASK/bin && \
|
||||||
cp /src/fmc/source/fmc /out/ASK/bin/ && \
|
cp /src/fmc/source/fmc /out/ASK/bin/ && \
|
||||||
cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin/ && \
|
cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin/ && \
|
||||||
cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin/ && \
|
cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin/
|
||||||
aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app
|
# aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app
|
||||||
|
|
||||||
# in-tree Linux kernel modules
|
# in-tree Linux kernel modules
|
||||||
RUN mkdir -p /out/rootfs && \
|
RUN mkdir -p /out/rootfs && \
|
||||||
@@ -282,7 +282,7 @@ RUN KERNEL_VER=$(ls /out/rootfs/lib/modules/) && \
|
|||||||
RUN mkdir -p /out/rootfs-cfg/etc/dpa && \
|
RUN mkdir -p /out/rootfs-cfg/etc/dpa && \
|
||||||
cp -r "${ASK_DIR}/dpa_app/files/etc/"* /out/rootfs-cfg/etc/dpa/ && \
|
cp -r "${ASK_DIR}/dpa_app/files/etc/"* /out/rootfs-cfg/etc/dpa/ && \
|
||||||
cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \
|
cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \
|
||||||
cp -r /src/fmc/etc /out/rootfs-cfg/etc
|
cp -r /src/fmc/etc/* /out/rootfs-cfg/etc
|
||||||
|
|
||||||
FROM scratch AS export
|
FROM scratch AS export
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
## ASK
|
||||||
|
The most important one is vendor's ASK. Which provides all the required resources to build the device-specific kernel
|
||||||
|
|
||||||
## Updating build.env
|
## Updating build.env
|
||||||
You can find the latest package versions in here
|
You can find the latest package versions in here
|
||||||
* [kernel](https://github.com/nxp-qoriq/linux/archive/refs/tags/)
|
* [kernel](https://github.com/nxp-qoriq/linux/archive/refs/tags/)
|
||||||
@@ -10,3 +13,68 @@ You can find the latest package versions in here
|
|||||||
https://github.com/we-are-mono/OpenWRT-ASK/tree/mono-25.12.0-rc3/target/linux/layerscape/files/arch/arm64/boot/dts/freescale
|
https://github.com/we-are-mono/OpenWRT-ASK/tree/mono-25.12.0-rc3/target/linux/layerscape/files/arch/arm64/boot/dts/freescale
|
||||||
* We need both `mono-gateway-dk-sdk.dts` and `mono-gateway-dk.dts` since the sdk one includes the non-sdk one.
|
* We need both `mono-gateway-dk-sdk.dts` and `mono-gateway-dk.dts` since the sdk one includes the non-sdk one.
|
||||||
* The actual dts being used is the `mono-gateway-dk-sdk.dts`
|
* The actual dts being used is the `mono-gateway-dk-sdk.dts`
|
||||||
|
|
||||||
|
## Testing dpa_app
|
||||||
|
Run this on the gateway device
|
||||||
|
```bash
|
||||||
|
while true; do nc -l -p 1234 -e sh; done
|
||||||
|
```
|
||||||
|
|
||||||
|
Run this script on your dev machine
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
FILES="
|
||||||
|
bin/dpa_app
|
||||||
|
rootfs-cfg/etc/dpa/cdx_cfg.xml
|
||||||
|
rootfs-cfg/etc/dpa/cdx_pcd.xml
|
||||||
|
rootfs-cfg/etc/dpa/cdx_sp.xml
|
||||||
|
rootfs-cfg/etc/dpa/cdx_cfg_ls1046_rdb.xml
|
||||||
|
rootfs-cfg/etc/fmc/config/hxs_pdl_v3.xml
|
||||||
|
rootfs-cfg/etc/fmc/config/cfgdata.xsd
|
||||||
|
rootfs-cfg/etc/fmc/config/netpcd.xsd
|
||||||
|
"
|
||||||
|
|
||||||
|
SIZE=$(
|
||||||
|
tar -C ./out/ASK -czf - $FILES | wc -c
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
echo 'set -eu'
|
||||||
|
|
||||||
|
echo 'rm -rf /var/dpa-test'
|
||||||
|
echo 'mkdir -p /var/dpa-test/bin'
|
||||||
|
echo 'mkdir -p /etc/dpa'
|
||||||
|
echo 'mkdir -p /etc/fmc/config'
|
||||||
|
|
||||||
|
echo 'base64 -d > /tmp/dpa-test.tar.gz <<'"'"'EOF'"'"''
|
||||||
|
tar -C ./out/ASK -czf - $FILES | pv -s "$SIZE" | base64
|
||||||
|
echo 'EOF'
|
||||||
|
|
||||||
|
echo 'tar -xzf /tmp/dpa-test.tar.gz -C /var/dpa-test'
|
||||||
|
|
||||||
|
echo 'cp /var/dpa-test/bin/dpa_app /var/dpa_app'
|
||||||
|
echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_cfg.xml /etc/dpa/cdx_cfg.xml'
|
||||||
|
echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_pcd.xml /etc/dpa/cdx_pcd.xml'
|
||||||
|
echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_sp.xml /etc/dpa/cdx_sp.xml'
|
||||||
|
echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/hxs_pdl_v3.xml /etc/fmc/config/hxs_pdl_v3.xml'
|
||||||
|
echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/cfgdata.xsd /etc/fmc/config/cfgdata.xsd'
|
||||||
|
echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/netpcd.xsd /etc/fmc/config/netpcd.xsd'
|
||||||
|
|
||||||
|
echo 'chmod +x /var/dpa_app'
|
||||||
|
|
||||||
|
echo 'export CDX_CFG_FILE=/etc/dpa/cdx_cfg.xml'
|
||||||
|
echo 'export CDX_PCD_FILE=/etc/dpa/cdx_pcd.xml'
|
||||||
|
echo 'export CDX_SP_FILE=/etc/dpa/cdx_sp.xml'
|
||||||
|
echo 'export CDX_PDL_FILE=/etc/fmc/config/hxs_pdl_v3.xml'
|
||||||
|
|
||||||
|
echo 'echo "CDX_CFG_FILE=$CDX_CFG_FILE"'
|
||||||
|
echo 'echo "CDX_PCD_FILE=$CDX_PCD_FILE"'
|
||||||
|
echo 'echo "CDX_SP_FILE=$CDX_SP_FILE"'
|
||||||
|
echo 'echo "CDX_PDL_FILE=$CDX_PDL_FILE"'
|
||||||
|
|
||||||
|
echo 'ls -l /var/dpa_app /etc/dpa /etc/fmc/config'
|
||||||
|
echo 'echo Running /var/dpa_app'
|
||||||
|
echo '/var/dpa_app'
|
||||||
|
echo 'echo exit=$?'
|
||||||
|
) | nc 10.0.0.10 1234
|
||||||
|
```
|
||||||
|
|||||||
@@ -264,19 +264,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ethernet@8 {
|
ethernet@8 {
|
||||||
compatible = "fsl,dpa-ethernet-init";
|
compatible = "fsl,dpa-ethernet";
|
||||||
fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
|
/delete-property/ fsl,bman-buffer-pools;
|
||||||
fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
|
/delete-property/ fsl,qman-frame-queues-rx;
|
||||||
fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
|
/delete-property/ fsl,qman-frame-queues-tx;
|
||||||
|
dma-coherent;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Add MAC10 - not in qoriq-dpaa-eth.dtsi */
|
/* Add MAC10 - not in qoriq-dpaa-eth.dtsi */
|
||||||
ethernet@9 {
|
ethernet@9 {
|
||||||
compatible = "fsl,dpa-ethernet-init";
|
compatible = "fsl,dpa-ethernet";
|
||||||
fsl,fman-mac = <&enet7>;
|
fsl,fman-mac = <&enet7>;
|
||||||
fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
|
/delete-property/ fsl,bman-buffer-pools;
|
||||||
fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
|
/delete-property/ fsl,qman-frame-queues-rx;
|
||||||
fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
|
/delete-property/ fsl,qman-frame-queues-tx;
|
||||||
dma-coherent;
|
dma-coherent;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -336,12 +337,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ethernet@f0000 {
|
ethernet@f0000 {
|
||||||
|
status = "okay";
|
||||||
/delete-property/ managed;
|
/delete-property/ managed;
|
||||||
fixed-link = <0 1 10000 0 0>;
|
fixed-link = <0 1 10000 0 0>;
|
||||||
phy-connection-type = "xgmii";
|
phy-connection-type = "xgmii";
|
||||||
};
|
};
|
||||||
|
|
||||||
ethernet@f2000 {
|
ethernet@f2000 {
|
||||||
|
status = "okay";
|
||||||
/delete-property/ managed;
|
/delete-property/ managed;
|
||||||
fixed-link = <0 1 10000 0 0>;
|
fixed-link = <0 1 10000 0 0>;
|
||||||
phy-connection-type = "xgmii";
|
phy-connection-type = "xgmii";
|
||||||
|
|||||||
@@ -500,14 +500,14 @@
|
|||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
fm1_mac9: ethernet@f0000 { /* 10GEC1 */
|
fm0_mac9: ethernet@f0000 { /* 10GEC1 */
|
||||||
sfp = <&sfp_xfi0>;
|
sfp = <&sfp_xfi0>;
|
||||||
phy-connection-type = "10gbase-r";
|
phy-connection-type = "10gbase-r";
|
||||||
managed = "in-band-status";
|
managed = "in-band-status";
|
||||||
pcs-handle-names = "xfi"; /* Match enet7 for consistency */
|
pcs-handle-names = "xfi"; /* Match enet7 for consistency */
|
||||||
};
|
};
|
||||||
|
|
||||||
fm1_mac10: ethernet@f2000 { /* 10GEC2 */
|
fm0_mac10: ethernet@f2000 { /* 10GEC2 */
|
||||||
sfp = <&sfp_xfi1>;
|
sfp = <&sfp_xfi1>;
|
||||||
phy-connection-type = "10gbase-r";
|
phy-connection-type = "10gbase-r";
|
||||||
managed = "in-band-status";
|
managed = "in-band-status";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
From: monok8s <monok8s@example.invalid>
|
From: monok8s <monok8s@example.invalid>
|
||||||
Date: Sun, 10 May 2026 00:00:00 +0000
|
Date: Sun, 10 May 2026 00:00:00 +0000
|
||||||
Subject: [PATCH] dpa_app: allow XML config paths to be overridden by env
|
Subject: [PATCH 1/4] dpa_app: allow XML config paths to be overridden by env
|
||||||
|
|
||||||
Keep the vendor default XML paths, but allow deployments to override them
|
Keep the vendor default XML paths, but allow deployments to override them
|
||||||
without patching the binary or placing board-specific XML files directly
|
without patching the binary or placing board-specific XML files directly
|
||||||
|
|||||||
152
patches/ask/dpa/0002-cdx-harden-fman-port-lookup.patch
Normal file
152
patches/ask/dpa/0002-cdx-harden-fman-port-lookup.patch
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: monok8s <monok8s@example.invalid>
|
||||||
|
Date: Sun, 10 May 2026 00:00:00 +0000
|
||||||
|
Subject: [PATCH 2/4] cdx: harden FMAN port lookup
|
||||||
|
|
||||||
|
The DPA userspace loader passes FMC-derived port metadata into the CDX
|
||||||
|
ioctl. If an Ethernet netdev has a partially initialized DPAA private
|
||||||
|
structure, find_osdev_by_fman_params() can dereference a missing mac_dev
|
||||||
|
or FM wrapper pointer while trying to match the FMC port.
|
||||||
|
|
||||||
|
Add lookup diagnostics and hard NULL guards so a mismatched board
|
||||||
|
model returns -ENODEV instead of oopsing the kernel.
|
||||||
|
---
|
||||||
|
cdx/devman.c | 85 +++++++++++++++++++++++++++++++++++++--------------
|
||||||
|
cdx/dpa_cfg.c | 18 ++++++++---
|
||||||
|
2 files changed, 76 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff -urN a/cdx/devman.c b/cdx/devman.c
|
||||||
|
--- a/cdx/devman.c 2026-05-10 00:32:28.745375897 +0000
|
||||||
|
+++ b/cdx/devman.c 2026-05-10 00:32:29.834300280 +0000
|
||||||
|
@@ -396,39 +396,74 @@
|
||||||
|
uint32_t speed)
|
||||||
|
{
|
||||||
|
struct net_device *device;
|
||||||
|
- struct dpa_priv_s *priv;
|
||||||
|
- struct mac_device *macdev;
|
||||||
|
+
|
||||||
|
+ DPA_INFO("%s::lookup fm %u port %u speed %uG\n",
|
||||||
|
+ __func__, fm_idx, port_idx, speed);
|
||||||
|
|
||||||
|
device = first_net_device(&init_net);
|
||||||
|
- while(1) {
|
||||||
|
- if (!device)
|
||||||
|
- break;
|
||||||
|
- if (device->type == ARPHRD_ETHER) {
|
||||||
|
- t_LnxWrpFmDev *p_LnxWrpFmDev;
|
||||||
|
- priv = netdev_priv(device);
|
||||||
|
- macdev = priv->mac_dev;
|
||||||
|
- if (macdev) {
|
||||||
|
- p_LnxWrpFmDev = (t_LnxWrpFmDev*)macdev->fm;
|
||||||
|
- if (speed == 10) {
|
||||||
|
- //10 gig interfaces upports only SUPPORTED_10000baseT_Full
|
||||||
|
- /*DGW board has 2 fixed-link interfaces
|
||||||
|
- 1 - (eth2)(xDSL)1G Fixed link interface linked to rgmii-txid
|
||||||
|
- 2 - eth5(G.fast)- 1G Fixed link interface linked to sgmii and
|
||||||
|
- connected to 10G link of the board.
|
||||||
|
- sgmii - considered as 1000baseT_Full and this has cell_index = 0*/
|
||||||
|
-
|
||||||
|
- if ( (!macdev->fixed_link) && (macdev->if_support != SUPPORTED_10000baseT_Full) )
|
||||||
|
- goto next_device;
|
||||||
|
- }
|
||||||
|
- if ((fm_idx == p_LnxWrpFmDev->id) &&
|
||||||
|
- (port_idx == macdev->cell_index))
|
||||||
|
- return device;
|
||||||
|
- }
|
||||||
|
+ while (device) {
|
||||||
|
+ struct dpa_priv_s *priv;
|
||||||
|
+ struct mac_device *macdev;
|
||||||
|
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
|
||||||
|
+
|
||||||
|
+ if (device->type != ARPHRD_ETHER)
|
||||||
|
+ goto next_device;
|
||||||
|
+
|
||||||
|
+ priv = netdev_priv(device);
|
||||||
|
+ if (!priv) {
|
||||||
|
+ DPA_INFO("%s::skip %s: null private data\n",
|
||||||
|
+ __func__, device->name);
|
||||||
|
+ goto next_device;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ macdev = priv->mac_dev;
|
||||||
|
+ if (!macdev) {
|
||||||
|
+ DPA_INFO("%s::skip %s: null mac_dev\n",
|
||||||
|
+ __func__, device->name);
|
||||||
|
+ goto next_device;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!macdev->fm) {
|
||||||
|
+ DPA_INFO("%s::skip %s: null mac_dev->fm cell_index %u max_speed %u fixed_link %u if_support 0x%x\n",
|
||||||
|
+ __func__, device->name, macdev->cell_index,
|
||||||
|
+ macdev->max_speed, macdev->fixed_link,
|
||||||
|
+ macdev->if_support);
|
||||||
|
+ goto next_device;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *)macdev->fm;
|
||||||
|
+ DPA_INFO("%s::candidate %s fm %u cell_index %u max_speed %u fixed_link %u if_support 0x%x\n",
|
||||||
|
+ __func__, device->name, p_LnxWrpFmDev->id,
|
||||||
|
+ macdev->cell_index, macdev->max_speed,
|
||||||
|
+ macdev->fixed_link, macdev->if_support);
|
||||||
|
+
|
||||||
|
+ if (speed == 10) {
|
||||||
|
+ //10 gig interfaces upports only SUPPORTED_10000baseT_Full
|
||||||
|
+ /*DGW board has 2 fixed-link interfaces
|
||||||
|
+ 1 - (eth2)(xDSL)1G Fixed link interface linked to rgmii-txid
|
||||||
|
+ 2 - eth5(G.fast)- 1G Fixed link interface linked to sgmii and
|
||||||
|
+ connected to 10G link of the board.
|
||||||
|
+ sgmii - considered as 1000baseT_Full and this has cell_index = 0*/
|
||||||
|
+
|
||||||
|
+ if ((!macdev->fixed_link) &&
|
||||||
|
+ (macdev->if_support != SUPPORTED_10000baseT_Full))
|
||||||
|
+ goto next_device;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((fm_idx == p_LnxWrpFmDev->id) &&
|
||||||
|
+ (port_idx == macdev->cell_index)) {
|
||||||
|
+ DPA_INFO("%s::matched %s for fm %u port %u speed %uG\n",
|
||||||
|
+ __func__, device->name, fm_idx, port_idx, speed);
|
||||||
|
+ return device;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
next_device:
|
||||||
|
device = next_net_device(device);
|
||||||
|
}
|
||||||
|
- return device;
|
||||||
|
+
|
||||||
|
+ DPA_ERROR("%s::no OS device found for fm %u port %u speed %uG\n",
|
||||||
|
+ __func__, fm_idx, port_idx, speed);
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff -urN a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c
|
||||||
|
--- a/cdx/dpa_cfg.c 2026-05-10 00:32:28.757992164 +0000
|
||||||
|
+++ b/cdx/dpa_cfg.c 2026-05-10 00:32:51.954850425 +0000
|
||||||
|
@@ -301,15 +301,21 @@
|
||||||
|
struct net_device *dev;
|
||||||
|
|
||||||
|
if (port_info->type) {
|
||||||
|
+ DPA_INFO("%s::mapping user port %s fm %u index %u portid %u type %uG\n",
|
||||||
|
+ __func__, port_info->name, port_info->fm_index,
|
||||||
|
+ port_info->index, port_info->portid, port_info->type);
|
||||||
|
dev = find_osdev_by_fman_params(port_info->fm_index,
|
||||||
|
port_info->index, port_info->type);
|
||||||
|
if (!dev) {
|
||||||
|
- DPA_ERROR("%s::could not map port %s\n",
|
||||||
|
- __func__, port_info->name);
|
||||||
|
- return -EIO;
|
||||||
|
- } else {
|
||||||
|
- strcpy(port_info->name, dev->name);
|
||||||
|
+ DPA_ERROR("%s::could not map port %s fm %u index %u portid %u type %uG\n",
|
||||||
|
+ __func__, port_info->name,
|
||||||
|
+ port_info->fm_index, port_info->index,
|
||||||
|
+ port_info->portid, port_info->type);
|
||||||
|
+ return -ENODEV;
|
||||||
|
}
|
||||||
|
+ DPA_INFO("%s::mapped user port %s to netdev %s\n",
|
||||||
|
+ __func__, port_info->name, dev->name);
|
||||||
|
+ strscpy(port_info->name, dev->name, sizeof(port_info->name));
|
||||||
|
}
|
||||||
|
#ifdef DPA_CFG_DEBUG
|
||||||
|
DPA_INFO("%s::port %s, fmindex %d, port index %d, port id %d\n",
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: monok8s <monok8s@example.invalid>
|
||||||
|
Date: Sun, 10 May 2026 00:00:00 +0000
|
||||||
|
Subject: [PATCH 3/4] cdx: avoid kfree of userspace dist_info pointers
|
||||||
|
|
||||||
|
get_port_info() copies an array of cdx_port_info from userspace. At that
|
||||||
|
point each cdx_port_info.dist_info field is still a userspace pointer.
|
||||||
|
However release_cfg_info() treats any non-NULL dist_info as a kernel
|
||||||
|
allocation and kfree()s it on error paths.
|
||||||
|
|
||||||
|
If a later step fails before get_dist_info() has replaced every dist_info
|
||||||
|
with a kernel allocation, release_cfg_info() can kfree a raw userspace
|
||||||
|
pointer and oops in kfree()/virt_to_folio().
|
||||||
|
|
||||||
|
Stash the userspace dist_info pointers in a temporary array, clear the
|
||||||
|
kernel-side cdx_port_info.dist_info fields immediately after copy_from_user(),
|
||||||
|
and pass the saved userspace pointer explicitly to get_dist_info(). This
|
||||||
|
keeps release_cfg_info() safe on partial-initialization failures.
|
||||||
|
---
|
||||||
|
cdx/dpa_cfg.c | 47 +++++++++++++++++++++++++++++++++++++----------
|
||||||
|
1 file changed, 37 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff -urN a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c
|
||||||
|
--- a/cdx/dpa_cfg.c 2026-05-10 00:46:34.295813594 +0000
|
||||||
|
+++ b/cdx/dpa_cfg.c 2026-05-10 00:46:35.558487337 +0000
|
||||||
|
@@ -169,11 +169,10 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
//allocate and copy distribution info from uspace
|
||||||
|
-static int get_dist_info(struct cdx_port_info *port_info)
|
||||||
|
+static int get_dist_info(struct cdx_port_info *port_info, void *uspace_info)
|
||||||
|
{
|
||||||
|
uint32_t mem_size;
|
||||||
|
struct cdx_dist_info *dist_info;
|
||||||
|
- void *uspace_info;
|
||||||
|
|
||||||
|
#ifdef DPA_CFG_DEBUG
|
||||||
|
DPA_INFO("%s::port %s dist %d\n", __func__,
|
||||||
|
@@ -187,7 +186,6 @@
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(dist_info, 0, mem_size);
|
||||||
|
- uspace_info = port_info->dist_info;
|
||||||
|
port_info->dist_info = dist_info;
|
||||||
|
if (copy_from_user(dist_info, uspace_info,
|
||||||
|
mem_size)) {
|
||||||
|
@@ -273,6 +271,7 @@
|
||||||
|
{
|
||||||
|
struct cdx_port_info *port_info;
|
||||||
|
void *uspace_info;
|
||||||
|
+ void **uspace_dist_info;
|
||||||
|
uint32_t mem_size;
|
||||||
|
uint32_t ii;
|
||||||
|
|
||||||
|
@@ -289,13 +288,40 @@
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(port_info, 0, mem_size);
|
||||||
|
+
|
||||||
|
+ uspace_dist_info = kcalloc(finfo->max_ports, sizeof(*uspace_dist_info),
|
||||||
|
+ GFP_KERNEL);
|
||||||
|
+ if (!uspace_dist_info) {
|
||||||
|
+ DPA_ERROR("%s::memalloc for uspace_dist_info failed\n",
|
||||||
|
+ __func__);
|
||||||
|
+ kfree(port_info);
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
uspace_info = finfo->portinfo;
|
||||||
|
finfo->portinfo = port_info;
|
||||||
|
if (copy_from_user(port_info, uspace_info, mem_size)) {
|
||||||
|
DPA_ERROR("%s::Read port_info failed\n",
|
||||||
|
__func__);
|
||||||
|
+ finfo->portinfo = NULL;
|
||||||
|
+ kfree(uspace_dist_info);
|
||||||
|
+ kfree(port_info);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * port_info has just been copied from userspace, so each dist_info
|
||||||
|
+ * member is still a userspace pointer. release_cfg_info() kfree()s
|
||||||
|
+ * non-NULL dist_info members, therefore keeping those raw userspace
|
||||||
|
+ * pointers in the kernel copy turns any later error path into an
|
||||||
|
+ * invalid kfree(). Stash the userspace pointers separately and clear
|
||||||
|
+ * the struct fields until get_dist_info() replaces them with real
|
||||||
|
+ * kernel allocations.
|
||||||
|
+ */
|
||||||
|
+ for (ii = 0; ii < finfo->max_ports; ii++) {
|
||||||
|
+ uspace_dist_info[ii] = port_info[ii].dist_info;
|
||||||
|
+ port_info[ii].dist_info = NULL;
|
||||||
|
+ }
|
||||||
|
//put the linux name for the port
|
||||||
|
for (ii = 0; ii < finfo->max_ports; ii++) {
|
||||||
|
struct net_device *dev;
|
||||||
|
@@ -311,6 +337,7 @@
|
||||||
|
__func__, port_info->name,
|
||||||
|
port_info->fm_index, port_info->index,
|
||||||
|
port_info->portid, port_info->type);
|
||||||
|
+ kfree(uspace_dist_info);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
DPA_INFO("%s::mapped user port %s to netdev %s\n",
|
||||||
|
@@ -330,11 +357,14 @@
|
||||||
|
for (ii = 0; ii < finfo->max_ports; ii++) {
|
||||||
|
int retval;
|
||||||
|
//get dist info for this port
|
||||||
|
- retval = get_dist_info(port_info);
|
||||||
|
- if (retval)
|
||||||
|
+ retval = get_dist_info(port_info, uspace_dist_info[ii]);
|
||||||
|
+ if (retval) {
|
||||||
|
+ kfree(uspace_dist_info);
|
||||||
|
return retval;
|
||||||
|
+ }
|
||||||
|
port_info++;
|
||||||
|
}
|
||||||
|
+ kfree(uspace_dist_info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: monok8s <monok8s@example.invalid>
|
||||||
|
Date: Sun, 10 May 2026 00:00:00 +0000
|
||||||
|
Subject: [PATCH 4/4] cdx: stash userspace fman nested pointers before cleanup
|
||||||
|
|
||||||
|
cdx_ioc_set_dpa_params() copies struct cdx_fman_info from userspace.
|
||||||
|
The nested portinfo and tbl_info members are userspace pointers at that
|
||||||
|
point, but release_cfg_info() treats non-NULL nested pointers as
|
||||||
|
kernel-owned allocations.
|
||||||
|
|
||||||
|
If setup fails before get_port_info() or get_cctbl_info() replaces those
|
||||||
|
members with kernel allocations, the error path can kfree a userspace
|
||||||
|
address and panic in kfree()/virt_to_folio().
|
||||||
|
|
||||||
|
Stash the userspace pointers in temporary arrays, clear the nested
|
||||||
|
members in fman_info immediately, and pass the stashed pointers into the
|
||||||
|
copy helpers explicitly. Also route early setup failures through the same
|
||||||
|
cleanup path so partial state is released consistently.
|
||||||
|
---
|
||||||
|
diff --git a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c
|
||||||
|
index c678d5d..55b910d 100644
|
||||||
|
--- a/cdx/dpa_cfg.c
|
||||||
|
+++ b/cdx/dpa_cfg.c
|
||||||
|
@@ -267,10 +267,9 @@ static void *get_dist_info_by_fman_params(struct cdx_fman_info *finfo, uint32_t
|
||||||
|
#endif //CDX_RTP_RELAY
|
||||||
|
|
||||||
|
//allocate and copy port releated info from uspace
|
||||||
|
-static int get_port_info(struct cdx_fman_info *finfo)
|
||||||
|
+static int get_port_info(struct cdx_fman_info *finfo, void *uspace_info)
|
||||||
|
{
|
||||||
|
struct cdx_port_info *port_info;
|
||||||
|
- void *uspace_info;
|
||||||
|
void **uspace_dist_info;
|
||||||
|
uint32_t mem_size;
|
||||||
|
uint32_t ii;
|
||||||
|
@@ -298,7 +297,6 @@ static int get_port_info(struct cdx_fman_info *finfo)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
- uspace_info = finfo->portinfo;
|
||||||
|
finfo->portinfo = port_info;
|
||||||
|
if (copy_from_user(port_info, uspace_info, mem_size)) {
|
||||||
|
DPA_ERROR("%s::Read port_info failed\n",
|
||||||
|
@@ -355,7 +353,7 @@ static int get_port_info(struct cdx_fman_info *finfo)
|
||||||
|
}
|
||||||
|
port_info = finfo->portinfo;
|
||||||
|
for (ii = 0; ii < finfo->max_ports; ii++) {
|
||||||
|
- int retval;
|
||||||
|
+ int retval = 0;
|
||||||
|
//get dist info for this port
|
||||||
|
retval = get_dist_info(port_info, uspace_dist_info[ii]);
|
||||||
|
if (retval) {
|
||||||
|
@@ -369,11 +367,10 @@ static int get_port_info(struct cdx_fman_info *finfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
//allocate and copy cc table infor from uspace
|
||||||
|
-static int get_cctbl_info(struct cdx_fman_info *finfo)
|
||||||
|
+static int get_cctbl_info(struct cdx_fman_info *finfo, void *uspace_info)
|
||||||
|
{
|
||||||
|
struct table_info *tbl_info;
|
||||||
|
uint32_t mem_size;
|
||||||
|
- void *uspace_info;
|
||||||
|
|
||||||
|
//allocate table information area
|
||||||
|
mem_size = (sizeof(struct table_info) * finfo->num_tables);
|
||||||
|
@@ -384,7 +381,6 @@ static int get_cctbl_info(struct cdx_fman_info *finfo)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(tbl_info, 0, mem_size);
|
||||||
|
- uspace_info = finfo->tbl_info;
|
||||||
|
finfo->tbl_info = tbl_info;
|
||||||
|
//copy table related info from user space
|
||||||
|
if (copy_from_user(tbl_info, (void *)uspace_info, mem_size)) {
|
||||||
|
@@ -625,9 +621,11 @@ int cdx_ioc_set_dpa_params(unsigned long args)
|
||||||
|
{
|
||||||
|
struct cdx_ctrl_set_dpa_params params;
|
||||||
|
struct cdx_fman_info *finfo;
|
||||||
|
+ void **uspace_port_info = NULL;
|
||||||
|
+ void **uspace_tbl_info = NULL;
|
||||||
|
uint32_t ii;
|
||||||
|
uint32_t mem_size;
|
||||||
|
- int retval;
|
||||||
|
+ int retval = 0;
|
||||||
|
|
||||||
|
if (copy_from_user(¶ms, (void *)args,
|
||||||
|
sizeof(struct cdx_ctrl_set_dpa_params))) {
|
||||||
|
@@ -655,6 +653,35 @@ int cdx_ioc_set_dpa_params(unsigned long args)
|
||||||
|
retval = -EIO;
|
||||||
|
goto err_ret;
|
||||||
|
}
|
||||||
|
+ uspace_port_info = kcalloc(num_fmans, sizeof(*uspace_port_info),
|
||||||
|
+ GFP_KERNEL);
|
||||||
|
+ uspace_tbl_info = kcalloc(num_fmans, sizeof(*uspace_tbl_info),
|
||||||
|
+ GFP_KERNEL);
|
||||||
|
+ if (!uspace_port_info || !uspace_tbl_info) {
|
||||||
|
+ DPA_ERROR("%s::unable to allocate user pointer stash\n",
|
||||||
|
+ __func__);
|
||||||
|
+ for (ii = 0; ii < num_fmans; ii++) {
|
||||||
|
+ fman_info[ii].portinfo = NULL;
|
||||||
|
+ fman_info[ii].tbl_info = NULL;
|
||||||
|
+ }
|
||||||
|
+ retval = -ENOMEM;
|
||||||
|
+ goto err_ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * fman_info is copied from userspace. Its nested portinfo and
|
||||||
|
+ * tbl_info members are userspace pointers until get_port_info() and
|
||||||
|
+ * get_cctbl_info() replace them with kernel allocations. Never leave
|
||||||
|
+ * raw userspace pointers in fman_info, because release_cfg_info() owns
|
||||||
|
+ * and frees non-NULL nested pointers on error paths.
|
||||||
|
+ */
|
||||||
|
+ for (ii = 0; ii < num_fmans; ii++) {
|
||||||
|
+ uspace_port_info[ii] = fman_info[ii].portinfo;
|
||||||
|
+ uspace_tbl_info[ii] = fman_info[ii].tbl_info;
|
||||||
|
+ fman_info[ii].portinfo = NULL;
|
||||||
|
+ fman_info[ii].tbl_info = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (copy_from_user(&ipr_info, (void *)params.ipr_info,
|
||||||
|
sizeof(struct cdx_ipr_info))) {
|
||||||
|
DPA_ERROR("%s::Read iprv_info failed\n",
|
||||||
|
@@ -665,22 +688,26 @@ int cdx_ioc_set_dpa_params(unsigned long args)
|
||||||
|
//init the fman handles
|
||||||
|
finfo = fman_info;
|
||||||
|
for (ii = 0; ii < num_fmans; ii++) {
|
||||||
|
- if (cdxdrv_get_fman_handles(finfo))
|
||||||
|
- return -1;
|
||||||
|
+ if (cdxdrv_get_fman_handles(finfo)) {
|
||||||
|
+ retval = -EIO;
|
||||||
|
+ goto err_ret;
|
||||||
|
+ }
|
||||||
|
finfo++;
|
||||||
|
}
|
||||||
|
finfo = fman_info;
|
||||||
|
//init interface stats module
|
||||||
|
- if (cdxdrv_init_stats(finfo->muram_handle))
|
||||||
|
- return -1;
|
||||||
|
+ if (cdxdrv_init_stats(finfo->muram_handle)) {
|
||||||
|
+ retval = -EIO;
|
||||||
|
+ goto err_ret;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
for (ii = 0; ii < num_fmans; ii++) {
|
||||||
|
//get port info
|
||||||
|
- retval = get_port_info(finfo);
|
||||||
|
+ retval = get_port_info(finfo, uspace_port_info[ii]);
|
||||||
|
if (retval)
|
||||||
|
goto err_ret;
|
||||||
|
//get cc table info
|
||||||
|
- retval = get_cctbl_info(finfo);
|
||||||
|
+ retval = get_cctbl_info(finfo, uspace_tbl_info[ii]);
|
||||||
|
if (retval)
|
||||||
|
goto err_ret;
|
||||||
|
finfo++;
|
||||||
|
@@ -727,29 +754,43 @@ int cdx_ioc_set_dpa_params(unsigned long args)
|
||||||
|
finfo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (cdx_create_port_fqs())
|
||||||
|
- return -1;
|
||||||
|
+ if (cdx_create_port_fqs()) {
|
||||||
|
+ retval = -EIO;
|
||||||
|
+ goto err_ret;
|
||||||
|
+ }
|
||||||
|
//create cp rate limit policier profiles
|
||||||
|
if (cdxdrv_create_missaction_policer_profiles(fman_info)) {
|
||||||
|
+ retval = -EIO;
|
||||||
|
goto err_ret;
|
||||||
|
}
|
||||||
|
#ifdef ENABLE_INGRESS_QOS
|
||||||
|
if (cdxdrv_create_ingress_qos_policer_profiles(fman_info)) {
|
||||||
|
+ retval = -EIO;
|
||||||
|
goto err_ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_EGRESS_QOS
|
||||||
|
- if(ceetm_init_cq_plcr())
|
||||||
|
+ if(ceetm_init_cq_plcr()) {
|
||||||
|
+ retval = -EIO;
|
||||||
|
goto err_ret;
|
||||||
|
+ }
|
||||||
|
#endif
|
||||||
|
//init the fman and its ports
|
||||||
|
for (ii = 0; ii < num_fmans; ii++) {
|
||||||
|
- if (cdxdrv_set_miss_action(ii))
|
||||||
|
+ if (cdxdrv_set_miss_action(ii)) {
|
||||||
|
+ retval = -EIO;
|
||||||
|
goto err_ret;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
display_dpa_cfg();
|
||||||
|
+ kfree(uspace_port_info);
|
||||||
|
+ kfree(uspace_tbl_info);
|
||||||
|
return 0;
|
||||||
|
err_ret:
|
||||||
|
+ DPA_ERROR("%s::error path retval %d, releasing partial DPA cfg\n",
|
||||||
|
+ __func__, retval);
|
||||||
|
+ kfree(uspace_port_info);
|
||||||
|
+ kfree(uspace_tbl_info);
|
||||||
|
release_cfg_info();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.5
|
||||||
Reference in New Issue
Block a user