From patchwork Tue Jan 14 14:25:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Andrzej Ostruszka [C]" X-Patchwork-Id: 64668 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id B19FDA04FF; Tue, 14 Jan 2020 15:25:34 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id A0B3C1C1AB; Tue, 14 Jan 2020 15:25:26 +0100 (CET) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by dpdk.org (Postfix) with ESMTP id 91D731C1A5 for ; Tue, 14 Jan 2020 15:25:25 +0100 (CET) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 00EEKUmO013360 for ; Tue, 14 Jan 2020 06:25:24 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0818; bh=YsQqc2Hj+Nvgdb5LVljYpZyCMMyAbbPYlzxjM07aWZk=; b=mP284PMJShHzqvO07jPZZO2SEiDwBrVL4CEzv+WZKKnpsIWU4ReIEZyAJZl2bvewzPUn Evrs/qHSKfZGO/nqEiSh8rL1guOTrWEMg5hbvpZStKM25+Noy6rgcIDkc5jBLQJAkQdh al3v+ekhDsRXNZdupa5BEx6E+8Wmvj8gojjRnBy0QyDjwzq5lFA3RMm8/uvh2ZQOR6pb nHjBm/rKIZRfqdWVXNeMyE2GOTckTma6VELmAszQ3jolcv2FzMb0UAKhUylO85eLfUKM 1cqwjSPfAcQs2XCYEFXxHXHj3KhVLHVThzoV4vLP5DwDpPdZM8aGtV/h1k3QQK8DmwOv 1g== Received: from sc-exch01.marvell.com ([199.233.58.181]) by mx0a-0016f401.pphosted.com with ESMTP id 2xhc6sgngc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 14 Jan 2020 06:25:24 -0800 Received: from SC-EXCH03.marvell.com (10.93.176.83) by SC-EXCH01.marvell.com (10.93.176.81) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Tue, 14 Jan 2020 06:25:22 -0800 Received: from maili.marvell.com (10.93.176.43) by SC-EXCH03.marvell.com (10.93.176.83) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 14 Jan 2020 06:25:22 -0800 Received: from amok.marvell.com (unknown [10.95.130.253]) by maili.marvell.com (Postfix) with ESMTP id 4D3E43F7040; Tue, 14 Jan 2020 06:25:21 -0800 (PST) From: Andrzej Ostruszka To: CC: Jerin Jacob Kollanukkaran , Nithin Kumar Dabilpuram , Pavan Nikhilesh Bhagavatula , Kiran Kumar Kokkilagadda , Krzysztof Kanas Date: Tue, 14 Jan 2020 15:25:15 +0100 Message-ID: <20200114142517.29522-2-aostruszka@marvell.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200114142517.29522-1-aostruszka@marvell.com> References: <20200114142517.29522-1-aostruszka@marvell.com> MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.572 definitions=2020-01-14_04:2020-01-13, 2020-01-14 signatures=0 Subject: [dpdk-dev] [RFC PATCH 1/3] lib: introduce IF proxy library (API) 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" This library allows to designate ports visible to the system (such as Tun/Tap or KNI) as port representors serving as proxies for other DPDK ports. When such a proxy is configured this library initially queries network configuration from the system and later monitors its changes. The information gathered is passed to the application via a set of user registered callbacks. This way user can use normal network utilities (like those from the iproute2 suite) to configure DPDK ports. Signed-off-by: Andrzej Ostruszka --- lib/librte_if_proxy/rte_if_proxy.h | 364 +++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 lib/librte_if_proxy/rte_if_proxy.h diff --git a/lib/librte_if_proxy/rte_if_proxy.h b/lib/librte_if_proxy/rte_if_proxy.h new file mode 100644 index 000000000..83895d8b7 --- /dev/null +++ b/lib/librte_if_proxy/rte_if_proxy.h @@ -0,0 +1,364 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#ifndef _RTE_IF_PROXY_H_ +#define _RTE_IF_PROXY_H_ + +/** + * @file + * RTE IF Proxy library + * + * The IF Proxy library allows for monitoring of system network configuration + * and configuration of DPDK ports by using usual system utilities (like the + * ones from iproute2 package). + * + * It is based on the notion of "proxy interface" which actually can be any DPDK + * port which is also visible to the system - that is it has non-zero 'if_index' + * field in 'rte_eth_dev_info' structure. + * + * If application doesn't have any such port (or doesn't want to use it for + * proxy) it can create one by calling: + * + * proxy_id = rte_ifpx_create(RTE_IFPX_DEFAULT); + * + * This function is just a wrapper that constructs valid 'devargs' string based + * on the proxy type chosen (currently Tap or KNI) and creates the interface by + * calling rte_ifpx_dev_create(). + * + * Once one has DPDK port capable of being proxy one can bind target DPDK port + * to it by calling. + * + * rte_ifpx_port_bind(port_id, proxy_id); + * + * This binding is a logical one - there is no automatic packet forwarding + * between port and it's proxy since the library doesn't know the structure of + * application's packet processing. It remains application responsibility to + * forward the packets from/to proxy port (by calling the usual DPDK RX/TX burst + * API). However when the library notes some change to the proxy interface it + * will simply call appropriate callback with 'port_id' of the DPDK port that is + * bound to this proxy interface. The binding can be 1 to many - that is many + * ports can point to one proxy - in that case registered callbacks will be + * called for every bound port. + * + * The callbacks that are used for notifications are described by the + * 'rte_ifpx_callbacks' structure and they are registered by calling: + * + * rte_ifpx_callbacks_register(&cbs); + * + * Finally the application should call: + * + * rte_ifpx_listen(); + * + * which will query system for present network configuration and start listening + * to its changes. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Enum naming the type of proxy to create. + * + * @see rte_ifpx_create() + */ +enum rte_ifpx_type { + RTE_IFPX_DEFAULT, /**< Use default proxy type for given arch. */ + RTE_IFPX_TAP, /**< Use Tap based port for proxy. */ + RTE_IFPX_KNI /**< Use KNI based port for proxy. */ +}; + +/** + * Create DPDK port that can serve as an interface proxy. + * + * This function is just a wrapper around rte_ifpx_create_by_devarg() that + * constructs its 'devarg' argument based on type of proxy requested. + * + * @param type + * A type of proxy to create. + * + * @return + * DPDK port id on success, RTE_MAX_ETHPORTS otherwise. + * + * @see enum rte_ifpx_type + * @see rte_ifpx_create_by_devarg() + */ +__rte_experimental +uint16_t rte_ifpx_create(enum rte_ifpx_type type); + +/** + * Create DPDK port that can serve as an interface proxy. + * + * @param devarg + * A string passed to rte_dev_probe() to create proxy port. + * + * @return + * DPDK port id on success, RTE_MAX_ETHPORTS otherwise. + */ +__rte_experimental +uint16_t rte_ifpx_create_by_devarg(const char *devarg); + +/** + * Remove DPDK proxy port. + * + * In addition to removing the proxy port the bindings (if any) are cleared. + * + * @param proxy_id + * Port id of the proxy that should be removed. + * + * @return + * 0 on success, negative on error. + */ +__rte_experimental +int rte_ifpx_destroy(uint16_t proxy_id); + +/** + * This structure groups the callbacks that might be called as a notification + * events for changing network configuration. Not every platform might + * implement all of them and you can query the availability with + * rte_ifpx_callbacks_available() function and testing each bit against bit mask + * values defined in enum rte_ifpx_cb_bit. + * @see enum rte_ifpx_cb_bit + * @see rte_ifpx_callbacks_available() + * @see rte_ifpx_callbacks_register() + */ +struct rte_ifpx_callbacks { + void (*mac_change)(uint16_t port_id, const struct rte_ether_addr *mac); + /**< Callback for notification about MAC change of the proxy interface. + * This callback (as all other port related callbacks) is called for + * each port (with its port_id as a first argument) bound to the proxy + * interface for which change has been observed. + * @see RTE_IFPX_MAC_CHANGE + */ + void (*mtu_change)(uint16_t port_id, uint16_t mtu); + /**< Callback for notification about MTU change. + * @see RTE_IFPX_MTU_CHANGE + */ + void (*link_change)(uint16_t port_id, int is_up); + /**< Callback for notification about link going up/down. + * @see RTE_IFPX_LINK_CHANGE + */ + /* All IPv4 addresses are in host order */ + void (*addr_add)(uint16_t port_id, uint32_t ip); + /**< Callback for notification about IPv4 address being added. + * @see RTE_IFPX_ADDR_ADD + */ + void (*addr_del)(uint16_t port_id, uint32_t ip); + /**< Callback for notification about IPv4 address removal. + * @see RTE_IFPX_ADDR_DEL + */ + void (*addr6_add)(uint16_t port_id, const uint8_t *ip); + /**< Callback for notification about IPv6 address being added. + * @see RTE_IFPX_ADDR6_ADD + */ + void (*addr6_del)(uint16_t port_id, const uint8_t *ip); + /**< Callback for notification about IPv4 address removal. + * @see RTE_IFPX_ADDR6_DEL + */ + void (*route_add)(uint32_t ip, uint8_t depth); + /**< Callback for notification about IPv4 route being added. + * Note that "route" callbacks might be also called when user adds + * address to the interface (that is in addition to address related + * callbacks). + * @see RTE_IFPX_ROUTE_ADD + */ + void (*route_del)(uint32_t ip, uint8_t depth); + /**< Callback for notification about IPv4 route removal. + * @see RTE_IFPX_ROUTE_DEL + */ + void (*route6_add)(const uint8_t *ip, uint8_t depth); + /**< Callback for notification about IPv6 route being added. + * @see RTE_IFPX_ROUTE6_ADD + */ + void (*route6_del)(const uint8_t *ip, uint8_t depth); + /**< Callback for notification about IPv6 route removal. + * @see RTE_IFPX_ROUTE6_DEL + */ + void (*cfg_finished)(void); + /**< Lib specific callback - called when initial network configuration + * query is finished. + */ +}; + +/** + * The rte_ifpx_cb_bit enum defines bit mask values to test against value + * returned by rte_ifpx_callbacks_available() to learn about type of callbacks + * implemented for this platform. + */ +enum rte_ifpx_cb_bit { + RTE_IFPX_MAC_CHANGE = 1ULL << 0, /**< @see mac_change callback */ + RTE_IFPX_MTU_CHANGE = 1ULL << 1, /**< @see mtu_change callback */ + RTE_IFPX_LINK_CHANGE = 1ULL << 2, /**< @see link_change callback */ + RTE_IFPX_ADDR_ADD = 1ULL << 3, /**< @see addr_add callback */ + RTE_IFPX_ADDR_DEL = 1ULL << 4, /**< @see addr_del callback */ + RTE_IFPX_ADDR6_ADD = 1ULL << 5, /**< @see addr6_add callback */ + RTE_IFPX_ADDR6_DEL = 1ULL << 6, /**< @see addr6_del callback */ + RTE_IFPX_ROUTE_ADD = 1ULL << 7, /**< @see route_add callback */ + RTE_IFPX_ROUTE_DEL = 1ULL << 8, /**< @see route_del callback */ + RTE_IFPX_ROUTE6_ADD = 1ULL << 9, /**< @see route6_add callback */ + RTE_IFPX_ROUTE6_DEL = 1ULL << 10, /**< @see route6_del callback */ +}; +/** + * Get the bit mask of implemented callbacks for this platform. + * + * @return + * Bit mask of callbacks implemented. + * @see enum rte_ifpx_cb_bit + */ +__rte_experimental +uint64_t rte_ifpx_callbacks_available(void); + +/** + * Typedef naming type of value returned during callback registration. + * + * @see rte_ifpx_callbacks_register() + */ +typedef const void *rte_ifpx_cbs_hndl; + +/** + * Register proxy callbacks. + * + * This function registers callbacks to be called upon appropriate network + * event notification. + * + * @param cbs + * Set of callbacks that will be called. The library does not take any + * ownership of the pointer passed - the callbacks are stored internally. + * + * @return + * Non-NULL pointer upon successful registration - that pointer can be used + * as a handle to unregister callbacks (and nothing more). On failure NULL + * is returned. + */ +__rte_experimental +rte_ifpx_cbs_hndl rte_ifpx_callbacks_register(const + struct rte_ifpx_callbacks *cbs); + +/** + * Unregister proxy callbacks. + * + * This function unregisters callbacks previously registered with + * rte_ifpx_callbacks_register(). + * + * @param cbs + * Handle/pointer returned on previous callback registration. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_ifpx_callbacks_unregister(rte_ifpx_cbs_hndl cbs); + +/** + * Bind the port to its proxy. + * + * After calling this function all network configuration of the proxy (and it's + * changes) will be passed to given port by calling registered callbacks with + * 'port_id' as an argument. + * + * Note: since both arguments are of the same type in order to not mix them and + * ease remembering the order the first one is kept the same for bind/unbind. + * + * @param port_id + * Id of the port to be bound. + * @param proxy_id + * Id of the proxy the port needs to be bound to. + * @return + * 0 on success, negative on error. + */ +__rte_experimental +int rte_ifpx_port_bind(uint16_t port_id, uint16_t proxy_id); + +/** + * Unbind the port from its proxy. + * + * After calling this function registered callbacks will no longer be called for + * this port (but they might be called for other ports in one to many binding + * scenario). + * + * @param port_id + * Id of the port to unbind. + * @return + * 0 on success, negative on error. + */ +__rte_experimental +int rte_ifpx_port_unbind(uint16_t port_id); + +/** + * Get the system network configuration and start listening to its changes. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_ifpx_listen(void); + +/** + * Remove all bindings/callbacks and stop listening to network configuration. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_ifpx_close(void); + +/** + * Get the id of the proxy the port is bound to. + * + * @param port_id + * Id of the port for which to get proxy. + * @return + * Port id of the proxy on success, RTE_ETH_MAXPORT on error. + */ +__rte_experimental +uint16_t rte_ifpx_proxy_get(uint16_t port_id); + +/** + * Get the ids of the ports bound to the proxy. + * + * @param proxy_id + * Id of the proxy for which to get ports. + * @param ports + * Array where to store the port ids. + * @param num + * Size of the 'ports' array. + * @return + * The number of ports bound to given proxy. Note that this function return + * value does not depend on the ports/num argument - so you can call it first + * with NULL/0 to query for the size of the buffer to create or call it with + * the buffer you have and later check if it was large enough. + */ +__rte_experimental +unsigned int rte_ifpx_port_get(uint16_t proxy_id, + uint16_t *ports, unsigned int num); + +/** + * The structure containing some properties of the proxy interface. + */ +struct rte_ifpx_info { + unsigned int if_index; /* entry valid iff if_index != 0 */ + uint16_t mtu; + struct rte_ether_addr mac; + char if_name[RTE_ETH_NAME_MAX_LEN]; +}; + +/** + * Get the properties of the proxy interface given port is bound to. + * + * @param port_id + * Id of the port for which to get proxy properties. + * @return + * Pointer to the proxy information structure. + */ +__rte_experimental +const struct rte_ifpx_info *rte_ifpx_info_get(uint16_t port_id); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_IF_PROXY_H_ */