[dpdk-dev] [PATCH V15 2/5] eal: add uevent pass and process function

Guo, Jia jia.guo at intel.com
Thu Mar 22 09:20:49 CET 2018


jianfeng, thanks for your review. almost make sense and comment as bellow.


On 3/21/2018 10:20 PM, Tan, Jianfeng wrote:
>
>
> On 3/21/2018 1:27 PM, Jeff Guo wrote:
>> In order to handle the uevent which have been detected from the kernel
>> side, add uevent process function, let hot plug event to be example to
>> show uevent mechanism how to pass the uevent and process the uevent.
>
> In fact, how to pass the uevent to eal/linux for processing, is 
> already done by last patch, by registering a callback into interrupt 
> thread.
>
> In this patch, we are actually showing how to process the uevent, and 
> translate it into RTE_DEV_EVENT_ADD, RTE_DEV_EVENT_DEL, etc.
>
> So the title would be something like:
>
> eal/linux: translate uevent to dev event
>
>
sorry, that what i mean should be uevent message parse but not pass, and 
what you say make sense.
>>
>> About uevent passing and processing, add below functions in linux eal
>> dev layer. FreeBSD not support uevent ,so let it to be void and do not
>> implement in function.
>> a.dev_uev_parse
>> b.dev_uev_receive
>> c.dev_uev_process
>
> We already have dummy rte_dev_event_monitor_start and 
> rte_dev_event_monitor_stop, we don't need to have those dummy internal 
> functions any more. Actually, you did not implement those dummy 
> functions.
>
yes, not dummy just internal function.
>>
>> Signed-off-by: Jeff Guo <jia.guo at intel.com>
>> ---
>> v15->v14:
>> remove the uevent type check and any policy from eal,
>> let it check and management in user's callback.
>> ---
>>   lib/librte_eal/common/include/rte_dev.h | 17 ++++++
>
> And if you agree with me in the above, we shall not touch this file. 
> Move the definition into the previous patch.
>
will check and split the definition more explicit.
>>   lib/librte_eal/linuxapp/eal/eal_dev.c | 95 
>> ++++++++++++++++++++++++++++++++-
>>   2 files changed, 111 insertions(+), 1 deletion(-)
>>
>> diff --git a/lib/librte_eal/common/include/rte_dev.h 
>> b/lib/librte_eal/common/include/rte_dev.h
>> index d2fcbc9..98ea12b 100644
>> --- a/lib/librte_eal/common/include/rte_dev.h
>> +++ b/lib/librte_eal/common/include/rte_dev.h
>> @@ -24,6 +24,23 @@ extern "C" {
>>   #include <rte_compat.h>
>>   #include <rte_log.h>
>>   +#define RTE_EAL_UEV_MSG_LEN 4096
>> +#define RTE_EAL_UEV_MSG_ELEM_LEN 128
>
> Such macro shall be linux uevent specific, so put them in linuxapp 
> folder.
>
agree.
>> +
>> +enum rte_dev_state {
>> +    RTE_DEV_UNDEFINED,    /**< unknown device state */
>> +    RTE_DEV_FAULT,    /**< device fault or error */
>> +    RTE_DEV_PARSED,    /**< device has been scanned on bus*/
>> +    RTE_DEV_PROBED,    /**< device has been probed driver */
>> +};
>
> This enum is not used in this patch series, I do see it's used in the 
> other series. So put the definition there.
>
yes.
>> +
>> +enum rte_dev_event_subsystem {
>> +    RTE_DEV_EVENT_SUBSYSTEM_UNKNOWN,
>
> I don't see where we use this macro. Seems that we now only implement 
> UIO, so I suppose, we shall set the other cases to this UNKNOWN.
>
ok.
>> +    RTE_DEV_EVENT_SUBSYSTEM_UIO,
>> +    RTE_DEV_EVENT_SUBSYSTEM_VFIO,
>
> If we don't support VFIO now, I prefer not defining it now.
>
will remove it at this stage and add later.
>> +    RTE_DEV_EVENT_SUBSYSTEM_MAX
>> +};
>
>> +
>>   /**
>>    * The device event type.
>>    */
>> diff --git a/lib/librte_eal/linuxapp/eal/eal_dev.c 
>> b/lib/librte_eal/linuxapp/eal/eal_dev.c
>> index 9d9e088..2b34e2c 100644
>> --- a/lib/librte_eal/linuxapp/eal/eal_dev.c
>> +++ b/lib/librte_eal/linuxapp/eal/eal_dev.c
>> @@ -78,9 +78,102 @@ dev_uev_monitor_create(int netlink_fd)
>>   }
>>     static void
>> +dev_uev_parse(const char *buf, struct rte_dev_event *event)
>> +{
>> +    char action[RTE_EAL_UEV_MSG_ELEM_LEN];
>> +    char subsystem[RTE_EAL_UEV_MSG_ELEM_LEN];
>> +    char dev_path[RTE_EAL_UEV_MSG_ELEM_LEN];
>> +    char pci_slot_name[RTE_EAL_UEV_MSG_ELEM_LEN];
>> +    int i = 0;
>> +
>> +    memset(action, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
>> +    memset(subsystem, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
>> +    memset(dev_path, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
>> +    memset(pci_slot_name, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
>> +
>
> Maybe we can put an example here for better understanding.
>
> And if this buf can contain multiple events? If yes, the 
> implementation is not correct, we will only record one event; if no, 
> we can simplify it a little bit.
>
the buf do not contain multiple event but will involve more string split 
by several  "/0" , so need check that by bellow code.
>> +    while (i < RTE_EAL_UEV_MSG_LEN) {
>> +        for (; i < RTE_EAL_UEV_MSG_LEN; i++) {
>> +            if (*buf)
>> +                break;
>> +            buf++;
>> +        }
>
> If we pass in the length of the buf, we don't have to skip "\0"?
>
the reason is show as above.
>> +        /**
>> +         * check device uevent from kernel side, no need to check
>> +         * uevent from udev.
>> +         */
>> +        if (!strncmp(buf, "libudev", 7)) {
>
> Use strcmp is enough. And we actually need to check left length enough 
> for strlen("libudev").
>
>> +            buf += 7;
>> +            i += 7;
>> +            return;
>> +        }
>> +        if (!strncmp(buf, "ACTION=", 7)) {
>> +            buf += 7;
>> +            i += 7;
>> +            snprintf(action, sizeof(action), "%s", buf);
>> +        } else if (!strncmp(buf, "DEVPATH=", 8)) {
>> +            buf += 8;
>> +            i += 8;
>> +            snprintf(dev_path, sizeof(dev_path), "%s", buf);
>> +        } else if (!strncmp(buf, "SUBSYSTEM=", 10)) {
>> +            buf += 10;
>> +            i += 10;
>> +            snprintf(subsystem, sizeof(subsystem), "%s", buf);
>> +        } else if (!strncmp(buf, "PCI_SLOT_NAME=", 14)) {
>> +            buf += 14;
>> +            i += 14;
>> +            snprintf(pci_slot_name, sizeof(subsystem), "%s", buf);
>> +            event->devname = pci_slot_name;
>> +        }
>> +        for (; i < RTE_EAL_UEV_MSG_LEN; i++) {
>> +            if (*buf == '\0')
>> +                break;
>> +            buf++;
>> +        }
>
> As we already check '\0' in the begin of the loop, we don't need it at 
> the end any more.
>
the reason is show as above.
>> +    }
>> +
>> +    if ((!strncmp(subsystem, "uio", 3)) ||
>> +        (!strncmp(subsystem, "pci", 3)))
>> +        event->subsystem = RTE_DEV_EVENT_SUBSYSTEM_UIO;
>> +    if (!strncmp(action, "add", 3))
>> +        event->type = RTE_DEV_EVENT_ADD;
>> +    if (!strncmp(action, "remove", 6))
>> +        event->type = RTE_DEV_EVENT_REMOVE;
>> +}
>> +
>> +static int
>> +dev_uev_receive(int fd, struct rte_dev_event *uevent)
>> +{
>> +    int ret;
>> +    char buf[RTE_EAL_UEV_MSG_LEN];
>> +
>> +    memset(uevent, 0, sizeof(struct rte_dev_event));
>> +    memset(buf, 0, RTE_EAL_UEV_MSG_LEN);
>> +
>> +    ret = recv(fd, buf, RTE_EAL_UEV_MSG_LEN - 1, MSG_DONTWAIT);
>> +    if (ret < 0) {
>> +        RTE_LOG(ERR, EAL,
>> +        "Socket read error(%d): %s\n",
>> +        errno, strerror(errno));
>> +        return -1;
>> +    } else if (ret == 0)
>> +        /* connection closed */
>> +        return -1;
>
> So we are sure how many bytes shall be parsed, we can pass the length 
> into dev_uev_parse().
>
might be better from what you said.
>> +
>> +    dev_uev_parse(buf, uevent);
>> +
>> +    return 0;
>> +}
>> +
>> +static void
>>   dev_uev_process(__rte_unused void *param)
>>   {
>> -    /* TODO: device uevent processing */
>> +    struct rte_dev_event uevent;
>> +
>> +    if (dev_uev_receive(intr_handle.fd, &uevent))
>> +        return;
>
> We don't use uevent->subsystem below, why we have to define it in 
> first place?
>
could check here and i will add that check only for uio now.
>> +
>> +    if (uevent.devname)
>> +        _rte_dev_callback_process(uevent.devname, uevent.type, NULL);
>>   }
>>     int __rte_experimental
>



More information about the dev mailing list