From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id E7C737F60 for ; Tue, 25 Nov 2014 15:04:23 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 25 Nov 2014 06:11:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,455,1413270000"; d="scan'208";a="643225203" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga002.jf.intel.com with ESMTP; 25 Nov 2014 06:11:52 -0800 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id sAPEBpmj023693; Tue, 25 Nov 2014 22:11:51 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id sAPEBm9r024228; Tue, 25 Nov 2014 22:11:51 +0800 Received: (from cliang18@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id sAPEBmYk024224; Tue, 25 Nov 2014 22:11:48 +0800 From: Cunming Liang To: dev@dpdk.org Date: Tue, 25 Nov 2014 22:11:18 +0800 Message-Id: <1416924682-24170-3-git-send-email-cunming.liang@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1416924682-24170-1-git-send-email-cunming.liang@intel.com> References: <1416924682-24170-1-git-send-email-cunming.liang@intel.com> Subject: [dpdk-dev] [RFC PATCH 2/6] eal: direct ring access support by linux af_packet X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Nov 2014 14:04:25 -0000 Signed-off-by: Cunming Liang --- lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/linuxapp/eal/eal_pci_bifurc.c | 336 +++++++++++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 lib/librte_eal/linuxapp/eal/eal_pci_bifurc.c diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile index 06c1dc5..f775203 100644 --- a/lib/librte_eal/linuxapp/eal/Makefile +++ b/lib/librte_eal/linuxapp/eal/Makefile @@ -61,6 +61,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_uio.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_vfio.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_vfio_mp_sync.c +SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_bifurc.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_debug.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_lcore.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_timer.c diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_bifurc.c b/lib/librte_eal/linuxapp/eal/eal_pci_bifurc.c new file mode 100644 index 0000000..94ad4df --- /dev/null +++ b/lib/librte_eal/linuxapp/eal/eal_pci_bifurc.c @@ -0,0 +1,336 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int +rte_eal_bifurc_get_ifinfo(int sockfd, char *iface_name, + int *if_index, uint8_t *hwaddr, int *mtu) +{ + struct ifreq req; + + if (iface_name == NULL) + return -1; + + memset(&req, 0, sizeof(req)); + + /* request for ifindex */ + if (if_index) { + memcpy(req.ifr_name, iface_name, IFNAMSIZ); + if (ioctl(sockfd, SIOCGIFINDEX, &req) == -1) { + RTE_LOG(ERR, EAL, + "%s: ioctl failed (SIOCGIFINDEX)\n", + iface_name); + return -1; + } + *if_index = req.ifr_ifindex; + } + + /* request for hwaddr */ + if (hwaddr) { + if (ioctl(sockfd, SIOCGIFHWADDR, &req) == -1) { + RTE_LOG(ERR, EAL, + "%s: ioctl failed (SIOCGIFHWADDR)\n", + iface_name); + return -1; + } + memcpy(hwaddr, req.ifr_hwaddr.sa_data, IFHWADDRLEN); + } + + /* request for mtu */ + if (mtu) { + if (ioctl(sockfd, SIOCGIFMTU, &req) == -1) { + RTE_LOG(ERR, EAL, + "%s: ioctl failed (SIOCGIFMTU)\n", + iface_name); + return -1; + } + *mtu = req.ifr_mtu; + } + + return 0; +} + +static int +get_map_size(int sockfd, uint32_t *size) +{ + struct tpacket_dev_qpair_map_region_info info; + socklen_t optlen; + int ret; + + /* request for map region info */ + optlen = sizeof(struct tpacket_dev_qpair_map_region_info); + ret = getsockopt(sockfd, SOL_PACKET, PACKET_DEV_QPAIR_MAP_REGION_INFO, + &info, &optlen); + if (ret == -1) { + RTE_LOG(ERR, PMD, + "could not get PACKET_DEV_QPAIR_MAP_REGION_INFO " + "on AF_PACKET socket, errno = %d\n", errno); + return -1; + } + + *size = info.tp_dev_bar_sz; + return 0; +} + +/* map PCIE configure space of queue pairs */ +int +rte_eal_bifurc_map(int sockfd, void **addr, uint32_t *size) +{ + if (addr == NULL || size == NULL) + return -1; + + if (get_map_size(sockfd, size)) + return -1; + + *addr = mmap(NULL, *size, PROT_READ | PROT_WRITE, + MAP_SHARED, sockfd, 0); + if (*addr == MAP_FAILED) { + RTE_LOG(ERR, EAL, + "call to mmap failed on AF_PACKET socket %d\n", + sockfd); + return -1; + } + + RTE_LOG(INFO, EAL, + "mapping sockfd %d PCIE configuraiton space," + "address = %p, size = 0x%x\n", sockfd, + *addr, *size); + + return 0; +} + +void +rte_eal_bifurc_unmap(int sockfd, void *addr) +{ + uint32_t size; + + if (addr && !get_map_size(sockfd, &size)) + munmap(addr, size); +} + +/* split queue pairs */ +int +rte_eal_bifurc_split(int sockfd, uint32_t *nb_qp, uint32_t *qp_start) +{ + struct tpacket_dev_qpairs_info qpairs_info; + socklen_t optlen; + int ret; + + optlen = sizeof(struct tpacket_dev_qpairs_info); + + /* request for qpairs split */ + qpairs_info.tp_qpairs_start_from = -1; + qpairs_info.tp_qpairs_num = *nb_qp; + ret = setsockopt(sockfd, SOL_PACKET, PACKET_RXTX_QPAIRS_SPLIT, + &qpairs_info, optlen); + if (ret == -1) { + RTE_LOG(ERR, EAL, + "request PACKET_RXTX_QPAIRS_SPLIT on AF_PACKET " + "socket for %d fail, errno = %d\n", + sockfd, errno); + return -1; + } + + /* parse respone of qpairs split */ + ret = getsockopt(sockfd, SOL_PACKET, PACKET_RXTX_QPAIRS_SPLIT, + &qpairs_info, &optlen); + if (ret == -1) { + RTE_LOG(ERR, EAL, + "could not get PACKET_RXTX_QPAIRS_SPLIT on AF_PACKET " + "socket for %d, errno = %d\n", sockfd, errno); + return -1; + } + + *nb_qp = qpairs_info.tp_qpairs_num; + *qp_start = qpairs_info.tp_qpairs_start_from; + + RTE_LOG(INFO, EAL, + "kernel driver allocates queue pairs from %u to %u\n", + qpairs_info.tp_qpairs_start_from, + qpairs_info.tp_qpairs_start_from + + qpairs_info.tp_qpairs_num - 1); + + return 0; +} + +/* retire queue pairs back */ +void +rte_eal_bifurc_retire(int sockfd, uint32_t nb_qp, uint32_t qp_start) +{ + struct tpacket_dev_qpairs_info qpairs_info; + int ret; + + /* return queues to kernel driver */ + qpairs_info.tp_qpairs_start_from = qp_start; + qpairs_info.tp_qpairs_num = nb_qp; + ret = setsockopt(sockfd, SOL_PACKET, PACKET_RXTX_QPAIRS_RETURN, + &qpairs_info, sizeof(qpairs_info)); + if (ret == -1) + RTE_LOG(ERR, EAL, + "could not set PACKET_RXTX_QPAIRS_RETURN on AF_PACKET " + "socket %d for queue pairs from %d to %d\n", + sockfd, qp_start, qp_start + nb_qp - 1); +} + +/* + * Opens an AF_PACKET socket + */ +int +rte_eal_bifurc_open(int *sockfd) +{ + /* Open an AF_PACKET socket... */ + if (sockfd) + *sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + + if (!sockfd || *sockfd == -1) { + RTE_LOG(ERR, EAL, "Could not open AF_PACKET socket\n"); + return -1; + } + + return 0; +} + +int +rte_eal_bifurc_bind(int sockfd, int if_index) +{ + struct sockaddr_ll sockaddr; + int ret; + + /* af_packet bind iface with sockfd */ + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sll_family = AF_PACKET; + sockaddr.sll_protocol = htons(ETH_P_ALL); + sockaddr.sll_ifindex = if_index; + ret = bind(sockfd, (const struct sockaddr *)&sockaddr, + sizeof(sockaddr)); + if (ret == -1) { + RTE_LOG(ERR, EAL, "could not bind AF_PACKET socket to %d\n", + if_index); + return ret; + } + + return 0; +} + +int +rte_eal_bifurc_set_pci(int sockfd, struct rte_pci_device *pci_dev) +{ + struct tpacket_dev_info dev_info; + socklen_t optlen; + int ret; + + /* request for desc info */ + optlen = sizeof(struct tpacket_dev_info); + ret = getsockopt(sockfd, SOL_PACKET, PACKET_DEV_DESC_INFO, + &dev_info, &optlen); + if (ret == -1) { + RTE_LOG(ERR, EAL, + "could not get PACKET_DEV_DESC_INFO on AF_PACKET " + "socket for %d, errno = %d\n", sockfd, errno); + return -1; + } + + RTE_LOG(INFO, EAL, + "vendorid = 0x%x, deviceid = 0x%x, " + "num of qpairs = %d, insue qpairs = %d\n", + dev_info.tp_vendor_id, dev_info.tp_device_id, + dev_info.tp_num_total_qpairs, dev_info.tp_num_inuse_qpairs); + + /* pci_dev update and mmap configure space */ + memset(pci_dev, 0, sizeof(*pci_dev)); + pci_dev->id.vendor_id = dev_info.tp_vendor_id; + pci_dev->id.device_id = dev_info.tp_device_id; + pci_dev->id.subsystem_vendor_id = PCI_ANY_ID; + pci_dev->id.subsystem_device_id = PCI_ANY_ID; + pci_dev->numa_node = dev_info.tp_numa_node; + + return 0; +} + +struct rte_devargs * +rte_eal_bifurc_get_devargs(const char *drv_name, const char *args) +{ + struct rte_devargs *devargs; + int ret; + + devargs = malloc(sizeof(*devargs)); + if (devargs == NULL) { + RTE_LOG(ERR, EAL, "cannot allocate devargs\n"); + return NULL; + } + memset(devargs, 0, sizeof(*devargs)); + devargs->type = RTE_DEVTYPE_VIRTUAL; + + ret = snprintf(devargs->virtual.drv_name, + sizeof(devargs->virtual.drv_name), "%s", drv_name); + if (ret < 0 || ret >= (int)sizeof(devargs->virtual.drv_name)) { + RTE_LOG(ERR, EAL, + "driver name too large: <%s>\n", drv_name); + free(devargs); + return NULL; + } + + ret = snprintf(devargs->args, sizeof(devargs->args), "%s", args); + if (ret < 0 || ret >= (int)sizeof(devargs->args)) { + RTE_LOG(ERR, EAL, + "driver args too large: <%s>\n", args); + free(devargs); + return NULL; + } + return devargs; +} + +void +rte_eal_bifurc_put_devargs(struct rte_devargs *devargs) +{ + if (devargs != NULL) + free(devargs); +} -- 1.8.1.4