ring: add link up/down
[dpdk.git] / lib / librte_pmd_ring / rte_eth_ring.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 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 "rte_eth_ring.h"
35 #include <rte_mbuf.h>
36 #include <rte_ethdev.h>
37 #include <rte_malloc.h>
38 #include <rte_memcpy.h>
39 #include <rte_string_fns.h>
40 #include <rte_dev.h>
41 #include <rte_kvargs.h>
42
43 #define ETH_RING_NUMA_NODE_ACTION_ARG   "nodeaction"
44 #define ETH_RING_ACTION_CREATE          "CREATE"
45 #define ETH_RING_ACTION_ATTACH          "ATTACH"
46
47 static const char *valid_arguments[] = {
48         ETH_RING_NUMA_NODE_ACTION_ARG,
49         NULL
50 };
51
52 struct ring_queue {
53         struct rte_ring *rng;
54         rte_atomic64_t rx_pkts;
55         rte_atomic64_t tx_pkts;
56         rte_atomic64_t err_pkts;
57 };
58
59 struct pmd_internals {
60         unsigned nb_rx_queues;
61         unsigned nb_tx_queues;
62
63         struct ring_queue rx_ring_queues[RTE_PMD_RING_MAX_RX_RINGS];
64         struct ring_queue tx_ring_queues[RTE_PMD_RING_MAX_TX_RINGS];
65 };
66
67
68 static struct ether_addr eth_addr = { .addr_bytes = {0} };
69 static const char *drivername = "Rings PMD";
70 static struct rte_eth_link pmd_link = {
71                 .link_speed = 10000,
72                 .link_duplex = ETH_LINK_FULL_DUPLEX,
73                 .link_status = 0
74 };
75
76 static uint16_t
77 eth_ring_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
78 {
79         void **ptrs = (void *)&bufs[0];
80         struct ring_queue *r = q;
81         const uint16_t nb_rx = (uint16_t)rte_ring_dequeue_burst(r->rng,
82                         ptrs, nb_bufs);
83         if (r->rng->flags & RING_F_SC_DEQ)
84                 r->rx_pkts.cnt += nb_rx;
85         else
86                 rte_atomic64_add(&(r->rx_pkts), nb_rx);
87         return nb_rx;
88 }
89
90 static uint16_t
91 eth_ring_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
92 {
93         void **ptrs = (void *)&bufs[0];
94         struct ring_queue *r = q;
95         const uint16_t nb_tx = (uint16_t)rte_ring_enqueue_burst(r->rng,
96                         ptrs, nb_bufs);
97         if (r->rng->flags & RING_F_SP_ENQ) {
98                 r->tx_pkts.cnt += nb_tx;
99                 r->err_pkts.cnt += nb_bufs - nb_tx;
100         } else {
101                 rte_atomic64_add(&(r->tx_pkts), nb_tx);
102                 rte_atomic64_add(&(r->err_pkts), nb_bufs - nb_tx);
103         }
104         return nb_tx;
105 }
106
107 static int
108 eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
109
110 static int
111 eth_dev_start(struct rte_eth_dev *dev)
112 {
113         dev->data->dev_link.link_status = 1;
114         return 0;
115 }
116
117 static void
118 eth_dev_stop(struct rte_eth_dev *dev)
119 {
120         dev->data->dev_link.link_status = 0;
121 }
122
123 static int
124 eth_dev_set_link_down(struct rte_eth_dev *dev)
125 {
126         dev->data->dev_link.link_status = 0;
127         return 0;
128 }
129
130 static int
131 eth_dev_set_link_up(struct rte_eth_dev *dev)
132 {
133         dev->data->dev_link.link_status = 1;
134         return 0;
135 }
136
137 static int
138 eth_rx_queue_setup(struct rte_eth_dev *dev,uint16_t rx_queue_id,
139                                     uint16_t nb_rx_desc __rte_unused,
140                                     unsigned int socket_id __rte_unused,
141                                     const struct rte_eth_rxconf *rx_conf __rte_unused,
142                                     struct rte_mempool *mb_pool __rte_unused)
143 {
144         struct pmd_internals *internals = dev->data->dev_private;
145         dev->data->rx_queues[rx_queue_id] = &internals->rx_ring_queues[rx_queue_id];
146         return 0;
147 }
148
149 static int
150 eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
151                                     uint16_t nb_tx_desc __rte_unused,
152                                     unsigned int socket_id __rte_unused,
153                                     const struct rte_eth_txconf *tx_conf __rte_unused)
154 {
155         struct pmd_internals *internals = dev->data->dev_private;
156         dev->data->tx_queues[tx_queue_id] = &internals->tx_ring_queues[tx_queue_id];
157         return 0;
158 }
159
160
161 static void
162 eth_dev_info(struct rte_eth_dev *dev,
163                 struct rte_eth_dev_info *dev_info)
164 {
165         struct pmd_internals *internals = dev->data->dev_private;
166         dev_info->driver_name = drivername;
167         dev_info->max_mac_addrs = 1;
168         dev_info->max_rx_pktlen = (uint32_t)-1;
169         dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
170         dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
171         dev_info->min_rx_bufsize = 0;
172         dev_info->pci_dev = NULL;
173 }
174
175 static void
176 eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
177 {
178         unsigned i;
179         unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
180         const struct pmd_internals *internal = dev->data->dev_private;
181
182         for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
183                         i < internal->nb_rx_queues; i++) {
184                 igb_stats->q_ipackets[i] = internal->rx_ring_queues[i].rx_pkts.cnt;
185                 rx_total += igb_stats->q_ipackets[i];
186         }
187
188         for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
189                         i < internal->nb_tx_queues; i++) {
190                 igb_stats->q_opackets[i] = internal->tx_ring_queues[i].tx_pkts.cnt;
191                 igb_stats->q_errors[i] = internal->tx_ring_queues[i].err_pkts.cnt;
192                 tx_total += igb_stats->q_opackets[i];
193                 tx_err_total += igb_stats->q_errors[i];
194         }
195
196         igb_stats->ipackets = rx_total;
197         igb_stats->opackets = tx_total;
198         igb_stats->oerrors = tx_err_total;
199 }
200
201 static void
202 eth_stats_reset(struct rte_eth_dev *dev)
203 {
204         unsigned i;
205         struct pmd_internals *internal = dev->data->dev_private;
206         for (i = 0; i < internal->nb_rx_queues; i++)
207                 internal->rx_ring_queues[i].rx_pkts.cnt = 0;
208         for (i = 0; i < internal->nb_tx_queues; i++) {
209                 internal->tx_ring_queues[i].tx_pkts.cnt = 0;
210                 internal->tx_ring_queues[i].err_pkts.cnt = 0;
211         }
212 }
213
214 static void
215 eth_queue_release(void *q __rte_unused) { ; }
216 static int
217 eth_link_update(struct rte_eth_dev *dev __rte_unused,
218                 int wait_to_complete __rte_unused) { return 0; }
219
220 static struct eth_dev_ops ops = {
221                 .dev_start = eth_dev_start,
222                 .dev_stop = eth_dev_stop,
223                 .dev_set_link_up = eth_dev_set_link_up,
224                 .dev_set_link_down = eth_dev_set_link_down,
225                 .dev_configure = eth_dev_configure,
226                 .dev_infos_get = eth_dev_info,
227                 .rx_queue_setup = eth_rx_queue_setup,
228                 .tx_queue_setup = eth_tx_queue_setup,
229                 .rx_queue_release = eth_queue_release,
230                 .tx_queue_release = eth_queue_release,
231                 .link_update = eth_link_update,
232                 .stats_get = eth_stats_get,
233                 .stats_reset = eth_stats_reset,
234 };
235
236 int
237 rte_eth_from_rings(const char *name, struct rte_ring *const rx_queues[],
238                 const unsigned nb_rx_queues,
239                 struct rte_ring *const tx_queues[],
240                 const unsigned nb_tx_queues,
241                 const unsigned numa_node)
242 {
243         struct rte_eth_dev_data *data = NULL;
244         struct rte_pci_device *pci_dev = NULL;
245         struct pmd_internals *internals = NULL;
246         struct rte_eth_dev *eth_dev = NULL;
247         unsigned i;
248
249         /* do some parameter checking */
250         if (rx_queues == NULL && nb_rx_queues > 0)
251                 goto error;
252         if (tx_queues == NULL && nb_tx_queues > 0)
253                 goto error;
254
255         RTE_LOG(INFO, PMD, "Creating rings-backed ethdev on numa socket %u\n",
256                         numa_node);
257
258         /* now do all data allocation - for eth_dev structure, dummy pci driver
259          * and internal (private) data
260          */
261         data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
262         if (data == NULL)
263                 goto error;
264
265         pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
266         if (pci_dev == NULL)
267                 goto error;
268
269         internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
270         if (internals == NULL)
271                 goto error;
272
273         /* reserve an ethdev entry */
274         eth_dev = rte_eth_dev_allocate(name);
275         if (eth_dev == NULL)
276                 goto error;
277
278         /* now put it all together
279          * - store queue data in internals,
280          * - store numa_node info in pci_driver
281          * - point eth_dev_data to internals and pci_driver
282          * - and point eth_dev structure to new eth_dev_data structure
283          */
284         /* NOTE: we'll replace the data element, of originally allocated eth_dev
285          * so the rings are local per-process */
286
287         internals->nb_rx_queues = nb_rx_queues;
288         internals->nb_tx_queues = nb_tx_queues;
289         for (i = 0; i < nb_rx_queues; i++) {
290                 internals->rx_ring_queues[i].rng = rx_queues[i];
291         }
292         for (i = 0; i < nb_tx_queues; i++) {
293                 internals->tx_ring_queues[i].rng = tx_queues[i];
294         }
295
296         pci_dev->numa_node = numa_node;
297
298         data->dev_private = internals;
299         data->port_id = eth_dev->data->port_id;
300         data->nb_rx_queues = (uint16_t)nb_rx_queues;
301         data->nb_tx_queues = (uint16_t)nb_tx_queues;
302         data->dev_link = pmd_link;
303         data->mac_addrs = &eth_addr;
304
305         eth_dev ->data = data;
306         eth_dev ->dev_ops = &ops;
307         eth_dev ->pci_dev = pci_dev;
308
309         /* finally assign rx and tx ops */
310         eth_dev->rx_pkt_burst = eth_ring_rx;
311         eth_dev->tx_pkt_burst = eth_ring_tx;
312
313         return 0;
314
315 error:
316         if (data)
317                 rte_free(data);
318         if (pci_dev)
319                 rte_free(pci_dev);
320         if (internals)
321                 rte_free(internals);
322         return -1;
323 }
324
325 enum dev_action{
326         DEV_CREATE,
327         DEV_ATTACH
328 };
329
330 static int
331 eth_dev_ring_create(const char *name, const unsigned numa_node,
332                 enum dev_action action)
333 {
334         /* rx and tx are so-called from point of view of first port.
335          * They are inverted from the point of view of second port
336          */
337         struct rte_ring *rxtx[RTE_PMD_RING_MAX_RX_RINGS];
338         unsigned i;
339         char rng_name[RTE_RING_NAMESIZE];
340         unsigned num_rings = RTE_MIN(RTE_PMD_RING_MAX_RX_RINGS,
341                         RTE_PMD_RING_MAX_TX_RINGS);
342
343         for (i = 0; i < num_rings; i++) {
344                 snprintf(rng_name, sizeof(rng_name), "ETH_RXTX%u_%s", i, name);
345                 rxtx[i] = (action == DEV_CREATE) ?
346                                 rte_ring_create(rng_name, 1024, numa_node,
347                                                 RING_F_SP_ENQ|RING_F_SC_DEQ) :
348                                 rte_ring_lookup(rng_name);
349                 if (rxtx[i] == NULL)
350                         return -1;
351         }
352
353         if (rte_eth_from_rings(name, rxtx, num_rings, rxtx, num_rings, numa_node))
354                 return -1;
355
356         return 0;
357 }
358
359
360 static int
361 eth_dev_ring_pair_create(const char *name, const unsigned numa_node,
362                 enum dev_action action)
363 {
364         /* rx and tx are so-called from point of view of first port.
365          * They are inverted from the point of view of second port
366          */
367         struct rte_ring *rx[RTE_PMD_RING_MAX_RX_RINGS];
368         struct rte_ring *tx[RTE_PMD_RING_MAX_TX_RINGS];
369         unsigned i;
370         char rx_rng_name[RTE_RING_NAMESIZE];
371         char tx_rng_name[RTE_RING_NAMESIZE];
372         unsigned num_rings = RTE_MIN(RTE_PMD_RING_MAX_RX_RINGS,
373                         RTE_PMD_RING_MAX_TX_RINGS);
374
375         for (i = 0; i < num_rings; i++) {
376                 snprintf(rx_rng_name, sizeof(rx_rng_name), "ETH_RX%u_%s", i, name);
377                 rx[i] = (action == DEV_CREATE) ?
378                                 rte_ring_create(rx_rng_name, 1024, numa_node,
379                                                 RING_F_SP_ENQ|RING_F_SC_DEQ) :
380                                 rte_ring_lookup(rx_rng_name);
381                 if (rx[i] == NULL)
382                         return -1;
383                 snprintf(tx_rng_name, sizeof(tx_rng_name), "ETH_TX%u_%s", i, name);
384                 tx[i] = (action == DEV_CREATE) ?
385                                 rte_ring_create(tx_rng_name, 1024, numa_node,
386                                                 RING_F_SP_ENQ|RING_F_SC_DEQ):
387                                 rte_ring_lookup(tx_rng_name);
388                 if (tx[i] == NULL)
389                         return -1;
390         }
391
392         if (rte_eth_from_rings(rx_rng_name, rx, num_rings, tx, num_rings,
393                         numa_node) || rte_eth_from_rings(tx_rng_name, tx, num_rings, rx,
394                                         num_rings, numa_node))
395                 return -1;
396
397         return 0;
398 }
399
400 int
401 rte_eth_ring_pair_create(const char *name, const unsigned numa_node)
402 {
403         RTE_LOG(WARNING, PMD, "rte_eth_ring_pair_create is deprecated\n");
404         return eth_dev_ring_pair_create(name, numa_node, DEV_CREATE);
405 }
406
407 int
408 rte_eth_ring_pair_attach(const char *name, const unsigned numa_node)
409 {
410         RTE_LOG(WARNING, PMD, "rte_eth_ring_pair_attach is deprecated\n");
411         return eth_dev_ring_pair_create(name, numa_node, DEV_ATTACH);
412 }
413
414 struct node_action_pair {
415         char name[PATH_MAX];
416         unsigned node;
417         enum dev_action action;
418 };
419
420 struct node_action_list {
421         unsigned total;
422         unsigned count;
423         struct node_action_pair *list;
424 };
425
426 static int parse_kvlist (const char *key __rte_unused, const char *value, void *data)
427 {
428         struct node_action_list *info = data;
429         int ret;
430         char *name;
431         char *action;
432         char *node;
433         char *end;
434
435         name = strdup(value);
436
437         ret = -EINVAL;
438
439         if (!name) {
440                 RTE_LOG(WARNING, PMD, "command line paramter is empty for ring pmd!\n");
441                 goto out;
442         }
443
444         node = strchr(name, ':');
445         if (!node) {
446                 RTE_LOG(WARNING, PMD, "could not parse node value from %s", name);
447                 goto out;
448         }
449
450         *node = '\0';
451         node++;
452
453         action = strchr(node, ':');
454         if (!action) {
455                 RTE_LOG(WARNING, PMD, "could not action value from %s", node);
456                 goto out;
457         }
458
459         *action = '\0';
460         action++;
461
462         /*
463          * Need to do some sanity checking here
464          */
465
466         if (strcmp(action, ETH_RING_ACTION_ATTACH) == 0)
467                 info->list[info->count].action = DEV_ATTACH;
468         else if (strcmp(action, ETH_RING_ACTION_CREATE) == 0)
469                 info->list[info->count].action = DEV_CREATE;
470         else
471                 goto out;
472
473         errno = 0;
474         info->list[info->count].node = strtol(node, &end, 10);
475
476         if ((errno != 0) || (*end != '\0')) {
477                 RTE_LOG(WARNING, PMD, "node value %s is unparseable as a number\n", node);
478                 goto out;
479         }
480
481         snprintf(info->list[info->count].name, sizeof(info->list[info->count].name), "%s", name);
482
483         info->count++;
484
485         ret = 0;
486 out:
487         free(name);
488         return ret;
489 }
490
491 static int
492 rte_pmd_ring_devinit(const char *name, const char *params)
493 {
494         struct rte_kvargs *kvlist;
495         int ret = 0;
496         struct node_action_list *info = NULL;
497
498         RTE_LOG(INFO, PMD, "Initializing pmd_ring for %s\n", name);
499
500         if (params == NULL || params[0] == '\0')
501                 eth_dev_ring_create(name, rte_socket_id(), DEV_CREATE);
502         else {
503                 kvlist = rte_kvargs_parse(params, valid_arguments);
504
505                 if (!kvlist) {
506                         RTE_LOG(INFO, PMD, "Ignoring unsupported parameters when creating"
507                                         " rings-backed ethernet device\n");
508                         eth_dev_ring_create(name, rte_socket_id(), DEV_CREATE);
509                         return 0;
510                 } else {
511                         ret = rte_kvargs_count(kvlist, ETH_RING_NUMA_NODE_ACTION_ARG);
512                         info = rte_zmalloc("struct node_action_list", sizeof(struct node_action_list) +
513                                            (sizeof(struct node_action_pair) * ret), 0);
514                         if (!info)
515                                 goto out;
516
517                         info->total = ret;
518                         info->list = (struct node_action_pair*)(info + 1);
519
520                         ret = rte_kvargs_process(kvlist, ETH_RING_NUMA_NODE_ACTION_ARG,
521                                                  parse_kvlist, info);
522
523                         if (ret < 0)
524                                 goto out_free;
525
526                         for (info->count = 0; info->count < info->total; info->count++) {
527                                 eth_dev_ring_create(name, info->list[info->count].node,
528                                                     info->list[info->count].action);
529                         }
530                 }
531         }
532
533 out_free:
534         rte_free(info);
535 out:
536         return ret;
537 }
538
539 static struct rte_driver pmd_ring_drv = {
540         .name = "eth_ring",
541         .type = PMD_VDEV,
542         .init = rte_pmd_ring_devinit,
543 };
544
545 PMD_REGISTER_DRIVER(pmd_ring_drv);