X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_port%2Frte_port_source_sink.c;h=4cad71097f785442076cde3e1def822645c5c0c3;hb=0c7a0c35f24c1997be7e30d53c8486eb546ae13a;hp=3d4e8d9efab0d846bde984d91848ee6d41bd00c0;hpb=d4b42133d85b5da3576773f2196a4a0aa49f459c;p=dpdk.git diff --git a/lib/librte_port/rte_port_source_sink.c b/lib/librte_port/rte_port_source_sink.c index 3d4e8d9efa..4cad71097f 100644 --- a/lib/librte_port/rte_port_source_sink.c +++ b/lib/librte_port/rte_port_source_sink.c @@ -36,17 +36,13 @@ #include #include #include - -#ifdef RTE_NEXT_ABI - #include #ifdef RTE_PORT_PCAP +#include #include #endif -#endif - #include "rte_port_source_sink.h" /* @@ -71,39 +67,22 @@ struct rte_port_source { struct rte_mempool *mempool; -#ifdef RTE_NEXT_ABI - /* PCAP buffers and indexes */ + /* PCAP buffers and indices */ uint8_t **pkts; uint8_t *pkt_buff; uint32_t *pkt_len; uint32_t n_pkts; uint32_t pkt_index; -#endif }; -#ifdef RTE_NEXT_ABI - #ifdef RTE_PORT_PCAP -/** - * Load PCAP file, allocate and copy packets in the file to memory - * - * @param p - * Parameters for source port - * @param port - * Handle to source port - * @param socket_id - * Socket id where the memory is created - * @return - * 0 on SUCCESS - * error code otherwise - */ static int -pcap_source_load(struct rte_port_source_params *p, - struct rte_port_source *port, +pcap_source_load(struct rte_port_source *port, + const char *file_name, + uint32_t n_bytes_per_pkt, int socket_id) { - uint32_t status = 0; uint32_t n_pkts = 0; uint32_t i; uint32_t *pkt_len_aligns = NULL; @@ -118,18 +97,16 @@ pcap_source_load(struct rte_port_source_params *p, (rte_pktmbuf_data_room_size(port->mempool) - RTE_PKTMBUF_HEADROOM); - if (p->file_name == NULL) - return 0; - - if (p->n_bytes_per_pkt == 0) + if (n_bytes_per_pkt == 0) max_len = pktmbuf_maxlen; else - max_len = RTE_MIN(p->n_bytes_per_pkt, pktmbuf_maxlen); + max_len = RTE_MIN(n_bytes_per_pkt, pktmbuf_maxlen); /* first time open, get packet number */ - pcap_handle = pcap_open_offline(p->file_name, pcap_errbuf); + pcap_handle = pcap_open_offline(file_name, pcap_errbuf); if (pcap_handle == NULL) { - status = -ENOENT; + RTE_LOG(ERR, PORT, "Failed to open pcap file " + "'%s' for reading\n", file_name); goto error_exit; } @@ -141,28 +118,29 @@ pcap_source_load(struct rte_port_source_params *p, port->pkt_len = rte_zmalloc_socket("PCAP", (sizeof(*port->pkt_len) * n_pkts), 0, socket_id); if (port->pkt_len == NULL) { - status = -ENOMEM; + RTE_LOG(ERR, PORT, "No enough memory\n"); goto error_exit; } pkt_len_aligns = rte_malloc("PCAP", (sizeof(*pkt_len_aligns) * n_pkts), 0); if (pkt_len_aligns == NULL) { - status = -ENOMEM; + RTE_LOG(ERR, PORT, "No enough memory\n"); goto error_exit; } port->pkts = rte_zmalloc_socket("PCAP", (sizeof(*port->pkts) * n_pkts), 0, socket_id); if (port->pkts == NULL) { - status = -ENOMEM; + RTE_LOG(ERR, PORT, "No enough memory\n"); goto error_exit; } /* open 2nd time, get pkt_len */ - pcap_handle = pcap_open_offline(p->file_name, pcap_errbuf); + pcap_handle = pcap_open_offline(file_name, pcap_errbuf); if (pcap_handle == NULL) { - status = -ENOENT; + RTE_LOG(ERR, PORT, "Failed to open pcap file " + "'%s' for reading\n", file_name); goto error_exit; } @@ -180,16 +158,17 @@ pcap_source_load(struct rte_port_source_params *p, buff = rte_zmalloc_socket("PCAP", total_buff_len, 0, socket_id); if (buff == NULL) { - status = -ENOMEM; + RTE_LOG(ERR, PORT, "No enough memory\n"); goto error_exit; } port->pkt_buff = buff; /* open file one last time to copy the pkt content */ - pcap_handle = pcap_open_offline(p->file_name, pcap_errbuf); + pcap_handle = pcap_open_offline(file_name, pcap_errbuf); if (pcap_handle == NULL) { - status = -ENOENT; + RTE_LOG(ERR, PORT, "Failed to open pcap file " + "'%s' for reading\n", file_name); goto error_exit; } @@ -206,6 +185,10 @@ pcap_source_load(struct rte_port_source_params *p, rte_free(pkt_len_aligns); + RTE_LOG(INFO, PORT, "Successfully load pcap file " + "'%s' with %u pkts\n", + file_name, port->n_pkts); + return 0; error_exit: @@ -218,25 +201,28 @@ error_exit: if (port->pkt_buff) rte_free(port->pkt_buff); - return status; + return -1; } -#else -static int -pcap_source_load(__rte_unused struct rte_port_source_params *p, - struct rte_port_source *port, - __rte_unused int socket_id) -{ - port->pkt_buff = NULL; - port->pkt_len = NULL; - port->pkts = NULL; - port->pkt_index = 0; +#define PCAP_SOURCE_LOAD(port, file_name, n_bytes, socket_id) \ + pcap_source_load(port, file_name, n_bytes, socket_id) - return -ENOTSUP; -} -#endif /* RTE_PORT_PCAP */ +#else /* RTE_PORT_PCAP */ -#endif +#define PCAP_SOURCE_LOAD(port, file_name, n_bytes, socket_id) \ +({ \ + int _ret = 0; \ + \ + if (file_name) { \ + RTE_LOG(ERR, PORT, "Source port field " \ + "\"file_name\" is not NULL.\n"); \ + _ret = -1; \ + } \ + \ + _ret; \ +}) + +#endif /* RTE_PORT_PCAP */ static void * rte_port_source_create(void *params, int socket_id) @@ -262,42 +248,16 @@ rte_port_source_create(void *params, int socket_id) /* Initialization */ port->mempool = (struct rte_mempool *) p->mempool; -#ifdef RTE_NEXT_ABI - - /* pcap file load and initialization */ - int status = pcap_source_load(p, port, socket_id); + if (p->file_name) { + int status = PCAP_SOURCE_LOAD(port, p->file_name, + p->n_bytes_per_pkt, socket_id); - if (status == 0) { - if (port->pkt_buff != NULL) { - RTE_LOG(INFO, PORT, "Successfully load pcap file " - "'%s' with %u pkts\n", - p->file_name, port->n_pkts); + if (status < 0) { + rte_free(port); + port = NULL; } - } else if (status != -ENOTSUP) { - /* ENOTSUP is not treated as error */ - switch (status) { - case -ENOENT: - RTE_LOG(ERR, PORT, "%s: Failed to open pcap file " - "'%s' for reading\n", - __func__, p->file_name); - break; - case -ENOMEM: - RTE_LOG(ERR, PORT, "%s: Not enough memory\n", - __func__); - break; - default: - RTE_LOG(ERR, PORT, "%s: Failed to enable PCAP " - "support for unknown reason\n", - __func__); - break; - } - - rte_free(port); - port = NULL; } -#endif - return port; } @@ -311,15 +271,12 @@ rte_port_source_free(void *port) if (p == NULL) return 0; -#ifdef RTE_NEXT_ABI - if (p->pkt_len) rte_free(p->pkt_len); if (p->pkts) rte_free(p->pkts); if (p->pkt_buff) rte_free(p->pkt_buff); -#endif rte_free(p); @@ -340,8 +297,6 @@ rte_port_source_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) rte_pktmbuf_reset(pkts[i]); } -#ifdef RTE_NEXT_ABI - if (p->pkt_buff != NULL) { for (i = 0; i < n_pkts; i++) { uint8_t *pkt_data = rte_pktmbuf_mtod(pkts[i], @@ -358,8 +313,6 @@ rte_port_source_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) } } -#endif - RTE_PORT_SOURCE_STATS_PKTS_IN_ADD(p, n_pkts); return n_pkts; @@ -400,12 +353,149 @@ rte_port_source_stats_read(void *port, struct rte_port_sink { struct rte_port_out_stats stats; + + /* PCAP dumper handle and pkts number */ + void *dumper; + uint32_t max_pkts; + uint32_t pkt_index; + uint32_t dump_finish; }; +#ifdef RTE_PORT_PCAP + +static int +pcap_sink_open(struct rte_port_sink *port, + const char *file_name, + uint32_t max_n_pkts) +{ + pcap_t *tx_pcap; + pcap_dumper_t *pcap_dumper; + + /** Open a dead pcap handler for opening dumper file */ + tx_pcap = pcap_open_dead(DLT_EN10MB, 65535); + if (tx_pcap == NULL) { + RTE_LOG(ERR, PORT, "Cannot open pcap dead handler\n"); + return -1; + } + + /* The dumper is created using the previous pcap_t reference */ + pcap_dumper = pcap_dump_open(tx_pcap, file_name); + if (pcap_dumper == NULL) { + RTE_LOG(ERR, PORT, "Failed to open pcap file " + "\"%s\" for writing\n", file_name); + return -1; + } + + port->dumper = pcap_dumper; + port->max_pkts = max_n_pkts; + port->pkt_index = 0; + port->dump_finish = 0; + + RTE_LOG(INFO, PORT, "Ready to dump packets to file \"%s\"\n", + file_name); + + return 0; +} + +static void +pcap_sink_write_pkt(struct rte_port_sink *port, struct rte_mbuf *mbuf) +{ + uint8_t *pcap_dumper = (uint8_t *)(port->dumper); + struct pcap_pkthdr pcap_hdr; + uint8_t jumbo_pkt_buf[ETHER_MAX_JUMBO_FRAME_LEN]; + uint8_t *pkt; + + /* Maximum num packets already reached */ + if (port->dump_finish) + return; + + pkt = rte_pktmbuf_mtod(mbuf, uint8_t *); + + pcap_hdr.len = mbuf->pkt_len; + pcap_hdr.caplen = pcap_hdr.len; + gettimeofday(&(pcap_hdr.ts), NULL); + + if (mbuf->nb_segs > 1) { + struct rte_mbuf *jumbo_mbuf; + uint32_t pkt_index = 0; + + /* if packet size longer than ETHER_MAX_JUMBO_FRAME_LEN, + * ignore it. + */ + if (mbuf->pkt_len > ETHER_MAX_JUMBO_FRAME_LEN) + return; + + for (jumbo_mbuf = mbuf; jumbo_mbuf != NULL; + jumbo_mbuf = jumbo_mbuf->next) { + rte_memcpy(&jumbo_pkt_buf[pkt_index], + rte_pktmbuf_mtod(jumbo_mbuf, uint8_t *), + jumbo_mbuf->data_len); + pkt_index += jumbo_mbuf->data_len; + } + + jumbo_pkt_buf[pkt_index] = '\0'; + + pkt = jumbo_pkt_buf; + } + + pcap_dump(pcap_dumper, &pcap_hdr, pkt); + + port->pkt_index++; + + if ((port->max_pkts != 0) && (port->pkt_index >= port->max_pkts)) { + port->dump_finish = 1; + RTE_LOG(INFO, PORT, "Dumped %u packets to file\n", + port->pkt_index); + } + +} + +#define PCAP_SINK_OPEN(port, file_name, max_n_pkts) \ + pcap_sink_open(port, file_name, max_n_pkts) + +#define PCAP_SINK_WRITE_PKT(port, mbuf) \ + pcap_sink_write_pkt(port, mbuf) + +#define PCAP_SINK_FLUSH_PKT(dumper) \ +do { \ + if (dumper) \ + pcap_dump_flush((pcap_dumper_t *)dumper); \ +} while (0) + +#define PCAP_SINK_CLOSE(dumper) \ +do { \ + if (dumper) \ + pcap_dump_close((pcap_dumper_t *)dumper); \ +} while (0) + +#else + +#define PCAP_SINK_OPEN(port, file_name, max_n_pkts) \ +({ \ + int _ret = 0; \ + \ + if (file_name) { \ + RTE_LOG(ERR, PORT, "Sink port field " \ + "\"file_name\" is not NULL.\n"); \ + _ret = -1; \ + } \ + \ + _ret; \ +}) + +#define PCAP_SINK_WRITE_PKT(port, mbuf) {} + +#define PCAP_SINK_FLUSH_PKT(dumper) + +#define PCAP_SINK_CLOSE(dumper) + +#endif + static void * -rte_port_sink_create(__rte_unused void *params, int socket_id) +rte_port_sink_create(void *params, int socket_id) { struct rte_port_sink *port; + struct rte_port_sink_params *p = params; /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), @@ -415,15 +505,30 @@ rte_port_sink_create(__rte_unused void *params, int socket_id) return NULL; } + if (!p) + return port; + + if (p->file_name) { + int status = PCAP_SINK_OPEN(port, p->file_name, + p->max_n_pkts); + + if (status < 0) { + rte_free(port); + port = NULL; + } + } + return port; } static int rte_port_sink_tx(void *port, struct rte_mbuf *pkt) { - __rte_unused struct rte_port_sink *p = (struct rte_port_sink *) port; + struct rte_port_sink *p = (struct rte_port_sink *) port; RTE_PORT_SINK_STATS_PKTS_IN_ADD(p, 1); + if (p->dumper != NULL) + PCAP_SINK_WRITE_PKT(p, pkt); rte_pktmbuf_free(pkt); RTE_PORT_SINK_STATS_PKTS_DROP_ADD(p, 1); @@ -434,7 +539,7 @@ static int rte_port_sink_tx_bulk(void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { - __rte_unused struct rte_port_sink *p = (struct rte_port_sink *) port; + struct rte_port_sink *p = (struct rte_port_sink *) port; if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); @@ -442,12 +547,31 @@ rte_port_sink_tx_bulk(void *port, struct rte_mbuf **pkts, RTE_PORT_SINK_STATS_PKTS_IN_ADD(p, n_pkts); RTE_PORT_SINK_STATS_PKTS_DROP_ADD(p, n_pkts); + + if (p->dumper) { + for (i = 0; i < n_pkts; i++) + PCAP_SINK_WRITE_PKT(p, pkts[i]); + } + for (i = 0; i < n_pkts; i++) { struct rte_mbuf *pkt = pkts[i]; rte_pktmbuf_free(pkt); } + } else { + if (p->dumper) { + uint64_t dump_pkts_mask = pkts_mask; + uint32_t pkt_index; + + for ( ; dump_pkts_mask; ) { + pkt_index = __builtin_ctzll( + dump_pkts_mask); + PCAP_SINK_WRITE_PKT(p, pkts[pkt_index]); + dump_pkts_mask &= ~(1LLU << pkt_index); + } + } + for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; @@ -463,6 +587,36 @@ rte_port_sink_tx_bulk(void *port, struct rte_mbuf **pkts, return 0; } +static int +rte_port_sink_flush(void *port) +{ + struct rte_port_sink *p = + (struct rte_port_sink *)port; + + if (p == NULL) + return 0; + + PCAP_SINK_FLUSH_PKT(p->dumper); + + return 0; +} + +static int +rte_port_sink_free(void *port) +{ + struct rte_port_sink *p = + (struct rte_port_sink *)port; + + if (p == NULL) + return 0; + + PCAP_SINK_CLOSE(p->dumper); + + rte_free(p); + + return 0; +} + static int rte_port_sink_stats_read(void *port, struct rte_port_out_stats *stats, int clear) @@ -491,9 +645,9 @@ struct rte_port_in_ops rte_port_source_ops = { struct rte_port_out_ops rte_port_sink_ops = { .f_create = rte_port_sink_create, - .f_free = NULL, + .f_free = rte_port_sink_free, .f_tx = rte_port_sink_tx, .f_tx_bulk = rte_port_sink_tx_bulk, - .f_flush = NULL, + .f_flush = rte_port_sink_flush, .f_stats = rte_port_sink_stats_read, };