/* - * (C) NTT TechnoCross Corporation 2019 All Rights Reserved */ #include #include /** /**<パケット処理API */ #include /**<パケットバッファAPI */ #include /**<メモリプールAPI */ /** * NIC初期化 */ static int initialize_port(uint16_t port_id, struct rte_mempool *pktmbuf_pool) { printf("\nInitializing port %u\n", port_id); /** * - 指定portに紐づいたNICの設定を実施 * - 使用するキュー数、オフロード機能の設定 */ static const struct rte_eth_conf port_conf = {0}; int ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf); if (ret < 0) { printf("Cannot configure device \n"); return -1; } /** * - 指定portに紐づいたNICの受信キューに対する設定を実施 * - 受信パケットの格納先メモリ領域、受信バッファの数 */ ret = rte_eth_rx_queue_setup(port_id, 0, 1024, rte_eth_dev_socket_id(port_id), NULL, pktmbuf_pool); if (ret < 0) { printf("error rte_eth_rx_queue_setup \n"); return -1; } /** * - 指定portに紐づいたNICの送信キューに対する設定を実施 * - 送信バッファの数 */ ret = rte_eth_tx_queue_setup(port_id, 0, 1024, rte_eth_dev_socket_id(port_id), NULL); if (ret < 0) { printf("error rte_eth_tx_queue_setup \n"); return -1; } /* NICを起動 */ ret = rte_eth_dev_start(port_id); if (ret < 0) { printf("error rte_eth_dev_start \n"); return -1; } /* NICをプロミスキャスモードにセット */ rte_eth_promiscuous_enable(port_id); /** * - 指定portに紐づいたNICのリンクアップ待ちを行う * - リンクアップ or タイムアウトするまでrte_eth_link_get()内で待ちが発生 */ printf("Please wait for the port %u to LinkUp... ", port_id); fflush(stdout); struct rte_eth_link link; rte_eth_link_get(port_id, &link); if (link.link_status == ETH_LINK_DOWN) { printf("timeout.\n"); return -1; } return 0; } /** * パケット転送処理(メインループ) * - 指定のportから受信したパケットを同じportに転送する */ static void forward_main_loop(uint16_t port_id) { struct rte_mbuf *pkts[32]; /* パケット取得用の領域 */ uint16_t nb_rx, nb_tx, i = 0; /* パケット受信/送信数 */ printf("\nForwards packets received on port %u to port %u.\n", port_id, port_id); /** * - パケットを受信したら、受信したパケットを同じportに転送 * - もしパケット送信に失敗したら送信しようとしたパケットを破棄 */ while (1) { nb_rx = rte_eth_rx_burst(port_id, 0, pkts, 32); if (nb_rx <= 0) continue; nb_tx = rte_eth_tx_burst(port_id, 0, pkts, nb_rx); if (nb_tx < nb_rx) for (i = nb_tx; i < nb_rx; i++) rte_pktmbuf_free(pkts[i]); } } /** * メイン関数 */ int main(int argc, char **argv) { /* DPDK初期化 */ int ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot init EAL \n"); printf("\nInitialize DPDK done.\n"); /* NICをひとつも利用できない(bind済でない場合など)はプログラム終了 */ if (rte_eth_dev_count_avail() <= 0) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool \n"); /* パケットバッファ確保 */ struct rte_mempool *pktmbuf_pool = rte_pktmbuf_pool_create( "mbuf_pool", 8192U, 256, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool.\n"); /* ポート0に紐づくNICを初期化 */ ret = initialize_port(0, pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "Initialize port is faild.\n"); /* ポート0に紐づくNICを利用してパケット転送処理実施(メインループ) */ forward_main_loop(0); return 0; }