[dpdk-dev] [RFC PATCH 1/3] lib: introduce IF proxy library (API)

Andrzej Ostruszka aostruszka at marvell.com
Tue Jan 14 15:25:15 CET 2020


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 at 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



More information about the dev mailing list