bond: unit tests
Including: - code to generate packet bursts for testing rx and tx functionality of bonded device - virtual/stubbed out ethdev for use as slave ethdev in testing Signed-off-by: Declan Doherty <declan.doherty@intel.com> Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
This commit is contained in:
parent
a155d43011
commit
92073ef961
@ -102,9 +102,11 @@ SRCS-$(CONFIG_RTE_APP_TEST) += test_ivshmem.c
|
|||||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_distributor.c
|
SRCS-$(CONFIG_RTE_APP_TEST) += test_distributor.c
|
||||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_distributor_perf.c
|
SRCS-$(CONFIG_RTE_APP_TEST) += test_distributor_perf.c
|
||||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_devargs.c
|
SRCS-$(CONFIG_RTE_APP_TEST) += test_devargs.c
|
||||||
|
SRCS-$(CONFIG_RTE_APP_TEST) += virtual_pmd.c
|
||||||
|
SRCS-$(CONFIG_RTE_APP_TEST) += packet_burst_generator.c
|
||||||
ifeq ($(CONFIG_RTE_APP_TEST),y)
|
ifeq ($(CONFIG_RTE_APP_TEST),y)
|
||||||
SRCS-$(CONFIG_RTE_LIBRTE_ACL) += test_acl.c
|
SRCS-$(CONFIG_RTE_LIBRTE_ACL) += test_acl.c
|
||||||
|
SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += test_link_bonding.c
|
||||||
SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_pmd_ring.c
|
SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_pmd_ring.c
|
||||||
SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c
|
SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c
|
||||||
endif
|
endif
|
||||||
|
@ -159,6 +159,10 @@ static void cmd_autotest_parsed(void *parsed_result,
|
|||||||
ret = test_timer();
|
ret = test_timer();
|
||||||
if (!strcmp(res->autotest, "timer_perf_autotest"))
|
if (!strcmp(res->autotest, "timer_perf_autotest"))
|
||||||
ret = test_timer_perf();
|
ret = test_timer_perf();
|
||||||
|
#ifdef RTE_LIBRTE_PMD_BOND
|
||||||
|
if (!strcmp(res->autotest, "link_bonding_autotest"))
|
||||||
|
ret = test_link_bonding();
|
||||||
|
#endif
|
||||||
if (!strcmp(res->autotest, "mempool_autotest"))
|
if (!strcmp(res->autotest, "mempool_autotest"))
|
||||||
ret = test_mempool();
|
ret = test_mempool();
|
||||||
if (!strcmp(res->autotest, "mempool_perf_autotest"))
|
if (!strcmp(res->autotest, "mempool_perf_autotest"))
|
||||||
@ -227,6 +231,9 @@ cmdline_parse_token_string_t cmd_autotest_autotest =
|
|||||||
"alarm_autotest#interrupt_autotest#"
|
"alarm_autotest#interrupt_autotest#"
|
||||||
"version_autotest#eal_fs_autotest#"
|
"version_autotest#eal_fs_autotest#"
|
||||||
"cmdline_autotest#func_reentrancy_autotest#"
|
"cmdline_autotest#func_reentrancy_autotest#"
|
||||||
|
#ifdef RTE_LIBRTE_PMD_BOND
|
||||||
|
"link_bonding_autotest#"
|
||||||
|
#endif
|
||||||
"mempool_perf_autotest#hash_perf_autotest#"
|
"mempool_perf_autotest#hash_perf_autotest#"
|
||||||
"memcpy_perf_autotest#ring_perf_autotest#"
|
"memcpy_perf_autotest#ring_perf_autotest#"
|
||||||
"red_autotest#meter_autotest#sched_autotest#"
|
"red_autotest#meter_autotest#sched_autotest#"
|
||||||
|
287
app/test/packet_burst_generator.c
Normal file
287
app/test/packet_burst_generator.c
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rte_byteorder.h>
|
||||||
|
#include <rte_mbuf.h>
|
||||||
|
|
||||||
|
#include "packet_burst_generator.h"
|
||||||
|
|
||||||
|
#define UDP_SRC_PORT 1024
|
||||||
|
#define UDP_DST_PORT 1024
|
||||||
|
|
||||||
|
|
||||||
|
#define IP_DEFTTL 64 /* from RFC 1340. */
|
||||||
|
#define IP_VERSION 0x40
|
||||||
|
#define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */
|
||||||
|
#define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)
|
||||||
|
|
||||||
|
static void
|
||||||
|
copy_buf_to_pkt_segs(void *buf, unsigned len, struct rte_mbuf *pkt,
|
||||||
|
unsigned offset)
|
||||||
|
{
|
||||||
|
struct rte_mbuf *seg;
|
||||||
|
void *seg_buf;
|
||||||
|
unsigned copy_len;
|
||||||
|
|
||||||
|
seg = pkt;
|
||||||
|
while (offset >= seg->pkt.data_len) {
|
||||||
|
offset -= seg->pkt.data_len;
|
||||||
|
seg = seg->pkt.next;
|
||||||
|
}
|
||||||
|
copy_len = seg->pkt.data_len - offset;
|
||||||
|
seg_buf = ((char *) seg->pkt.data + offset);
|
||||||
|
while (len > copy_len) {
|
||||||
|
rte_memcpy(seg_buf, buf, (size_t) copy_len);
|
||||||
|
len -= copy_len;
|
||||||
|
buf = ((char *) buf + copy_len);
|
||||||
|
seg = seg->pkt.next;
|
||||||
|
seg_buf = seg->pkt.data;
|
||||||
|
}
|
||||||
|
rte_memcpy(seg_buf, buf, (size_t) len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
copy_buf_to_pkt(void *buf, unsigned len, struct rte_mbuf *pkt, unsigned offset)
|
||||||
|
{
|
||||||
|
if (offset + len <= pkt->pkt.data_len) {
|
||||||
|
rte_memcpy(((char *) pkt->pkt.data + offset), buf, (size_t) len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
copy_buf_to_pkt_segs(buf, len, pkt, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
initialize_eth_header(struct ether_hdr *eth_hdr, struct ether_addr *src_mac,
|
||||||
|
struct ether_addr *dst_mac, uint8_t vlan_enabled, uint16_t van_id)
|
||||||
|
{
|
||||||
|
ether_addr_copy(dst_mac, ð_hdr->d_addr);
|
||||||
|
ether_addr_copy(src_mac, ð_hdr->s_addr);
|
||||||
|
|
||||||
|
if (vlan_enabled) {
|
||||||
|
struct vlan_hdr *vhdr = (struct vlan_hdr *)((uint8_t *)eth_hdr +
|
||||||
|
sizeof(struct ether_hdr));
|
||||||
|
|
||||||
|
eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
|
||||||
|
|
||||||
|
vhdr->eth_proto = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
|
||||||
|
vhdr->vlan_tci = van_id;
|
||||||
|
} else {
|
||||||
|
eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
initialize_udp_header(struct udp_hdr *udp_hdr, uint16_t src_port,
|
||||||
|
uint16_t dst_port, uint16_t pkt_data_len)
|
||||||
|
{
|
||||||
|
uint16_t pkt_len;
|
||||||
|
|
||||||
|
pkt_len = (uint16_t) (pkt_data_len + sizeof(struct udp_hdr));
|
||||||
|
|
||||||
|
udp_hdr->src_port = rte_cpu_to_be_16(src_port);
|
||||||
|
udp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
|
||||||
|
udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len);
|
||||||
|
udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
|
||||||
|
|
||||||
|
return pkt_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
initialize_ipv6_header(struct ipv6_hdr *ip_hdr, uint8_t *src_addr,
|
||||||
|
uint8_t *dst_addr, uint16_t pkt_data_len)
|
||||||
|
{
|
||||||
|
ip_hdr->vtc_flow = 0;
|
||||||
|
ip_hdr->payload_len = pkt_data_len;
|
||||||
|
ip_hdr->proto = IPPROTO_UDP;
|
||||||
|
ip_hdr->hop_limits = IP_DEFTTL;
|
||||||
|
|
||||||
|
rte_memcpy(ip_hdr->src_addr, src_addr, sizeof(ip_hdr->src_addr));
|
||||||
|
rte_memcpy(ip_hdr->dst_addr, dst_addr, sizeof(ip_hdr->dst_addr));
|
||||||
|
|
||||||
|
return (uint16_t) (pkt_data_len + sizeof(struct ipv6_hdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr,
|
||||||
|
uint32_t dst_addr, uint16_t pkt_data_len)
|
||||||
|
{
|
||||||
|
uint16_t pkt_len;
|
||||||
|
uint16_t *ptr16;
|
||||||
|
uint32_t ip_cksum;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize IP header.
|
||||||
|
*/
|
||||||
|
pkt_len = (uint16_t) (pkt_data_len + sizeof(struct ipv4_hdr));
|
||||||
|
|
||||||
|
ip_hdr->version_ihl = IP_VHL_DEF;
|
||||||
|
ip_hdr->type_of_service = 0;
|
||||||
|
ip_hdr->fragment_offset = 0;
|
||||||
|
ip_hdr->time_to_live = IP_DEFTTL;
|
||||||
|
ip_hdr->next_proto_id = IPPROTO_UDP;
|
||||||
|
ip_hdr->packet_id = 0;
|
||||||
|
ip_hdr->total_length = rte_cpu_to_be_16(pkt_len);
|
||||||
|
ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
|
||||||
|
ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute IP header checksum.
|
||||||
|
*/
|
||||||
|
ptr16 = (uint16_t *)ip_hdr;
|
||||||
|
ip_cksum = 0;
|
||||||
|
ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
|
||||||
|
ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
|
||||||
|
ip_cksum += ptr16[4];
|
||||||
|
ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
|
||||||
|
ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reduce 32 bit checksum to 16 bits and complement it.
|
||||||
|
*/
|
||||||
|
ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
|
||||||
|
(ip_cksum & 0x0000FFFF);
|
||||||
|
ip_cksum %= 65536;
|
||||||
|
ip_cksum = (~ip_cksum) & 0x0000FFFF;
|
||||||
|
if (ip_cksum == 0)
|
||||||
|
ip_cksum = 0xFFFF;
|
||||||
|
ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
|
||||||
|
|
||||||
|
return pkt_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of segments per packet is used when creating
|
||||||
|
* scattered transmit packets composed of a list of mbufs.
|
||||||
|
*/
|
||||||
|
#define RTE_MAX_SEGS_PER_PKT 255 /**< pkt.nb_segs is a 8-bit unsigned char. */
|
||||||
|
|
||||||
|
#define TXONLY_DEF_PACKET_LEN 64
|
||||||
|
#define TXONLY_DEF_PACKET_LEN_128 128
|
||||||
|
|
||||||
|
uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN;
|
||||||
|
uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = {
|
||||||
|
TXONLY_DEF_PACKET_LEN_128,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t tx_pkt_nb_segs = 1;
|
||||||
|
|
||||||
|
int
|
||||||
|
generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst,
|
||||||
|
struct ether_hdr *eth_hdr, uint8_t vlan_enabled, void *ip_hdr,
|
||||||
|
uint8_t ipv4, struct udp_hdr *udp_hdr, int nb_pkt_per_burst)
|
||||||
|
{
|
||||||
|
int i, nb_pkt = 0;
|
||||||
|
size_t eth_hdr_size;
|
||||||
|
|
||||||
|
struct rte_mbuf *pkt_seg;
|
||||||
|
struct rte_mbuf *pkt;
|
||||||
|
|
||||||
|
for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
|
||||||
|
pkt = rte_pktmbuf_alloc(mp);
|
||||||
|
if (pkt == NULL) {
|
||||||
|
nomore_mbuf:
|
||||||
|
if (nb_pkt == 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt->pkt.data_len = tx_pkt_seg_lengths[0];
|
||||||
|
pkt_seg = pkt;
|
||||||
|
for (i = 1; i < tx_pkt_nb_segs; i++) {
|
||||||
|
pkt_seg->pkt.next = rte_pktmbuf_alloc(mp);
|
||||||
|
if (pkt_seg->pkt.next == NULL) {
|
||||||
|
pkt->pkt.nb_segs = i;
|
||||||
|
rte_pktmbuf_free(pkt);
|
||||||
|
goto nomore_mbuf;
|
||||||
|
}
|
||||||
|
pkt_seg = pkt_seg->pkt.next;
|
||||||
|
pkt_seg->pkt.data_len = tx_pkt_seg_lengths[i];
|
||||||
|
}
|
||||||
|
pkt_seg->pkt.next = NULL; /* Last segment of packet. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy headers in first packet segment(s).
|
||||||
|
*/
|
||||||
|
if (vlan_enabled)
|
||||||
|
eth_hdr_size = sizeof(struct ether_hdr) + sizeof(struct vlan_hdr);
|
||||||
|
else
|
||||||
|
eth_hdr_size = sizeof(struct ether_hdr);
|
||||||
|
|
||||||
|
copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0);
|
||||||
|
|
||||||
|
if (ipv4) {
|
||||||
|
copy_buf_to_pkt(ip_hdr, sizeof(struct ipv4_hdr), pkt, eth_hdr_size);
|
||||||
|
copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt, eth_hdr_size +
|
||||||
|
sizeof(struct ipv4_hdr));
|
||||||
|
} else {
|
||||||
|
copy_buf_to_pkt(ip_hdr, sizeof(struct ipv6_hdr), pkt, eth_hdr_size);
|
||||||
|
copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt, eth_hdr_size +
|
||||||
|
sizeof(struct ipv6_hdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complete first mbuf of packet and append it to the
|
||||||
|
* burst of packets to be transmitted.
|
||||||
|
*/
|
||||||
|
pkt->pkt.nb_segs = tx_pkt_nb_segs;
|
||||||
|
pkt->pkt.pkt_len = tx_pkt_length;
|
||||||
|
pkt->pkt.vlan_macip.f.l2_len = eth_hdr_size;
|
||||||
|
|
||||||
|
if (ipv4) {
|
||||||
|
pkt->pkt.vlan_macip.f.vlan_tci = ETHER_TYPE_IPv4;
|
||||||
|
pkt->pkt.vlan_macip.f.l3_len = sizeof(struct ipv4_hdr);
|
||||||
|
|
||||||
|
if (vlan_enabled)
|
||||||
|
pkt->ol_flags = PKT_RX_IPV4_HDR | PKT_RX_VLAN_PKT;
|
||||||
|
else
|
||||||
|
pkt->ol_flags = PKT_RX_IPV4_HDR;
|
||||||
|
} else {
|
||||||
|
pkt->pkt.vlan_macip.f.vlan_tci = ETHER_TYPE_IPv6;
|
||||||
|
pkt->pkt.vlan_macip.f.l3_len = sizeof(struct ipv6_hdr);
|
||||||
|
|
||||||
|
if (vlan_enabled)
|
||||||
|
pkt->ol_flags = PKT_RX_IPV6_HDR | PKT_RX_VLAN_PKT;
|
||||||
|
else
|
||||||
|
pkt->ol_flags = PKT_RX_IPV6_HDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkts_burst[nb_pkt] = pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nb_pkt;
|
||||||
|
}
|
78
app/test/packet_burst_generator.h
Normal file
78
app/test/packet_burst_generator.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PACKET_BURST_GENERATOR_H_
|
||||||
|
#define PACKET_BURST_GENERATOR_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rte_mbuf.h>
|
||||||
|
#include <rte_ether.h>
|
||||||
|
#include <rte_ip.h>
|
||||||
|
#include <rte_udp.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define IPV4_ADDR(a, b, c, d)(((a & 0xff) << 24) | ((b & 0xff) << 16) | \
|
||||||
|
((c & 0xff) << 8) | (d & 0xff))
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
initialize_eth_header(struct ether_hdr *eth_hdr, struct ether_addr *src_mac,
|
||||||
|
struct ether_addr *dst_mac, uint8_t vlan_enabled, uint16_t van_id);
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
initialize_udp_header(struct udp_hdr *udp_hdr, uint16_t src_port,
|
||||||
|
uint16_t dst_port, uint16_t pkt_data_len);
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
initialize_ipv6_header(struct ipv6_hdr *ip_hdr, uint8_t *src_addr,
|
||||||
|
uint8_t *dst_addr, uint16_t pkt_data_len);
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr,
|
||||||
|
uint32_t dst_addr, uint16_t pkt_data_len);
|
||||||
|
|
||||||
|
int
|
||||||
|
generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst,
|
||||||
|
struct ether_hdr *eth_hdr, uint8_t vlan_enabled, void *ip_hdr,
|
||||||
|
uint8_t ipv4, struct udp_hdr *udp_hdr, int nb_pkt_per_burst);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PACKET_BURST_GENERATOR_H_ */
|
@ -97,6 +97,7 @@ int test_distributor(void);
|
|||||||
int test_distributor_perf(void);
|
int test_distributor_perf(void);
|
||||||
int test_kvargs(void);
|
int test_kvargs(void);
|
||||||
int test_devargs(void);
|
int test_devargs(void);
|
||||||
|
int test_link_bonding(void);
|
||||||
|
|
||||||
int test_pci_run;
|
int test_pci_run;
|
||||||
|
|
||||||
|
3958
app/test/test_link_bonding.c
Normal file
3958
app/test/test_link_bonding.c
Normal file
File diff suppressed because it is too large
Load Diff
574
app/test/virtual_pmd.c
Normal file
574
app/test/virtual_pmd.c
Normal file
@ -0,0 +1,574 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rte_mbuf.h>
|
||||||
|
#include <rte_ethdev.h>
|
||||||
|
#include <rte_malloc.h>
|
||||||
|
#include <rte_memcpy.h>
|
||||||
|
#include <rte_memory.h>
|
||||||
|
|
||||||
|
#include "virtual_pmd.h"
|
||||||
|
|
||||||
|
#define MAX_PKT_BURST 512
|
||||||
|
|
||||||
|
static const char *virtual_ethdev_driver_name = "Virtual PMD";
|
||||||
|
|
||||||
|
struct virtual_ethdev_private {
|
||||||
|
struct rte_eth_stats eth_stats;
|
||||||
|
|
||||||
|
struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST];
|
||||||
|
int rx_pkt_burst_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct virtual_ethdev_queue {
|
||||||
|
int port_id;
|
||||||
|
int queue_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_start_success(struct rte_eth_dev *eth_dev __rte_unused)
|
||||||
|
{
|
||||||
|
eth_dev->data->dev_started = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_start_fail(struct rte_eth_dev *eth_dev __rte_unused)
|
||||||
|
{
|
||||||
|
eth_dev->data->dev_started = 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static void virtual_ethdev_stop(struct rte_eth_dev *eth_dev __rte_unused)
|
||||||
|
{
|
||||||
|
eth_dev->data->dev_link.link_status = 0;
|
||||||
|
eth_dev->data->dev_started = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_close(struct rte_eth_dev *dev __rte_unused)
|
||||||
|
{}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_configure_success(struct rte_eth_dev *dev __rte_unused)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_configure_fail(struct rte_eth_dev *dev __rte_unused)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_info_get(struct rte_eth_dev *dev __rte_unused,
|
||||||
|
struct rte_eth_dev_info *dev_info)
|
||||||
|
{
|
||||||
|
dev_info->driver_name = virtual_ethdev_driver_name;
|
||||||
|
dev_info->max_mac_addrs = 1;
|
||||||
|
|
||||||
|
dev_info->max_rx_pktlen = (uint32_t)2048;
|
||||||
|
|
||||||
|
dev_info->max_rx_queues = (uint16_t)128;
|
||||||
|
dev_info->max_tx_queues = (uint16_t)512;
|
||||||
|
|
||||||
|
dev_info->min_rx_bufsize = 0;
|
||||||
|
dev_info->pci_dev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_rx_queue_setup_success(struct rte_eth_dev *dev,
|
||||||
|
uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused,
|
||||||
|
unsigned int socket_id,
|
||||||
|
const struct rte_eth_rxconf *rx_conf __rte_unused,
|
||||||
|
struct rte_mempool *mb_pool __rte_unused)
|
||||||
|
{
|
||||||
|
struct virtual_ethdev_queue *rx_q;
|
||||||
|
|
||||||
|
rx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
|
||||||
|
sizeof(struct virtual_ethdev_queue), 0, socket_id);
|
||||||
|
|
||||||
|
if (rx_q == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rx_q->port_id = dev->data->port_id;
|
||||||
|
rx_q->queue_id = rx_queue_id;
|
||||||
|
|
||||||
|
dev->data->rx_queues[rx_queue_id] = rx_q;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_rx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
|
||||||
|
uint16_t rx_queue_id __rte_unused, uint16_t nb_rx_desc __rte_unused,
|
||||||
|
unsigned int socket_id __rte_unused,
|
||||||
|
const struct rte_eth_rxconf *rx_conf __rte_unused,
|
||||||
|
struct rte_mempool *mb_pool __rte_unused)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_tx_queue_setup_success(struct rte_eth_dev *dev,
|
||||||
|
uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused,
|
||||||
|
unsigned int socket_id,
|
||||||
|
const struct rte_eth_txconf *tx_conf __rte_unused)
|
||||||
|
{
|
||||||
|
struct virtual_ethdev_queue *tx_q;
|
||||||
|
|
||||||
|
tx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
|
||||||
|
sizeof(struct virtual_ethdev_queue), 0, socket_id);
|
||||||
|
|
||||||
|
if (tx_q == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
tx_q->port_id = dev->data->port_id;
|
||||||
|
tx_q->queue_id = tx_queue_id;
|
||||||
|
|
||||||
|
dev->data->tx_queues[tx_queue_id] = tx_q;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_tx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
|
||||||
|
uint16_t tx_queue_id __rte_unused, uint16_t nb_tx_desc __rte_unused,
|
||||||
|
unsigned int socket_id __rte_unused,
|
||||||
|
const struct rte_eth_txconf *tx_conf __rte_unused)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_rx_queue_release(void *q __rte_unused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_tx_queue_release(void *q __rte_unused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_link_update_success(struct rte_eth_dev *bonded_eth_dev,
|
||||||
|
int wait_to_complete __rte_unused)
|
||||||
|
{
|
||||||
|
if (!bonded_eth_dev->data->dev_started)
|
||||||
|
bonded_eth_dev->data->dev_link.link_status = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virtual_ethdev_link_update_fail(struct rte_eth_dev *bonded_eth_dev __rte_unused,
|
||||||
|
int wait_to_complete __rte_unused)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
|
||||||
|
{
|
||||||
|
struct virtual_ethdev_private *dev_private = dev->data->dev_private;
|
||||||
|
|
||||||
|
if (stats)
|
||||||
|
rte_memcpy(stats, &dev_private->eth_stats, sizeof(*stats));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_stats_reset(struct rte_eth_dev *dev)
|
||||||
|
{
|
||||||
|
struct virtual_ethdev_private *dev_private = dev->data->dev_private;
|
||||||
|
|
||||||
|
dev_private->rx_pkt_burst_len = 0;
|
||||||
|
|
||||||
|
/* Reset internal statistics */
|
||||||
|
memset(&dev_private->eth_stats, 0, sizeof(dev_private->eth_stats));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_promiscuous_mode_enable(struct rte_eth_dev *dev __rte_unused)
|
||||||
|
{}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev *dev __rte_unused)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
static struct eth_dev_ops virtual_ethdev_default_dev_ops = {
|
||||||
|
.dev_configure = virtual_ethdev_configure_success,
|
||||||
|
.dev_start = virtual_ethdev_start_success,
|
||||||
|
.dev_stop = virtual_ethdev_stop,
|
||||||
|
.dev_close = virtual_ethdev_close,
|
||||||
|
.dev_infos_get = virtual_ethdev_info_get,
|
||||||
|
.rx_queue_setup = virtual_ethdev_rx_queue_setup_success,
|
||||||
|
.tx_queue_setup = virtual_ethdev_tx_queue_setup_success,
|
||||||
|
.rx_queue_release = virtual_ethdev_rx_queue_release,
|
||||||
|
.tx_queue_release = virtual_ethdev_tx_queue_release,
|
||||||
|
.link_update = virtual_ethdev_link_update_success,
|
||||||
|
.stats_get = virtual_ethdev_stats_get,
|
||||||
|
.stats_reset = virtual_ethdev_stats_reset,
|
||||||
|
.promiscuous_enable = virtual_ethdev_promiscuous_mode_enable,
|
||||||
|
.promiscuous_disable = virtual_ethdev_promiscuous_mode_disable
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
vrtl_eth_dev->dev_ops->dev_start = virtual_ethdev_start_success;
|
||||||
|
else
|
||||||
|
vrtl_eth_dev->dev_ops->dev_start = virtual_ethdev_start_fail;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_configure_fn_set_success(uint8_t port_id, uint8_t success)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
vrtl_eth_dev->dev_ops->dev_configure = virtual_ethdev_configure_success;
|
||||||
|
else
|
||||||
|
vrtl_eth_dev->dev_ops->dev_configure = virtual_ethdev_configure_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_rx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
vrtl_eth_dev->dev_ops->rx_queue_setup =
|
||||||
|
virtual_ethdev_rx_queue_setup_success;
|
||||||
|
else
|
||||||
|
vrtl_eth_dev->dev_ops->rx_queue_setup =
|
||||||
|
virtual_ethdev_rx_queue_setup_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_tx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
vrtl_eth_dev->dev_ops->tx_queue_setup =
|
||||||
|
virtual_ethdev_tx_queue_setup_success;
|
||||||
|
else
|
||||||
|
vrtl_eth_dev->dev_ops->tx_queue_setup =
|
||||||
|
virtual_ethdev_tx_queue_setup_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_link_update_fn_set_success(uint8_t port_id, uint8_t success)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
vrtl_eth_dev->dev_ops->link_update = virtual_ethdev_link_update_success;
|
||||||
|
else
|
||||||
|
vrtl_eth_dev->dev_ops->link_update = virtual_ethdev_link_update_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
virtual_ethdev_rx_burst_success(void *queue __rte_unused,
|
||||||
|
struct rte_mbuf **bufs,
|
||||||
|
uint16_t nb_pkts)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev;
|
||||||
|
struct virtual_ethdev_queue *pq_map;
|
||||||
|
struct virtual_ethdev_private *dev_private;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pq_map = (struct virtual_ethdev_queue *)queue;
|
||||||
|
|
||||||
|
vrtl_eth_dev = &rte_eth_devices[pq_map->port_id];
|
||||||
|
|
||||||
|
dev_private = vrtl_eth_dev->data->dev_private;
|
||||||
|
|
||||||
|
if (dev_private->rx_pkt_burst_len > 0) {
|
||||||
|
if (dev_private->rx_pkt_burst_len < nb_pkts) {
|
||||||
|
|
||||||
|
for (i = 0; i < dev_private->rx_pkt_burst_len; i++) {
|
||||||
|
bufs[i] = dev_private->rx_pkt_burst[i];
|
||||||
|
dev_private->rx_pkt_burst[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_private->eth_stats.ipackets = dev_private->rx_pkt_burst_len;
|
||||||
|
}
|
||||||
|
/* reset private burst values */
|
||||||
|
dev_private->rx_pkt_burst_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dev_private->eth_stats.ipackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
virtual_ethdev_rx_burst_fail(void *queue __rte_unused,
|
||||||
|
struct rte_mbuf **bufs __rte_unused,
|
||||||
|
uint16_t nb_pkts __rte_unused)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
virtual_ethdev_tx_burst_success(void *queue,
|
||||||
|
struct rte_mbuf **bufs __rte_unused,
|
||||||
|
uint16_t nb_pkts)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev;
|
||||||
|
struct virtual_ethdev_queue *tx_q;
|
||||||
|
struct virtual_ethdev_private *dev_private;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
tx_q = (struct virtual_ethdev_queue *)queue;
|
||||||
|
|
||||||
|
vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
|
||||||
|
|
||||||
|
if (vrtl_eth_dev->data->dev_link.link_status) {
|
||||||
|
dev_private = vrtl_eth_dev->data->dev_private;
|
||||||
|
dev_private->eth_stats.opackets += nb_pkts;
|
||||||
|
|
||||||
|
return nb_pkts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free packets in burst */
|
||||||
|
for (i = 0; i < nb_pkts; i++) {
|
||||||
|
if (bufs[i] != NULL)
|
||||||
|
rte_pktmbuf_free(bufs[i]);
|
||||||
|
|
||||||
|
bufs[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
virtual_ethdev_tx_burst_fail(void *queue __rte_unused,
|
||||||
|
struct rte_mbuf **bufs __rte_unused, uint16_t nb_pkts __rte_unused)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
|
||||||
|
else
|
||||||
|
vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
|
||||||
|
else
|
||||||
|
vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id, uint8_t link_status)
|
||||||
|
{
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
vrtl_eth_dev->data->dev_link.link_status = link_status;
|
||||||
|
|
||||||
|
_rte_eth_dev_callback_process(vrtl_eth_dev, RTE_ETH_EVENT_INTR_LSC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virtual_ethdev_add_mbufs_to_rx_queue(uint8_t port_id,
|
||||||
|
struct rte_mbuf **pkt_burst, int burst_length)
|
||||||
|
{
|
||||||
|
struct virtual_ethdev_private *dev_private = NULL;
|
||||||
|
struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev_private = vrtl_eth_dev->data->dev_private;
|
||||||
|
|
||||||
|
for (i = 0; i < burst_length; i++)
|
||||||
|
dev_private->rx_pkt_burst[i] = pkt_burst[i];
|
||||||
|
|
||||||
|
dev_private->rx_pkt_burst_len = burst_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
get_number_of_sockets(void)
|
||||||
|
{
|
||||||
|
int sockets = 0;
|
||||||
|
int i;
|
||||||
|
const struct rte_memseg *ms = rte_eal_get_physmem_layout();
|
||||||
|
|
||||||
|
for (i = 0; i < RTE_MAX_MEMSEG && ms[i].addr != NULL; i++) {
|
||||||
|
if (sockets < ms[i].socket_id)
|
||||||
|
sockets = ms[i].socket_id;
|
||||||
|
}
|
||||||
|
/* Number of sockets = maximum socket_id + 1 */
|
||||||
|
return ++sockets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virtual_ethdev_create(const char *name, struct ether_addr *mac_addr,
|
||||||
|
uint8_t socket_id)
|
||||||
|
{
|
||||||
|
struct rte_pci_device *pci_dev = NULL;
|
||||||
|
struct rte_eth_dev *eth_dev = NULL;
|
||||||
|
struct eth_driver *eth_drv = NULL;
|
||||||
|
struct rte_pci_driver *pci_drv = NULL;
|
||||||
|
struct eth_dev_ops *dev_ops = NULL;
|
||||||
|
struct rte_pci_id *id_table = NULL;
|
||||||
|
struct virtual_ethdev_private *dev_private = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* now do all data allocation - for eth_dev structure, dummy pci driver
|
||||||
|
* and internal (dev_private) data
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (socket_id >= get_number_of_sockets())
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id);
|
||||||
|
if (pci_dev == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
eth_drv = rte_zmalloc_socket(name, sizeof(*eth_drv), 0, socket_id);
|
||||||
|
if (eth_drv == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pci_drv = rte_zmalloc_socket(name, sizeof(*pci_drv), 0, socket_id);
|
||||||
|
if (pci_drv == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
dev_ops = rte_zmalloc_socket(name, sizeof(*dev_ops), 0, socket_id);
|
||||||
|
if (dev_ops == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
id_table = rte_zmalloc_socket(name, sizeof(*id_table), 0, socket_id);
|
||||||
|
if (id_table == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
dev_private = rte_zmalloc_socket(name, sizeof(*dev_private), 0, socket_id);
|
||||||
|
if (dev_private == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* reserve an ethdev entry */
|
||||||
|
eth_dev = rte_eth_dev_allocate(name);
|
||||||
|
if (eth_dev == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pci_dev->numa_node = socket_id;
|
||||||
|
pci_drv->name = virtual_ethdev_driver_name;
|
||||||
|
pci_drv->id_table = id_table;
|
||||||
|
|
||||||
|
eth_drv->pci_drv = (struct rte_pci_driver)(*pci_drv);
|
||||||
|
eth_dev->driver = eth_drv;
|
||||||
|
|
||||||
|
eth_dev->data->nb_rx_queues = (uint16_t)1;
|
||||||
|
eth_dev->data->nb_tx_queues = (uint16_t)1;
|
||||||
|
|
||||||
|
TAILQ_INIT(&(eth_dev->callbacks));
|
||||||
|
|
||||||
|
eth_dev->data->dev_link.link_status = 0;
|
||||||
|
eth_dev->data->dev_link.link_speed = ETH_LINK_SPEED_10000;
|
||||||
|
eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
|
||||||
|
|
||||||
|
eth_dev->data->mac_addrs = rte_zmalloc(name, ETHER_ADDR_LEN, 0);
|
||||||
|
if (eth_dev->data->mac_addrs == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
memcpy(eth_dev->data->mac_addrs, mac_addr,
|
||||||
|
sizeof(*eth_dev->data->mac_addrs));
|
||||||
|
eth_dev->data->mac_addrs->addr_bytes[5] = eth_dev->data->port_id;
|
||||||
|
|
||||||
|
eth_dev->data->dev_started = 0;
|
||||||
|
eth_dev->data->promiscuous = 0;
|
||||||
|
eth_dev->data->scattered_rx = 0;
|
||||||
|
eth_dev->data->all_multicast = 0;
|
||||||
|
|
||||||
|
memset(dev_private, 0, sizeof(*dev_private));
|
||||||
|
eth_dev->data->dev_private = dev_private;
|
||||||
|
|
||||||
|
eth_dev->dev_ops = dev_ops;
|
||||||
|
|
||||||
|
/* Copy default device operation functions */
|
||||||
|
memcpy(eth_dev->dev_ops, &virtual_ethdev_default_dev_ops,
|
||||||
|
sizeof(*eth_dev->dev_ops));
|
||||||
|
|
||||||
|
eth_dev->pci_dev = pci_dev;
|
||||||
|
eth_dev->pci_dev->driver = ð_drv->pci_drv;
|
||||||
|
|
||||||
|
eth_dev->pci_dev->driver->id_table->device_id = 0xBEEF;
|
||||||
|
|
||||||
|
eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
|
||||||
|
eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
|
||||||
|
|
||||||
|
return eth_dev->data->port_id;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (pci_dev)
|
||||||
|
rte_free(pci_dev);
|
||||||
|
if (pci_drv)
|
||||||
|
rte_free(pci_drv);
|
||||||
|
if (eth_drv)
|
||||||
|
rte_free(eth_drv);
|
||||||
|
if (dev_ops)
|
||||||
|
rte_free(dev_ops);
|
||||||
|
if (id_table)
|
||||||
|
rte_free(id_table);
|
||||||
|
if (dev_private)
|
||||||
|
rte_free(dev_private);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
74
app/test/virtual_pmd.h
Normal file
74
app/test/virtual_pmd.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VIRTUAL_ETHDEV_H_
|
||||||
|
#define __VIRTUAL_ETHDEV_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rte_ether.h>
|
||||||
|
|
||||||
|
int virtual_ethdev_init(void);
|
||||||
|
|
||||||
|
int virtual_ethdev_create(const char *name, struct ether_addr *mac_addr, uint8_t socket_id);
|
||||||
|
|
||||||
|
void virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id, uint8_t link_status);
|
||||||
|
|
||||||
|
void virtual_ethdev_add_mbufs_to_rx_queue(uint8_t port_id, struct rte_mbuf **pkts_burst, int burst_length);
|
||||||
|
|
||||||
|
|
||||||
|
/** Control methods for the dev_ops functions pointer to control the behavior of the Virtual PMD */
|
||||||
|
|
||||||
|
void virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
void virtual_ethdev_stop_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
void virtual_ethdev_configure_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
void virtual_ethdev_rx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
void virtual_ethdev_tx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
void virtual_ethdev_link_update_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
void virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
void virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __VIRTUAL_ETHDEV_H_ */
|
Loading…
Reference in New Issue
Block a user