execuse me, one of the Windows check is failing but I didn't find where's the build log, nor to determine whether it is related.<br><br>> KNI ioctl functions copy data from userspace lib, and this interface<br>> of kmod is not compatible indeed. If the user use incompatible rte_kni.ko<br>> bad things happen: sometimes various fields contain garbage value,<br>> sometimes it cause a kmod soft lockup.<br>><br>> Some common distros ship their own rte_kni.ko, so this is likely to<br>> happen.<br>><br>> This patch add abi version checking between userland lib and kmod so<br>> that:<br>><br>> * if kmod ioctl got a wrong abi magic, it refuse to go on<br>> * if userland lib, probed a wrong abi version via newly added ioctl, it<br>>   also refuse to go on<br>><br>> Bugzilla ID: 998<br>><br>> Signed-off-by: youcai <<a href="mailto:omegacoleman@gmail.com">omegacoleman@gmail.com</a>><br>><br>> ---<br>> V3: fix code format issues<br>><br>> V2: use ABI_VERSION instead of a new magic<br>> V2: fix some indent<br>> ---<br>>  kernel/linux/kni/kni_misc.c  | 42 ++++++++++++++++++++++++++++++++++++<br>>  kernel/linux/kni/meson.build |  4 ++--<br>>  lib/kni/meson.build          |  1 +<br>>  lib/kni/rte_kni.c            | 18 ++++++++++++++++<br>>  lib/kni/rte_kni_abi.h        | 17 +++++++++++++++<br>>  lib/kni/rte_kni_common.h     |  3 +++<br>>  6 files changed, 83 insertions(+), 2 deletions(-)<br>>  create mode 100644 lib/kni/rte_kni_abi.h<br>><br>> diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c<br>> index 780187d8bf..d92500414d 100644<br>> --- a/kernel/linux/kni/kni_misc.c<br>> +++ b/kernel/linux/kni/kni_misc.c<br>> @@ -17,6 +17,7 @@<br>>  #include <net/netns/generic.h><br>><br>>  #include <rte_kni_common.h><br>> +#include <rte_kni_abi.h><br>><br>>  #include "compat.h"<br>>  #include "kni_dev.h"<br>> @@ -236,12 +237,26 @@ kni_release(struct inode *inode, struct file *file)<br>>         return 0;<br>>  }<br>><br>> +static int<br>> +kni_check_abi_version_magic(uint16_t abi_version_magic)<br>> +{<br>> +       if (abi_version_magic != RTE_KNI_ABI_VERSION_MAGIC) {<br>> +               pr_err("KNI kmod ABI incompatible with librte_kni -- %u\n",<br>> +                               RTE_KNI_ABI_VERSION_FROM_MAGIC(abi_version_magic));<br>> +               return -1;<br>> +       }<br>> +       return 0;<br>> +}<br>> +<br>>  static int<br>>  kni_check_param(struct kni_dev *kni, struct rte_kni_device_info *dev)<br>>  {<br>>         if (!kni || !dev)<br>>                 return -1;<br>><br>> +       if (kni_check_abi_version_magic(dev->abi_version_magic) < 0)<br>> +               return -1;<br>> +<br>>         /* Check if network name has been used */<br>>         if (!strncmp(kni->name, dev->name, RTE_KNI_NAMESIZE)) {<br>>                 pr_err("KNI name %s duplicated\n", dev->name);<br>> @@ -301,12 +316,19 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,<br>>         struct rte_kni_device_info dev_info;<br>>         struct net_device *net_dev = NULL;<br>>         struct kni_dev *kni, *dev, *n;<br>> +       uint16_t abi_version_magic;<br>><br>>         pr_info("Creating kni...\n");<br>>         /* Check the buffer size, to avoid warning */<br>>         if (_IOC_SIZE(ioctl_num) > sizeof(dev_info))<br>>                 return -EINVAL;<br>><br>> +       /* perform abi check ahead of copy, to avoid possible violation */<br>> +       if (copy_from_user(&abi_version_magic, (void *)ioctl_param, sizeof(uint16_t)))<br>> +               return -EFAULT;<br>> +       if (kni_check_abi_version_magic(abi_version_magic) < 0)<br>> +               return -EINVAL;<br>> +<br>>         /* Copy kni info from user space */<br>>         if (copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info)))<br>>                 return -EFAULT;<br>> @@ -451,10 +473,17 @@ kni_ioctl_release(struct net *net, uint32_t ioctl_num,<br>>         int ret = -EINVAL;<br>>         struct kni_dev *dev, *n;<br>>         struct rte_kni_device_info dev_info;<br>> +       uint16_t abi_version_magic;<br>><br>>         if (_IOC_SIZE(ioctl_num) > sizeof(dev_info))<br>>                 return -EINVAL;<br>><br>> +       /* perform abi check ahead of copy, to avoid possible violation */<br>> +       if (copy_from_user(&abi_version_magic, (void *)ioctl_param, sizeof(uint16_t)))<br>> +               return -EFAULT;<br>> +       if (kni_check_abi_version_magic(abi_version_magic) < 0)<br>> +               return -EINVAL;<br>> +<br>>         if (copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info)))<br>>                 return -EFAULT;<br>><br>> @@ -484,6 +513,16 @@ kni_ioctl_release(struct net *net, uint32_t ioctl_num,<br>>         return ret;<br>>  }<br>><br>> +static int<br>> +kni_ioctl_abi_version(struct net *net, uint32_t ioctl_num,<br>> +               unsigned long ioctl_param)<br>> +{<br>> +       uint16_t abi_version = ABI_VERSION_MAJOR;<br>> +       if (copy_to_user((void *)ioctl_param, &abi_version, sizeof(uint16_t)))<br>> +               return -EFAULT;<br>> +       return 0;<br>> +}<br>> +<br>>  static long<br>>  kni_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)<br>>  {<br>> @@ -505,6 +544,9 @@ kni_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)<br>>         case _IOC_NR(RTE_KNI_IOCTL_RELEASE):<br>>                 ret = kni_ioctl_release(net, ioctl_num, ioctl_param);<br>>                 break;<br>> +       case _IOC_NR(RTE_KNI_IOCTL_ABI_VERSION):<br>> +               ret = kni_ioctl_abi_version(net, ioctl_num, ioctl_param);<br>> +               break;<br>>         default:<br>>                 pr_debug("IOCTL default\n");<br>>                 break;<br>> diff --git a/kernel/linux/kni/meson.build b/kernel/linux/kni/meson.build<br>> index 4c90069e99..c8cd23acd9 100644<br>> --- a/kernel/linux/kni/meson.build<br>> +++ b/kernel/linux/kni/meson.build<br>> @@ -3,12 +3,12 @@<br>><br>>  # For SUSE build check function arguments of ndo_tx_timeout API<br>>  # Ref: <a href="https://jira.devtools.intel.com/browse/DPDK-29263">https://jira.devtools.intel.com/browse/DPDK-29263</a><br>> -kmod_cflags = ''<br>> +kmod_cflags = '-DABI_VERSION_MAJOR=@0@'.format(abi_version.split('.')[0])<br>>  file_path = kernel_source_dir + '/include/linux/netdevice.h'<br>>  run_cmd = run_command('grep', 'ndo_tx_timeout', file_path, check: false)<br>><br>>  if run_cmd.stdout().contains('txqueue') == true<br>> -   kmod_cflags = '-DHAVE_ARG_TX_QUEUE'<br>> +   kmod_cflags += ' -DHAVE_ARG_TX_QUEUE'<br>>  endif<br>><br>><br>> diff --git a/lib/kni/meson.build b/lib/kni/meson.build<br>> index 8a71d8ba6f..f22a27b15b 100644<br>> --- a/lib/kni/meson.build<br>> +++ b/lib/kni/meson.build<br>> @@ -14,3 +14,4 @@ endif<br>>  sources = files('rte_kni.c')<br>>  headers = files('rte_kni.h', 'rte_kni_common.h')<br>>  deps += ['ethdev', 'pci']<br>> +cflags += ['-DABI_VERSION_MAJOR=@0@'.format(abi_version.split('.')[0])]<br>> diff --git a/lib/kni/rte_kni.c b/lib/kni/rte_kni.c<br>> index 7971c56bb4..9bdeeb3806 100644<br>> --- a/lib/kni/rte_kni.c<br>> +++ b/lib/kni/rte_kni.c<br>> @@ -22,6 +22,7 @@<br>>  #include <rte_eal_memconfig.h><br>>  #include <rte_kni_common.h><br>>  #include "rte_kni_fifo.h"<br>> +#include "rte_kni_abi.h"<br>><br>>  #define MAX_MBUF_BURST_NUM            32<br>><br>> @@ -113,6 +114,20 @@ rte_kni_init(unsigned int max_kni_ifaces __rte_unused)<br>>                 }<br>>         }<br>><br>> +       uint16_t abi_version;<br>> +       int ret = ioctl(kni_fd, RTE_KNI_IOCTL_ABI_VERSION, &abi_version);<br>> +       if (ret < 0) {<br>> +               RTE_LOG(ERR, KNI, "Cannot verify rte_kni kmod ABI version: ioctl failed\n");<br>> +               return -1;<br>> +       }<br>> +       if (abi_version != ABI_VERSION_MAJOR) {<br>> +               RTE_LOG(ERR, KNI,<br>> +                               "rte_kni kmod ABI version mismatch: "<br>> +                               "need %" PRIu16 " got %" PRIu16 "\n",<br>> +                               ABI_VERSION_MAJOR, abi_version);<br>> +               return -1;<br>> +       }<br>> +<br>>         return 0;<br>>  }<br>><br>> @@ -255,6 +270,7 @@ rte_kni_alloc(struct rte_mempool *pktmbuf_pool,<br>>                 kni->ops.port_id = UINT16_MAX;<br>><br>>         memset(&dev_info, 0, sizeof(dev_info));<br>> +       dev_info.abi_version_magic = RTE_KNI_ABI_VERSION_MAGIC;<br>>         dev_info.core_id = conf->core_id;<br>>         dev_info.force_bind = conf->force_bind;<br>>         dev_info.group_id = conf->group_id;<br>> @@ -409,6 +425,8 @@ rte_kni_release(struct rte_kni *kni)<br>>         if (!kni)<br>>                 return -1;<br>><br>> +       dev_info.abi_version_magic = RTE_KNI_ABI_VERSION_MAGIC;<br>> +<br>>         kni_list = RTE_TAILQ_CAST(rte_kni_tailq.head, rte_kni_list);<br>><br>>         rte_mcfg_tailq_write_lock();<br>> diff --git a/lib/kni/rte_kni_abi.h b/lib/kni/rte_kni_abi.h<br>> new file mode 100644<br>> index 0000000000..7dde394c72<br>> --- /dev/null<br>> +++ b/lib/kni/rte_kni_abi.h<br>> @@ -0,0 +1,17 @@<br>> +/* SPDX-License-Identifier: (BSD-3-Clause OR LGPL-2.1) */<br>> +/*<br>> + * Copyright(c) 2007-2014 Intel Corporation.<br>> + */<br>> +<br>> +#ifndef _RTE_KNI_ABI_H_<br>> +#define _RTE_KNI_ABI_H_<br>> +<br>> +#ifndef ABI_VERSION_MAJOR<br>> +#error Need ABI_VERSION_MAJOR being the major part of dpdk/ABI_VERSION<br>> +#endif<br>> +#define RTE_KNI_ABI_VERSION_MAGIC_MASK 0xAAAA<br>> +#define RTE_KNI_ABI_VERSION_MAGIC (((ABI_VERSION_MAJOR) ^ RTE_KNI_ABI_VERSION_MAGIC_MASK))<br>> +#define RTE_KNI_ABI_VERSION_FROM_MAGIC(__magic) (((__magic) ^ RTE_KNI_ABI_VERSION_MAGIC_MASK))<br>> +<br>> +#endif<br>> +<br>> diff --git a/lib/kni/rte_kni_common.h b/lib/kni/rte_kni_common.h<br>> index 8d3ee0fa4f..f9432b742c 100644<br>> --- a/lib/kni/rte_kni_common.h<br>> +++ b/lib/kni/rte_kni_common.h<br>> @@ -102,6 +102,8 @@ struct rte_kni_mbuf {<br>>   */<br>><br>>  struct rte_kni_device_info {<br>> +       uint16_t abi_version_magic;<br>> +<br>>         char name[RTE_KNI_NAMESIZE];  /**< Network device name for KNI */<br>><br>>         phys_addr_t tx_phys;<br>> @@ -139,6 +141,7 @@ struct rte_kni_device_info {<br>>  #define RTE_KNI_IOCTL_TEST    _IOWR(0, 1, int)<br>>  #define RTE_KNI_IOCTL_CREATE  _IOWR(0, 2, struct rte_kni_device_info)<br>>  #define RTE_KNI_IOCTL_RELEASE _IOWR(0, 3, struct rte_kni_device_info)<br>> +#define RTE_KNI_IOCTL_ABI_VERSION _IOWR(0, 4, uint16_t)<br>><br>>  #ifdef __cplusplus<br>>  }<br>> --<br>> 2.35.1<br>><br>>