下面是一个使用DPDK的KNI(Kernel Network Interface)的简单例子,包括初始化KNI、接收数据包和发送数据包。
”`c
#include
#include
#define MAX_PKT_BURST 32
/* KNI interface configuration */ static struct rte_kni_conf kni_conf = {
.group_id = 0,
.mbuf_size = (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM),
.hdr_len = 0,
.addr = {},
.id = {}
};
/* KNI interface status */ static struct rte_kni *kni;
/* Ethernet port configuration */ static const uint16_t nb_rxd = 128; static const uint16_t nb_txd = 512;
struct rte_eth_conf port_conf = {
.rxmode = {
.max_rx_pkt_len = ETHER_MAX_LEN,
.split_hdr_size = 0,
.header_split = 0, /**< Header Split disabled. */
.hw_ip_checksum_ok = 1, /**< IP checksum verification enabled. */
.hw_vlan_filter = 0, /**< VLAN filtering enabled. */
.jumbo_frame = 0, /**< Jumbo Frame Support disabled. */
.hw_strip_crc = 1, /**< CRC stripped by hardware. */
},
.txmode = {
/* No need to configure anything here for transmit mode */
},
};
/* Ethernet port status */ struct rte_eth_dev_info dev_info; struct ether_addr addr;
/**
Initialize the KNI interface. *
@return
- On success, zero.
-
- On failure, a negative value. */ int kni_init(void) { int ret;
/* Set the KNI interface name */ snprintf(kni_conf.name, RTE_KNI_NAMESIZE, “vEth0”);
/* Create the KNI interface */ kni = rte_kni_alloc(rte_eth_dev_get_port_by_name(“eth0”), &kni_conf);
if (kni == NULL) {
printf("Failed to create kni\n"); return -1;
}
/* Initialize the KNI interface */ ret = rte_kni_init(kni, &kni_conf); if (ret < 0) {
printf("Failed to init kni: %s\n", strerror(-ret)); return ret;
}
return 0; }
/**
- Receive packets from the Ethernet port and forward them to the KNI
- interface. *
- @param[in] port_id
- The Ethernet port ID. */ void rx_packets(uint16_t port_id) { #define MAX_PKT_BURST 32
#define RX_RING_SIZE 128 #define TX_RING_SIZE 512
static struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, .hw_ip_checksum_ok = 1, .hw_vlan_filter = 0, .jumbo_frame = 0, .hw_strip_crc = 1, }, .txmode = { /* No need to configure anything here for transmit mode */ }, };
struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned nb_rx_pkts;
/* Receive packets from the Ethernet port */ nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts_burst, MAX_PKT_BURST);
if (nb_rx_pkts == 0) return;
/* Forward packets to the KNI interface */ for (unsigned i = 0; i < nb_rx_pkts; i++) {
struct rte_mbuf *pkt = pkts_burst[i];
rte_pktmbuf_free(pkt);
} }
/**
- Send packets received from the KNI interface back out on the Ethernet
- port. *
- @param[in] port_id
- The Ethernet port ID. */ void tx_packets(uint16_t port_id) { #define MAX_PKT_BURST 32
#define RX_RING_SIZE 128 #define TX_RING_SIZE 512
struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned nb_tx_pkts;
/* Receive packets from the KNI interface */ nb_tx_pkts = rte_kni_tx_burst(kni, pkts_burst, MAX_PKT_BURST);
if (nb_tx_pkts == 0) return;
/* Send packets to the Ethernet port */ rte_eth_tx_burst(port_id, 0, pkts_burst, nb_tx_pkts); }
int main(int argc, char **argv) { uint16_t nb_ports; uint16_t port_id = -1;
/* Initialize DPDK */ int ret = rte_eal_init(argc, argv); if (ret < 0) { printf(“Failed to initialize dpdk: %s\n”, strerror(-ret)); return -1; }
argc -= ret; argv += ret;
/* Get number of available ports */ nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) { printf(“No ethernet ports available\n”); return -1; }
/* Find first available Ethernet port */ for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
if ((rte_eth_devices[port_id].state == RTE_ETH_DEV_ATTACHED) &&
(rte_eth_devices[port_id].data->dev_flags & RTE_ETH_DEV_DETACHABLE)) {
break;
}
}
/* Check if an available Ethernet port was found */ if (port_id == RTE_MAX_ETHPORTS) { printf(“No available ethernet ports\n”); return -1; }
/* Initialize the KNI interface */ ret = kni_init(); if (ret < 0) { printf(“Failed to initialize KNI interface: %s\n”, strerror(-ret)); return -1; }
/* Configure Ethernet port */ memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info); memset(&addr, 0, sizeof(addr)); ether_addr_copy(&dev_info.default_mac_addr, &addr); rte_eth_dev_configure(port_id, 1, 1, &port_conf);
/* Start the Ethernet port */ rte_eth_dev_start(port_id);
for (;;) {
/* Receive packets from the Ethernet port and forward them to the KNI
* interface.
*/
rx_packets(port_id);
/* Send packets received from the KNI interface back out on the Ethernet
* port.
*/
tx_packets(port_id);
内容由零声教学AI助手提供,问题来源于学员提问