From patchwork Thu Jun 28 22:55:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Gora X-Patchwork-Id: 41897 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 294301B3AF; Fri, 29 Jun 2018 00:56:01 +0200 (CEST) Received: from mail-oi0-f65.google.com (mail-oi0-f65.google.com [209.85.218.65]) by dpdk.org (Postfix) with ESMTP id C209A1B000 for ; Fri, 29 Jun 2018 00:55:59 +0200 (CEST) Received: by mail-oi0-f65.google.com with SMTP id s198-v6so2880808oih.11 for ; Thu, 28 Jun 2018 15:55:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id; bh=cdEl1hq7skaMWXoPPo1VTqfPWn0cWRE6baagA8ej7DY=; b=Xfr6BZ+uW7I2b4DzkT7FsYNiX14w7tyZHtDFvOecfyec9HeRnCBCfvXQjWF4m2PEPo ZX9tz3+8iN3BT1rdKJpms/2ohzRp6A9XBniEOCZwrtxofG7apRJdvYxTCH5Eu9qopKgs Vqi0a7D6ty8fXpTpP6no0Xvwys2grhdoZ4fHKjNN5gBkM+IejibDfbyIuC1cHFucu81O ILttMa02vuOASWvHbPtt5YWzOVM4q7UG4uar/kk1OHWfb9ebOQbuUk46R16dzINZ/VAM gSYmEqEvXqThmXZXbTnEtzMElFaXCDLq9GpfTFNjmGIMG/fDN9CzugYls5IrFzYS/DIi +Dhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=cdEl1hq7skaMWXoPPo1VTqfPWn0cWRE6baagA8ej7DY=; b=EwQ0nZlhAn8+Syx+gPsDlUFShsZVJaixGgWHri6Udh/qyoriV7WddOLPdrmZ+AZN2x qYqOFTfjoond4KYTaLnEaVF+EUBpz41IIrfNiv7vmUuM18hAMaAJ+3id1OP990AdgbIH 4P74e0saANFGgwldzv2SdWph32mdqA2CJ0BW5E6gmrXkLHxVe0WC0xPU+jCeiAByG+Yc R8kGeHEbVJGf3RER/jHBumIFzKPsi2DrSMjaeAA/EYLznFJ+TzQwE42e4DZTkHBK1cqQ /N9oXsHKTJQp4/9+SOYM+7hfWnUEvfjkcHJQvD1p83dH1cWoTwM+y7JpDA5PHEOKF2kT E5+w== X-Gm-Message-State: APt69E1A/P8xXIGQDZem7wwIT8S7mDehiWs5XdNXzVv1o8QdEewE0UIn HjfwBq9tOAO7WKGJ57velfo= X-Google-Smtp-Source: AAOMgpcK4L/7tUrLKCx3q7PTmoz13ufzyqVliTWTMRNexsprOPP/A/TaAM38iZ5HQkn67KyYg1i5zQ== X-Received: by 2002:aca:6749:: with SMTP id b9-v6mr2238476oiy.247.1530226558972; Thu, 28 Jun 2018 15:55:58 -0700 (PDT) Received: from linux.adax.com (172-11-198-60.lightspeed.sntcca.sbcglobal.net. [172.11.198.60]) by smtp.gmail.com with ESMTPSA id q93-v6sm1052935ota.58.2018.06.28.15.55.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 28 Jun 2018 15:55:58 -0700 (PDT) From: Dan Gora To: Ferruh Yigit Cc: dev@dpdk.org, Dan Gora Date: Thu, 28 Jun 2018 15:55:48 -0700 Message-Id: <20180628225548.21885-1-dg@adax.com> X-Mailer: git-send-email 2.18.0.rc1.1.g6f333ff2f Subject: [dpdk-dev] [PATCH 10/10] kni: add API to set link status on kernel interface 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add a new API function to KNI, rte_kni_update_link() to allow DPDK applications to update the link state for the KNI network interfaces in the linux kernel. Note that the default carrier state is set to off when the interface is opened. Signed-off-by: Dan Gora --- kernel/linux/kni/kni_misc.c | 63 +++++++++++++++++++ kernel/linux/kni/kni_net.c | 2 + .../eal/include/exec-env/rte_kni_common.h | 19 ++++++ lib/librte_kni/rte_kni.c | 37 ++++++++++- lib/librte_kni/rte_kni.h | 16 +++++ 5 files changed, 136 insertions(+), 1 deletion(-) diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c index 1c38cfa1a..b5784ad1b 100644 --- a/kernel/linux/kni/kni_misc.c +++ b/kernel/linux/kni/kni_misc.c @@ -585,6 +585,66 @@ kni_ioctl_free(struct net *net, uint32_t ioctl_num, return ret; } +static int +kni_ioctl_linkstat(struct net *net, uint32_t ioctl_num, + unsigned long ioctl_param) +{ + struct kni_net *knet = net_generic(net, kni_net_id); + int ret = -EINVAL; + struct kni_dev *dev, *n; + struct rte_kni_link_info link_info; + struct net_device *netdev; + uint16_t link; + + if (_IOC_SIZE(ioctl_num) > sizeof(link_info)) + return -EINVAL; + + ret = copy_from_user(&link_info, (void *)ioctl_param, + sizeof(link_info)); + if (ret) { + pr_err("copy_from_user in kni_ioctl_release"); + return -EIO; + } + + /* Release the network device according to its name */ + if (strlen(link_info.name) == 0) + return ret; + + down_read(&knet->kni_list_lock); + list_for_each_entry_safe(dev, n, &knet->kni_list_head, list) { + if (strncmp(dev->name, link_info.name, RTE_KNI_NAMESIZE) != 0) + continue; + + netdev = dev->net_dev; + if (netdev == NULL) { + up_read(&knet->kni_list_lock); + return ret; + } + + link = link_info.link_status; + + if (!netif_carrier_ok(netdev) && link) { + pr_info("%s NIC Link is Up %d Mbps %s.\n", + netdev->name, + link_info.link_speed, + link_info.link_duplex == + RTE_KNI_LINK_FULL_DUPLEX ? + "Full Duplex" : "Half Duplex"); + netif_carrier_on(netdev); + } else if (netif_carrier_ok(netdev) && !link) { + pr_info("%s NIC Link is Down.\n", + netdev->name); + netif_carrier_off(netdev); + } + + ret = 0; + break; + } + up_read(&knet->kni_list_lock); + + return ret; +} + static int kni_ioctl(struct inode *inode, uint32_t ioctl_num, unsigned long ioctl_param) { @@ -609,6 +669,9 @@ kni_ioctl(struct inode *inode, uint32_t ioctl_num, unsigned long ioctl_param) case _IOC_NR(RTE_KNI_IOCTL_FREE): ret = kni_ioctl_free(net, ioctl_num, ioctl_param); break; + case _IOC_NR(RTE_KNI_IOCTL_LINKSTAT): + ret = kni_ioctl_linkstat(net, ioctl_num, ioctl_param); + break; default: pr_debug("IOCTL default\n"); break; diff --git a/kernel/linux/kni/kni_net.c b/kernel/linux/kni/kni_net.c index 0850be434..fea3ec7e7 100644 --- a/kernel/linux/kni/kni_net.c +++ b/kernel/linux/kni/kni_net.c @@ -134,6 +134,7 @@ kni_net_open(struct net_device *dev) struct kni_dev *kni = netdev_priv(dev); netif_start_queue(dev); + netif_carrier_off(dev); memset(&req, 0, sizeof(req)); req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF; @@ -153,6 +154,7 @@ kni_net_release(struct net_device *dev) struct kni_dev *kni = netdev_priv(dev); netif_stop_queue(dev); /* can't transmit any more */ + netif_carrier_off(dev); memset(&req, 0, sizeof(req)); req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF; diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h index 318a3f939..f617d8026 100644 --- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h +++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h @@ -124,11 +124,30 @@ struct rte_kni_device_info { char mac_addr[6]; }; + +struct rte_kni_link_info { + char name[RTE_KNI_NAMESIZE]; /**< Network device name for KNI */ + uint32_t link_speed; /**< ETH_SPEED_NUM_ */ + +#define RTE_KNI_LINK_HALF_DUPLEX 0 /**< Half-duplex connection. */ +#define RTE_KNI_LINK_FULL_DUPLEX 1 /**< Full-duplex connection. */ + uint16_t link_duplex : 1; /**< RTE_KNI_LINK_[HALF/FULL]_DUPLEX */ + +#define RTE_KNI_LINK_FIXED 0 /**< No autonegotiation. */ +#define RTE_KNI_LINK_AUTONEG 1 /**< Autonegotiated. */ + uint16_t link_autoneg : 1; /**< RTE_KNI_LINK_[AUTONEG/FIXED] */ + +#define RTE_KNI_LINK_DOWN 0 /**< Link is down. */ +#define RTE_KNI_LINK_UP 1 /**< Link is up. */ + uint16_t link_status : 1; /**< RTE_KNI_LINK_[DOWN/UP] */ +}; + #define KNI_DEVICE "kni" #define RTE_KNI_IOCTL_TEST _IOWR(0, 1, int) #define RTE_KNI_IOCTL_CREATE _IOWR(0, 2, struct rte_kni_device_info) #define RTE_KNI_IOCTL_RELEASE _IOWR(0, 3, struct rte_kni_device_info) #define RTE_KNI_IOCTL_FREE _IOWR(0, 4, struct rte_kni_device_info) +#define RTE_KNI_IOCTL_LINKSTAT _IOWR(0, 5, struct rte_kni_link_info) #endif /* _RTE_KNI_COMMON_H_ */ diff --git a/lib/librte_kni/rte_kni.c b/lib/librte_kni/rte_kni.c index 6ef0859bf..aa3559306 100644 --- a/lib/librte_kni/rte_kni.c +++ b/lib/librte_kni/rte_kni.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -817,6 +816,42 @@ rte_kni_unregister_handlers(struct rte_kni *kni) return 0; } + +int +rte_kni_update_link(struct rte_kni *kni, struct rte_eth_link *link) +{ + struct rte_kni_link_info link_info; + + if (kni == NULL || !kni->in_use || link == NULL) + return -1; + + snprintf(link_info.name, sizeof(link_info.name), "%s", kni->name); + + link_info.link_speed = link->link_speed; + if (link->link_duplex == ETH_LINK_FULL_DUPLEX) + link_info.link_duplex = RTE_KNI_LINK_FULL_DUPLEX; + else + link_info.link_duplex = RTE_KNI_LINK_FULL_DUPLEX; + + if (link->link_autoneg == ETH_LINK_FIXED) + link_info.link_autoneg = RTE_KNI_LINK_FIXED; + else + link_info.link_autoneg = RTE_KNI_LINK_AUTONEG; + + if (link->link_status == ETH_LINK_UP) + link_info.link_status = RTE_KNI_LINK_UP; + else + link_info.link_status = RTE_KNI_LINK_DOWN; + + if (ioctl(kni_fd, RTE_KNI_IOCTL_LINKSTAT, &link_info) < 0) { + RTE_LOG(ERR, KNI, + "Failed to update kni link info for dev '%s'.\n", + kni->name); + return -1; + } + return 0; +} + void rte_kni_close(void) { diff --git a/lib/librte_kni/rte_kni.h b/lib/librte_kni/rte_kni.h index 94516c38f..02d781a32 100644 --- a/lib/librte_kni/rte_kni.h +++ b/lib/librte_kni/rte_kni.h @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -255,6 +256,21 @@ int rte_kni_register_handlers(struct rte_kni *kni, struct rte_kni_ops *ops); */ int rte_kni_unregister_handlers(struct rte_kni *kni); +/** + * Update link status info for KNI port. + * + * Update the linkup/linkdown status of a KNI interface in the kernel. + * + * @param kni + * pointer to struct rte_kni. + * + * @return + * On success: 0 + * On failure: -1 + */ +int __rte_experimental +rte_kni_update_link(struct rte_kni *kni, struct rte_eth_link *link); + /** * Close KNI device. */