From: Andrzej Ostruszka <aostruszka@marvell.com>
To: <dev@dpdk.org>
Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>,
Nithin Kumar Dabilpuram <ndabilpuram@marvell.com>,
Pavan Nikhilesh Bhagavatula <pbhagavatula@marvell.com>,
Kiran Kumar Kokkilagadda <kirankumark@marvell.com>,
Krzysztof Kanas <kkanas@marvell.com>
Subject: [dpdk-dev] [RFC PATCH 1/3] lib: introduce IF proxy library (API)
Date: Tue, 14 Jan 2020 15:25:15 +0100 [thread overview]
Message-ID: <20200114142517.29522-2-aostruszka@marvell.com> (raw)
In-Reply-To: <20200114142517.29522-1-aostruszka@marvell.com>
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 <aostruszka@marvell.com>
---
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 <rte_eal.h>
+#include <rte_ethdev.h>
+
+#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_ */
--
2.17.1
next prev parent reply other threads:[~2020-01-14 14:25 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-14 14:25 [dpdk-dev] [RFC PATCH 0/3] introduce IF proxy library Andrzej Ostruszka
2020-01-14 14:25 ` Andrzej Ostruszka [this message]
2020-01-14 14:25 ` [dpdk-dev] [RFC PATCH 2/3] if_proxy: add preliminary Linux implementation Andrzej Ostruszka
2020-01-14 14:25 ` [dpdk-dev] [RFC PATCH 3/3] if_proxy: add example, test and documentation Andrzej Ostruszka
2020-01-14 15:16 ` [dpdk-dev] [RFC PATCH 0/3] introduce IF proxy library Morten Brørup
2020-01-14 17:38 ` Andrzej Ostruszka
2020-01-15 10:15 ` Bruce Richardson
2020-01-15 11:27 ` Jerin Jacob
2020-01-15 12:28 ` Morten Brørup
2020-01-15 12:57 ` Jerin Jacob
2020-01-15 15:30 ` Morten Brørup
2020-01-15 16:04 ` Jerin Jacob
2020-01-15 18:15 ` Morten Brørup
2020-01-16 7:15 ` Jerin Jacob
2020-01-16 9:11 ` Morten Brørup
2020-01-16 9:09 ` Andrzej Ostruszka
2020-01-16 9:30 ` Morten Brørup
2020-01-16 10:42 ` Andrzej Ostruszka
2020-01-16 10:58 ` Morten Brørup
2020-01-16 12:06 ` Andrzej Ostruszka
2020-01-15 14:09 ` Bruce Richardson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200114142517.29522-2-aostruszka@marvell.com \
--to=aostruszka@marvell.com \
--cc=dev@dpdk.org \
--cc=jerinj@marvell.com \
--cc=kirankumark@marvell.com \
--cc=kkanas@marvell.com \
--cc=ndabilpuram@marvell.com \
--cc=pbhagavatula@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).