pdump: add new library for packet capture
[dpdk.git] / lib / librte_pdump / rte_pdump.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2016 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <sys/socket.h>
35 #include <sys/un.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <pthread.h>
40 #include <stdbool.h>
41 #include <stdio.h>
42
43 #include <rte_memcpy.h>
44 #include <rte_mbuf.h>
45 #include <rte_ethdev.h>
46 #include <rte_lcore.h>
47 #include <rte_log.h>
48 #include <rte_errno.h>
49 #include <rte_pci.h>
50
51 #include "rte_pdump.h"
52
53 #define SOCKET_PATH_VAR_RUN "/var/run/pdump_sockets"
54 #define SOCKET_PATH_HOME "HOME/pdump_sockets"
55 #define SERVER_SOCKET "%s/pdump_server_socket"
56 #define CLIENT_SOCKET "%s/pdump_client_socket_%d_%u"
57 #define DEVICE_ID_SIZE 64
58 /* Macros for printing using RTE_LOG */
59 #define RTE_LOGTYPE_PDUMP RTE_LOGTYPE_USER1
60
61 enum pdump_operation {
62         DISABLE = 1,
63         ENABLE = 2
64 };
65
66 enum pdump_version {
67         V1 = 1
68 };
69
70 static pthread_t pdump_thread;
71 static int pdump_socket_fd;
72 static char server_socket_dir[PATH_MAX];
73 static char client_socket_dir[PATH_MAX];
74
75 struct pdump_request {
76         uint16_t ver;
77         uint16_t op;
78         uint32_t flags;
79         union pdump_data {
80                 struct enable_v1 {
81                         char device[DEVICE_ID_SIZE];
82                         uint16_t queue;
83                         struct rte_ring *ring;
84                         struct rte_mempool *mp;
85                         void *filter;
86                 } en_v1;
87                 struct disable_v1 {
88                         char device[DEVICE_ID_SIZE];
89                         uint16_t queue;
90                         struct rte_ring *ring;
91                         struct rte_mempool *mp;
92                         void *filter;
93                 } dis_v1;
94         } data;
95 };
96
97 struct pdump_response {
98         uint16_t ver;
99         uint16_t res_op;
100         int32_t err_value;
101 };
102
103 static struct pdump_rxtx_cbs {
104         struct rte_ring *ring;
105         struct rte_mempool *mp;
106         struct rte_eth_rxtx_callback *cb;
107         void *filter;
108 } rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],
109 tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
110
111 static inline int
112 pdump_pktmbuf_copy_data(struct rte_mbuf *seg, const struct rte_mbuf *m)
113 {
114         if (rte_pktmbuf_tailroom(seg) < m->data_len) {
115                 RTE_LOG(ERR, PDUMP,
116                         "User mempool: insufficient data_len of mbuf\n");
117                 return -EINVAL;
118         }
119
120         seg->port = m->port;
121         seg->vlan_tci = m->vlan_tci;
122         seg->hash = m->hash;
123         seg->tx_offload = m->tx_offload;
124         seg->ol_flags = m->ol_flags;
125         seg->packet_type = m->packet_type;
126         seg->vlan_tci_outer = m->vlan_tci_outer;
127         seg->data_len = m->data_len;
128         seg->pkt_len = seg->data_len;
129         rte_memcpy(rte_pktmbuf_mtod(seg, void *),
130                         rte_pktmbuf_mtod(m, void *),
131                         rte_pktmbuf_data_len(seg));
132
133         return 0;
134 }
135
136 static inline struct rte_mbuf *
137 pdump_pktmbuf_copy(struct rte_mbuf *m, struct rte_mempool *mp)
138 {
139         struct rte_mbuf *m_dup, *seg, **prev;
140         uint32_t pktlen;
141         uint8_t nseg;
142
143         m_dup = rte_pktmbuf_alloc(mp);
144         if (unlikely(m_dup == NULL))
145                 return NULL;
146
147         seg = m_dup;
148         prev = &seg->next;
149         pktlen = m->pkt_len;
150         nseg = 0;
151
152         do {
153                 nseg++;
154                 if (pdump_pktmbuf_copy_data(seg, m) < 0) {
155                         rte_pktmbuf_free(m_dup);
156                         return NULL;
157                 }
158                 *prev = seg;
159                 prev = &seg->next;
160         } while ((m = m->next) != NULL &&
161                         (seg = rte_pktmbuf_alloc(mp)) != NULL);
162
163         *prev = NULL;
164         m_dup->nb_segs = nseg;
165         m_dup->pkt_len = pktlen;
166
167         /* Allocation of new indirect segment failed */
168         if (unlikely(seg == NULL)) {
169                 rte_pktmbuf_free(m_dup);
170                 return NULL;
171         }
172
173         __rte_mbuf_sanity_check(m_dup, 1);
174         return m_dup;
175 }
176
177 static inline void
178 pdump_copy(struct rte_mbuf **pkts, uint16_t nb_pkts, void *user_params)
179 {
180         unsigned i;
181         int ring_enq;
182         uint16_t d_pkts = 0;
183         struct rte_mbuf *dup_bufs[nb_pkts];
184         struct pdump_rxtx_cbs *cbs;
185         struct rte_ring *ring;
186         struct rte_mempool *mp;
187         struct rte_mbuf *p;
188
189         cbs  = user_params;
190         ring = cbs->ring;
191         mp = cbs->mp;
192         for (i = 0; i < nb_pkts; i++) {
193                 p = pdump_pktmbuf_copy(pkts[i], mp);
194                 if (p)
195                         dup_bufs[d_pkts++] = p;
196         }
197
198         ring_enq = rte_ring_enqueue_burst(ring, (void *)dup_bufs, d_pkts);
199         if (unlikely(ring_enq < d_pkts)) {
200                 RTE_LOG(DEBUG, PDUMP,
201                         "only %d of packets enqueued to ring\n", ring_enq);
202                 do {
203                         rte_pktmbuf_free(dup_bufs[ring_enq]);
204                 } while (++ring_enq < d_pkts);
205         }
206 }
207
208 static uint16_t
209 pdump_rx(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
210         struct rte_mbuf **pkts, uint16_t nb_pkts,
211         uint16_t max_pkts __rte_unused,
212         void *user_params)
213 {
214         pdump_copy(pkts, nb_pkts, user_params);
215         return nb_pkts;
216 }
217
218 static uint16_t
219 pdump_tx(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
220                 struct rte_mbuf **pkts, uint16_t nb_pkts, void *user_params)
221 {
222         pdump_copy(pkts, nb_pkts, user_params);
223         return nb_pkts;
224 }
225
226 static int
227 pdump_get_dombdf(char *device_id, char *domBDF, size_t len)
228 {
229         int ret;
230         struct rte_pci_addr dev_addr = {0};
231
232         /* identify if device_id is pci address or name */
233         ret = eal_parse_pci_DomBDF(device_id, &dev_addr);
234         if (ret < 0)
235                 return -1;
236
237         if (dev_addr.domain)
238                 ret = snprintf(domBDF, len, "%u:%u:%u.%u", dev_addr.domain,
239                                 dev_addr.bus, dev_addr.devid,
240                                 dev_addr.function);
241         else
242                 ret = snprintf(domBDF, len, "%u:%u.%u", dev_addr.bus,
243                                 dev_addr.devid,
244                                 dev_addr.function);
245
246         return ret;
247 }
248
249 static int
250 pdump_regitser_rx_callbacks(uint16_t end_q, uint8_t port, uint16_t queue,
251                                 struct rte_ring *ring, struct rte_mempool *mp,
252                                 uint16_t operation)
253 {
254         uint16_t qid;
255         struct pdump_rxtx_cbs *cbs = NULL;
256
257         qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue;
258         for (; qid < end_q; qid++) {
259                 cbs = &rx_cbs[port][qid];
260                 if (cbs && operation == ENABLE) {
261                         if (cbs->cb) {
262                                 RTE_LOG(ERR, PDUMP,
263                                         "failed to add rx callback for port=%d "
264                                         "and queue=%d, callback already exists\n",
265                                         port, qid);
266                                 return -EEXIST;
267                         }
268                         cbs->ring = ring;
269                         cbs->mp = mp;
270                         cbs->cb = rte_eth_add_first_rx_callback(port, qid,
271                                                                 pdump_rx, cbs);
272                         if (cbs->cb == NULL) {
273                                 RTE_LOG(ERR, PDUMP,
274                                         "failed to add rx callback, errno=%d\n",
275                                         rte_errno);
276                                 return rte_errno;
277                         }
278                 }
279                 if (cbs && operation == DISABLE) {
280                         int ret;
281
282                         if (cbs->cb == NULL) {
283                                 RTE_LOG(ERR, PDUMP,
284                                         "failed to delete non existing rx "
285                                         "callback for port=%d and queue=%d\n",
286                                         port, qid);
287                                 return -EINVAL;
288                         }
289                         ret = rte_eth_remove_rx_callback(port, qid, cbs->cb);
290                         if (ret < 0) {
291                                 RTE_LOG(ERR, PDUMP,
292                                         "failed to remove rx callback, errno=%d\n",
293                                         rte_errno);
294                                 return ret;
295                         }
296                         cbs->cb = NULL;
297                 }
298         }
299
300         return 0;
301 }
302
303 static int
304 pdump_regitser_tx_callbacks(uint16_t end_q, uint8_t port, uint16_t queue,
305                                 struct rte_ring *ring, struct rte_mempool *mp,
306                                 uint16_t operation)
307 {
308
309         uint16_t qid;
310         struct pdump_rxtx_cbs *cbs = NULL;
311
312         qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue;
313         for (; qid < end_q; qid++) {
314                 cbs = &tx_cbs[port][qid];
315                 if (cbs && operation == ENABLE) {
316                         if (cbs->cb) {
317                                 RTE_LOG(ERR, PDUMP,
318                                         "failed to add tx callback for port=%d "
319                                         "and queue=%d, callback already exists\n",
320                                         port, qid);
321                                 return -EEXIST;
322                         }
323                         cbs->ring = ring;
324                         cbs->mp = mp;
325                         cbs->cb = rte_eth_add_tx_callback(port, qid, pdump_tx,
326                                                                 cbs);
327                         if (cbs->cb == NULL) {
328                                 RTE_LOG(ERR, PDUMP,
329                                         "failed to add tx callback, errno=%d\n",
330                                         rte_errno);
331                                 return rte_errno;
332                         }
333                 }
334                 if (cbs && operation == DISABLE) {
335                         int ret;
336
337                         if (cbs->cb == NULL) {
338                                 RTE_LOG(ERR, PDUMP,
339                                         "failed to delete non existing tx "
340                                         "callback for port=%d and queue=%d\n",
341                                         port, qid);
342                                 return -EINVAL;
343                         }
344                         ret = rte_eth_remove_tx_callback(port, qid, cbs->cb);
345                         if (ret < 0) {
346                                 RTE_LOG(ERR, PDUMP,
347                                         "failed to remove tx callback, errno=%d\n",
348                                         rte_errno);
349                                 return ret;
350                         }
351                         cbs->cb = NULL;
352                 }
353         }
354
355         return 0;
356 }
357
358 static int
359 set_pdump_rxtx_cbs(struct pdump_request *p)
360 {
361         uint16_t nb_rx_q, nb_tx_q = 0, end_q, queue;
362         uint8_t port;
363         int ret = 0;
364         uint32_t flags;
365         uint16_t operation;
366         struct rte_ring *ring;
367         struct rte_mempool *mp;
368
369         flags = p->flags;
370         operation = p->op;
371         if (operation == ENABLE) {
372                 ret = rte_eth_dev_get_port_by_name(p->data.en_v1.device,
373                                 &port);
374                 if (ret < 0) {
375                         RTE_LOG(ERR, PDUMP,
376                                 "failed to get potid for device id=%s\n",
377                                 p->data.en_v1.device);
378                         return -EINVAL;
379                 }
380                 queue = p->data.en_v1.queue;
381                 ring = p->data.en_v1.ring;
382                 mp = p->data.en_v1.mp;
383         } else {
384                 ret = rte_eth_dev_get_port_by_name(p->data.dis_v1.device,
385                                 &port);
386                 if (ret < 0) {
387                         RTE_LOG(ERR, PDUMP,
388                                 "failed to get potid for device id=%s\n",
389                                 p->data.dis_v1.device);
390                         return -EINVAL;
391                 }
392                 queue = p->data.dis_v1.queue;
393                 ring = p->data.dis_v1.ring;
394                 mp = p->data.dis_v1.mp;
395         }
396
397         /* validation if packet capture is for all queues */
398         if (queue == RTE_PDUMP_ALL_QUEUES) {
399                 struct rte_eth_dev_info dev_info;
400
401                 rte_eth_dev_info_get(port, &dev_info);
402                 nb_rx_q = dev_info.nb_rx_queues;
403                 nb_tx_q = dev_info.nb_tx_queues;
404                 if (nb_rx_q == 0 && flags & RTE_PDUMP_FLAG_RX) {
405                         RTE_LOG(ERR, PDUMP,
406                                 "number of rx queues cannot be 0\n");
407                         return -EINVAL;
408                 }
409                 if (nb_tx_q == 0 && flags & RTE_PDUMP_FLAG_TX) {
410                         RTE_LOG(ERR, PDUMP,
411                                 "number of tx queues cannot be 0\n");
412                         return -EINVAL;
413                 }
414                 if ((nb_tx_q == 0 || nb_rx_q == 0) &&
415                         flags == RTE_PDUMP_FLAG_RXTX) {
416                         RTE_LOG(ERR, PDUMP,
417                                 "both tx&rx queues must be non zero\n");
418                         return -EINVAL;
419                 }
420         }
421
422         /* register RX callback */
423         if (flags & RTE_PDUMP_FLAG_RX) {
424                 end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_rx_q : queue + 1;
425                 ret = pdump_regitser_rx_callbacks(end_q, port, queue, ring, mp,
426                                                         operation);
427                 if (ret < 0)
428                         return ret;
429         }
430
431         /* register TX callback */
432         if (flags & RTE_PDUMP_FLAG_TX) {
433                 end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_tx_q : queue + 1;
434                 ret = pdump_regitser_tx_callbacks(end_q, port, queue, ring, mp,
435                                                         operation);
436                 if (ret < 0)
437                         return ret;
438         }
439
440         return ret;
441 }
442
443 /* get socket path (/var/run if root, $HOME otherwise) */
444 static void
445 pdump_get_socket_path(char *buffer, int bufsz, enum rte_pdump_socktype type)
446 {
447         const char *dir = NULL;
448
449         if (type == RTE_PDUMP_SOCKET_SERVER && server_socket_dir[0] != 0)
450                 dir = server_socket_dir;
451         else if (type == RTE_PDUMP_SOCKET_CLIENT && client_socket_dir[0] != 0)
452                 dir = client_socket_dir;
453         else {
454                 if (getuid() != 0)
455                         dir = getenv(SOCKET_PATH_HOME);
456                 else
457                         dir = SOCKET_PATH_VAR_RUN;
458         }
459
460         mkdir(dir, 700);
461         if (type == RTE_PDUMP_SOCKET_SERVER)
462                 snprintf(buffer, bufsz, SERVER_SOCKET, dir);
463         else
464                 snprintf(buffer, bufsz, CLIENT_SOCKET, dir, getpid(),
465                                 rte_sys_gettid());
466 }
467
468 static int
469 pdump_create_server_socket(void)
470 {
471         int ret, socket_fd;
472         struct sockaddr_un addr;
473         socklen_t addr_len;
474
475         pdump_get_socket_path(addr.sun_path, sizeof(addr.sun_path),
476                                 RTE_PDUMP_SOCKET_SERVER);
477         addr.sun_family = AF_UNIX;
478
479         /* remove if file already exists */
480         unlink(addr.sun_path);
481
482         /* set up a server socket */
483         socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
484         if (socket_fd < 0) {
485                 RTE_LOG(ERR, PDUMP,
486                         "Failed to create server socket: %s, %s:%d\n",
487                         strerror(errno), __func__, __LINE__);
488                 return -1;
489         }
490
491         addr_len = sizeof(struct sockaddr_un);
492         ret = bind(socket_fd, (struct sockaddr *) &addr, addr_len);
493         if (ret) {
494                 RTE_LOG(ERR, PDUMP,
495                         "Failed to bind to server socket: %s, %s:%d\n",
496                         strerror(errno), __func__, __LINE__);
497                 close(socket_fd);
498                 return -1;
499         }
500
501         /* save the socket in local configuration */
502         pdump_socket_fd = socket_fd;
503
504         return 0;
505 }
506
507 static __attribute__((noreturn)) void *
508 pdump_thread_main(__rte_unused void *arg)
509 {
510         struct sockaddr_un cli_addr;
511         socklen_t cli_len;
512         struct pdump_request cli_req;
513         struct pdump_response resp;
514         int n;
515         int ret = 0;
516
517         /* host thread, never break out */
518         for (;;) {
519                 /* recv client requests */
520                 cli_len = sizeof(cli_addr);
521                 n = recvfrom(pdump_socket_fd, &cli_req,
522                                 sizeof(struct pdump_request), 0,
523                                 (struct sockaddr *)&cli_addr, &cli_len);
524                 if (n < 0) {
525                         RTE_LOG(ERR, PDUMP,
526                                 "failed to recv from client:%s, %s:%d\n",
527                                 strerror(errno), __func__, __LINE__);
528                         continue;
529                 }
530
531                 ret = set_pdump_rxtx_cbs(&cli_req);
532
533                 resp.ver = cli_req.ver;
534                 resp.res_op = cli_req.op;
535                 resp.err_value = ret;
536                 n = sendto(pdump_socket_fd, &resp,
537                                 sizeof(struct pdump_response),
538                                 0, (struct sockaddr *)&cli_addr, cli_len);
539                 if (n < 0) {
540                         RTE_LOG(ERR, PDUMP,
541                                 "failed to send to client:%s, %s:%d\n",
542                                 strerror(errno), __func__, __LINE__);
543                 }
544         }
545 }
546
547 int
548 rte_pdump_init(const char *path)
549 {
550         int ret = 0;
551         char thread_name[RTE_MAX_THREAD_NAME_LEN];
552
553         ret = rte_pdump_set_socket_dir(path, RTE_PDUMP_SOCKET_SERVER);
554         if (ret != 0)
555                 return -1;
556
557         ret = pdump_create_server_socket();
558         if (ret != 0) {
559                 RTE_LOG(ERR, PDUMP,
560                         "Failed to create server socket:%s:%d\n",
561                         __func__, __LINE__);
562                 return -1;
563         }
564
565         /* create the host thread to wait/handle pdump requests */
566         ret = pthread_create(&pdump_thread, NULL, pdump_thread_main, NULL);
567         if (ret != 0) {
568                 RTE_LOG(ERR, PDUMP,
569                         "Failed to create the pdump thread:%s, %s:%d\n",
570                         strerror(errno), __func__, __LINE__);
571                 return -1;
572         }
573         /* Set thread_name for aid in debugging. */
574         snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "pdump-thread");
575         ret = rte_thread_setname(pdump_thread, thread_name);
576         if (ret != 0) {
577                 RTE_LOG(DEBUG, PDUMP,
578                         "Failed to set thread name for pdump handling\n");
579         }
580
581         return 0;
582 }
583
584 int
585 rte_pdump_uninit(void)
586 {
587         int ret;
588
589         ret = pthread_cancel(pdump_thread);
590         if (ret != 0) {
591                 RTE_LOG(ERR, PDUMP,
592                         "Failed to cancel the pdump thread:%s, %s:%d\n",
593                         strerror(errno), __func__, __LINE__);
594                 return -1;
595         }
596
597         ret = close(pdump_socket_fd);
598         if (ret != 0) {
599                 RTE_LOG(ERR, PDUMP,
600                         "Failed to close server socket: %s, %s:%d\n",
601                         strerror(errno), __func__, __LINE__);
602                 return -1;
603         }
604
605         struct sockaddr_un addr;
606
607         pdump_get_socket_path(addr.sun_path, sizeof(addr.sun_path),
608                                 RTE_PDUMP_SOCKET_SERVER);
609         ret = unlink(addr.sun_path);
610         if (ret != 0) {
611                 RTE_LOG(ERR, PDUMP,
612                         "Failed to remove server socket addr: %s, %s:%d\n",
613                         strerror(errno), __func__, __LINE__);
614                 return -1;
615         }
616
617         return 0;
618 }
619
620 static int
621 pdump_create_client_socket(struct pdump_request *p)
622 {
623         int ret, socket_fd;
624         int pid;
625         int n;
626         struct pdump_response server_resp;
627         struct sockaddr_un addr, serv_addr, from;
628         socklen_t addr_len, serv_len;
629
630         pid = getpid();
631
632         socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
633         if (socket_fd < 0) {
634                 RTE_LOG(ERR, PDUMP,
635                         "client socket(): %s:pid(%d):tid(%u), %s:%d\n",
636                         strerror(errno), pid, rte_sys_gettid(),
637                         __func__, __LINE__);
638                 ret = errno;
639                 return ret;
640         }
641
642         pdump_get_socket_path(addr.sun_path, sizeof(addr.sun_path),
643                                 RTE_PDUMP_SOCKET_CLIENT);
644         addr.sun_family = AF_UNIX;
645         addr_len = sizeof(struct sockaddr_un);
646
647         do {
648                 ret = bind(socket_fd, (struct sockaddr *) &addr, addr_len);
649                 if (ret) {
650                         RTE_LOG(ERR, PDUMP,
651                                 "client bind(): %s, %s:%d\n",
652                                 strerror(errno), __func__, __LINE__);
653                         ret = errno;
654                         break;
655                 }
656
657                 serv_len = sizeof(struct sockaddr_un);
658                 memset(&serv_addr, 0, sizeof(serv_addr));
659                 pdump_get_socket_path(serv_addr.sun_path,
660                                         sizeof(serv_addr.sun_path),
661                                         RTE_PDUMP_SOCKET_SERVER);
662                 serv_addr.sun_family = AF_UNIX;
663
664                 n =  sendto(socket_fd, p, sizeof(struct pdump_request), 0,
665                                 (struct sockaddr *)&serv_addr, serv_len);
666                 if (n < 0) {
667                         RTE_LOG(ERR, PDUMP,
668                                 "failed to send to server:%s, %s:%d\n",
669                                 strerror(errno), __func__, __LINE__);
670                         ret =  errno;
671                         break;
672                 }
673
674                 n = recvfrom(socket_fd, &server_resp,
675                                 sizeof(struct pdump_response), 0,
676                                 (struct sockaddr *)&from, &serv_len);
677                 if (n < 0) {
678                         RTE_LOG(ERR, PDUMP,
679                                 "failed to recv from server:%s, %s:%d\n",
680                                 strerror(errno), __func__, __LINE__);
681                         ret = errno;
682                         break;
683                 }
684                 ret = server_resp.err_value;
685         } while (0);
686
687         close(socket_fd);
688         unlink(addr.sun_path);
689         return ret;
690 }
691
692 static int
693 pdump_validate_ring_mp(struct rte_ring *ring, struct rte_mempool *mp)
694 {
695         if (ring == NULL || mp == NULL) {
696                 RTE_LOG(ERR, PDUMP, "NULL ring or mempool are passed %s:%d\n",
697                         __func__, __LINE__);
698                 rte_errno = EINVAL;
699                 return -1;
700         }
701         if (mp->flags & MEMPOOL_F_SP_PUT || mp->flags & MEMPOOL_F_SC_GET) {
702                 RTE_LOG(ERR, PDUMP, "mempool with either SP or SC settings"
703                 " is not valid for pdump, should have MP and MC settings\n");
704                 rte_errno = EINVAL;
705                 return -1;
706         }
707         if (ring->prod.sp_enqueue || ring->cons.sc_dequeue) {
708                 RTE_LOG(ERR, PDUMP, "ring with either SP or SC settings"
709                 " is not valid for pdump, should have MP and MC settings\n");
710                 rte_errno = EINVAL;
711                 return -1;
712         }
713
714         return 0;
715 }
716
717 static int
718 pdump_validate_flags(uint32_t flags)
719 {
720         if (flags != RTE_PDUMP_FLAG_RX && flags != RTE_PDUMP_FLAG_TX &&
721                 flags != RTE_PDUMP_FLAG_RXTX) {
722                 RTE_LOG(ERR, PDUMP,
723                         "invalid flags, should be either rx/tx/rxtx\n");
724                 rte_errno = EINVAL;
725                 return -1;
726         }
727
728         return 0;
729 }
730
731 static int
732 pdump_validate_port(uint8_t port, char *name)
733 {
734         int ret = 0;
735
736         if (port >= RTE_MAX_ETHPORTS) {
737                 RTE_LOG(ERR, PDUMP, "Invalid port id %u, %s:%d\n", port,
738                         __func__, __LINE__);
739                 rte_errno = EINVAL;
740                 return -1;
741         }
742
743         ret = rte_eth_dev_get_name_by_port(port, name);
744         if (ret < 0) {
745                 RTE_LOG(ERR, PDUMP,
746                         "port id to name mapping failed for port id=%u, %s:%d\n",
747                         port, __func__, __LINE__);
748                 rte_errno = EINVAL;
749                 return -1;
750         }
751
752         return 0;
753 }
754
755 static int
756 pdump_prepare_client_request(char *device, uint16_t queue,
757                                 uint32_t flags,
758                                 uint16_t operation,
759                                 struct rte_ring *ring,
760                                 struct rte_mempool *mp,
761                                 void *filter)
762 {
763         int ret;
764         struct pdump_request req = {.ver = 1,};
765
766         req.flags = flags;
767         req.op =  operation;
768         if ((operation & ENABLE) != 0) {
769                 strncpy(req.data.en_v1.device, device, strlen(device));
770                 req.data.en_v1.queue = queue;
771                 req.data.en_v1.ring = ring;
772                 req.data.en_v1.mp = mp;
773                 req.data.en_v1.filter = filter;
774         } else {
775                 strncpy(req.data.dis_v1.device, device, strlen(device));
776                 req.data.dis_v1.queue = queue;
777                 req.data.dis_v1.ring = NULL;
778                 req.data.dis_v1.mp = NULL;
779                 req.data.dis_v1.filter = NULL;
780         }
781
782         ret = pdump_create_client_socket(&req);
783         if (ret < 0) {
784                 RTE_LOG(ERR, PDUMP,
785                         "client request for pdump enable/disable failed\n");
786                 rte_errno = ret;
787                 return -1;
788         }
789
790         return 0;
791 }
792
793 int
794 rte_pdump_enable(uint8_t port, uint16_t queue, uint32_t flags,
795                         struct rte_ring *ring,
796                         struct rte_mempool *mp,
797                         void *filter)
798 {
799
800         int ret = 0;
801         char name[DEVICE_ID_SIZE];
802
803         ret = pdump_validate_port(port, name);
804         if (ret < 0)
805                 return ret;
806         ret = pdump_validate_ring_mp(ring, mp);
807         if (ret < 0)
808                 return ret;
809         ret = pdump_validate_flags(flags);
810         if (ret < 0)
811                 return ret;
812
813         ret = pdump_prepare_client_request(name, queue, flags,
814                                                 ENABLE, ring, mp, filter);
815
816         return ret;
817 }
818
819 int
820 rte_pdump_enable_by_deviceid(char *device_id, uint16_t queue,
821                                 uint32_t flags,
822                                 struct rte_ring *ring,
823                                 struct rte_mempool *mp,
824                                 void *filter)
825 {
826         int ret = 0;
827         char domBDF[DEVICE_ID_SIZE];
828
829         ret = pdump_validate_ring_mp(ring, mp);
830         if (ret < 0)
831                 return ret;
832         ret = pdump_validate_flags(flags);
833         if (ret < 0)
834                 return ret;
835
836         if (pdump_get_dombdf(device_id, domBDF, sizeof(domBDF)) > 0)
837                 ret = pdump_prepare_client_request(domBDF, queue, flags,
838                                                 ENABLE, ring, mp, filter);
839         else
840                 ret = pdump_prepare_client_request(device_id, queue, flags,
841                                                 ENABLE, ring, mp, filter);
842
843         return ret;
844 }
845
846 int
847 rte_pdump_disable(uint8_t port, uint16_t queue, uint32_t flags)
848 {
849         int ret = 0;
850         char name[DEVICE_ID_SIZE];
851
852         ret = pdump_validate_port(port, name);
853         if (ret < 0)
854                 return ret;
855         ret = pdump_validate_flags(flags);
856         if (ret < 0)
857                 return ret;
858
859         ret = pdump_prepare_client_request(name, queue, flags,
860                                                 DISABLE, NULL, NULL, NULL);
861
862         return ret;
863 }
864
865 int
866 rte_pdump_disable_by_deviceid(char *device_id, uint16_t queue,
867                                 uint32_t flags)
868 {
869         int ret = 0;
870         char domBDF[DEVICE_ID_SIZE];
871
872         ret = pdump_validate_flags(flags);
873         if (ret < 0)
874                 return ret;
875
876         if (pdump_get_dombdf(device_id, domBDF, sizeof(domBDF)) > 0)
877                 ret = pdump_prepare_client_request(domBDF, queue, flags,
878                                                 DISABLE, NULL, NULL, NULL);
879         else
880                 ret = pdump_prepare_client_request(device_id, queue, flags,
881                                                 DISABLE, NULL, NULL, NULL);
882
883         return ret;
884 }
885
886 int
887 rte_pdump_set_socket_dir(const char *path, enum rte_pdump_socktype type)
888 {
889         int ret, count;
890
891         if (path != NULL) {
892                 if (type == RTE_PDUMP_SOCKET_SERVER) {
893                         count = sizeof(server_socket_dir);
894                         ret = snprintf(server_socket_dir, count, "%s", path);
895                 } else {
896                         count = sizeof(client_socket_dir);
897                         ret = snprintf(client_socket_dir, count, "%s", path);
898                 }
899
900                 if (ret < 0  || ret >= count) {
901                         RTE_LOG(ERR, PDUMP,
902                                         "Invalid socket path:%s:%d\n",
903                                         __func__, __LINE__);
904                         if (type == RTE_PDUMP_SOCKET_SERVER)
905                                 server_socket_dir[0] = 0;
906                         else
907                                 client_socket_dir[0] = 0;
908                         return -EINVAL;
909                 }
910         }
911
912         return 0;
913 }