- ff_run(loop_func_t loop, void* arg)
- loop为入口函数
- arg为user pointer
void ff_run(loop_func_t loop, void* arg)
{
ff_dpdk_run(loop, arg);
}
- ff_dpdk_run函数
void ff_dpdk_run(loop_func_t loop, void *arg)
{
struct loop_routine *lr = rte_malloc(NULL,
sizeof(struct loop_routine), 0);
lr->loop = loop;
lr->arg = arg;
rte_eal_mp_remote_launch(main_loop, lr, CALL_MASTER);
rte_eal_mp_wait_lcore();
rte_free(lr);
}
- main_loop函数
- dpdk lcore上实际入口
- 功能
- 定时器管理
- pcap处理
- 刷新tx缓冲
- rx数据包
- 通过dispatch_ring传递过来的数据包
- 当前queue接收的数据包
- msg_ring消息处理
- 用户loop回调
static int main_loop(void *arg)
{
struct loop_routine *lr = (struct loop_routine *)arg;
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
uint64_t prev_tsc, diff_tsc, cur_tsc, usch_tsc, div_tsc, usr_tsc, sys_tsc, end_tsc, idle_sleep_tsc;
int i, j, nb_rx, idle;
uint16_t port_id, queue_id;
struct lcore_conf *qconf;
const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
US_PER_S * BURST_TX_DRAIN_US;
struct ff_dpdk_if_context *ctx;
prev_tsc = 0;
usch_tsc = 0;
qconf = &lcore_conf;
while (1) {
cur_tsc = rte_rdtsc();
if (unlikely(freebsd_clock.expire < cur_tsc)) {
rte_timer_manage();
}
idle = 1;
sys_tsc = 0;
usr_tsc = 0;
diff_tsc = cur_tsc - prev_tsc;
if (unlikely(diff_tsc > drain_tsc)) {
for (i = 0; i < qconf->nb_tx_port; i++) {
port_id = qconf->tx_port_id[i];
if (qconf->tx_mbufs[port_id].len == 0)
continue;
idle = 0;
send_burst(qconf,
qconf->tx_mbufs[port_id].len,
port_id);
qconf->tx_mbufs[port_id].len = 0;
}
prev_tsc = cur_tsc;
}
for (i = 0; i < qconf->nb_rx_queue; ++i) {
port_id = qconf->rx_queue_list[i].port_id;
queue_id = qconf->rx_queue_list[i].queue_id;
ctx = veth_ctx[port_id];
#ifdef FF_KNI
if (enable_kni && rte_eal_process_type() == RTE_PROC_PRIMARY) {
ff_kni_process(port_id, queue_id, pkts_burst, MAX_PKT_BURST);
}
#endif
process_dispatch_ring(port_id, queue_id, pkts_burst, ctx);
nb_rx = rte_eth_rx_burst(port_id, queue_id, pkts_burst,
MAX_PKT_BURST);
if (nb_rx == 0)
continue;
idle = 0;
for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) {
rte_prefetch0(rte_pktmbuf_mtod(
pkts_burst[j], void *));
}
for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
j + PREFETCH_OFFSET], void *));
process_packets(port_id, queue_id, &pkts_burst[j], 1, ctx, 0);
}
for (; j < nb_rx; j++) {
process_packets(port_id, queue_id, &pkts_burst[j], 1, ctx, 0);
}
}
process_msg_ring(qconf->proc_id);
div_tsc = rte_rdtsc();
if (likely(lr->loop != NULL && (!idle || cur_tsc - usch_tsc > drain_tsc))) {
usch_tsc = cur_tsc;
lr->loop(lr->arg);
}
idle_sleep_tsc = rte_rdtsc();
if (likely(idle && idle_sleep)) {
usleep(idle_sleep);
end_tsc = rte_rdtsc();
} else {
end_tsc = idle_sleep_tsc;
}
end_tsc = rte_rdtsc();
if (usch_tsc == cur_tsc) {
usr_tsc = idle_sleep_tsc - div_tsc;
}
if (!idle) {
sys_tsc = div_tsc - cur_tsc;
ff_top_status.sys_tsc += sys_tsc;
}
ff_top_status.usr_tsc += usr_tsc;
ff_top_status.work_tsc += end_tsc - cur_tsc;
ff_top_status.idle_tsc += end_tsc - cur_tsc - usr_tsc - sys_tsc;
ff_top_status.loops++;
}
return 0;
}
- process_packets
static inline void process_packets(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **bufs,
uint16_t count, const struct ff_dpdk_if_context *ctx, int pkts_from_ring)
{
struct lcore_conf *qconf = &lcore_conf;
uint16_t nb_queues = qconf->nb_queue_list[port_id];
uint16_t i;
for (i = 0; i < count; i++) {
struct rte_mbuf *rtem = bufs[i];
if (unlikely(qconf->pcap[port_id] != NULL)) {
if (!pkts_from_ring) {
ff_dump_packets(qconf->pcap[port_id], rtem);
}
}
void *data = rte_pktmbuf_mtod(rtem, void *);
uint16_t len = rte_pktmbuf_data_len(rtem);
if (!pkts_from_ring) {
ff_traffic.rx_packets++;
ff_traffic.rx_bytes += len;
}
if (!pkts_from_ring && packet_dispatcher) {
int ret = (*packet_dispatcher)(data, &len, queue_id, nb_queues);
if (ret == FF_DISPATCH_RESPONSE) {
rte_pktmbuf_pkt_len(rtem) = rte_pktmbuf_data_len(rtem) = len;
send_single_packet(rtem, port_id);
continue;
}
if (ret == FF_DISPATCH_ERROR || ret >= nb_queues) {
rte_pktmbuf_free(rtem);
continue;
}
if (ret != queue_id) {
ret = rte_ring_enqueue(dispatch_ring[port_id][ret], rtem);
if (ret < 0)
rte_pktmbuf_free(rtem);
continue;
}
}
enum FilterReturn filter = protocol_filter(data, len);
if (filter == FILTER_ARP) {
struct rte_mempool *mbuf_pool;
struct rte_mbuf *mbuf_clone;
if (!pkts_from_ring) {
uint16_t j;
for (j = 0; j < nb_queues; ++j) {
if (j == queue_id)
continue;
unsigned socket_id = 0;
if (numa_on) {
uint16_t lcore_id = qconf->port_cfgs[port_id].lcore_list[j];
socket_id = rte_lcore_to_socket_id(lcore_id);
}
mbuf_pool = pktmbuf_pool[socket_id];
mbuf_clone = pktmbuf_deep_clone(rtem, mbuf_pool);
if (mbuf_clone) {
int ret = rte_ring_enqueue(dispatch_ring[port_id][j],
mbuf_clone);
if (ret < 0)
rte_pktmbuf_free(mbuf_clone);
}
}
}
#ifdef FF_KNI
if (enable_kni && rte_eal_process_type() == RTE_PROC_PRIMARY) {
mbuf_pool = pktmbuf_pool[qconf->socket_id];
mbuf_clone = pktmbuf_deep_clone(rtem, mbuf_pool);
if (mbuf_clone) {
ff_kni_enqueue(port_id, mbuf_clone);
}
}
#endif
ff_veth_input(ctx, rtem);
#ifdef FF_KNI
} else if (enable_kni &&
((filter == FILTER_KNI && kni_accept) ||
(filter == FILTER_UNKNOWN && !kni_accept))) {
ff_kni_enqueue(port_id, rtem);
#endif
} else {
ff_veth_input(ctx, rtem);
}
}
}
- ff_veth_input
- 该函数主要将rte_mbuf转化成freebsd协议栈中mbuf数据结构
- 将mbuf递交给ether_input处理
static void ff_veth_input(const struct ff_dpdk_if_context *ctx, struct rte_mbuf *pkt)
{
uint8_t rx_csum = ctx->hw_features.rx_csum;
if (rx_csum) {
if (pkt->ol_flags & (PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD)) {
rte_pktmbuf_free(pkt);
return;
}
}
void *data = rte_pktmbuf_mtod(pkt, void*);
uint16_t len = rte_pktmbuf_data_len(pkt);
void *hdr = ff_mbuf_gethdr(pkt, pkt->pkt_len, data, len, rx_csum);
if (hdr == NULL) {
rte_pktmbuf_free(pkt);
return;
}
if (pkt->ol_flags & PKT_RX_VLAN_STRIPPED) {
ff_mbuf_set_vlan_info(hdr, pkt->vlan_tci);
}
struct rte_mbuf *pn = pkt->next;
void *prev = hdr;
while (pn != NULL) {
data = rte_pktmbuf_mtod(pn, void *);
len = rte_pktmbuf_data_len(pn);
void *mb = ff_mbuf_get(prev, data, len);
if (mb == NULL) {
ff_mbuf_free(hdr);
rte_pktmbuf_free(pkt);
return;
}
pn = pn->next;
prev = mb;
}
ff_veth_process_packet(ctx->ifp, hdr);
}