@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, Linaro Limited
+/* Copyright (c) 2013, Linaro Limited
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -19,29 +19,29 @@ extern "C" {
#endif
#include <odp_std_types.h>
+#include <odp_platform_types.h>
#include <odp_buffer_pool.h>
#include <odp_packet.h>
#include <odp_queue.h>
-#include <odp_pktio_types.h>
-
-/** ODP packet IO handle */
-typedef uint32_t odp_pktio_t;
-
-/** Invalid packet IO handle */
-#define ODP_PKTIO_INVALID 0
+/** @defgroup odp_packet_io ODP PACKET IO
+ * Operations on a packet.
+ * @{
+ */
/**
* Open an ODP packet IO instance
*
* @param dev Packet IO device
* @param pool Pool to use for packet IO
- * @param params Set of parameters to pass to the arch dependent implementation
*
* @return ODP packet IO handle or ODP_PKTIO_INVALID on error
+ *
+ * @note dev name loop is specially pktio reserved name for
+ * device used for testing. Usually it's loop back
+ * interface.
*/
-odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
- odp_pktio_params_t *params);
+odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool);
/**
* Close an ODP packet IO instance
@@ -130,21 +130,77 @@ void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t id);
odp_pktio_t odp_pktio_get_input(odp_packet_t pkt);
/**
- * Defines the maximum length of mac address supported by this platform
+ * Configure the MTU for a packet IO interface.
+ *
+ * @param[in] id ODP packet IO handle.
+ * @param[in] mtu The value of MTU that the interface will be configured to
+ * use.
+ *
+ * @retval 0 on success.
+ * @retval -1 if specified mtu can not be handled.
+ * @retval -1 on any other error or illegal input parameters.
+ */
+int odp_pktio_set_mtu(odp_pktio_t id, int mtu);
+
+/**
+ * Return the currently configured MTU value of a packet IO interface.
+ *
+ * @param[in] id ODP packet IO handle.
+ *
+ * @retval MTU value >0 on success.
+ * @retval -1 on any error or not existance pktio id.
+ */
+int odp_pktio_mtu(odp_pktio_t id);
+
+/**
+ * Enable/Disable promiscuous mode on a packet IO interface.
+ *
+ * @param[in] id ODP packet IO handle.
+ * @param[in] enable 1 to enable, 0 to disable.
+ *
+ * @retval 0 on success.
+ * @retval non-zero on any error.
+ */
+int odp_pktio_promisc_mode_set(odp_pktio_t id, odp_bool_t enable);
+
+/**
+ * Determine if promiscuous mode is enabled for a packet IO interface.
+ *
+ * @param[in] id ODP packet IO handle.
+ *
+ * @retval 1 if promiscuous mode is enabled.
+ * @retval 0 if promiscuous mode is disabled.
+ * @retval -1 on any error.
+*/
+int odp_pktio_promisc_mode(odp_pktio_t id);
+
+/**
+ * Get the default MAC address of a packet IO interface.
+ *
+ * @param id ODP packet IO handle.
+ * @param[out] mac_addr Storage for MAC address of the packet IO interface.
+ * @param addr_size Storage size for the address
+ *
+ * @retval Number of bytes written on success, 0 on failure.
*/
-#define ODP_MAC_ADDR_MAX_LENGTH ETH_ALEN
+size_t odp_pktio_mac_addr(odp_pktio_t id, void *mac_addr,
+ size_t addr_size);
/**
* Get mac address of the interface
*
- * @param id ODP packet IO handle
- * @param mac_addr Storage for Mac address of the packet IO interface
- * Storage provided by the caller should be equal
- * to ODP_MAC_ADDR_MAX_LENGTH (filled by function)
+ * @param id ODP packet IO handle
+ * @param mac_addr Storage for Mac address of the packet IO interface
+ * Storage provided by the caller should be equal
+ * to ODP_MAC_ADDR_MAX_LENGTH (filled by function)
* @return 0 on success or -1 on error
-**/
+ */
int odp_pktio_get_mac_addr(odp_pktio_t id, unsigned char *mac_addr);
+/**
+ * @}
+ */
+
#ifdef __cplusplus
}
#endif
@@ -20,17 +20,36 @@ extern "C" {
#include <odp_spinlock.h>
#include <odp_packet_socket.h>
-#ifdef ODP_HAVE_NETMAP
-#include <odp_packet_netmap.h>
-#endif
+#include <odp_classification_datamodel.h>
+#include <odp_align_internal.h>
+
+#include <odp_config.h>
+#include <odp_hints.h>
+#include <linux/if.h>
+
+/* DPDK */
#include <odp_packet_dpdk.h>
+/**
+ * Packet IO types
+ */
+typedef enum {
+ ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
+ ODP_PKTIO_TYPE_SOCKET_MMSG,
+ ODP_PKTIO_TYPE_SOCKET_MMAP,
+} odp_pktio_type_t;
+
struct pktio_entry {
odp_spinlock_t lock; /**< entry spinlock */
int taken; /**< is entry taken(1) or free(0) */
odp_queue_t inq_default; /**< default input queue, if set */
odp_queue_t outq_default; /**< default out queue */
- odp_pktio_params_t params; /**< pktio parameters */
+ odp_pktio_type_t type; /**< pktio type */
+ pkt_sock_t pkt_sock; /**< using socket API for IO */
+ pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap API for IO */
+ classifier_t cls; /**< classifier linked with this pktio*/
+ char name[IFNAMSIZ]; /**< name of pktio provided to
+ pktio_open() */
pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */
};
@@ -39,6 +58,21 @@ typedef union {
uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct pktio_entry))];
} pktio_entry_t;
+typedef struct {
+ pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
+} pktio_table_t;
+
+extern void *pktio_entry_ptr[];
+
+
+static inline pktio_entry_t *get_pktio_entry(odp_pktio_t id)
+{
+ if (odp_unlikely(id == ODP_PKTIO_INVALID ||
+ id > ODP_CONFIG_PKTIO_ENTRIES))
+ return NULL;
+
+ return pktio_entry_ptr[id - 1];
+}
#ifdef __cplusplus
}
#endif
@@ -16,34 +16,21 @@
#ifdef ODP_HAVE_NETMAP
#include <odp_packet_netmap.h>
#endif
-#include <odp_hints.h>
#include <odp_config.h>
#include <odp_queue_internal.h>
#include <odp_schedule_internal.h>
-#include <odp_debug.h>
-
-#include <odp_pktio_socket.h>
-#ifdef ODP_HAVE_NETMAP
-#include <odp_pktio_netmap.h>
-#endif
+#include <odp_classification_internal.h>
+#include <odp_debug_internal.h>
#include <string.h>
-
-typedef struct {
- pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
-} pktio_table_t;
+#include <sys/ioctl.h>
+#include <linux/if_arp.h>
+#include <ifaddrs.h>
static pktio_table_t *pktio_tbl;
-
-static pktio_entry_t *get_entry(odp_pktio_t id)
-{
- if (odp_unlikely(id == ODP_PKTIO_INVALID ||
- id > ODP_CONFIG_PKTIO_ENTRIES))
- return NULL;
-
- return &pktio_tbl->entries[id - 1];
-}
+/* pktio pointer entries ( for inlines) */
+void *pktio_entry_ptr[ODP_CONFIG_PKTIO_ENTRIES];
int odp_pktio_init_global(void)
{
@@ -65,10 +52,12 @@ int odp_pktio_init_global(void)
memset(pktio_tbl, 0, sizeof(pktio_table_t));
for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
- pktio_entry = get_entry(id);
+ pktio_entry = &pktio_tbl->entries[id - 1];
odp_spinlock_init(&pktio_entry->s.lock);
+ odp_spinlock_init(&pktio_entry->s.cls.lock);
+ pktio_entry_ptr[id - 1] = pktio_entry;
/* Create a default output queue for each pktio resource */
snprintf(name, sizeof(name), "%i-pktio_outq_default", (int)id);
name[ODP_QUEUE_NAME_LEN-1] = '\0';
@@ -115,16 +104,27 @@ static void unlock_entry(pktio_entry_t *entry)
odp_spinlock_unlock(&entry->s.lock);
}
-static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t *params)
+static void lock_entry_classifier(pktio_entry_t *entry)
+{
+ odp_spinlock_lock(&entry->s.lock);
+ odp_spinlock_lock(&entry->s.cls.lock);
+}
+
+static void unlock_entry_classifier(pktio_entry_t *entry)
+{
+ odp_spinlock_unlock(&entry->s.cls.lock);
+ odp_spinlock_unlock(&entry->s.lock);
+}
+
+static void init_pktio_entry(pktio_entry_t *entry)
{
set_taken(entry);
entry->s.inq_default = ODP_QUEUE_INVALID;
memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk));
- /* Save pktio parameters, type is the most useful */
- memcpy(&entry->s.params, params, sizeof(*params));
+ pktio_classifier_init(entry);
}
-static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
+static odp_pktio_t alloc_lock_pktio_entry(void)
{
odp_pktio_t id;
pktio_entry_t *entry;
@@ -133,13 +133,13 @@ static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
entry = &pktio_tbl->entries[i];
if (is_free(entry)) {
- lock_entry(entry);
+ lock_entry_classifier(entry);
if (is_free(entry)) {
- init_pktio_entry(entry, params);
+ init_pktio_entry(entry);
id = i + 1;
return id; /* return with entry locked! */
}
- unlock_entry(entry);
+ unlock_entry_classifier(entry);
}
}
@@ -148,7 +148,7 @@ static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
static int free_pktio_entry(odp_pktio_t id)
{
- pktio_entry_t *entry = get_entry(id);
+ pktio_entry_t *entry = get_pktio_entry(id);
if (entry == NULL)
return -1;
@@ -158,28 +158,22 @@ static int free_pktio_entry(odp_pktio_t id)
return 0;
}
-odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
- odp_pktio_params_t *params)
+odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool)
{
odp_pktio_t id;
pktio_entry_t *pktio_entry;
int res;
- if (params == NULL) {
- ODP_ERR("Invalid pktio params\n");
- return ODP_PKTIO_INVALID;
- }
-
ODP_DBG("Allocating dpdk pktio\n");
- id = alloc_lock_pktio_entry(params);
+ id = alloc_lock_pktio_entry();
if (id == ODP_PKTIO_INVALID) {
ODP_ERR("No resources available.\n");
return ODP_PKTIO_INVALID;
}
/* if successful, alloc_pktio_entry() returns with the entry locked */
- pktio_entry = get_entry(id);
+ pktio_entry = get_pktio_entry(id);
res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool);
if (res == -1) {
@@ -188,7 +182,7 @@ odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
id = ODP_PKTIO_INVALID;
}
- unlock_entry(pktio_entry);
+ unlock_entry_classifier(pktio_entry);
return id;
}
@@ -197,7 +191,7 @@ int odp_pktio_close(odp_pktio_t id)
pktio_entry_t *entry;
int res = -1;
- entry = get_entry(id);
+ entry = get_pktio_entry(id);
if (entry == NULL)
return -1;
@@ -226,7 +220,7 @@ odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
{
- pktio_entry_t *pktio_entry = get_entry(id);
+ pktio_entry_t *pktio_entry = get_pktio_entry(id);
int pkts;
int i;
@@ -249,7 +243,7 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
{
- pktio_entry_t *pktio_entry = get_entry(id);
+ pktio_entry_t *pktio_entry = get_pktio_entry(id);
int pkts;
if (pktio_entry == NULL)
@@ -265,15 +259,17 @@ int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
{
- pktio_entry_t *pktio_entry = get_entry(id);
+ pktio_entry_t *pktio_entry = get_pktio_entry(id);
queue_entry_t *qentry = queue_to_qentry(queue);
- if (pktio_entry == NULL || qentry == NULL)
+ if (pktio_entry == NULL || qentry == ODP_QUEUE_INVALID)
return -1;
if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
return -1;
+ qentry = queue_to_qentry(queue);
+
lock_entry(pktio_entry);
pktio_entry->s.inq_default = queue;
unlock_entry(pktio_entry);
@@ -295,7 +291,7 @@ int odp_pktio_inq_remdef(odp_pktio_t id)
odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
{
- pktio_entry_t *pktio_entry = get_entry(id);
+ pktio_entry_t *pktio_entry = get_pktio_entry(id);
if (pktio_entry == NULL)
return ODP_QUEUE_INVALID;
@@ -305,7 +301,7 @@ odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
{
- pktio_entry_t *pktio_entry = get_entry(id);
+ pktio_entry_t *pktio_entry = get_pktio_entry(id);
if (pktio_entry == NULL)
return ODP_QUEUE_INVALID;
@@ -362,32 +358,32 @@ int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
{
odp_buffer_hdr_t *buf_hdr;
+ odp_buffer_t buf;
+ odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
+ odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
+ int pkts, i, j;
buf_hdr = queue_deq(qentry);
+ if (buf_hdr != NULL)
+ return buf_hdr;
- if (buf_hdr == NULL) {
- odp_packet_t pkt;
- odp_buffer_t buf;
- odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
- odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
- int pkts, i, j;
-
- pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
- QUEUE_MULTI_MAX);
-
- if (pkts > 0) {
- pkt = pkt_tbl[0];
- buf = odp_buffer_from_packet(pkt);
- buf_hdr = odp_buf_to_hdr(buf);
+ pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, QUEUE_MULTI_MAX);
+ if (pkts <= 0)
+ return NULL;
- for (i = 1, j = 0; i < pkts; ++i) {
- buf = odp_buffer_from_packet(pkt_tbl[i]);
- tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf);
- }
- queue_enq_multi(qentry, tmp_hdr_tbl, j);
- }
+ for (i = 0, j = 0; i < pkts; ++i) {
+ buf = odp_packet_to_buffer(pkt_tbl[i]);
+ buf_hdr = odp_buf_to_hdr(buf);
+ if (0 > packet_classifier(qentry->s.pktin, pkt_tbl[i]))
+ tmp_hdr_tbl[j++] = buf_hdr;
}
+ if (0 == j)
+ return NULL;
+
+ if (j > 1)
+ queue_enq_multi(qentry, &tmp_hdr_tbl[1], j-1);
+ buf_hdr = tmp_hdr_tbl[0];
return buf_hdr;
}
@@ -400,32 +396,179 @@ int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
{
int nbr;
+ odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
+ odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
+ odp_buffer_hdr_t *tmp_hdr;
+ odp_buffer_t buf;
+ int pkts, i, j;
nbr = queue_deq_multi(qentry, buf_hdr, num);
-
- if (nbr < num) {
- odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
- odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
- odp_buffer_t buf;
- int pkts, i;
-
- pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
- QUEUE_MULTI_MAX);
- if (pkts > 0) {
- for (i = 0; i < pkts; ++i) {
- buf = odp_buffer_from_packet(pkt_tbl[i]);
- tmp_hdr_tbl[i] = odp_buf_to_hdr(buf);
- }
- queue_enq_multi(qentry, tmp_hdr_tbl, pkts);
- }
+ if (odp_unlikely(nbr > num))
+ ODP_ABORT("queue_deq_multi req: %d, returned %d\n",
+ num, nbr);
+
+ /** queue already has number of requsted buffers,
+ * do not do receive in that case.
+ */
+ if (nbr == num)
+ return nbr;
+
+ pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, QUEUE_MULTI_MAX);
+ if (pkts <= 0)
+ return nbr;
+
+ for (i = 0, j = 0; i < pkts; ++i) {
+ buf = odp_packet_to_buffer(pkt_tbl[i]);
+ tmp_hdr = odp_buf_to_hdr(buf);
+ if (0 > packet_classifier(qentry->s.pktin, pkt_tbl[i]))
+ tmp_hdr_tbl[j++] = tmp_hdr;
}
+ if (j)
+ queue_enq_multi(qentry, tmp_hdr_tbl, j);
return nbr;
}
+int odp_pktio_set_mtu(odp_pktio_t id, int mtu)
+{
+ pktio_entry_t *entry;
+ int ret;
+
+ if (mtu <= 0) {
+ ODP_DBG("illegal MTU value %d\n", mtu);
+ return -1;
+ }
+
+ entry = get_pktio_entry(id);
+ if (entry == NULL) {
+ ODP_DBG("pktio entry %d does not exist\n", id);
+ return -1;
+ }
+
+ lock_entry(entry);
+
+ if (odp_unlikely(is_free(entry))) {
+ unlock_entry(entry);
+ ODP_DBG("already freed pktio\n");
+ return -1;
+ }
+
+ ret = rte_eth_dev_set_mtu(entry->s.pkt_dpdk.portid, (uint16_t)mtu);
+
+ unlock_entry(entry);
+ return ret;
+}
+
+int odp_pktio_mtu(odp_pktio_t id)
+{
+ pktio_entry_t *entry;
+ int mtu;
+
+ entry = get_pktio_entry(id);
+ if (entry == NULL) {
+ ODP_DBG("pktio entry %d does not exist\n", id);
+ return -1;
+ }
+
+ lock_entry(entry);
+
+ if (odp_unlikely(is_free(entry))) {
+ unlock_entry(entry);
+ ODP_DBG("already freed pktio\n");
+ return -1;
+ }
+
+ rte_eth_dev_get_mtu(entry->s.pkt_dpdk.portid , (uint16_t *)&mtu);
+
+ unlock_entry(entry);
+ return mtu;
+}
+
+int odp_pktio_promisc_mode_set(odp_pktio_t id, odp_bool_t enable)
+{
+ pktio_entry_t *entry;
+
+ entry = get_pktio_entry(id);
+ if (entry == NULL) {
+ ODP_DBG("pktio entry %d does not exist\n", id);
+ return -1;
+ }
+
+ lock_entry(entry);
+
+ if (odp_unlikely(is_free(entry))) {
+ unlock_entry(entry);
+ ODP_DBG("already freed pktio\n");
+ return -1;
+ }
+
+ if (enable)
+ rte_eth_promiscuous_enable(entry->s.pkt_dpdk.portid);
+ else
+ rte_eth_promiscuous_disable(entry->s.pkt_dpdk.portid);
+
+ unlock_entry(entry);
+ return 0;
+}
+
+int odp_pktio_promisc_mode(odp_pktio_t id)
+{
+ pktio_entry_t *entry;
+ int promisc;
+
+ entry = get_pktio_entry(id);
+ if (entry == NULL) {
+ ODP_DBG("pktio entry %d does not exist\n", id);
+ return -1;
+ }
+
+ lock_entry(entry);
+
+ if (odp_unlikely(is_free(entry))) {
+ unlock_entry(entry);
+ ODP_DBG("already freed pktio\n");
+ return -1;
+ }
+
+ promisc = rte_eth_promiscuous_get(entry->s.pkt_dpdk.portid);
+
+ unlock_entry(entry);
+
+ return promisc;
+}
+
+size_t odp_pktio_mac_addr(odp_pktio_t id, void *mac_addr,
+ size_t addr_size)
+{
+ pktio_entry_t *entry;
+
+ if (addr_size < ETH_ALEN)
+ return 0;
+
+ entry = get_pktio_entry(id);
+ if (entry == NULL) {
+ ODP_DBG("pktio entry %d does not exist\n", id);
+ return 0;
+ }
+
+ lock_entry(entry);
+
+ if (odp_unlikely(is_free(entry))) {
+ unlock_entry(entry);
+ ODP_DBG("already freed pktio\n");
+ return -1;
+ }
+
+ rte_eth_macaddr_get(entry->s.pkt_dpdk.portid,
+ (struct ether_addr *)mac_addr);
+ unlock_entry(entry);
+
+ return ETH_ALEN;
+}
+
int odp_pktio_get_mac_addr(odp_pktio_t id, unsigned char *mac_addr)
{
- pktio_entry_t *pktio_entry = get_entry(id);
+ pktio_entry_t *pktio_entry = get_pktio_entry(id);
if (!pktio_entry) {
ODP_ERR("Invalid odp_pktio_t value\n");
return -1;