New upstream version 16.11.5
[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                         if (seg != m_dup)
158                                 rte_pktmbuf_free_seg(seg);
159                         rte_pktmbuf_free(m_dup);
160                         return NULL;
161                 }
162                 *prev = seg;
163                 prev = &seg->next;
164         } while ((m = m->next) != NULL &&
165                         (seg = rte_pktmbuf_alloc(mp)) != NULL);
166
167         *prev = NULL;
168         m_dup->nb_segs = nseg;
169         m_dup->pkt_len = pktlen;
170
171         /* Allocation of new indirect segment failed */
172         if (unlikely(seg == NULL)) {
173                 rte_pktmbuf_free(m_dup);
174                 return NULL;
175         }
176
177         __rte_mbuf_sanity_check(m_dup, 1);
178         return m_dup;
179 }
180
181 static inline void
182 pdump_copy(struct rte_mbuf **pkts, uint16_t nb_pkts, void *user_params)
183 {
184         unsigned i;
185         int ring_enq;
186         uint16_t d_pkts = 0;
187         struct rte_mbuf *dup_bufs[nb_pkts];
188         struct pdump_rxtx_cbs *cbs;
189         struct rte_ring *ring;
190         struct rte_mempool *mp;
191         struct rte_mbuf *p;
192
193         cbs  = user_params;
194         ring = cbs->ring;
195         mp = cbs->mp;
196         for (i = 0; i < nb_pkts; i++) {
197                 p = pdump_pktmbuf_copy(pkts[i], mp);
198                 if (p)
199                         dup_bufs[d_pkts++] = p;
200         }
201
202         ring_enq = rte_ring_enqueue_burst(ring, (void *)dup_bufs, d_pkts);
203         if (unlikely(ring_enq < d_pkts)) {
204                 RTE_LOG(DEBUG, PDUMP,
205                         "only %d of packets enqueued to ring\n", ring_enq);
206                 do {
207                         rte_pktmbuf_free(dup_bufs[ring_enq]);
208                 } while (++ring_enq < d_pkts);
209         }
210 }
211
212 static uint16_t
213 pdump_rx(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
214         struct rte_mbuf **pkts, uint16_t nb_pkts,
215         uint16_t max_pkts __rte_unused,
216         void *user_params)
217 {
218         pdump_copy(pkts, nb_pkts, user_params);
219         return nb_pkts;
220 }
221
222 static uint16_t
223 pdump_tx(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
224                 struct rte_mbuf **pkts, uint16_t nb_pkts, void *user_params)
225 {
226         pdump_copy(pkts, nb_pkts, user_params);
227         return nb_pkts;
228 }
229
230 static int
231 pdump_regitser_rx_callbacks(uint16_t end_q, uint8_t port, uint16_t queue,
232                                 struct rte_ring *ring, struct rte_mempool *mp,
233                                 uint16_t operation)
234 {
235         uint16_t qid;
236         struct pdump_rxtx_cbs *cbs = NULL;
237
238         qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue;
239         for (; qid < end_q; qid++) {
240                 cbs = &rx_cbs[port][qid];
241                 if (cbs && operation == ENABLE) {
242                         if (cbs->cb) {
243                                 RTE_LOG(ERR, PDUMP,
244                                         "failed to add rx callback for port=%d "
245                                         "and queue=%d, callback already exists\n",
246                                         port, qid);
247                                 return -EEXIST;
248                         }
249                         cbs->ring = ring;
250                         cbs->mp = mp;
251                         cbs->cb = rte_eth_add_first_rx_callback(port, qid,
252                                                                 pdump_rx, cbs);
253                         if (cbs->cb == NULL) {
254                                 RTE_LOG(ERR, PDUMP,
255                                         "failed to add rx callback, errno=%d\n",
256                                         rte_errno);
257                                 return rte_errno;
258                         }
259                 }
260                 if (cbs && operation == DISABLE) {
261                         int ret;
262
263                         if (cbs->cb == NULL) {
264                                 RTE_LOG(ERR, PDUMP,
265                                         "failed to delete non existing rx "
266                                         "callback for port=%d and queue=%d\n",
267                                         port, qid);
268                                 return -EINVAL;
269                         }
270                         ret = rte_eth_remove_rx_callback(port, qid, cbs->cb);
271                         if (ret < 0) {
272                                 RTE_LOG(ERR, PDUMP,
273                                         "failed to remove rx callback, errno=%d\n",
274                                         -ret);
275                                 return ret;
276                         }
277                         cbs->cb = NULL;
278                 }
279         }
280
281         return 0;
282 }
283
284 static int
285 pdump_regitser_tx_callbacks(uint16_t end_q, uint8_t port, uint16_t queue,
286                                 struct rte_ring *ring, struct rte_mempool *mp,
287                                 uint16_t operation)
288 {
289
290         uint16_t qid;
291         struct pdump_rxtx_cbs *cbs = NULL;
292
293         qid = (queue == RTE_PDUMP_ALL_QUEUES) ? 0 : queue;
294         for (; qid < end_q; qid++) {
295                 cbs = &tx_cbs[port][qid];
296                 if (cbs && operation == ENABLE) {
297                         if (cbs->cb) {
298                                 RTE_LOG(ERR, PDUMP,
299                                         "failed to add tx callback for port=%d "
300                                         "and queue=%d, callback already exists\n",
301                                         port, qid);
302                                 return -EEXIST;
303                         }
304                         cbs->ring = ring;
305                         cbs->mp = mp;
306                         cbs->cb = rte_eth_add_tx_callback(port, qid, pdump_tx,
307                                                                 cbs);
308                         if (cbs->cb == NULL) {
309                                 RTE_LOG(ERR, PDUMP,
310                                         "failed to add tx callback, errno=%d\n",
311                                         rte_errno);
312                                 return rte_errno;
313                         }
314                 }
315                 if (cbs && operation == DISABLE) {
316                         int ret;
317
318                         if (cbs->cb == NULL) {
319                                 RTE_LOG(ERR, PDUMP,
320                                         "failed to delete non existing tx "
321                                         "callback for port=%d and queue=%d\n",
322                                         port, qid);
323                                 return -EINVAL;
324                         }
325                         ret = rte_eth_remove_tx_callback(port, qid, cbs->cb);
326                         if (ret < 0) {
327                                 RTE_LOG(ERR, PDUMP,
328                                         "failed to remove tx callback, errno=%d\n",
329                                         -ret);
330                                 return ret;
331                         }
332                         cbs->cb = NULL;
333                 }
334         }
335
336         return 0;
337 }
338
339 static int
340 set_pdump_rxtx_cbs(struct pdump_request *p)
341 {
342         uint16_t nb_rx_q, nb_tx_q = 0, end_q, queue;
343         uint8_t port;
344         int ret = 0;
345         uint32_t flags;
346         uint16_t operation;
347         struct rte_ring *ring;
348         struct rte_mempool *mp;
349
350         flags = p->flags;
351         operation = p->op;
352         if (operation == ENABLE) {
353                 ret = rte_eth_dev_get_port_by_name(p->data.en_v1.device,
354                                 &port);
355                 if (ret < 0) {
356                         RTE_LOG(ERR, PDUMP,
357                                 "failed to get potid for device id=%s\n",
358                                 p->data.en_v1.device);
359                         return -EINVAL;
360                 }
361                 queue = p->data.en_v1.queue;
362                 ring = p->data.en_v1.ring;
363                 mp = p->data.en_v1.mp;
364         } else {
365                 ret = rte_eth_dev_get_port_by_name(p->data.dis_v1.device,
366                                 &port);
367                 if (ret < 0) {
368                         RTE_LOG(ERR, PDUMP,
369                                 "failed to get potid for device id=%s\n",
370                                 p->data.dis_v1.device);
371                         return -EINVAL;
372                 }
373                 queue = p->data.dis_v1.queue;
374                 ring = p->data.dis_v1.ring;
375                 mp = p->data.dis_v1.mp;
376         }
377
378         /* validation if packet capture is for all queues */
379         if (queue == RTE_PDUMP_ALL_QUEUES) {
380                 struct rte_eth_dev_info dev_info;
381
382                 rte_eth_dev_info_get(port, &dev_info);
383                 nb_rx_q = dev_info.nb_rx_queues;
384                 nb_tx_q = dev_info.nb_tx_queues;
385                 if (nb_rx_q == 0 && flags & RTE_PDUMP_FLAG_RX) {
386                         RTE_LOG(ERR, PDUMP,
387                                 "number of rx queues cannot be 0\n");
388                         return -EINVAL;
389                 }
390                 if (nb_tx_q == 0 && flags & RTE_PDUMP_FLAG_TX) {
391                         RTE_LOG(ERR, PDUMP,
392                                 "number of tx queues cannot be 0\n");
393                         return -EINVAL;
394                 }
395                 if ((nb_tx_q == 0 || nb_rx_q == 0) &&
396                         flags == RTE_PDUMP_FLAG_RXTX) {
397                         RTE_LOG(ERR, PDUMP,
398                                 "both tx&rx queues must be non zero\n");
399                         return -EINVAL;
400                 }
401         }
402
403         /* register RX callback */
404         if (flags & RTE_PDUMP_FLAG_RX) {
405                 end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_rx_q : queue + 1;
406                 ret = pdump_regitser_rx_callbacks(end_q, port, queue, ring, mp,
407                                                         operation);
408                 if (ret < 0)
409                         return ret;
410         }
411
412         /* register TX callback */
413         if (flags & RTE_PDUMP_FLAG_TX) {
414                 end_q = (queue == RTE_PDUMP_ALL_QUEUES) ? nb_tx_q : queue + 1;
415                 ret = pdump_regitser_tx_callbacks(end_q, port, queue, ring, mp,
416                                                         operation);
417                 if (ret < 0)
418                         return ret;
419         }
420
421         return ret;
422 }
423
424 /* get socket path (/var/run if root, $HOME otherwise) */
425 static int
426 pdump_get_socket_path(char *buffer, int bufsz, enum rte_pdump_socktype type)
427 {
428         char dpdk_dir[PATH_MAX] = {0};
429         char dir[PATH_MAX] = {0};
430         char *dir_home = NULL;
431         int ret = 0;
432
433         if (type == RTE_PDUMP_SOCKET_SERVER && server_socket_dir[0] != 0)
434                 snprintf(dir, sizeof(dir), "%s", server_socket_dir);
435         else if (type == RTE_PDUMP_SOCKET_CLIENT && client_socket_dir[0] != 0)
436                 snprintf(dir, sizeof(dir), "%s", client_socket_dir);
437         else {
438                 if (getuid() != 0) {
439                         dir_home = getenv(SOCKET_PATH_HOME);
440                         if (!dir_home) {
441                                 RTE_LOG(ERR, PDUMP,
442                                         "Failed to get environment variable"
443                                         " value for %s, %s:%d\n",
444                                         SOCKET_PATH_HOME, __func__, __LINE__);
445                                 return -1;
446                         }
447                         snprintf(dpdk_dir, sizeof(dpdk_dir), "%s%s",
448                                         dir_home, DPDK_DIR);
449                 } else
450                         snprintf(dpdk_dir, sizeof(dpdk_dir), "%s%s",
451                                         SOCKET_PATH_VAR_RUN, DPDK_DIR);
452
453                 mkdir(dpdk_dir, 0700);
454                 snprintf(dir, sizeof(dir), "%s%s",
455                                         dpdk_dir, SOCKET_DIR);
456         }
457
458         ret =  mkdir(dir, 0700);
459         /* if user passed socket path is invalid, return immediately */
460         if (ret < 0 && errno != EEXIST) {
461                 RTE_LOG(ERR, PDUMP,
462                         "Failed to create dir:%s:%s\n", dir,
463                         strerror(errno));
464                 rte_errno = errno;
465                 return -1;
466         }
467
468         if (type == RTE_PDUMP_SOCKET_SERVER)
469                 snprintf(buffer, bufsz, SERVER_SOCKET, dir);
470         else
471                 snprintf(buffer, bufsz, CLIENT_SOCKET, dir, getpid(),
472                                 rte_sys_gettid());
473
474         return 0;
475 }
476
477 static int
478 pdump_create_server_socket(void)
479 {
480         int ret, socket_fd;
481         struct sockaddr_un addr;
482         socklen_t addr_len;
483
484         ret = pdump_get_socket_path(addr.sun_path, sizeof(addr.sun_path),
485                                 RTE_PDUMP_SOCKET_SERVER);
486         if (ret != 0) {
487                 RTE_LOG(ERR, PDUMP,
488                         "Failed to get server socket path: %s:%d\n",
489                         __func__, __LINE__);
490                 return -1;
491         }
492         addr.sun_family = AF_UNIX;
493
494         /* remove if file already exists */
495         unlink(addr.sun_path);
496
497         /* set up a server socket */
498         socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
499         if (socket_fd < 0) {
500                 RTE_LOG(ERR, PDUMP,
501                         "Failed to create server socket: %s, %s:%d\n",
502                         strerror(errno), __func__, __LINE__);
503                 return -1;
504         }
505
506         addr_len = sizeof(struct sockaddr_un);
507         ret = bind(socket_fd, (struct sockaddr *) &addr, addr_len);
508         if (ret) {
509                 RTE_LOG(ERR, PDUMP,
510                         "Failed to bind to server socket: %s, %s:%d\n",
511                         strerror(errno), __func__, __LINE__);
512                 close(socket_fd);
513                 return -1;
514         }
515
516         /* save the socket in local configuration */
517         pdump_socket_fd = socket_fd;
518
519         return 0;
520 }
521
522 static __attribute__((noreturn)) void *
523 pdump_thread_main(__rte_unused void *arg)
524 {
525         struct sockaddr_un cli_addr;
526         socklen_t cli_len;
527         struct pdump_request cli_req;
528         struct pdump_response resp;
529         int n;
530         int ret = 0;
531
532         /* host thread, never break out */
533         for (;;) {
534                 /* recv client requests */
535                 cli_len = sizeof(cli_addr);
536                 n = recvfrom(pdump_socket_fd, &cli_req,
537                                 sizeof(struct pdump_request), 0,
538                                 (struct sockaddr *)&cli_addr, &cli_len);
539                 if (n < 0) {
540                         RTE_LOG(ERR, PDUMP,
541                                 "failed to recv from client:%s, %s:%d\n",
542                                 strerror(errno), __func__, __LINE__);
543                         continue;
544                 }
545
546                 ret = set_pdump_rxtx_cbs(&cli_req);
547
548                 resp.ver = cli_req.ver;
549                 resp.res_op = cli_req.op;
550                 resp.err_value = ret;
551                 n = sendto(pdump_socket_fd, &resp,
552                                 sizeof(struct pdump_response),
553                                 0, (struct sockaddr *)&cli_addr, cli_len);
554                 if (n < 0) {
555                         RTE_LOG(ERR, PDUMP,
556                                 "failed to send to client:%s, %s:%d\n",
557                                 strerror(errno), __func__, __LINE__);
558                 }
559         }
560 }
561
562 int
563 rte_pdump_init(const char *path)
564 {
565         int ret = 0;
566         char thread_name[RTE_MAX_THREAD_NAME_LEN];
567
568         ret = rte_pdump_set_socket_dir(path, RTE_PDUMP_SOCKET_SERVER);
569         if (ret != 0)
570                 return -1;
571
572         ret = pdump_create_server_socket();
573         if (ret != 0) {
574                 RTE_LOG(ERR, PDUMP,
575                         "Failed to create server socket:%s:%d\n",
576                         __func__, __LINE__);
577                 return -1;
578         }
579
580         /* create the host thread to wait/handle pdump requests */
581         ret = pthread_create(&pdump_thread, NULL, 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.sp_enqueue || ring->cons.sc_dequeue) {
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(uint8_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(uint8_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(uint8_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 }