bond: support link status interrupt
[dpdk.git] / lib / librte_pmd_bond / rte_eth_bond_api.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_mbuf.h>
35 #include <rte_malloc.h>
36 #include <rte_ethdev.h>
37 #include <rte_tcp.h>
38
39 #include "rte_eth_bond.h"
40 #include "rte_eth_bond_private.h"
41
42 int
43 valid_bonded_ethdev(struct rte_eth_dev *eth_dev)
44 {
45         size_t len;
46
47         /* Check valid pointer */
48         if (eth_dev->driver->pci_drv.name == NULL || driver_name == NULL)
49                 return -1;
50
51         /* Check string lengths are equal */
52         len = strlen(driver_name);
53         if (strlen(eth_dev->driver->pci_drv.name) != len)
54                 return -1;
55
56         /* Compare strings */
57         return strncmp(eth_dev->driver->pci_drv.name, driver_name, len);
58 }
59
60 int
61 valid_port_id(uint8_t port_id)
62 {
63         /* Verify that port id is valid */
64         int ethdev_count = rte_eth_dev_count();
65         if (port_id >= ethdev_count) {
66                 RTE_LOG(ERR, PMD,
67                                 "%s: port Id %d is greater than rte_eth_dev_count %d\n",
68                                 __func__, port_id, ethdev_count);
69                 return -1;
70         }
71
72         return 0;
73 }
74
75 int
76 valid_bonded_port_id(uint8_t port_id)
77 {
78         /* Verify that port id's are valid */
79         if (valid_port_id(port_id))
80                 return -1;
81
82         /* Verify that bonded_port_id refers to a bonded port */
83         if (valid_bonded_ethdev(&rte_eth_devices[port_id])) {
84                 RTE_LOG(ERR, PMD,
85                                 "%s: Specified port Id %d is not a bonded eth_dev device\n",
86                                 __func__, port_id);
87                 return -1;
88         }
89
90         return 0;
91 }
92
93 int
94 valid_slave_port_id(uint8_t port_id)
95 {
96         /* Verify that port id's are valid */
97         if (valid_port_id(port_id))
98                 return -1;
99
100         /* Verify that port_id refers to a non bonded port */
101         if (!valid_bonded_ethdev(&rte_eth_devices[port_id]))
102                 return -1;
103
104         return 0;
105 }
106
107 uint8_t
108 number_of_sockets(void)
109 {
110         int sockets = 0;
111         int i;
112         const struct rte_memseg *ms = rte_eal_get_physmem_layout();
113
114         for (i = 0; ((i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL)); i++) {
115                 if (sockets < ms[i].socket_id)
116                         sockets = ms[i].socket_id;
117         }
118
119         /* Number of sockets = maximum socket_id + 1 */
120         return ++sockets;
121 }
122
123 const char *driver_name = "Link Bonding PMD";
124
125 int
126 rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
127 {
128         struct rte_pci_device *pci_dev = NULL;
129         struct bond_dev_private *internals = NULL;
130         struct rte_eth_dev *eth_dev = NULL;
131         struct eth_driver *eth_drv = NULL;
132         struct rte_pci_driver *pci_drv = NULL;
133         struct rte_pci_id *pci_id_table = NULL;
134         /* now do all data allocation - for eth_dev structure, dummy pci driver
135          * and internal (private) data
136          */
137
138         if (name == NULL) {
139                 RTE_LOG(ERR, PMD, "Invalid name specified\n");
140                 goto err;
141         }
142
143         if (socket_id >= number_of_sockets()) {
144                 RTE_LOG(ERR, PMD,
145                                 "%s: invalid socket id specified to create bonded device on.\n",
146                                 __func__);
147                 goto err;
148         }
149
150         pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id);
151         if (pci_dev == NULL) {
152                 RTE_LOG(ERR, PMD, "Unable to malloc pci dev on socket\n");
153                 goto err;
154         }
155
156         eth_drv = rte_zmalloc_socket(name, sizeof(*eth_drv), 0, socket_id);
157         if (eth_drv == NULL) {
158                 RTE_LOG(ERR, PMD, "Unable to malloc eth_drv on socket\n");
159                 goto err;
160         }
161
162         pci_drv = rte_zmalloc_socket(name, sizeof(*pci_drv), 0, socket_id);
163         if (pci_drv == NULL) {
164                 RTE_LOG(ERR, PMD, "Unable to malloc pci_drv on socket\n");
165                 goto err;
166         }
167         pci_id_table = rte_zmalloc_socket(name, sizeof(*pci_id_table), 0, socket_id);
168         if (pci_drv == NULL) {
169                 RTE_LOG(ERR, PMD, "Unable to malloc pci_id_table on socket\n");
170                 goto err;
171         }
172
173         pci_drv->id_table = pci_id_table;
174
175         pci_drv->id_table->device_id = PCI_ANY_ID;
176         pci_drv->id_table->subsystem_device_id = PCI_ANY_ID;
177         pci_drv->id_table->vendor_id = PCI_ANY_ID;
178         pci_drv->id_table->subsystem_vendor_id = PCI_ANY_ID;
179
180         pci_drv->drv_flags = RTE_PCI_DRV_INTR_LSC;
181
182         internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id);
183         if (internals == NULL) {
184                 RTE_LOG(ERR, PMD, "Unable to malloc internals on socket\n");
185                 goto err;
186         }
187
188         /* reserve an ethdev entry */
189         eth_dev = rte_eth_dev_allocate(name);
190         if (eth_dev == NULL) {
191                 RTE_LOG(ERR, PMD, "Unable to allocate rte_eth_dev\n");
192                 goto err;
193         }
194
195         pci_dev->numa_node = socket_id;
196         pci_drv->name = driver_name;
197
198         eth_drv->pci_drv = (struct rte_pci_driver)(*pci_drv);
199         eth_dev->driver = eth_drv;
200
201         eth_dev->data->dev_private = internals;
202         eth_dev->data->nb_rx_queues = (uint16_t)1;
203         eth_dev->data->nb_tx_queues = (uint16_t)1;
204
205         TAILQ_INIT(&(eth_dev->callbacks));
206
207         eth_dev->data->dev_link.link_status = 0;
208
209         eth_dev->data->mac_addrs = rte_zmalloc_socket(name, ETHER_ADDR_LEN, 0,
210                         socket_id);
211
212         eth_dev->data->dev_started = 0;
213         eth_dev->data->promiscuous = 0;
214         eth_dev->data->scattered_rx = 0;
215         eth_dev->data->all_multicast = 0;
216
217         eth_dev->dev_ops = &default_dev_ops;
218         eth_dev->pci_dev = pci_dev;
219
220         if (bond_ethdev_mode_set(eth_dev, mode)) {
221                 RTE_LOG(ERR, PMD,
222                                 "%s: failed to set bonded device %d mode too %d\n",
223                                 __func__, eth_dev->data->port_id, mode);
224                 goto err;
225         }
226
227         internals->current_primary_port = 0;
228         internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2;
229         internals->user_defined_mac = 0;
230         internals->link_props_set = 0;
231         internals->slave_count = 0;
232         internals->active_slave_count = 0;
233
234         memset(internals->active_slaves, 0, sizeof(internals->active_slaves));
235         memset(internals->slaves, 0, sizeof(internals->slaves));
236
237         memset(internals->presisted_slaves_conf, 0,
238                         sizeof(internals->presisted_slaves_conf));
239
240         return eth_dev->data->port_id;
241
242 err:
243         if (pci_dev)
244                 rte_free(pci_dev);
245         if (pci_drv)
246                 rte_free(pci_drv);
247         if (pci_id_table)
248                 rte_free(pci_id_table);
249         if (eth_drv)
250                 rte_free(eth_drv);
251         if (internals)
252                 rte_free(internals);
253         return -1;
254 }
255
256 int
257 rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id)
258 {
259         struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev;
260         struct bond_dev_private *internals;
261         struct bond_dev_private *temp_internals;
262         struct rte_eth_link link_props;
263
264         int i, j;
265
266         /* Verify that port id's are valid bonded and slave ports */
267         if (valid_bonded_port_id(bonded_port_id) != 0)
268                 goto err_add;
269
270         if (valid_slave_port_id(slave_port_id) != 0)
271                 goto err_add;
272
273         /*
274          * Verify that new slave device is not already a slave of another bonded
275          * device */
276         for (i = rte_eth_dev_count()-1; i >= 0; i--) {
277                 if (valid_bonded_ethdev(&rte_eth_devices[i]) == 0) {
278                         temp_internals = rte_eth_devices[i].data->dev_private;
279                         for (j = 0; j < temp_internals->slave_count; j++) {
280                                 /* Device already a slave of a bonded device */
281                                 if (temp_internals->slaves[j] == slave_port_id)
282                                         goto err_add;
283                         }
284                 }
285         }
286
287         bonded_eth_dev = &rte_eth_devices[bonded_port_id];
288         internals = bonded_eth_dev->data->dev_private;
289
290         slave_eth_dev = &rte_eth_devices[slave_port_id];
291
292         if (internals->slave_count > 0) {
293                 /* Check that new slave device is the same type as the other slaves
294                  * and not repetitive */
295                 for (i = 0; i < internals->slave_count; i++) {
296                         if (slave_eth_dev->pci_dev->driver->id_table->device_id !=
297                                         rte_eth_devices[internals->slaves[i]].pci_dev->driver->id_table->device_id ||
298                                 internals->slaves[i] == slave_port_id)
299                                 goto err_add;
300                 }
301         }
302
303         /* Add slave details to bonded device */
304         internals->slaves[internals->slave_count] = slave_port_id;
305
306         slave_config_store(internals, slave_eth_dev);
307
308         if (internals->slave_count < 1) {
309                 /* if MAC is not user defined then use MAC of first slave add to bonded
310                  * device */
311                 if (!internals->user_defined_mac)
312                         mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs);
313
314                 /* Inherit eth dev link properties from first slave */
315                 link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link));
316
317                 /* Make primary slave */
318                 internals->primary_port = slave_port_id;
319         } else {
320                 /* Check slave link properties are supported if props are set,
321                  * all slaves must be the same */
322                 if (internals->link_props_set) {
323                         if (link_properties_valid(&(bonded_eth_dev->data->dev_link),
324                                                                           &(slave_eth_dev->data->dev_link))) {
325                                 RTE_LOG(ERR, PMD,
326                                                 "%s: Slave port %d link speed/duplex not supported\n",
327                                                 __func__, slave_port_id);
328                                 goto err_add;
329                         }
330                 } else {
331                         link_properties_set(bonded_eth_dev,
332                                         &(slave_eth_dev->data->dev_link));
333                 }
334         }
335
336         internals->slave_count++;
337
338         /* Update all slave devices MACs*/
339         mac_address_slaves_update(bonded_eth_dev);
340
341         if (bonded_eth_dev->data->dev_started) {
342                 if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) {
343                         RTE_LOG(ERR, PMD, "rte_bond_slaves_configure: port=%d\n",
344                                         slave_port_id);
345                         goto err_add;
346                 }
347         }
348
349         /* Register link status change callback with bonded device pointer as
350          * argument*/
351         rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC,
352                         bond_ethdev_lsc_event_callback, &bonded_eth_dev->data->port_id);
353
354         /* If bonded device is started then we can add the slave to our active
355          * slave array */
356         if (bonded_eth_dev->data->dev_started) {
357                 rte_eth_link_get_nowait(slave_port_id, &link_props);
358
359                  if (link_props.link_status == 1) {
360                         internals->active_slaves[internals->active_slave_count++] =
361                                         slave_port_id;
362                 }
363         }
364
365         return 0;
366
367 err_add:
368         RTE_LOG(ERR, PMD, "Failed to add port %d as slave\n", slave_port_id);
369         return -1;
370
371 }
372
373 int
374 rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id)
375 {
376         struct bond_dev_private *internals;
377         struct slave_conf *slave_conf;
378
379         int i;
380         int pos = -1;
381
382         /* Verify that port id's are valid bonded and slave ports */
383         if (valid_bonded_port_id(bonded_port_id) != 0)
384                 goto err_del;
385
386         if (valid_slave_port_id(slave_port_id) != 0)
387                 goto err_del;
388
389         internals = rte_eth_devices[bonded_port_id].data->dev_private;
390
391         /* first remove from active slave list */
392         for (i = 0; i < internals->active_slave_count; i++) {
393                 if (internals->active_slaves[i] == slave_port_id)
394                         pos = i;
395
396                 /* shift active slaves up active array list */
397                 if (pos >= 0 && i < (internals->active_slave_count - 1))
398                         internals->active_slaves[i] = internals->active_slaves[i+1];
399         }
400
401         if (pos >= 0)
402                 internals->active_slave_count--;
403
404         pos = -1;
405         /* now remove from slave list */
406         for (i = 0; i < internals->slave_count; i++) {
407                 if (internals->slaves[i] == slave_port_id)
408                         pos = i;
409
410                 /* shift slaves up list */
411                 if (pos >= 0 && i < internals->slave_count)
412                         internals->slaves[i] = internals->slaves[i+1];
413         }
414
415         if (pos < 0)
416                 goto err_del;
417
418         /* Un-register link status change callback with bonded device pointer as
419          * argument*/
420         rte_eth_dev_callback_unregister(slave_port_id, RTE_ETH_EVENT_INTR_LSC,
421                         bond_ethdev_lsc_event_callback,
422                         &rte_eth_devices[bonded_port_id].data->port_id);
423
424         /* Restore original MAC address of slave device */
425         slave_conf = slave_config_get(internals, slave_port_id);
426
427         mac_address_set(&rte_eth_devices[slave_port_id], &(slave_conf->mac_addr));
428
429         slave_config_clear(internals, &rte_eth_devices[slave_port_id]);
430
431         internals->slave_count--;
432
433         /*  first slave in the active list will be the primary by default,
434          *  otherwise use first device in list */
435         if (internals->current_primary_port == slave_port_id) {
436                 if (internals->active_slave_count > 0)
437                         internals->current_primary_port = internals->active_slaves[0];
438                 else if (internals->slave_count > 0)
439                         internals->current_primary_port = internals->slaves[0];
440                 else
441                         internals->primary_port = 0;
442         }
443
444         if (internals->active_slave_count < 1) {
445                 /* reset device link properties as no slaves are active */
446                 link_properties_reset(&rte_eth_devices[bonded_port_id]);
447
448                 /* if no slaves are any longer attached to bonded device and MAC is not
449                  * user defined then clear MAC of bonded device as it will be reset
450                  * when a new slave is added */
451                 if (internals->slave_count < 1 && !internals->user_defined_mac)
452                         memset(rte_eth_devices[bonded_port_id].data->mac_addrs, 0,
453                                         sizeof(*(rte_eth_devices[bonded_port_id].data->mac_addrs)));
454         }
455
456         return 0;
457
458 err_del:
459         RTE_LOG(ERR, PMD,
460                         "Cannot remove slave device (not present in bonded device)\n");
461         return -1;
462
463 }
464
465 int
466 rte_eth_bond_mode_set(uint8_t bonded_port_id, uint8_t mode)
467 {
468         if (valid_bonded_port_id(bonded_port_id) != 0)
469                 return -1;
470
471         return bond_ethdev_mode_set(&rte_eth_devices[bonded_port_id], mode);
472 }
473
474 int
475 rte_eth_bond_mode_get(uint8_t bonded_port_id)
476 {
477         struct bond_dev_private *internals;
478
479         if (valid_bonded_port_id(bonded_port_id) != 0)
480                 return -1;
481
482         internals = rte_eth_devices[bonded_port_id].data->dev_private;
483
484         return internals->mode;
485 }
486
487 int
488 rte_eth_bond_primary_set(uint8_t bonded_port_id, uint8_t slave_port_id)
489 {
490         struct bond_dev_private *internals;
491
492         if (valid_bonded_port_id(bonded_port_id) != 0)
493                 return -1;
494
495         if (valid_slave_port_id(slave_port_id) != 0)
496                 return -1;
497
498         internals =  rte_eth_devices[bonded_port_id].data->dev_private;
499
500         internals->user_defined_primary_port = 1;
501         internals->primary_port = slave_port_id;
502
503         bond_ethdev_primary_set(internals, slave_port_id);
504
505         return 0;
506 }
507
508 int
509 rte_eth_bond_primary_get(uint8_t bonded_port_id)
510 {
511         struct bond_dev_private *internals;
512
513         if (valid_bonded_port_id(bonded_port_id) != 0)
514                 return -1;
515
516         internals = rte_eth_devices[bonded_port_id].data->dev_private;
517
518         if (internals->slave_count < 1)
519                 return -1;
520
521         return internals->current_primary_port;
522 }
523 int
524 rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len)
525 {
526         struct bond_dev_private *internals;
527
528         if (valid_bonded_port_id(bonded_port_id) != 0)
529                 return -1;
530
531         if (slaves == NULL)
532                 return -1;
533
534         internals = rte_eth_devices[bonded_port_id].data->dev_private;
535
536         if (internals->slave_count > len)
537                 return -1;
538
539         memcpy(slaves, internals->slaves, internals->slave_count);
540
541         return internals->slave_count;
542
543 }
544
545 int
546 rte_eth_bond_active_slaves_get(uint8_t bonded_port_id, uint8_t slaves[],
547                 uint8_t len)
548 {
549         struct bond_dev_private *internals;
550
551         if (valid_bonded_port_id(bonded_port_id) != 0)
552                 return -1;
553
554         if (slaves == NULL)
555                 return -1;
556
557         internals = rte_eth_devices[bonded_port_id].data->dev_private;
558
559         if (internals->active_slave_count > len)
560                 return -1;
561
562         memcpy(slaves, internals->active_slaves, internals->active_slave_count);
563
564         return internals->active_slave_count;
565 }
566
567 int
568 rte_eth_bond_mac_address_set(uint8_t bonded_port_id,
569                 struct ether_addr *mac_addr)
570 {
571         struct rte_eth_dev *bonded_eth_dev;
572         struct bond_dev_private *internals;
573
574         if (valid_bonded_port_id(bonded_port_id) != 0)
575                 return -1;
576
577         bonded_eth_dev = &rte_eth_devices[bonded_port_id];
578         internals = bonded_eth_dev->data->dev_private;
579
580         /* Set MAC Address of Bonded Device */
581         if (mac_address_set(bonded_eth_dev, mac_addr))
582                 return -1;
583
584         internals->user_defined_mac = 1;
585
586         /* Update all slave devices MACs*/
587         if (internals->slave_count > 0)
588                 return mac_address_slaves_update(bonded_eth_dev);
589
590         return 0;
591 }
592
593 int
594 rte_eth_bond_mac_address_reset(uint8_t bonded_port_id)
595 {
596         struct rte_eth_dev *bonded_eth_dev;
597         struct bond_dev_private *internals;
598
599         if (valid_bonded_port_id(bonded_port_id) != 0)
600                 return -1;
601
602         bonded_eth_dev = &rte_eth_devices[bonded_port_id];
603         internals = bonded_eth_dev->data->dev_private;
604
605         internals->user_defined_mac = 0;
606
607         if (internals->slave_count > 0) {
608                 struct slave_conf *conf;
609                 conf = slave_config_get(internals, internals->primary_port);
610
611                 /* Set MAC Address of Bonded Device */
612                 if (mac_address_set(bonded_eth_dev, &conf->mac_addr) != 0)
613                         return -1;
614
615                 /* Update all slave devices MAC addresses */
616                 return mac_address_slaves_update(bonded_eth_dev);
617         }
618         /* No need to update anything as no slaves present */
619         return 0;
620 }
621
622 int
623 rte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy)
624 {
625         struct bond_dev_private *internals;
626
627         if (valid_bonded_port_id(bonded_port_id) != 0)
628                 return -1;
629
630         internals = rte_eth_devices[bonded_port_id].data->dev_private;
631
632         switch (policy) {
633         case BALANCE_XMIT_POLICY_LAYER2:
634         case BALANCE_XMIT_POLICY_LAYER23:
635         case BALANCE_XMIT_POLICY_LAYER34:
636                 internals->balance_xmit_policy = policy;
637                 break;
638
639         default:
640                 return -1;
641         }
642         return 0;
643 }
644
645 int
646 rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id)
647 {
648         struct bond_dev_private *internals;
649
650         if (valid_bonded_port_id(bonded_port_id) != 0)
651                 return -1;
652
653         internals = rte_eth_devices[bonded_port_id].data->dev_private;
654
655         return internals->balance_xmit_policy;
656 }