kni: memzone pool for alloc and release
The previous implementation of rte_kni_alloc() was allocating memzones with a name composed of a fixed string and the interface name. When an application was allocating and deallocating multiple interfaces with different names, memzones were quickly exhausted, even though memzones from deallocated interfaces were never used anymore (unless an interface with the same name was re-allocated). As a result, the application was unable to allocate more KNI interfaces with different names. This patch implements the KNI memzone pool in order to prevent memzone exhaustion when allocating/deallocating KNI interfaces. It adds a new API call, rte_kni_init(max_kni_ifaces) that shall be called before any call to rte_kni_alloc() if KNI is used. The memzones are pre-allocated with interface- independent names so that they can be reused. Signed-off-by: Marc Sune <marc.sune@bisdn.de> Acked-by: Helin Zhang <helin.zhang@intel.com>
This commit is contained in:
parent
3ead3080aa
commit
0c6bc8ef70
@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
#define IFCONFIG "/sbin/ifconfig "
|
#define IFCONFIG "/sbin/ifconfig "
|
||||||
#define TEST_KNI_PORT "test_kni_port"
|
#define TEST_KNI_PORT "test_kni_port"
|
||||||
|
#define KNI_TEST_MAX_PORTS 4
|
||||||
/* The threshold number of mbufs to be transmitted or received. */
|
/* The threshold number of mbufs to be transmitted or received. */
|
||||||
#define KNI_NUM_MBUF_THRESHOLD 100
|
#define KNI_NUM_MBUF_THRESHOLD 100
|
||||||
static int kni_pkt_mtu = 0;
|
static int kni_pkt_mtu = 0;
|
||||||
@ -498,6 +498,9 @@ test_kni(void)
|
|||||||
struct rte_eth_dev_info info;
|
struct rte_eth_dev_info info;
|
||||||
struct rte_kni_ops ops;
|
struct rte_kni_ops ops;
|
||||||
|
|
||||||
|
/* Initialize KNI subsytem */
|
||||||
|
rte_kni_init(KNI_TEST_MAX_PORTS);
|
||||||
|
|
||||||
if (test_kni_allocate_lcores() < 0) {
|
if (test_kni_allocate_lcores() < 0) {
|
||||||
printf("No enough lcores for kni processing\n");
|
printf("No enough lcores for kni processing\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -586,6 +586,25 @@ parse_args(int argc, char **argv)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize KNI subsystem */
|
||||||
|
static void
|
||||||
|
init_kni(void)
|
||||||
|
{
|
||||||
|
unsigned int num_of_kni_ports = 0, i;
|
||||||
|
struct kni_port_params **params = kni_port_params_array;
|
||||||
|
|
||||||
|
/* Calculate the maximum number of KNI interfaces that will be used */
|
||||||
|
for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
|
||||||
|
if (kni_port_params_array[i]) {
|
||||||
|
num_of_kni_ports += (params[i]->nb_lcore_k ?
|
||||||
|
params[i]->nb_lcore_k : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke rte KNI init to preallocate the ports */
|
||||||
|
rte_kni_init(num_of_kni_ports);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialise a single port on an Ethernet device */
|
/* Initialise a single port on an Ethernet device */
|
||||||
static void
|
static void
|
||||||
init_port(uint8_t port)
|
init_port(uint8_t port)
|
||||||
@ -872,6 +891,9 @@ main(int argc, char** argv)
|
|||||||
rte_exit(EXIT_FAILURE, "Configured invalid "
|
rte_exit(EXIT_FAILURE, "Configured invalid "
|
||||||
"port ID %u\n", i);
|
"port ID %u\n", i);
|
||||||
|
|
||||||
|
/* Initialize KNI subsystem */
|
||||||
|
init_kni();
|
||||||
|
|
||||||
/* Initialise each port */
|
/* Initialise each port */
|
||||||
for (port = 0; port < nb_sys_ports; port++) {
|
for (port = 0; port < nb_sys_ports; port++) {
|
||||||
/* Skip ports that are not enabled */
|
/* Skip ports that are not enabled */
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <rte_spinlock.h>
|
||||||
#include <rte_string_fns.h>
|
#include <rte_string_fns.h>
|
||||||
#include <rte_ethdev.h>
|
#include <rte_ethdev.h>
|
||||||
#include <rte_malloc.h>
|
#include <rte_malloc.h>
|
||||||
@ -58,7 +59,7 @@
|
|||||||
|
|
||||||
#define KNI_REQUEST_MBUF_NUM_MAX 32
|
#define KNI_REQUEST_MBUF_NUM_MAX 32
|
||||||
|
|
||||||
#define KNI_MZ_CHECK(mz) do { if (mz) goto fail; } while (0)
|
#define KNI_MEM_CHECK(cond) do { if (cond) goto kni_fail; } while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* KNI context
|
* KNI context
|
||||||
@ -66,6 +67,7 @@
|
|||||||
struct rte_kni {
|
struct rte_kni {
|
||||||
char name[RTE_KNI_NAMESIZE]; /**< KNI interface name */
|
char name[RTE_KNI_NAMESIZE]; /**< KNI interface name */
|
||||||
uint16_t group_id; /**< Group ID of KNI devices */
|
uint16_t group_id; /**< Group ID of KNI devices */
|
||||||
|
uint32_t slot_id; /**< KNI pool slot ID */
|
||||||
struct rte_mempool *pktmbuf_pool; /**< pkt mbuf mempool */
|
struct rte_mempool *pktmbuf_pool; /**< pkt mbuf mempool */
|
||||||
unsigned mbuf_size; /**< mbuf size */
|
unsigned mbuf_size; /**< mbuf size */
|
||||||
|
|
||||||
@ -88,10 +90,48 @@ enum kni_ops_status {
|
|||||||
KNI_REQ_REGISTERED,
|
KNI_REQ_REGISTERED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KNI memzone pool slot
|
||||||
|
*/
|
||||||
|
struct rte_kni_memzone_slot {
|
||||||
|
uint32_t id;
|
||||||
|
uint8_t in_use : 1; /**< slot in use */
|
||||||
|
|
||||||
|
/* Memzones */
|
||||||
|
const struct rte_memzone *m_ctx; /**< KNI ctx */
|
||||||
|
const struct rte_memzone *m_tx_q; /**< TX queue */
|
||||||
|
const struct rte_memzone *m_rx_q; /**< RX queue */
|
||||||
|
const struct rte_memzone *m_alloc_q; /**< Allocated mbufs queue */
|
||||||
|
const struct rte_memzone *m_free_q; /**< To be freed mbufs queue */
|
||||||
|
const struct rte_memzone *m_req_q; /**< Request queue */
|
||||||
|
const struct rte_memzone *m_resp_q; /**< Response queue */
|
||||||
|
const struct rte_memzone *m_sync_addr;
|
||||||
|
|
||||||
|
/* Free linked list */
|
||||||
|
struct rte_kni_memzone_slot *next; /**< Next slot link.list */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KNI memzone pool
|
||||||
|
*/
|
||||||
|
struct rte_kni_memzone_pool {
|
||||||
|
uint8_t initialized : 1; /**< Global KNI pool init flag */
|
||||||
|
|
||||||
|
uint32_t max_ifaces; /**< Max. num of KNI ifaces */
|
||||||
|
struct rte_kni_memzone_slot *slots; /**< Pool slots */
|
||||||
|
rte_spinlock_t mutex; /**< alloc/relase mutex */
|
||||||
|
|
||||||
|
/* Free memzone slots linked-list */
|
||||||
|
struct rte_kni_memzone_slot *free; /**< First empty slot */
|
||||||
|
struct rte_kni_memzone_slot *free_tail; /**< Last empty slot */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void kni_free_mbufs(struct rte_kni *kni);
|
static void kni_free_mbufs(struct rte_kni *kni);
|
||||||
static void kni_allocate_mbufs(struct rte_kni *kni);
|
static void kni_allocate_mbufs(struct rte_kni *kni);
|
||||||
|
|
||||||
static volatile int kni_fd = -1;
|
static volatile int kni_fd = -1;
|
||||||
|
static struct rte_kni_memzone_pool kni_memzone_pool = {0};
|
||||||
|
|
||||||
static const struct rte_memzone *
|
static const struct rte_memzone *
|
||||||
kni_memzone_reserve(const char *name, size_t len, int socket_id,
|
kni_memzone_reserve(const char *name, size_t len, int socket_id,
|
||||||
@ -105,6 +145,163 @@ kni_memzone_reserve(const char *name, size_t len, int socket_id,
|
|||||||
return mz;
|
return mz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pool mgmt */
|
||||||
|
static struct rte_kni_memzone_slot*
|
||||||
|
kni_memzone_pool_alloc(void)
|
||||||
|
{
|
||||||
|
struct rte_kni_memzone_slot *slot;
|
||||||
|
|
||||||
|
rte_spinlock_lock(&kni_memzone_pool.mutex);
|
||||||
|
|
||||||
|
if (!kni_memzone_pool.free) {
|
||||||
|
rte_spinlock_unlock(&kni_memzone_pool.mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = kni_memzone_pool.free;
|
||||||
|
kni_memzone_pool.free = slot->next;
|
||||||
|
slot->in_use = 1;
|
||||||
|
|
||||||
|
if (!kni_memzone_pool.free)
|
||||||
|
kni_memzone_pool.free_tail = NULL;
|
||||||
|
|
||||||
|
rte_spinlock_unlock(&kni_memzone_pool.mutex);
|
||||||
|
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kni_memzone_pool_release(struct rte_kni_memzone_slot *slot)
|
||||||
|
{
|
||||||
|
rte_spinlock_lock(&kni_memzone_pool.mutex);
|
||||||
|
|
||||||
|
if (kni_memzone_pool.free)
|
||||||
|
kni_memzone_pool.free_tail->next = slot;
|
||||||
|
else
|
||||||
|
kni_memzone_pool.free = slot;
|
||||||
|
|
||||||
|
kni_memzone_pool.free_tail = slot;
|
||||||
|
slot->next = NULL;
|
||||||
|
slot->in_use = 0;
|
||||||
|
|
||||||
|
rte_spinlock_unlock(&kni_memzone_pool.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Shall be called before any allocation happens */
|
||||||
|
void
|
||||||
|
rte_kni_init(unsigned int max_kni_ifaces)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
struct rte_kni_memzone_slot *it;
|
||||||
|
const struct rte_memzone *mz;
|
||||||
|
#define OBJNAMSIZ 32
|
||||||
|
char obj_name[OBJNAMSIZ];
|
||||||
|
char mz_name[RTE_MEMZONE_NAMESIZE];
|
||||||
|
|
||||||
|
if (max_kni_ifaces == 0) {
|
||||||
|
RTE_LOG(ERR, KNI, "Invalid number of max_kni_ifaces %d\n",
|
||||||
|
max_kni_ifaces);
|
||||||
|
rte_panic("Unable to initialize KNI\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check FD and open */
|
||||||
|
if (kni_fd < 0) {
|
||||||
|
kni_fd = open("/dev/" KNI_DEVICE, O_RDWR);
|
||||||
|
if (kni_fd < 0)
|
||||||
|
rte_panic("Can not open /dev/%s\n", KNI_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate slot objects */
|
||||||
|
kni_memzone_pool.slots = (struct rte_kni_memzone_slot *)
|
||||||
|
rte_malloc(NULL,
|
||||||
|
sizeof(struct rte_kni_memzone_slot) *
|
||||||
|
max_kni_ifaces,
|
||||||
|
0);
|
||||||
|
KNI_MEM_CHECK(kni_memzone_pool.slots == NULL);
|
||||||
|
|
||||||
|
/* Initialize general pool variables */
|
||||||
|
kni_memzone_pool.initialized = 1;
|
||||||
|
kni_memzone_pool.max_ifaces = max_kni_ifaces;
|
||||||
|
kni_memzone_pool.free = &kni_memzone_pool.slots[0];
|
||||||
|
|
||||||
|
/* Pre-allocate all memzones of all the slots; panic on error */
|
||||||
|
for (i = 0; i < max_kni_ifaces; i++) {
|
||||||
|
|
||||||
|
/* Recover current slot */
|
||||||
|
it = &kni_memzone_pool.slots[i];
|
||||||
|
it->id = i;
|
||||||
|
|
||||||
|
/* Allocate KNI context */
|
||||||
|
snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "KNI_INFO_%d", i);
|
||||||
|
mz = kni_memzone_reserve(mz_name, sizeof(struct rte_kni),
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_ctx = mz;
|
||||||
|
|
||||||
|
/* TX RING */
|
||||||
|
snprintf(obj_name, OBJNAMSIZ, "kni_tx_%d", i);
|
||||||
|
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE,
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_tx_q = mz;
|
||||||
|
|
||||||
|
/* RX RING */
|
||||||
|
snprintf(obj_name, OBJNAMSIZ, "kni_rx_%d", i);
|
||||||
|
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE,
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_rx_q = mz;
|
||||||
|
|
||||||
|
/* ALLOC RING */
|
||||||
|
snprintf(obj_name, OBJNAMSIZ, "kni_alloc_%d", i);
|
||||||
|
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE,
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_alloc_q = mz;
|
||||||
|
|
||||||
|
/* FREE RING */
|
||||||
|
snprintf(obj_name, OBJNAMSIZ, "kni_free_%d", i);
|
||||||
|
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE,
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_free_q = mz;
|
||||||
|
|
||||||
|
/* Request RING */
|
||||||
|
snprintf(obj_name, OBJNAMSIZ, "kni_req_%d", i);
|
||||||
|
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE,
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_req_q = mz;
|
||||||
|
|
||||||
|
/* Response RING */
|
||||||
|
snprintf(obj_name, OBJNAMSIZ, "kni_resp_%d", i);
|
||||||
|
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE,
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_resp_q = mz;
|
||||||
|
|
||||||
|
/* Req/Resp sync mem area */
|
||||||
|
snprintf(obj_name, OBJNAMSIZ, "kni_sync_%d", i);
|
||||||
|
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE,
|
||||||
|
SOCKET_ID_ANY, 0);
|
||||||
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
|
it->m_sync_addr = mz;
|
||||||
|
|
||||||
|
if ((i+1) == max_kni_ifaces) {
|
||||||
|
it->next = NULL;
|
||||||
|
kni_memzone_pool.free_tail = it;
|
||||||
|
} else
|
||||||
|
it->next = &kni_memzone_pool.slots[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
kni_fail:
|
||||||
|
rte_panic("Unable to allocate memory for max_kni_ifaces:%d. Increase the amount of hugepages memory\n",
|
||||||
|
max_kni_ifaces);
|
||||||
|
}
|
||||||
|
|
||||||
/* It is deprecated and just for backward compatibility */
|
/* It is deprecated and just for backward compatibility */
|
||||||
struct rte_kni *
|
struct rte_kni *
|
||||||
rte_kni_create(uint8_t port_id,
|
rte_kni_create(uint8_t port_id,
|
||||||
@ -140,34 +337,34 @@ rte_kni_alloc(struct rte_mempool *pktmbuf_pool,
|
|||||||
struct rte_kni_device_info dev_info;
|
struct rte_kni_device_info dev_info;
|
||||||
struct rte_kni *ctx;
|
struct rte_kni *ctx;
|
||||||
char intf_name[RTE_KNI_NAMESIZE];
|
char intf_name[RTE_KNI_NAMESIZE];
|
||||||
#define OBJNAMSIZ 32
|
|
||||||
char obj_name[OBJNAMSIZ];
|
|
||||||
char mz_name[RTE_MEMZONE_NAMESIZE];
|
char mz_name[RTE_MEMZONE_NAMESIZE];
|
||||||
const struct rte_memzone *mz;
|
const struct rte_memzone *mz;
|
||||||
|
struct rte_kni_memzone_slot *slot = NULL;
|
||||||
|
|
||||||
if (!pktmbuf_pool || !conf || !conf->name[0])
|
if (!pktmbuf_pool || !conf || !conf->name[0])
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Check FD and open once */
|
/* Check if KNI subsystem has been initialized */
|
||||||
if (kni_fd < 0) {
|
if (kni_memzone_pool.initialized != 1) {
|
||||||
kni_fd = open("/dev/" KNI_DEVICE, O_RDWR);
|
RTE_LOG(ERR, KNI, "KNI subsystem has not been initialized. Invoke rte_kni_init() first\n");
|
||||||
if (kni_fd < 0) {
|
return NULL;
|
||||||
RTE_LOG(ERR, KNI, "Can not open /dev/%s\n",
|
|
||||||
KNI_DEVICE);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get an available slot from the pool */
|
||||||
|
slot = kni_memzone_pool_alloc();
|
||||||
|
if (!slot) {
|
||||||
|
RTE_LOG(ERR, KNI, "Cannot allocate more KNI interfaces; increase the number of max_kni_ifaces(current %d) or release unusued ones.\n",
|
||||||
|
kni_memzone_pool.max_ifaces);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recover ctx */
|
||||||
|
ctx = slot->m_ctx->addr;
|
||||||
snprintf(intf_name, RTE_KNI_NAMESIZE, "%s", conf->name);
|
snprintf(intf_name, RTE_KNI_NAMESIZE, "%s", conf->name);
|
||||||
snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "KNI_INFO_%s", intf_name);
|
|
||||||
mz = kni_memzone_reserve(mz_name, sizeof(struct rte_kni),
|
|
||||||
SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx = mz->addr;
|
|
||||||
|
|
||||||
if (ctx->in_use) {
|
if (ctx->in_use) {
|
||||||
RTE_LOG(ERR, KNI, "KNI %s is in use\n", ctx->name);
|
RTE_LOG(ERR, KNI, "KNI %s is in use\n", ctx->name);
|
||||||
goto fail;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(ctx, 0, sizeof(struct rte_kni));
|
memset(ctx, 0, sizeof(struct rte_kni));
|
||||||
if (ops)
|
if (ops)
|
||||||
@ -190,82 +387,71 @@ rte_kni_alloc(struct rte_mempool *pktmbuf_pool,
|
|||||||
RTE_LOG(INFO, KNI, "pci: %02x:%02x:%02x \t %02x:%02x\n",
|
RTE_LOG(INFO, KNI, "pci: %02x:%02x:%02x \t %02x:%02x\n",
|
||||||
dev_info.bus, dev_info.devid, dev_info.function,
|
dev_info.bus, dev_info.devid, dev_info.function,
|
||||||
dev_info.vendor_id, dev_info.device_id);
|
dev_info.vendor_id, dev_info.device_id);
|
||||||
|
|
||||||
/* TX RING */
|
/* TX RING */
|
||||||
snprintf(obj_name, OBJNAMSIZ, "kni_tx_%s", intf_name);
|
mz = slot->m_tx_q;
|
||||||
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx->tx_q = mz->addr;
|
ctx->tx_q = mz->addr;
|
||||||
kni_fifo_init(ctx->tx_q, KNI_FIFO_COUNT_MAX);
|
kni_fifo_init(ctx->tx_q, KNI_FIFO_COUNT_MAX);
|
||||||
dev_info.tx_phys = mz->phys_addr;
|
dev_info.tx_phys = mz->phys_addr;
|
||||||
|
|
||||||
/* RX RING */
|
/* RX RING */
|
||||||
snprintf(obj_name, OBJNAMSIZ, "kni_rx_%s", intf_name);
|
mz = slot->m_rx_q;
|
||||||
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx->rx_q = mz->addr;
|
ctx->rx_q = mz->addr;
|
||||||
kni_fifo_init(ctx->rx_q, KNI_FIFO_COUNT_MAX);
|
kni_fifo_init(ctx->rx_q, KNI_FIFO_COUNT_MAX);
|
||||||
dev_info.rx_phys = mz->phys_addr;
|
dev_info.rx_phys = mz->phys_addr;
|
||||||
|
|
||||||
/* ALLOC RING */
|
/* ALLOC RING */
|
||||||
snprintf(obj_name, OBJNAMSIZ, "kni_alloc_%s", intf_name);
|
mz = slot->m_alloc_q;
|
||||||
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx->alloc_q = mz->addr;
|
ctx->alloc_q = mz->addr;
|
||||||
kni_fifo_init(ctx->alloc_q, KNI_FIFO_COUNT_MAX);
|
kni_fifo_init(ctx->alloc_q, KNI_FIFO_COUNT_MAX);
|
||||||
dev_info.alloc_phys = mz->phys_addr;
|
dev_info.alloc_phys = mz->phys_addr;
|
||||||
|
|
||||||
/* FREE RING */
|
/* FREE RING */
|
||||||
snprintf(obj_name, OBJNAMSIZ, "kni_free_%s", intf_name);
|
mz = slot->m_free_q;
|
||||||
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx->free_q = mz->addr;
|
ctx->free_q = mz->addr;
|
||||||
kni_fifo_init(ctx->free_q, KNI_FIFO_COUNT_MAX);
|
kni_fifo_init(ctx->free_q, KNI_FIFO_COUNT_MAX);
|
||||||
dev_info.free_phys = mz->phys_addr;
|
dev_info.free_phys = mz->phys_addr;
|
||||||
|
|
||||||
/* Request RING */
|
/* Request RING */
|
||||||
snprintf(obj_name, OBJNAMSIZ, "kni_req_%s", intf_name);
|
mz = slot->m_req_q;
|
||||||
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx->req_q = mz->addr;
|
ctx->req_q = mz->addr;
|
||||||
kni_fifo_init(ctx->req_q, KNI_FIFO_COUNT_MAX);
|
kni_fifo_init(ctx->req_q, KNI_FIFO_COUNT_MAX);
|
||||||
dev_info.req_phys = mz->phys_addr;
|
dev_info.req_phys = mz->phys_addr;
|
||||||
|
|
||||||
/* Response RING */
|
/* Response RING */
|
||||||
snprintf(obj_name, OBJNAMSIZ, "kni_resp_%s", intf_name);
|
mz = slot->m_resp_q;
|
||||||
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx->resp_q = mz->addr;
|
ctx->resp_q = mz->addr;
|
||||||
kni_fifo_init(ctx->resp_q, KNI_FIFO_COUNT_MAX);
|
kni_fifo_init(ctx->resp_q, KNI_FIFO_COUNT_MAX);
|
||||||
dev_info.resp_phys = mz->phys_addr;
|
dev_info.resp_phys = mz->phys_addr;
|
||||||
|
|
||||||
/* Req/Resp sync mem area */
|
/* Req/Resp sync mem area */
|
||||||
snprintf(obj_name, OBJNAMSIZ, "kni_sync_%s", intf_name);
|
mz = slot->m_sync_addr;
|
||||||
mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
|
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
|
||||||
ctx->sync_addr = mz->addr;
|
ctx->sync_addr = mz->addr;
|
||||||
dev_info.sync_va = mz->addr;
|
dev_info.sync_va = mz->addr;
|
||||||
dev_info.sync_phys = mz->phys_addr;
|
dev_info.sync_phys = mz->phys_addr;
|
||||||
|
|
||||||
|
|
||||||
/* MBUF mempool */
|
/* MBUF mempool */
|
||||||
snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_OBJ_NAME,
|
snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_OBJ_NAME,
|
||||||
pktmbuf_pool->name);
|
pktmbuf_pool->name);
|
||||||
mz = rte_memzone_lookup(mz_name);
|
mz = rte_memzone_lookup(mz_name);
|
||||||
KNI_MZ_CHECK(mz == NULL);
|
KNI_MEM_CHECK(mz == NULL);
|
||||||
dev_info.mbuf_va = mz->addr;
|
dev_info.mbuf_va = mz->addr;
|
||||||
dev_info.mbuf_phys = mz->phys_addr;
|
dev_info.mbuf_phys = mz->phys_addr;
|
||||||
ctx->pktmbuf_pool = pktmbuf_pool;
|
ctx->pktmbuf_pool = pktmbuf_pool;
|
||||||
ctx->group_id = conf->group_id;
|
ctx->group_id = conf->group_id;
|
||||||
|
ctx->slot_id = slot->id;
|
||||||
ctx->mbuf_size = conf->mbuf_size;
|
ctx->mbuf_size = conf->mbuf_size;
|
||||||
|
|
||||||
ret = ioctl(kni_fd, RTE_KNI_IOCTL_CREATE, &dev_info);
|
ret = ioctl(kni_fd, RTE_KNI_IOCTL_CREATE, &dev_info);
|
||||||
KNI_MZ_CHECK(ret < 0);
|
KNI_MEM_CHECK(ret < 0);
|
||||||
|
|
||||||
ctx->in_use = 1;
|
ctx->in_use = 1;
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
fail:
|
kni_fail:
|
||||||
|
if (slot)
|
||||||
|
kni_memzone_pool_release(&kni_memzone_pool.slots[slot->id]);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -287,6 +473,7 @@ int
|
|||||||
rte_kni_release(struct rte_kni *kni)
|
rte_kni_release(struct rte_kni *kni)
|
||||||
{
|
{
|
||||||
struct rte_kni_device_info dev_info;
|
struct rte_kni_device_info dev_info;
|
||||||
|
uint32_t slot_id;
|
||||||
|
|
||||||
if (!kni || !kni->in_use)
|
if (!kni || !kni->in_use)
|
||||||
return -1;
|
return -1;
|
||||||
@ -302,8 +489,19 @@ rte_kni_release(struct rte_kni *kni)
|
|||||||
kni_free_fifo(kni->rx_q);
|
kni_free_fifo(kni->rx_q);
|
||||||
kni_free_fifo(kni->alloc_q);
|
kni_free_fifo(kni->alloc_q);
|
||||||
kni_free_fifo(kni->free_q);
|
kni_free_fifo(kni->free_q);
|
||||||
|
|
||||||
|
slot_id = kni->slot_id;
|
||||||
|
|
||||||
|
/* Memset the KNI struct */
|
||||||
memset(kni, 0, sizeof(struct rte_kni));
|
memset(kni, 0, sizeof(struct rte_kni));
|
||||||
|
|
||||||
|
/* Release memzone */
|
||||||
|
if (slot_id > kni_memzone_pool.max_ifaces) {
|
||||||
|
rte_panic("KNI pool: corrupted slot ID: %d, max: %d\n",
|
||||||
|
slot_id, kni_memzone_pool.max_ifaces);
|
||||||
|
}
|
||||||
|
kni_memzone_pool_release(&kni_memzone_pool.slots[slot_id]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,23 +635,21 @@ rte_kni_get_port_id(struct rte_kni *kni)
|
|||||||
struct rte_kni *
|
struct rte_kni *
|
||||||
rte_kni_get(const char *name)
|
rte_kni_get(const char *name)
|
||||||
{
|
{
|
||||||
|
uint32_t i;
|
||||||
|
struct rte_kni_memzone_slot *it;
|
||||||
struct rte_kni *kni;
|
struct rte_kni *kni;
|
||||||
const struct rte_memzone *mz;
|
|
||||||
char mz_name[RTE_MEMZONE_NAMESIZE];
|
|
||||||
|
|
||||||
if (!name || !name[0])
|
/* Note: could be improved perf-wise if necessary */
|
||||||
return NULL;
|
for (i = 0; i < kni_memzone_pool.max_ifaces; i++) {
|
||||||
|
it = &kni_memzone_pool.slots[i];
|
||||||
|
if (it->in_use == 0)
|
||||||
|
continue;
|
||||||
|
kni = it->m_ctx->addr;
|
||||||
|
if (strncmp(kni->name, name, RTE_KNI_NAMESIZE) == 0)
|
||||||
|
return kni;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "KNI_INFO_%s", name);
|
return NULL;
|
||||||
mz = rte_memzone_lookup(mz_name);
|
|
||||||
if (!mz)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
kni = mz->addr;
|
|
||||||
if (!kni->in_use)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return kni;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -502,8 +698,7 @@ rte_kni_register_handlers(struct rte_kni *kni,struct rte_kni_ops *ops)
|
|||||||
|
|
||||||
req_status = kni_check_request_register(&kni->ops);
|
req_status = kni_check_request_register(&kni->ops);
|
||||||
if ( KNI_REQ_REGISTERED == req_status) {
|
if ( KNI_REQ_REGISTERED == req_status) {
|
||||||
RTE_LOG(ERR, KNI, "The KNI request operation"
|
RTE_LOG(ERR, KNI, "The KNI request operation has already registered.\n");
|
||||||
"has already registered.\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +89,28 @@ struct rte_kni_conf {
|
|||||||
uint8_t force_bind : 1; /* Flag to bind kernel thread */
|
uint8_t force_bind : 1; /* Flag to bind kernel thread */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize and preallocate KNI subsystem
|
||||||
|
*
|
||||||
|
* This function is to be executed on the MASTER lcore only, after EAL
|
||||||
|
* initialization and before any KNI interface is attempted to be
|
||||||
|
* allocated
|
||||||
|
*
|
||||||
|
* @param max_kni_ifaces
|
||||||
|
* The maximum number of KNI interfaces that can coexist concurrently
|
||||||
|
*/
|
||||||
|
extern void rte_kni_init(unsigned int max_kni_ifaces);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate KNI interface according to the port id, mbuf size, mbuf pool,
|
* Allocate KNI interface according to the port id, mbuf size, mbuf pool,
|
||||||
* configurations and callbacks for kernel requests.The KNI interface created
|
* configurations and callbacks for kernel requests.The KNI interface created
|
||||||
* in the kernel space is the net interface the traditional Linux application
|
* in the kernel space is the net interface the traditional Linux application
|
||||||
* talking to.
|
* talking to.
|
||||||
*
|
*
|
||||||
|
* The rte_kni_alloc shall not be called before rte_kni_init() has been
|
||||||
|
* called. rte_kni_alloc is thread safe.
|
||||||
|
*
|
||||||
* @param pktmbuf_pool
|
* @param pktmbuf_pool
|
||||||
* The mempool for allocting mbufs for packets.
|
* The mempool for allocting mbufs for packets.
|
||||||
* @param conf
|
* @param conf
|
||||||
@ -139,6 +155,8 @@ extern struct rte_kni *rte_kni_create(uint8_t port_id,
|
|||||||
* paired KNI interface in kernel space. All processing on the specific KNI
|
* paired KNI interface in kernel space. All processing on the specific KNI
|
||||||
* context need to be stopped before calling this interface.
|
* context need to be stopped before calling this interface.
|
||||||
*
|
*
|
||||||
|
* rte_kni_release is thread safe.
|
||||||
|
*
|
||||||
* @param kni
|
* @param kni
|
||||||
* The pointer to the context of an existent KNI interface.
|
* The pointer to the context of an existent KNI interface.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user