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