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