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