From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 445E61CE08 for ; Fri, 6 Apr 2018 05:47:41 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Apr 2018 20:47:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,413,1517904000"; d="scan'208";a="214351598" Received: from jguo15x-mobl3.ccr.corp.intel.com (HELO [10.67.68.27]) ([10.67.68.27]) by orsmga005.jf.intel.com with ESMTP; 05 Apr 2018 20:47:35 -0700 To: "Tan, Jianfeng" , stephen@networkplumber.org, bruce.richardson@intel.com, ferruh.yigit@intel.com, konstantin.ananyev@intel.com, gaetan.rivet@6wind.com, jingjing.wu@intel.com, thomas@monjalon.net, motih@mellanox.com, harry.van.haaren@intel.com References: <1522918968-15290-5-git-send-email-jia.guo@intel.com> <1522944617-16601-1-git-send-email-jia.guo@intel.com> <1522944617-16601-4-git-send-email-jia.guo@intel.com> <31a33a14-814e-4971-94db-d9c8ee76e6d3@intel.com> Cc: jblunck@infradead.org, shreyansh.jain@nxp.com, dev@dpdk.org, helin.zhang@intel.com From: "Guo, Jia" Message-ID: <35a85c32-8a60-5940-e943-fef87ea87743@intel.com> Date: Fri, 6 Apr 2018 11:47:35 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <31a33a14-814e-4971-94db-d9c8ee76e6d3@intel.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [dpdk-dev] [PATCH V20 3/4] eal/linux: uevent parse and process X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Apr 2018 03:47:43 -0000 thanks. On 4/6/2018 12:22 AM, Tan, Jianfeng wrote: > > > On 4/6/2018 12:10 AM, Jeff Guo wrote: >> In order to handle the uevent which has been detected from the kernel >> side, add uevent parse and process function to translate the uevent into >> device event, which user has subscribed to monitor. >> >> Signed-off-by: Jeff Guo > > Other than two nits below, > Reviewed-by: Jianfeng Tan > >> --- >> v20->v19: >> add socket error handler >> --- >> lib/librte_eal/linuxapp/eal/eal_dev.c | 206 >> +++++++++++++++++++++++++++++++++- >> 1 file changed, 204 insertions(+), 2 deletions(-) >> >> diff --git a/lib/librte_eal/linuxapp/eal/eal_dev.c >> b/lib/librte_eal/linuxapp/eal/eal_dev.c >> index 9c8d1a0..bde595c 100644 >> --- a/lib/librte_eal/linuxapp/eal/eal_dev.c >> +++ b/lib/librte_eal/linuxapp/eal/eal_dev.c >> @@ -2,21 +2,223 @@ >> * Copyright(c) 2018 Intel Corporation >> */ >> +#include >> +#include >> +#include >> +#include >> + >> #include >> #include >> #include >> +#include >> +#include >> +#include >> + >> +#include "eal_private.h" >> + >> +static struct rte_intr_handle intr_handle = {.fd = -1 }; >> +static bool monitor_started; >> + >> +#define EAL_UEV_MSG_LEN 4096 >> +#define EAL_UEV_MSG_ELEM_LEN 128 >> + >> +static void dev_uev_handler(__rte_unused void *param); >> + >> +/* identify the system layer which reports this event. */ >> +enum eal_dev_event_subsystem { >> + EAL_DEV_EVENT_SUBSYSTEM_PCI, /* PCI bus device event */ >> + EAL_DEV_EVENT_SUBSYSTEM_UIO, /* UIO driver device event */ >> + EAL_DEV_EVENT_SUBSYSTEM_VFIO, /* VFIO driver device event */ >> + EAL_DEV_EVENT_SUBSYSTEM_MAX >> +}; >> + >> +static int >> +dev_uev_socket_fd_create(void) >> +{ >> + struct sockaddr_nl addr; >> + int ret; >> + >> + intr_handle.fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC | >> + SOCK_NONBLOCK, >> + NETLINK_KOBJECT_UEVENT); >> + if (intr_handle.fd < 0) { >> + RTE_LOG(ERR, EAL, "create uevent fd failed.\n"); >> + return -1; >> + } >> + >> + memset(&addr, 0, sizeof(addr)); >> + addr.nl_family = AF_NETLINK; >> + addr.nl_pid = 0; >> + addr.nl_groups = 0xffffffff; >> + >> + ret = bind(intr_handle.fd, (struct sockaddr *) &addr, >> sizeof(addr)); >> + if (ret < 0) { >> + RTE_LOG(ERR, EAL, "Failed to bind uevent socket.\n"); >> + goto err; >> + } >> + return 0; >> +err: >> + close(intr_handle.fd); >> + intr_handle.fd = -1; >> + return ret; >> +} >> + >> +static int >> +dev_uev_parse(const char *buf, struct rte_dev_event *event, int length) >> +{ >> + char action[EAL_UEV_MSG_ELEM_LEN]; >> + char subsystem[EAL_UEV_MSG_ELEM_LEN]; >> + char pci_slot_name[EAL_UEV_MSG_ELEM_LEN]; >> + int i = 0; >> + >> + memset(action, 0, EAL_UEV_MSG_ELEM_LEN); >> + memset(subsystem, 0, EAL_UEV_MSG_ELEM_LEN); >> + memset(pci_slot_name, 0, EAL_UEV_MSG_ELEM_LEN); >> + >> + while (i < length) { >> + for (; i < length; i++) { >> + if (*buf) >> + break; >> + buf++; >> + } >> + /** >> + * check device uevent from kernel side, no need to check >> + * uevent from udev. >> + */ >> + if (!strncmp(buf, "libudev", 7)) { >> + buf += 7; >> + i += 7; >> + return -1; >> + } >> + if (!strncmp(buf, "ACTION=", 7)) { >> + buf += 7; >> + i += 7; >> + snprintf(action, sizeof(action), "%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 = strdup(pci_slot_name); >> + } >> + for (; i < length; i++) { >> + if (*buf == '\0') >> + break; >> + buf++; >> + } >> + } >> + >> + /* parse the subsystem layer */ >> + if (!strncmp(subsystem, "uio", 3)) >> + event->subsystem = EAL_DEV_EVENT_SUBSYSTEM_UIO; >> + else if (!strncmp(subsystem, "pci", 3)) >> + event->subsystem = EAL_DEV_EVENT_SUBSYSTEM_PCI; >> + else if (!strncmp(subsystem, "vfio", 4)) >> + event->subsystem = EAL_DEV_EVENT_SUBSYSTEM_VFIO; >> + else >> + return -1; >> + >> + /* parse the action type */ >> + if (!strncmp(action, "add", 3)) >> + event->type = RTE_DEV_EVENT_ADD; >> + else if (!strncmp(action, "remove", 6)) >> + event->type = RTE_DEV_EVENT_REMOVE; >> + else >> + return -1; >> + return 0; >> +} >> + >> +static void >> +dev_delayed_unregister(void *param) >> +{ >> + rte_intr_callback_unregister(&intr_handle, dev_uev_handler, param); > > You might also want to: > > + close(intr_handle.fd); > + intr_handle.fd = -1; > > >> +} >> + >> +static void >> +dev_uev_handler(__rte_unused void *param) >> +{ >> + struct rte_dev_event uevent; >> + int ret; >> + char buf[EAL_UEV_MSG_LEN]; >> + >> + memset(&uevent, 0, sizeof(struct rte_dev_event)); >> + memset(buf, 0, EAL_UEV_MSG_LEN); >> + >> + ret = recv(intr_handle.fd, buf, EAL_UEV_MSG_LEN, MSG_DONTWAIT); >> + if (ret == 0 || (ret < 0 && errno != EAGAIN)) { >> + /* connection is closed or broken, can not up again. */ >> + RTE_LOG(ERR, EAL, "uevent socket connection is broken.\n"); >> + rte_eal_alarm_set(1, dev_delayed_unregister, NULL); >> + return; >> + } else if (ret < 0) { >> + RTE_LOG(ERR, EAL, >> + "uevent socket read error(%d): %s.\n", >> + errno, strerror(errno)); >> + return; >> + } > > Above error handle can be rewritten a little bit: > > + if (ret < 0 && errno == EAGAIN) > + return; > + else if (ret <= 0) { > + /* connection is closed or broken, can not up again. */ > + RTE_LOG(ERR, EAL, "uevent socket connection is broken.\n"); > + rte_eal_alarm_set(1, dev_delayed_unregister, NULL); > + return; > + } > > >> + >> + ret = dev_uev_parse(buf, &uevent, EAL_UEV_MSG_LEN); >> + if (ret < 0) { >> + RTE_LOG(DEBUG, EAL, "It is not an valid event " >> + "that need to be handle.\n"); >> + return; >> + } >> + >> + RTE_LOG(DEBUG, EAL, "receive uevent(name:%s, type:%d, >> subsystem:%d)\n", >> + uevent.devname, uevent.type, uevent.subsystem); >> + >> + if (uevent.devname) >> + dev_callback_process(uevent.devname, uevent.type); >> +} >> int __rte_experimental >> rte_dev_event_monitor_start(void) >> { >> - /* TODO: start uevent monitor for linux */ >> + int ret; >> + >> + if (monitor_started) >> + return 0; >> + >> + ret = dev_uev_socket_fd_create(); >> + if (ret) { >> + RTE_LOG(ERR, EAL, "error create device event fd.\n"); >> + return -1; >> + } >> + >> + intr_handle.type = RTE_INTR_HANDLE_DEV_EVENT; >> + ret = rte_intr_callback_register(&intr_handle, dev_uev_handler, >> NULL); >> + >> + if (ret) { >> + RTE_LOG(ERR, EAL, "fail to register uevent callback.\n"); >> + return -1; >> + } >> + >> + monitor_started = true; >> + >> return 0; >> } >> int __rte_experimental >> rte_dev_event_monitor_stop(void) >> { >> - /* TODO: stop uevent monitor for linux */ >> + int ret; >> + >> + if (!monitor_started) >> + return 0; >> + >> + ret = rte_intr_callback_unregister(&intr_handle, dev_uev_handler, >> + (void *)-1); >> + if (ret < 0) { >> + RTE_LOG(ERR, EAL, "fail to unregister uevent callback.\n"); >> + return ret; >> + } >> + >> + close(intr_handle.fd); >> + intr_handle.fd = -1; >> + monitor_started = false; >> return 0; >> } >