trex-core中run_in_rx_core的工作流程

run_in_rx_core的工作主要是将绑定到本port端的网络节点数据接收后转发到dpdk发送,工作流程如下图所示

flowchart LR subgraph CRxCore start --> _do_start _do_start --> cold_state_loop _do_start --> hot_state_loop cold_state_loop --> work_tick hot_state_loop --> work_tick work_tick --> process_all_pending_pkts process_all_pending_pkts --> handle_msg_packets end
  • process_all_pending_pkts 的工作流程

process_all_pending_pkts函数处理数据面数据接收发送的工作

523     for (auto &mngr_pair : m_rx_port_mngr_map) {
524         total_pkts += mngr_pair.second->process_all_pending_pkts(flush_rx);
525     }
flowchart TD subgraph CRxCore id1[[process_all_pending_pkts]] end subgraph RXPortManager id2[[process_all_pending_pkts]] id3[["cnt_rx=handle_tx"]] id6[["tx_pkt(string&)"]] id7[["tx_pkt(rte_mbuf_t*)"]] id12[[handle_pkt]] end subgraph CStackLinuxBased id4[handle_tx] id15[[handle_pkt]] end subgraph CNamespacedIfNode id16[[filter_and_send]] end subgraph RXFeatureAPI id5[[tx_pkt]] end subgraph CZmqPacketWriter id14[["write_pkt 将接收到的数据转发给emq插件"]] end id1 -- "for (RXPortManager &mngr_pair : m_rx_port_mngr_map)" --> id2 id2 --> id3 id3 ---|handle_tx内部流程|id4 id3 -- "for (int j = 0; j < cnt_rx; j++)" --> id12 id12 -- "is_feature_set(EZMQ) && is_emu_filter(rte_mbuf_t *m) " --> id14 id12 -- "is_feature_set(STACK)" --> id15 id15 -- "将接收到的数据转发到namespace对应的veth网络接口" --> id16 id4 --> id5 id5 --> id6 id6 --> id7

遍历m_rx_port_mngr_map容器中的RXPortManager对象,调用其函数process_all_pending_pkts;

每个物理端口都对应一个RXPortManager实例

int RXPortManager::process_all_pending_pkts(bool flush_rx) {
    ....
    uint16_t cnt_tx = handle_tx();

   ....
    for (int j = 0; j < cnt_rx; j++) {
        rte_mbuf_t *m = rx_pkts[j];

        if (!flush_rx) {
            handle_pkt(m);
        } else {
            rte_pktmbuf_free(m);
        }
    }
   ....
}
  • handle_tx

handle_tx会调用CStackLinuxBased::handle_tx函数

该函数主要监听m_epoll_fd,当接收到数据后,根据mac地址找到对应的node节点,将接收到的数据通过m_api转发出去:

int event_count = epoll_wait(m_epoll_fd, events, MAX_EVENTS, 0);
if (event_count) {
  uint16_t pkt_len = recv(m_rw_buf...);
  auto iter_pair = m_nodes.find(src_mac);
  CNamespacedIfNode *node = (CNamespacedIfNode*)iter_pair->second;
  string &vlans_insert_to_pkt = node->get_vlans_insert_to_pkt();
  if ( vlans_insert_to_pkt.size() ) {
      read_buf_str.assign(m_rw_buf, 12);
      read_buf_str += vlans_insert_to_pkt;
      read_buf_str.append(m_rw_buf + 12, pkt_len - 12);
  } else {
      read_buf_str.assign(m_rw_buf, pkt_len);
  }
  m_api->tx_pkt(read_buf_str);
}

m_api是 RXFeatureAPI 类

每当添加一个CNamespacedIfNode (分为CLinuxIfNode或者CSharedNSIfNode)节点,会将该节点添加到m_epoll_fd监控该节点对应的veth网络接口上的数据

CNamespacedIfNode *node;
node->m_event.events = EPOLLIN;
node->m_event.data.fd = node->get_pair_id();

// thread safe 
epoll_ctl(m_epoll_fd, EPOLL_CTL_ADD, node->get_pair_id(), &node->m_event);

posted @ 2022-05-23 18:11  staylight  阅读(87)  评论(0编辑  收藏  举报