Facebook
From Vipin Varghese, 4 Years ago, written in C.
Embed
Download Paste or View Raw
Hits: 252
  1. #include <inttypes.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <inttypes.h>
  6. #include <sys/types.h>
  7. #include <string.h>
  8. #include <sys/queue.h>
  9. #include <stdarg.h>
  10. #include <errno.h>
  11. #include <getopt.h>
  12. #include <signal.h>
  13. #include <sys/param.h>
  14.  
  15. #include <rte_common.h>
  16. #include <rte_byteorder.h>
  17. #include <rte_log.h>
  18. #include <rte_memory.h>
  19. #include <rte_memcpy.h>
  20. #include <rte_eal.h>
  21. #include <rte_launch.h>
  22. #include <rte_atomic.h>
  23. #include <rte_cycles.h>
  24. #include <rte_prefetch.h>
  25. #include <rte_lcore.h>
  26. #include <rte_per_lcore.h>
  27. #include <rte_branch_prediction.h>
  28. #include <rte_interrupts.h>
  29. #include <rte_random.h>
  30. #include <rte_debug.h>
  31. #include <rte_ether.h>
  32. #include <rte_ethdev.h>
  33. #include <rte_mempool.h>
  34. #include <rte_mbuf.h>
  35. #include <rte_malloc.h>
  36. #include <rte_ip.h>
  37. #include <rte_tcp.h>
  38. #include <rte_udp.h>
  39. #include <rte_string_fns.h>
  40. #include <rte_lpm.h>
  41. #include <rte_lpm6.h>
  42.  
  43. #include <rte_ip_frag.h>
  44.  
  45. #define DEF_FLOW_NUM    0x1000
  46. #define DEF_FLOW_TTL    0x100000
  47. #define IP_FRAG_TBL_BUCKET_ENTRIES  128
  48.  
  49. #define RX_RING_SIZE 1024
  50. #define TX_RING_SIZE 1024
  51.  
  52. #define NUM_MBUFS 8191
  53. #define MBUF_CACHE_SIZE 250
  54. #define BURST_SIZE 32
  55.  
  56. static volatile uint8_t force_quit;
  57.  
  58. static const struct rte_eth_conf port_conf_default = {
  59.         .rxmode = {
  60.                 .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
  61.         },
  62. };
  63.  
  64.  
  65. static uint32_t max_flow_num = DEF_FLOW_NUM;
  66. static uint32_t max_flow_ttl = DEF_FLOW_TTL;
  67.  
  68. struct lcore_queue_conf {
  69.     struct rte_ip_frag_tbl *frag_tbl;
  70.     struct rte_mempool *pool;
  71.     struct rte_ip_frag_death_row death_row;
  72. }__rte_cache_aligned;
  73. static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
  74.  
  75.  
  76. static void
  77. signal_handler(int signum)
  78. {
  79.         if (signum == SIGINT || signum == SIGTERM) {
  80.                 printf("\n\nSignal %d received, preparing to exit...\n",
  81.                                 signum);
  82.                 force_quit = 1;
  83.         }
  84. }
  85.  
  86.  
  87. static inline int setup_queue_tbl(struct lcore_queue_conf *qconf)
  88. {
  89.  
  90.     uint64_t frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl;
  91.    
  92.     qconf->frag_tbl = rte_ip_frag_table_create(max_flow_num, IP_FRAG_TBL_BUCKET_ENTRIES, max_flow_num, frag_cycles, rte_socket_id());
  93.  
  94.     if((qconf->frag_tbl) == NULL){
  95.         printf("ERR, IP_RSMBL, Table Failed.");
  96.         return -1;
  97.     }  
  98.  
  99.     qconf->pool=rte_pktmbuf_pool_create("BUFFER", 8000, 256, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
  100.  
  101.     if(qconf->pool== NULL){
  102.         printf("ERR, IP_RSMBL, Mem Pool Failed.");
  103.         return -1;
  104.     }
  105.  
  106.     return 0;
  107. }
  108.  
  109.  
  110. static inline void reassemble(struct rte_mbuf *reassemblepkt, struct lcore_queue_conf *qconf, uint64_t cur_tsc)
  111. {
  112.     struct rte_mbuf *mo;
  113.     struct rte_ether_hdr *eth_hdr;
  114.     struct rte_ipv4_hdr *ip_hdr;
  115.  
  116.     eth_hdr = rte_pktmbuf_mtod(reassemblepkt, struct rte_ether_hdr *);
  117.     ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
  118.  
  119.     if (rte_ipv4_frag_pkt_is_fragmented(ip_hdr)){
  120.         reassemblepkt->l2_len = sizeof(*eth_hdr);
  121.         reassemblepkt->l3_len = sizeof(*ip_hdr);
  122.        
  123.         int ip_len;
  124.         ip_len = rte_be_to_cpu_16(ip_hdr->total_length);
  125.  
  126.         mo = rte_ipv4_frag_reassemble_packet(qconf->frag_tbl, &qconf->death_row, reassemblepkt, cur_tsc, ip_hdr);
  127.            
  128.         if (mo == NULL){
  129.                 printf("Total Length: %u, l3 length: %u, Packet ID: %u \n", ip_len, reassemblepkt->l3_len, ip_hdr->packet_id);
  130.                 printf("src add: %x dst add: %x \n", ip_hdr->src_addr,ip_hdr->dst_addr);
  131.                 printf("ERR, IP_RSMBL, Reassemble Failed.\n");
  132.         }  
  133.  
  134.         if ((mo != reassemblepkt) && (mo != NULL)){
  135.             printf("Reassemble is success.");
  136.             reassemblepkt = mo;
  137.  
  138.         rte_pktmbuf_dump(stdout, mo, 64);
  139.         rte_pktmbuf_free(mo);
  140.         }
  141.     }
  142. }
  143.  
  144. static int
  145. lcore_main(struct lcore_queue_conf *qconf)
  146. {
  147. #define BUFFER_LENGTH 32
  148.     int rx, rec;
  149.     struct rte_mbuf *bufs[BUFFER_LENGTH];
  150.     uint64_t cur_tsc;  
  151.     int i;
  152.  
  153.         uint16_t port;
  154.  
  155.     RTE_ETH_FOREACH_DEV(port){
  156.     printf("RX Thread: Socket ID: %u\n", rte_socket_id());
  157.     printf("RX Thread: lcore count: %u\n", rte_lcore_count());
  158.     printf("RX Thread: lcore ID: %u\n", rte_lcore_id());
  159.     }  
  160.        
  161.         while(!force_quit) {
  162.             cur_tsc = rte_rdtsc();
  163.             RTE_ETH_FOREACH_DEV(port){
  164.                             rx=rte_eth_rx_burst(port, 0, bufs, BUFFER_LENGTH);
  165.                             if(likely(rx)) {
  166.                                 for(i=0; i<rx; i++)
  167.                                         reassemble(bufs[i], qconf, cur_tsc);
  168.  
  169.                                 rte_ip_frag_free_death_row(&qconf->death_row, 2);
  170.                             }
  171.             }
  172.         }
  173.         return 0;
  174. }
  175.  
  176. int port_init(uint16_t port, struct rte_mempool *mbuf_pool)
  177. {
  178.         struct rte_eth_conf port_conf = port_conf_default;
  179.         const uint16_t rx_rings = 1, tx_rings = 1;
  180.         uint16_t nb_rxd = RX_RING_SIZE;
  181.         uint16_t nb_txd = TX_RING_SIZE;
  182.         int retval;
  183.         uint16_t q;
  184.         struct rte_eth_dev_info dev_info;
  185.         struct rte_eth_txconf txconf;
  186.  
  187.         if (!rte_eth_dev_is_valid_port(port))
  188.                 return -1;
  189.  
  190.         retval = rte_eth_dev_info_get(port, &dev_info);
  191.         if (retval != 0) {
  192.                 printf("Error during getting device (port %u) info: %s\n",
  193.                                 port, strerror(-retval));
  194.                 return retval;
  195.         }
  196.  
  197.         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
  198.                 port_conf.txmode.offloads |=
  199.                         DEV_TX_OFFLOAD_MBUF_FAST_FREE;
  200.  
  201.         /* Configure the Ethernet device. */
  202.         retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
  203.         if (retval != 0)
  204.                 return retval;
  205.  
  206.         retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
  207.         if (retval != 0)
  208.                 return retval;
  209.  
  210.         /* Allocate and set up 1 RX queue per Ethernet port. */
  211.         for (q = 0; q < rx_rings; q++) {
  212.                 retval = rte_eth_rx_queue_setup(port, q, nb_rxd,
  213.                                 rte_eth_dev_socket_id(port), NULL, mbuf_pool);
  214.                 if (retval < 0)
  215.                         return retval;
  216.         }
  217.         txconf = dev_info.default_txconf;
  218.         txconf.offloads = port_conf.txmode.offloads;
  219.         /* Allocate and set up 1 TX queue per Ethernet port. */
  220.         for (q = 0; q < tx_rings; q++) {
  221.                 retval = rte_eth_tx_queue_setup(port, q, nb_txd,
  222.                                 rte_eth_dev_socket_id(port), &txconf);
  223.                 if (retval < 0)
  224.                         return retval;
  225.         }
  226.  
  227.         /* Start the Ethernet port. */
  228.         retval = rte_eth_dev_start(port);
  229.         if (retval < 0)
  230.                 return retval;
  231.  
  232.         /* Display the port MAC address. */
  233.         struct rte_ether_addr addr;
  234.         retval = rte_eth_macaddr_get(port, &addr);
  235.         if (retval != 0)
  236.                 return retval;
  237.  
  238.         printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
  239.                            " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
  240.                         port,
  241.                         addr.addr_bytes[0], addr.addr_bytes[1],
  242.                         addr.addr_bytes[2], addr.addr_bytes[3],
  243.                         addr.addr_bytes[4], addr.addr_bytes[5]);
  244.  
  245.         /* Enable RX in promiscuous mode for the Ethernet device. */
  246.         retval = rte_eth_promiscuous_enable(port);
  247.         if (retval != 0)
  248.                 return retval;
  249.  
  250.         return 0;
  251. }
  252.  
  253.  
  254. int main(int argc, char *argv[])
  255. {
  256.  
  257.     int ret;
  258.     uint16_t portcheck;
  259.     uint16_t p1;
  260.     struct lcore_queue_conf *qconf;
  261.  
  262.     force_quit = 0;
  263.     signal(SIGINT, signal_handler);
  264.     signal(SIGTERM, signal_handler);
  265.  
  266.     /* EAL setup */
  267.     ret=rte_eal_init(argc, argv);
  268.     if(ret < 0)
  269.         rte_exit(EXIT_FAILURE, "EAL initialising failed.");
  270.  
  271.     qconf = &lcore_queue_conf[rte_get_master_lcore()];
  272.  
  273.     if(setup_queue_tbl(qconf) != 0)
  274.     rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
  275.  
  276.         RTE_ETH_FOREACH_DEV(portcheck){
  277.             if(port_init(portcheck, qconf->pool) != 0)
  278.                 rte_exit(EXIT_FAILURE, "Ethernet port initialisation failed.");
  279.     }
  280.  
  281.  
  282.     /* Master core call */  
  283.     lcore_main(qconf);
  284.  
  285.     return 0;
  286. }
  287.