eal: new function to create control threads
[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 = rte_ctrl_thread_create(&pdump_thread, NULL,
581                                 pdump_thread_main, NULL);
582         if (ret != 0) {
583                 RTE_LOG(ERR, PDUMP,
584                         "Failed to create the pdump thread:%s, %s:%d\n",
585                         strerror(-ret), __func__, __LINE__);
586                 return -1;
587         }
588         /* Set thread_name for aid in debugging. */
589         snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "pdump-thread");
590         ret = rte_thread_setname(pdump_thread, thread_name);
591         if (ret != 0) {
592                 RTE_LOG(DEBUG, PDUMP,
593                         "Failed to set thread name for pdump handling\n");
594         }
595
596         return 0;
597 }
598
599 int
600 rte_pdump_uninit(void)
601 {
602         int ret;
603
604         ret = pthread_cancel(pdump_thread);
605         if (ret != 0) {
606                 RTE_LOG(ERR, PDUMP,
607                         "Failed to cancel the pdump thread:%s, %s:%d\n",
608                         strerror(ret), __func__, __LINE__);
609                 return -1;
610         }
611
612         ret = close(pdump_socket_fd);
613         if (ret != 0) {
614                 RTE_LOG(ERR, PDUMP,
615                         "Failed to close server socket: %s, %s:%d\n",
616                         strerror(errno), __func__, __LINE__);
617                 return -1;
618         }
619
620         struct sockaddr_un addr;
621
622         ret = pdump_get_socket_path(addr.sun_path, sizeof(addr.sun_path),
623                                 RTE_PDUMP_SOCKET_SERVER);
624         if (ret != 0) {
625                 RTE_LOG(ERR, PDUMP,
626                         "Failed to get server socket path: %s:%d\n",
627                         __func__, __LINE__);
628                 return -1;
629         }
630         ret = unlink(addr.sun_path);
631         if (ret != 0) {
632                 RTE_LOG(ERR, PDUMP,
633                         "Failed to remove server socket addr: %s, %s:%d\n",
634                         strerror(errno), __func__, __LINE__);
635                 return -1;
636         }
637
638         return 0;
639 }
640
641 static int
642 pdump_create_client_socket(struct pdump_request *p)
643 {
644         int ret, socket_fd;
645         int pid;
646         int n;
647         struct pdump_response server_resp;
648         struct sockaddr_un addr, serv_addr, from;
649         socklen_t addr_len, serv_len;
650
651         pid = getpid();
652
653         socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
654         if (socket_fd < 0) {
655                 RTE_LOG(ERR, PDUMP,
656                         "client socket(): %s:pid(%d):tid(%u), %s:%d\n",
657                         strerror(errno), pid, rte_sys_gettid(),
658                         __func__, __LINE__);
659                 rte_errno = errno;
660                 return -1;
661         }
662
663         ret = pdump_get_socket_path(addr.sun_path, sizeof(addr.sun_path),
664                                 RTE_PDUMP_SOCKET_CLIENT);
665         if (ret != 0) {
666                 RTE_LOG(ERR, PDUMP,
667                         "Failed to get client socket path: %s:%d\n",
668                         __func__, __LINE__);
669                 rte_errno = errno;
670                 goto exit;
671         }
672         addr.sun_family = AF_UNIX;
673         addr_len = sizeof(struct sockaddr_un);
674
675         do {
676                 ret = bind(socket_fd, (struct sockaddr *) &addr, addr_len);
677                 if (ret) {
678                         RTE_LOG(ERR, PDUMP,
679                                 "client bind(): %s, %s:%d\n",
680                                 strerror(errno), __func__, __LINE__);
681                         rte_errno = errno;
682                         break;
683                 }
684
685                 serv_len = sizeof(struct sockaddr_un);
686                 memset(&serv_addr, 0, sizeof(serv_addr));
687                 ret = pdump_get_socket_path(serv_addr.sun_path,
688                                         sizeof(serv_addr.sun_path),
689                                         RTE_PDUMP_SOCKET_SERVER);
690                 if (ret != 0) {
691                         RTE_LOG(ERR, PDUMP,
692                                 "Failed to get server socket path: %s:%d\n",
693                                 __func__, __LINE__);
694                         rte_errno = errno;
695                         break;
696                 }
697                 serv_addr.sun_family = AF_UNIX;
698
699                 n =  sendto(socket_fd, p, sizeof(struct pdump_request), 0,
700                                 (struct sockaddr *)&serv_addr, serv_len);
701                 if (n < 0) {
702                         RTE_LOG(ERR, PDUMP,
703                                 "failed to send to server:%s, %s:%d\n",
704                                 strerror(errno), __func__, __LINE__);
705                         rte_errno = errno;
706                         ret = -1;
707                         break;
708                 }
709
710                 n = recvfrom(socket_fd, &server_resp,
711                                 sizeof(struct pdump_response), 0,
712                                 (struct sockaddr *)&from, &serv_len);
713                 if (n < 0) {
714                         RTE_LOG(ERR, PDUMP,
715                                 "failed to recv from server:%s, %s:%d\n",
716                                 strerror(errno), __func__, __LINE__);
717                         rte_errno = errno;
718                         ret = -1;
719                         break;
720                 }
721                 ret = server_resp.err_value;
722         } while (0);
723
724 exit:
725         close(socket_fd);
726         unlink(addr.sun_path);
727         return ret;
728 }
729
730 static int
731 pdump_validate_ring_mp(struct rte_ring *ring, struct rte_mempool *mp)
732 {
733         if (ring == NULL || mp == NULL) {
734                 RTE_LOG(ERR, PDUMP, "NULL ring or mempool are passed %s:%d\n",
735                         __func__, __LINE__);
736                 rte_errno = EINVAL;
737                 return -1;
738         }
739         if (mp->flags & MEMPOOL_F_SP_PUT || mp->flags & MEMPOOL_F_SC_GET) {
740                 RTE_LOG(ERR, PDUMP, "mempool with either SP or SC settings"
741                 " is not valid for pdump, should have MP and MC settings\n");
742                 rte_errno = EINVAL;
743                 return -1;
744         }
745         if (ring->prod.single || ring->cons.single) {
746                 RTE_LOG(ERR, PDUMP, "ring with either SP or SC settings"
747                 " is not valid for pdump, should have MP and MC settings\n");
748                 rte_errno = EINVAL;
749                 return -1;
750         }
751
752         return 0;
753 }
754
755 static int
756 pdump_validate_flags(uint32_t flags)
757 {
758         if (flags != RTE_PDUMP_FLAG_RX && flags != RTE_PDUMP_FLAG_TX &&
759                 flags != RTE_PDUMP_FLAG_RXTX) {
760                 RTE_LOG(ERR, PDUMP,
761                         "invalid flags, should be either rx/tx/rxtx\n");
762                 rte_errno = EINVAL;
763                 return -1;
764         }
765
766         return 0;
767 }
768
769 static int
770 pdump_validate_port(uint16_t port, char *name)
771 {
772         int ret = 0;
773
774         if (port >= RTE_MAX_ETHPORTS) {
775                 RTE_LOG(ERR, PDUMP, "Invalid port id %u, %s:%d\n", port,
776                         __func__, __LINE__);
777                 rte_errno = EINVAL;
778                 return -1;
779         }
780
781         ret = rte_eth_dev_get_name_by_port(port, name);
782         if (ret < 0) {
783                 RTE_LOG(ERR, PDUMP,
784                         "port id to name mapping failed for port id=%u, %s:%d\n",
785                         port, __func__, __LINE__);
786                 rte_errno = EINVAL;
787                 return -1;
788         }
789
790         return 0;
791 }
792
793 static int
794 pdump_prepare_client_request(char *device, uint16_t queue,
795                                 uint32_t flags,
796                                 uint16_t operation,
797                                 struct rte_ring *ring,
798                                 struct rte_mempool *mp,
799                                 void *filter)
800 {
801         int ret;
802         struct pdump_request req = {.ver = 1,};
803
804         req.flags = flags;
805         req.op =  operation;
806         if ((operation & ENABLE) != 0) {
807                 snprintf(req.data.en_v1.device, sizeof(req.data.en_v1.device),
808                                 "%s", device);
809                 req.data.en_v1.queue = queue;
810                 req.data.en_v1.ring = ring;
811                 req.data.en_v1.mp = mp;
812                 req.data.en_v1.filter = filter;
813         } else {
814                 snprintf(req.data.dis_v1.device, sizeof(req.data.dis_v1.device),
815                                 "%s", device);
816                 req.data.dis_v1.queue = queue;
817                 req.data.dis_v1.ring = NULL;
818                 req.data.dis_v1.mp = NULL;
819                 req.data.dis_v1.filter = NULL;
820         }
821
822         ret = pdump_create_client_socket(&req);
823         if (ret < 0) {
824                 RTE_LOG(ERR, PDUMP,
825                         "client request for pdump enable/disable failed\n");
826                 rte_errno = ret;
827                 return -1;
828         }
829
830         return 0;
831 }
832
833 int
834 rte_pdump_enable(uint16_t port, uint16_t queue, uint32_t flags,
835                         struct rte_ring *ring,
836                         struct rte_mempool *mp,
837                         void *filter)
838 {
839
840         int ret = 0;
841         char name[DEVICE_ID_SIZE];
842
843         ret = pdump_validate_port(port, name);
844         if (ret < 0)
845                 return ret;
846         ret = pdump_validate_ring_mp(ring, mp);
847         if (ret < 0)
848                 return ret;
849         ret = pdump_validate_flags(flags);
850         if (ret < 0)
851                 return ret;
852
853         ret = pdump_prepare_client_request(name, queue, flags,
854                                                 ENABLE, ring, mp, filter);
855
856         return ret;
857 }
858
859 int
860 rte_pdump_enable_by_deviceid(char *device_id, uint16_t queue,
861                                 uint32_t flags,
862                                 struct rte_ring *ring,
863                                 struct rte_mempool *mp,
864                                 void *filter)
865 {
866         int ret = 0;
867
868         ret = pdump_validate_ring_mp(ring, mp);
869         if (ret < 0)
870                 return ret;
871         ret = pdump_validate_flags(flags);
872         if (ret < 0)
873                 return ret;
874
875         ret = pdump_prepare_client_request(device_id, queue, flags,
876                                                 ENABLE, ring, mp, filter);
877
878         return ret;
879 }
880
881 int
882 rte_pdump_disable(uint16_t port, uint16_t queue, uint32_t flags)
883 {
884         int ret = 0;
885         char name[DEVICE_ID_SIZE];
886
887         ret = pdump_validate_port(port, name);
888         if (ret < 0)
889                 return ret;
890         ret = pdump_validate_flags(flags);
891         if (ret < 0)
892                 return ret;
893
894         ret = pdump_prepare_client_request(name, queue, flags,
895                                                 DISABLE, NULL, NULL, NULL);
896
897         return ret;
898 }
899
900 int
901 rte_pdump_disable_by_deviceid(char *device_id, uint16_t queue,
902                                 uint32_t flags)
903 {
904         int ret = 0;
905
906         ret = pdump_validate_flags(flags);
907         if (ret < 0)
908                 return ret;
909
910         ret = pdump_prepare_client_request(device_id, queue, flags,
911                                                 DISABLE, NULL, NULL, NULL);
912
913         return ret;
914 }
915
916 int
917 rte_pdump_set_socket_dir(const char *path, enum rte_pdump_socktype type)
918 {
919         int ret, count;
920
921         if (path != NULL) {
922                 if (type == RTE_PDUMP_SOCKET_SERVER) {
923                         count = sizeof(server_socket_dir);
924                         ret = snprintf(server_socket_dir, count, "%s", path);
925                 } else {
926                         count = sizeof(client_socket_dir);
927                         ret = snprintf(client_socket_dir, count, "%s", path);
928                 }
929
930                 if (ret < 0  || ret >= count) {
931                         RTE_LOG(ERR, PDUMP,
932                                         "Invalid socket path:%s:%d\n",
933                                         __func__, __LINE__);
934                         if (type == RTE_PDUMP_SOCKET_SERVER)
935                                 server_socket_dir[0] = 0;
936                         else
937                                 client_socket_dir[0] = 0;
938                         return -EINVAL;
939                 }
940         }
941
942         return 0;
943 }