#include "mlx5_defs.h"
#include "mlx5_utils.h"
#include "mlx5_mr.h"
+#include "mlx5_nl.h"
#include "mlx5_autoconf.h"
/* Request types for IPC. */
/** Key string for IPC. */
#define MLX5_MP_NAME "net_mlx5_mp"
-/* Recognized Infiniband device physical port name types. */
-enum mlx5_phys_port_name_type {
- MLX5_PHYS_PORT_NAME_TYPE_NOTSET = 0, /* Not set. */
- MLX5_PHYS_PORT_NAME_TYPE_LEGACY, /* before kernel ver < 5.0 */
- MLX5_PHYS_PORT_NAME_TYPE_UPLINK, /* p0, kernel ver >= 5.0 */
- MLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */
- MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */
-};
-
-/** Switch information returned by mlx5_nl_switch_info(). */
-struct mlx5_switch_info {
- uint32_t master:1; /**< Master device. */
- uint32_t representor:1; /**< Representor device. */
- enum mlx5_phys_port_name_type name_type; /** < Port name type. */
- int32_t pf_num; /**< PF number (valid for pfxvfx format only). */
- int32_t port_name; /**< Representor port name. */
- uint64_t switch_id; /**< Switch identifier. */
-};
LIST_HEAD(mlx5_dev_list, mlx5_ibv_shared);
MLX5_VERBS_ALLOC_TYPE_RX_QUEUE,
};
-/* VLAN netdev for VLAN workaround. */
-struct mlx5_vlan_dev {
- uint32_t refcnt;
- uint32_t ifindex; /**< Own interface index. */
-};
-
/* Structure for VF VLAN workaround. */
struct mlx5_vf_vlan {
uint32_t tag:12;
uint32_t created:1;
};
-/*
- * Array of VLAN devices created on the base of VF
- * used for workaround in virtual environments.
- */
-struct mlx5_vlan_vmwa_context {
- int nl_socket;
- uint32_t nl_sn;
- uint32_t vf_ifindex;
- struct rte_eth_dev *dev;
- struct mlx5_vlan_dev vlan_dev[4096];
-};
-
/**
* Verbs allocator needs a context to know in the callback which kind of
* resources it is allocating.
int nl_socket_route; /* Netlink socket (NETLINK_ROUTE). */
uint32_t nl_sn; /* Netlink message sequence number. */
LIST_HEAD(dbrpage, mlx5_devx_dbr_page) dbrpgs; /* Door-bell pages. */
- struct mlx5_vlan_vmwa_context *vmwa_context; /* VLAN WA context. */
+ struct mlx5_nl_vlan_vmwa_context *vmwa_context; /* VLAN WA context. */
struct mlx5_flow_id_pool *qrss_id_pool;
struct mlx5_hlist *mreg_cp_tbl;
/* Hash table of Rx metadata register copy table. */
void mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index);
int mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
uint32_t index, uint32_t vmdq);
+struct mlx5_nl_vlan_vmwa_context *mlx5_vlan_vmwa_init
+ (struct rte_eth_dev *dev, uint32_t ifindex);
int mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr);
int mlx5_set_mc_addr_list(struct rte_eth_dev *dev,
struct rte_ether_addr *mc_addr_set,
int mlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on);
void mlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on);
int mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+void mlx5_vlan_vmwa_exit(struct mlx5_nl_vlan_vmwa_context *ctx);
+void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
+ struct mlx5_vf_vlan *vf_vlan);
+void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
+ struct mlx5_vf_vlan *vf_vlan);
/* mlx5_trigger.c */
int mlx5_pmd_socket_init(void);
void mlx5_pmd_socket_uninit(void);
-/* mlx5_nl.c */
-
-int mlx5_nl_init(int protocol);
-int mlx5_nl_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
- uint32_t index);
-int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
- uint32_t index);
-void mlx5_nl_mac_addr_sync(struct rte_eth_dev *dev);
-void mlx5_nl_mac_addr_flush(struct rte_eth_dev *dev);
-int mlx5_nl_promisc(struct rte_eth_dev *dev, int enable);
-int mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable);
-unsigned int mlx5_nl_portnum(int nl, const char *name);
-unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);
-int mlx5_nl_vf_mac_addr_modify(struct rte_eth_dev *dev,
- struct rte_ether_addr *mac, int vf_index);
-int mlx5_nl_switch_info(int nl, unsigned int ifindex,
- struct mlx5_switch_info *info);
-
-struct mlx5_vlan_vmwa_context *mlx5_vlan_vmwa_init(struct rte_eth_dev *dev,
- uint32_t ifindex);
-void mlx5_vlan_vmwa_exit(struct mlx5_vlan_vmwa_context *ctx);
-void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
- struct mlx5_vf_vlan *vf_vlan);
-void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
- struct mlx5_vf_vlan *vf_vlan);
-
/* mlx5_flow_meter.c */
int mlx5_flow_meter_ops_get(struct rte_eth_dev *dev, void *arg);
#include <errno.h>
#include <linux/if_link.h>
-#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <rdma/rdma_netlink.h>
#include <unistd.h>
#include <rte_errno.h>
-#include <rte_malloc.h>
-#include <rte_hypervisor.h>
#include "mlx5.h"
#include "mlx5_utils.h"
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
int
-mlx5_nl_switch_info(int nl, unsigned int ifindex, struct mlx5_switch_info *info)
+mlx5_nl_switch_info(int nl, unsigned int ifindex,
+ struct mlx5_switch_info *info)
{
uint32_t seq = random();
struct {
* Delete VLAN network device by ifindex.
*
* @param[in] tcf
- * Context object initialized by mlx5_vlan_vmwa_init().
+ * Context object initialized by mlx5_nl_vlan_vmwa_init().
* @param[in] ifindex
* Interface index of network device to delete.
*/
-static void
-mlx5_vlan_vmwa_delete(struct mlx5_vlan_vmwa_context *vmwa,
+void
+mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,
uint32_t ifindex)
{
int ret;
* Create network VLAN device with specified VLAN tag.
*
* @param[in] tcf
- * Context object initialized by mlx5_vlan_vmwa_init().
+ * Context object initialized by mlx5_nl_vlan_vmwa_init().
* @param[in] ifindex
* Base network interface index.
* @param[in] tag
* VLAN tag for VLAN network device to create.
*/
-static uint32_t
-mlx5_vlan_vmwa_create(struct mlx5_vlan_vmwa_context *vmwa,
+uint32_t
+mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,
uint32_t ifindex,
uint16_t tag)
{
}
return ret;
}
-
-/*
- * Release VLAN network device, created for VM workaround.
- *
- * @param[in] dev
- * Ethernet device object, Netlink context provider.
- * @param[in] vlan
- * Object representing the network device to release.
- */
-void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
- struct mlx5_vf_vlan *vlan)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_vlan_vmwa_context *vmwa = priv->vmwa_context;
- struct mlx5_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
-
- assert(vlan->created);
- assert(priv->vmwa_context);
- if (!vlan->created || !vmwa)
- return;
- vlan->created = 0;
- assert(vlan_dev[vlan->tag].refcnt);
- if (--vlan_dev[vlan->tag].refcnt == 0 &&
- vlan_dev[vlan->tag].ifindex) {
- mlx5_vlan_vmwa_delete(vmwa, vlan_dev[vlan->tag].ifindex);
- vlan_dev[vlan->tag].ifindex = 0;
- }
-}
-
-/**
- * Acquire VLAN interface with specified tag for VM workaround.
- *
- * @param[in] dev
- * Ethernet device object, Netlink context provider.
- * @param[in] vlan
- * Object representing the network device to acquire.
- */
-void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
- struct mlx5_vf_vlan *vlan)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_vlan_vmwa_context *vmwa = priv->vmwa_context;
- struct mlx5_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
-
- assert(!vlan->created);
- assert(priv->vmwa_context);
- if (vlan->created || !vmwa)
- return;
- if (vlan_dev[vlan->tag].refcnt == 0) {
- assert(!vlan_dev[vlan->tag].ifindex);
- vlan_dev[vlan->tag].ifindex =
- mlx5_vlan_vmwa_create(vmwa,
- vmwa->vf_ifindex,
- vlan->tag);
- }
- if (vlan_dev[vlan->tag].ifindex) {
- vlan_dev[vlan->tag].refcnt++;
- vlan->created = 1;
- }
-}
-
-/*
- * Create per ethernet device VLAN VM workaround context
- */
-struct mlx5_vlan_vmwa_context *
-mlx5_vlan_vmwa_init(struct rte_eth_dev *dev,
- uint32_t ifindex)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_dev_config *config = &priv->config;
- struct mlx5_vlan_vmwa_context *vmwa;
- enum rte_hypervisor hv_type;
-
- /* Do not engage workaround over PF. */
- if (!config->vf)
- return NULL;
- /* Check whether there is desired virtual environment */
- hv_type = rte_hypervisor_get();
- switch (hv_type) {
- case RTE_HYPERVISOR_UNKNOWN:
- case RTE_HYPERVISOR_VMWARE:
- /*
- * The "white list" of configurations
- * to engage the workaround.
- */
- break;
- default:
- /*
- * The configuration is not found in the "white list".
- * We should not engage the VLAN workaround.
- */
- return NULL;
- }
- vmwa = rte_zmalloc(__func__, sizeof(*vmwa), sizeof(uint32_t));
- if (!vmwa) {
- DRV_LOG(WARNING,
- "Can not allocate memory"
- " for VLAN workaround context");
- return NULL;
- }
- vmwa->nl_socket = mlx5_nl_init(NETLINK_ROUTE);
- if (vmwa->nl_socket < 0) {
- DRV_LOG(WARNING,
- "Can not create Netlink socket"
- " for VLAN workaround context");
- rte_free(vmwa);
- return NULL;
- }
- vmwa->nl_sn = random();
- vmwa->vf_ifindex = ifindex;
- vmwa->dev = dev;
- /* Cleanup for existing VLAN devices. */
- return vmwa;
-}
-
-/*
- * Destroy per ethernet device VLAN VM workaround context
- */
-void mlx5_vlan_vmwa_exit(struct mlx5_vlan_vmwa_context *vmwa)
-{
- unsigned int i;
-
- /* Delete all remaining VLAN devices. */
- for (i = 0; i < RTE_DIM(vmwa->vlan_dev); i++) {
- if (vmwa->vlan_dev[i].ifindex)
- mlx5_vlan_vmwa_delete(vmwa, vmwa->vlan_dev[i].ifindex);
- }
- if (vmwa->nl_socket >= 0)
- close(vmwa->nl_socket);
- rte_free(vmwa);
-}
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 Mellanox Technologies, Ltd
+ */
+
+#ifndef RTE_PMD_MLX5_NL_H_
+#define RTE_PMD_MLX5_NL_H_
+
+#include <linux/netlink.h>
+
+
+/* Recognized Infiniband device physical port name types. */
+enum mlx5_nl_phys_port_name_type {
+ MLX5_PHYS_PORT_NAME_TYPE_NOTSET = 0, /* Not set. */
+ MLX5_PHYS_PORT_NAME_TYPE_LEGACY, /* before kernel ver < 5.0 */
+ MLX5_PHYS_PORT_NAME_TYPE_UPLINK, /* p0, kernel ver >= 5.0 */
+ MLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */
+ MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */
+};
+
+/** Switch information returned by mlx5_nl_switch_info(). */
+struct mlx5_switch_info {
+ uint32_t master:1; /**< Master device. */
+ uint32_t representor:1; /**< Representor device. */
+ enum mlx5_nl_phys_port_name_type name_type; /** < Port name type. */
+ int32_t pf_num; /**< PF number (valid for pfxvfx format only). */
+ int32_t port_name; /**< Representor port name. */
+ uint64_t switch_id; /**< Switch identifier. */
+};
+
+/* VLAN netdev for VLAN workaround. */
+struct mlx5_nl_vlan_dev {
+ uint32_t refcnt;
+ uint32_t ifindex; /**< Own interface index. */
+};
+
+/*
+ * Array of VLAN devices created on the base of VF
+ * used for workaround in virtual environments.
+ */
+struct mlx5_nl_vlan_vmwa_context {
+ int nl_socket;
+ uint32_t nl_sn;
+ uint32_t vf_ifindex;
+ struct mlx5_nl_vlan_dev vlan_dev[4096];
+};
+
+
+int mlx5_nl_init(int protocol);
+int mlx5_nl_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
+ uint32_t index);
+int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
+ uint32_t index);
+void mlx5_nl_mac_addr_sync(struct rte_eth_dev *dev);
+void mlx5_nl_mac_addr_flush(struct rte_eth_dev *dev);
+int mlx5_nl_promisc(struct rte_eth_dev *dev, int enable);
+int mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable);
+unsigned int mlx5_nl_portnum(int nl, const char *name);
+unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);
+int mlx5_nl_vf_mac_addr_modify(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac, int vf_index);
+int mlx5_nl_switch_info(int nl, unsigned int ifindex,
+ struct mlx5_switch_info *info);
+
+void mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,
+ uint32_t ifindex);
+uint32_t mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,
+ uint32_t ifindex, uint16_t tag);
+
+#endif /* RTE_PMD_MLX5_NL_H_ */
#include <errno.h>
#include <assert.h>
#include <stdint.h>
+#include <unistd.h>
+
/*
* Not needed by this file; included to work around the lack of off_t
#include <rte_ethdev_driver.h>
#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_hypervisor.h>
#include <mlx5_glue.h>
#include <mlx5_devx_cmds.h>
#include "mlx5.h"
#include "mlx5_autoconf.h"
#include "mlx5_rxtx.h"
+#include "mlx5_nl.h"
#include "mlx5_utils.h"
/**
}
return 0;
}
+
+/*
+ * Release VLAN network device, created for VM workaround.
+ *
+ * @param[in] dev
+ * Ethernet device object, Netlink context provider.
+ * @param[in] vlan
+ * Object representing the network device to release.
+ */
+void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
+ struct mlx5_vf_vlan *vlan)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_nl_vlan_vmwa_context *vmwa = priv->vmwa_context;
+ struct mlx5_nl_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
+
+ assert(vlan->created);
+ assert(priv->vmwa_context);
+ if (!vlan->created || !vmwa)
+ return;
+ vlan->created = 0;
+ assert(vlan_dev[vlan->tag].refcnt);
+ if (--vlan_dev[vlan->tag].refcnt == 0 &&
+ vlan_dev[vlan->tag].ifindex) {
+ mlx5_nl_vlan_vmwa_delete(vmwa, vlan_dev[vlan->tag].ifindex);
+ vlan_dev[vlan->tag].ifindex = 0;
+ }
+}
+
+/**
+ * Acquire VLAN interface with specified tag for VM workaround.
+ *
+ * @param[in] dev
+ * Ethernet device object, Netlink context provider.
+ * @param[in] vlan
+ * Object representing the network device to acquire.
+ */
+void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
+ struct mlx5_vf_vlan *vlan)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_nl_vlan_vmwa_context *vmwa = priv->vmwa_context;
+ struct mlx5_nl_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
+
+ assert(!vlan->created);
+ assert(priv->vmwa_context);
+ if (vlan->created || !vmwa)
+ return;
+ if (vlan_dev[vlan->tag].refcnt == 0) {
+ assert(!vlan_dev[vlan->tag].ifindex);
+ vlan_dev[vlan->tag].ifindex =
+ mlx5_nl_vlan_vmwa_create(vmwa, vmwa->vf_ifindex,
+ vlan->tag);
+ }
+ if (vlan_dev[vlan->tag].ifindex) {
+ vlan_dev[vlan->tag].refcnt++;
+ vlan->created = 1;
+ }
+}
+
+/*
+ * Create per ethernet device VLAN VM workaround context
+ */
+struct mlx5_nl_vlan_vmwa_context *
+mlx5_vlan_vmwa_init(struct rte_eth_dev *dev, uint32_t ifindex)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_dev_config *config = &priv->config;
+ struct mlx5_nl_vlan_vmwa_context *vmwa;
+ enum rte_hypervisor hv_type;
+
+ /* Do not engage workaround over PF. */
+ if (!config->vf)
+ return NULL;
+ /* Check whether there is desired virtual environment */
+ hv_type = rte_hypervisor_get();
+ switch (hv_type) {
+ case RTE_HYPERVISOR_UNKNOWN:
+ case RTE_HYPERVISOR_VMWARE:
+ /*
+ * The "white list" of configurations
+ * to engage the workaround.
+ */
+ break;
+ default:
+ /*
+ * The configuration is not found in the "white list".
+ * We should not engage the VLAN workaround.
+ */
+ return NULL;
+ }
+ vmwa = rte_zmalloc(__func__, sizeof(*vmwa), sizeof(uint32_t));
+ if (!vmwa) {
+ DRV_LOG(WARNING,
+ "Can not allocate memory"
+ " for VLAN workaround context");
+ return NULL;
+ }
+ vmwa->nl_socket = mlx5_nl_init(NETLINK_ROUTE);
+ if (vmwa->nl_socket < 0) {
+ DRV_LOG(WARNING,
+ "Can not create Netlink socket"
+ " for VLAN workaround context");
+ rte_free(vmwa);
+ return NULL;
+ }
+ vmwa->nl_sn = random();
+ vmwa->vf_ifindex = ifindex;
+ /* Cleanup for existing VLAN devices. */
+ return vmwa;
+}
+
+/*
+ * Destroy per ethernet device VLAN VM workaround context
+ */
+void mlx5_vlan_vmwa_exit(struct mlx5_nl_vlan_vmwa_context *vmwa)
+{
+ unsigned int i;
+
+ /* Delete all remaining VLAN devices. */
+ for (i = 0; i < RTE_DIM(vmwa->vlan_dev); i++) {
+ if (vmwa->vlan_dev[i].ifindex)
+ mlx5_nl_vlan_vmwa_delete(vmwa,
+ vmwa->vlan_dev[i].ifindex);
+ }
+ if (vmwa->nl_socket >= 0)
+ close(vmwa->nl_socket);
+ rte_free(vmwa);
+}