2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 #include <rte_cycles.h>
20 #include "prox_malloc.h"
24 #include "task_init.h"
25 #include "task_base.h"
29 struct task_base base;
31 struct rte_mbuf **mbufs;
36 static uint16_t buffer_packets(struct task_dump *task, struct rte_mbuf **mbufs, uint16_t n_pkts)
40 if (task->n_mbufs == task->n_pkts)
43 for (j = 0; j < n_pkts && task->n_mbufs < task->n_pkts; ++j) {
44 mbufs[j]->udata64 = rte_rdtsc();
45 task->mbufs[task->n_mbufs++] = mbufs[j];
51 static int handle_dump_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
53 struct task_dump *task = (struct task_dump *)tbase;
54 const uint16_t ofs = buffer_packets(task, mbufs, n_pkts);
56 for (uint16_t j = ofs; j < n_pkts; ++j)
57 rte_pktmbuf_free(mbufs[j]);
58 TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, n_pkts - ofs);
62 static void init_task_dump(struct task_base *tbase, __attribute__((unused)) struct task_args *targ)
64 struct task_dump *task = (struct task_dump *)tbase;
65 const int socket_id = rte_lcore_to_socket_id(targ->lconf->id);
67 task->mbufs = prox_zmalloc(sizeof(*task->mbufs) * targ->n_pkts, socket_id);
68 task->n_pkts = targ->n_pkts;
69 if (!strcmp(targ->pcap_file, "")) {
70 strcpy(targ->pcap_file, "out.pcap");
72 strncpy(task->pcap_file, targ->pcap_file, sizeof(task->pcap_file));
75 static void stop(struct task_base *tbase)
77 struct task_dump *task = (struct task_dump *)tbase;
78 static pcap_dumper_t *pcap_dump_handle;
80 uint32_t n_pkts = 65536;
81 struct pcap_pkthdr header = {{0}, 0, 0};
83 char err_str[PCAP_ERRBUF_SIZE];
84 const uint64_t hz = rte_get_tsc_hz();
85 struct timeval tv = {0};
86 uint64_t tsc, beg = 0;
88 plogx_info("Dumping %d packets to '%s'\n", task->n_mbufs, task->pcap_file);
89 handle = pcap_open_dead(DLT_EN10MB, n_pkts);
90 pcap_dump_handle = pcap_dump_open(handle, task->pcap_file);
93 beg = task->mbufs[0]->udata64;
95 for (uint32_t j = 0; j < task->n_mbufs; ++j) {
96 tsc = task->mbufs[j]->udata64 - beg;
97 header.len = rte_pktmbuf_pkt_len(task->mbufs[j]);
98 header.caplen = header.len;
99 tsc_to_tv(&header.ts, tsc);
100 pcap_dump((unsigned char *)pcap_dump_handle, &header, rte_pktmbuf_mtod(task->mbufs[j], void *));
103 pcap_dump_close(pcap_dump_handle);
105 plogx_info("Dump complete, releasing mbufs\n");
109 while (j + 64 < task->n_mbufs) {
110 tbase->tx_pkt(tbase, &task->mbufs[j], 64, NULL);
113 if (j < task->n_mbufs) {
114 tbase->tx_pkt(tbase, &task->mbufs[j], task->n_mbufs - j, NULL);
119 static struct task_init task_init_dump = {
121 .init = init_task_dump,
122 .handle = handle_dump_bulk,
124 .flag_features = TASK_FEATURE_ZERO_RX,
125 .size = sizeof(struct task_dump)
128 __attribute__((constructor)) static void reg_task_dump(void)
130 reg_task(&task_init_dump);