4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
35 #include <rte_malloc.h>
36 #include <rte_ethdev.h>
40 #include <rte_devargs.h>
41 #include <rte_kvargs.h>
44 #include "rte_eth_bond.h"
45 #include "rte_eth_bond_private.h"
48 bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
50 struct bond_dev_private *internals;
52 uint16_t num_rx_slave = 0;
53 uint16_t num_rx_total = 0;
57 /* Cast to structure, containing bonded device's port id and queue id */
58 struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
60 internals = bd_rx_q->dev_private;
63 for (i = 0; i < internals->active_slave_count && nb_pkts; i++) {
64 /* Offset of pointer to *bufs increases as packets are received
65 * from other slaves */
66 num_rx_slave = rte_eth_rx_burst(internals->active_slaves[i],
67 bd_rx_q->queue_id, bufs + num_rx_total, nb_pkts);
69 num_rx_total += num_rx_slave;
70 nb_pkts -= num_rx_slave;
78 bond_ethdev_rx_burst_active_backup(void *queue, struct rte_mbuf **bufs,
81 struct bond_dev_private *internals;
83 /* Cast to structure, containing bonded device's port id and queue id */
84 struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
86 internals = bd_rx_q->dev_private;
88 return rte_eth_rx_burst(internals->current_primary_port,
89 bd_rx_q->queue_id, bufs, nb_pkts);
93 bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
96 struct bond_dev_private *internals;
97 struct bond_tx_queue *bd_tx_q;
99 struct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][nb_pkts];
100 uint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] = { 0 };
102 uint8_t num_of_slaves;
103 uint8_t slaves[RTE_MAX_ETHPORTS];
105 uint16_t num_tx_total = 0, num_tx_slave;
107 static int slave_idx = 0;
108 int i, cslave_idx = 0, tx_fail_total = 0;
110 bd_tx_q = (struct bond_tx_queue *)queue;
111 internals = bd_tx_q->dev_private;
113 /* Copy slave list to protect against slave up/down changes during tx
115 num_of_slaves = internals->active_slave_count;
116 memcpy(slaves, internals->active_slaves,
117 sizeof(internals->active_slaves[0]) * num_of_slaves);
119 if (num_of_slaves < 1)
122 /* Populate slaves mbuf with which packets are to be sent on it */
123 for (i = 0; i < nb_pkts; i++) {
124 cslave_idx = (slave_idx + i) % num_of_slaves;
125 slave_bufs[cslave_idx][(slave_nb_pkts[cslave_idx])++] = bufs[i];
128 /* increment current slave index so the next call to tx burst starts on the
130 slave_idx = ++cslave_idx;
132 /* Send packet burst on each slave device */
133 for (i = 0; i < num_of_slaves; i++) {
134 if (slave_nb_pkts[i] > 0) {
135 num_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,
136 slave_bufs[i], slave_nb_pkts[i]);
138 /* if tx burst fails move packets to end of bufs */
139 if (unlikely(num_tx_slave < slave_nb_pkts[i])) {
140 int tx_fail_slave = slave_nb_pkts[i] - num_tx_slave;
142 tx_fail_total += tx_fail_slave;
144 memcpy(&bufs[nb_pkts - tx_fail_total],
145 &slave_bufs[i][num_tx_slave], tx_fail_slave * sizeof(bufs[0]));
147 num_tx_total += num_tx_slave;
155 bond_ethdev_tx_burst_active_backup(void *queue,
156 struct rte_mbuf **bufs, uint16_t nb_pkts)
158 struct bond_dev_private *internals;
159 struct bond_tx_queue *bd_tx_q;
161 bd_tx_q = (struct bond_tx_queue *)queue;
162 internals = bd_tx_q->dev_private;
164 if (internals->active_slave_count < 1)
167 return rte_eth_tx_burst(internals->current_primary_port, bd_tx_q->queue_id,
171 static inline uint16_t
172 ether_hash(struct ether_hdr *eth_hdr)
174 uint16_t *word_src_addr = (uint16_t *)eth_hdr->s_addr.addr_bytes;
175 uint16_t *word_dst_addr = (uint16_t *)eth_hdr->d_addr.addr_bytes;
177 return (word_src_addr[0] ^ word_dst_addr[0]) ^
178 (word_src_addr[1] ^ word_dst_addr[1]) ^
179 (word_src_addr[2] ^ word_dst_addr[2]);
182 static inline uint32_t
183 ipv4_hash(struct ipv4_hdr *ipv4_hdr)
185 return (ipv4_hdr->src_addr ^ ipv4_hdr->dst_addr);
188 static inline uint32_t
189 ipv6_hash(struct ipv6_hdr *ipv6_hdr)
191 uint32_t *word_src_addr = (uint32_t *)&(ipv6_hdr->src_addr[0]);
192 uint32_t *word_dst_addr = (uint32_t *)&(ipv6_hdr->dst_addr[0]);
194 return (word_src_addr[0] ^ word_dst_addr[0]) ^
195 (word_src_addr[1] ^ word_dst_addr[1]) ^
196 (word_src_addr[2] ^ word_dst_addr[2]) ^
197 (word_src_addr[3] ^ word_dst_addr[3]);
201 udp_hash(struct udp_hdr *hdr)
203 return hdr->src_port ^ hdr->dst_port;
206 static inline uint16_t
207 xmit_slave_hash(const struct rte_mbuf *buf, uint8_t slave_count, uint8_t policy)
209 struct ether_hdr *eth_hdr;
210 struct udp_hdr *udp_hdr;
211 size_t eth_offset = 0;
214 if (slave_count == 1)
218 case BALANCE_XMIT_POLICY_LAYER2:
219 eth_hdr = rte_pktmbuf_mtod(buf, struct ether_hdr *);
221 hash = ether_hash(eth_hdr);
223 return hash % slave_count;
225 case BALANCE_XMIT_POLICY_LAYER23:
226 eth_hdr = rte_pktmbuf_mtod(buf, struct ether_hdr *);
228 if (buf->ol_flags & PKT_RX_VLAN_PKT)
229 eth_offset = sizeof(struct ether_hdr) + sizeof(struct vlan_hdr);
231 eth_offset = sizeof(struct ether_hdr);
233 if (buf->ol_flags & PKT_RX_IPV4_HDR) {
234 struct ipv4_hdr *ipv4_hdr;
235 ipv4_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(buf,
236 unsigned char *) + eth_offset);
238 hash = ether_hash(eth_hdr) ^ ipv4_hash(ipv4_hdr);
241 struct ipv6_hdr *ipv6_hdr;
243 ipv6_hdr = (struct ipv6_hdr *)(rte_pktmbuf_mtod(buf,
244 unsigned char *) + eth_offset);
246 hash = ether_hash(eth_hdr) ^ ipv6_hash(ipv6_hdr);
250 case BALANCE_XMIT_POLICY_LAYER34:
251 if (buf->ol_flags & PKT_RX_VLAN_PKT)
252 eth_offset = sizeof(struct ether_hdr) + sizeof(struct vlan_hdr);
254 eth_offset = sizeof(struct ether_hdr);
256 if (buf->ol_flags & PKT_RX_IPV4_HDR) {
257 struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *)
258 (rte_pktmbuf_mtod(buf, unsigned char *) + eth_offset);
260 if (ipv4_hdr->next_proto_id == IPPROTO_UDP) {
261 udp_hdr = (struct udp_hdr *)
262 (rte_pktmbuf_mtod(buf, unsigned char *) + eth_offset +
263 sizeof(struct ipv4_hdr));
264 hash = ipv4_hash(ipv4_hdr) ^ udp_hash(udp_hdr);
266 hash = ipv4_hash(ipv4_hdr);
269 struct ipv6_hdr *ipv6_hdr = (struct ipv6_hdr *)
270 (rte_pktmbuf_mtod(buf, unsigned char *) + eth_offset);
272 if (ipv6_hdr->proto == IPPROTO_UDP) {
273 udp_hdr = (struct udp_hdr *)
274 (rte_pktmbuf_mtod(buf, unsigned char *) + eth_offset +
275 sizeof(struct ipv6_hdr));
276 hash = ipv6_hash(ipv6_hdr) ^ udp_hash(udp_hdr);
278 hash = ipv6_hash(ipv6_hdr);
287 return hash % slave_count;
291 bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,
294 struct bond_dev_private *internals;
295 struct bond_tx_queue *bd_tx_q;
297 uint8_t num_of_slaves;
298 uint8_t slaves[RTE_MAX_ETHPORTS];
300 uint16_t num_tx_total = 0, num_tx_slave = 0, tx_fail_total = 0;
304 struct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][nb_pkts];
305 uint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] = { 0 };
307 bd_tx_q = (struct bond_tx_queue *)queue;
308 internals = bd_tx_q->dev_private;
310 /* Copy slave list to protect against slave up/down changes during tx
312 num_of_slaves = internals->active_slave_count;
313 memcpy(slaves, internals->active_slaves,
314 sizeof(internals->active_slaves[0]) * num_of_slaves);
316 if (num_of_slaves < 1)
319 /* Populate slaves mbuf with the packets which are to be sent on it */
320 for (i = 0; i < nb_pkts; i++) {
321 /* Select output slave using hash based on xmit policy */
322 op_slave_id = xmit_slave_hash(bufs[i], num_of_slaves,
323 internals->balance_xmit_policy);
325 /* Populate slave mbuf arrays with mbufs for that slave */
326 slave_bufs[op_slave_id][slave_nb_pkts[op_slave_id]++] = bufs[i];
329 /* Send packet burst on each slave device */
330 for (i = 0; i < num_of_slaves; i++) {
331 if (slave_nb_pkts[i] > 0) {
332 num_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,
333 slave_bufs[i], slave_nb_pkts[i]);
335 /* if tx burst fails move packets to end of bufs */
336 if (unlikely(num_tx_slave < slave_nb_pkts[i])) {
337 int slave_tx_fail_count = slave_nb_pkts[i] - num_tx_slave;
339 tx_fail_total += slave_tx_fail_count;
340 memcpy(bufs[nb_pkts - tx_fail_total],
341 slave_bufs[i][num_tx_slave], slave_tx_fail_count);
344 num_tx_total += num_tx_slave;
352 #ifdef RTE_MBUF_REFCNT
354 bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs,
357 struct bond_dev_private *internals;
358 struct bond_tx_queue *bd_tx_q;
360 uint8_t tx_failed_flag = 0, num_of_slaves;
361 uint8_t slaves[RTE_MAX_ETHPORTS];
363 uint16_t max_nb_of_tx_pkts = 0;
365 int slave_tx_total[RTE_MAX_ETHPORTS];
366 int i, most_successful_tx_slave = -1;
368 bd_tx_q = (struct bond_tx_queue *)queue;
369 internals = bd_tx_q->dev_private;
371 /* Copy slave list to protect against slave up/down changes during tx
373 num_of_slaves = internals->active_slave_count;
374 memcpy(slaves, internals->active_slaves,
375 sizeof(internals->active_slaves[0]) * num_of_slaves);
377 if (num_of_slaves < 1)
380 /* Increment reference count on mbufs */
381 for (i = 0; i < nb_pkts; i++)
382 rte_mbuf_refcnt_update(bufs[i], num_of_slaves - 1);
384 /* Transmit burst on each active slave */
385 for (i = 0; i < num_of_slaves; i++) {
386 slave_tx_total[i] = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id,
389 if (unlikely(slave_tx_total[i] < nb_pkts))
392 /* record the value and slave index for the slave which transmits the
393 * maximum number of packets */
394 if (slave_tx_total[i] > max_nb_of_tx_pkts) {
395 max_nb_of_tx_pkts = slave_tx_total[i];
396 most_successful_tx_slave = i;
400 /* if slaves fail to transmit packets from burst, the calling application
401 * is not expected to know about multiple references to packets so we must
402 * handle failures of all packets except those of the most successful slave
404 if (unlikely(tx_failed_flag))
405 for (i = 0; i < num_of_slaves; i++)
406 if (i != most_successful_tx_slave)
407 while (slave_tx_total[i] < nb_pkts)
408 rte_pktmbuf_free(bufs[slave_tx_total[i]++]);
410 return max_nb_of_tx_pkts;
415 link_properties_set(struct rte_eth_dev *bonded_eth_dev,
416 struct rte_eth_link *slave_dev_link)
418 struct rte_eth_link *bonded_dev_link = &bonded_eth_dev->data->dev_link;
419 struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
421 if (slave_dev_link->link_status &&
422 bonded_eth_dev->data->dev_started) {
423 bonded_dev_link->link_duplex = slave_dev_link->link_duplex;
424 bonded_dev_link->link_speed = slave_dev_link->link_speed;
426 internals->link_props_set = 1;
431 link_properties_reset(struct rte_eth_dev *bonded_eth_dev)
433 struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
435 memset(&(bonded_eth_dev->data->dev_link), 0,
436 sizeof(bonded_eth_dev->data->dev_link));
438 internals->link_props_set = 0;
442 link_properties_valid(struct rte_eth_link *bonded_dev_link,
443 struct rte_eth_link *slave_dev_link)
445 if (bonded_dev_link->link_duplex != slave_dev_link->link_duplex ||
446 bonded_dev_link->link_speed != slave_dev_link->link_speed)
453 mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr *new_mac_addr)
455 struct ether_addr *mac_addr;
457 mac_addr = eth_dev->data->mac_addrs;
459 if (eth_dev == NULL) {
460 RTE_LOG(ERR, PMD, "%s: NULL pointer eth_dev specified\n", __func__);
464 if (new_mac_addr == NULL) {
465 RTE_LOG(ERR, PMD, "%s: NULL pointer MAC specified\n", __func__);
469 /* if new MAC is different to current MAC then update */
470 if (memcmp(mac_addr, new_mac_addr, sizeof(*mac_addr)) != 0)
471 memcpy(mac_addr, new_mac_addr, sizeof(*mac_addr));
477 mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)
479 struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
482 /* Update slave devices MAC addresses */
483 if (internals->slave_count < 1)
486 switch (internals->mode) {
487 case BONDING_MODE_ROUND_ROBIN:
488 case BONDING_MODE_BALANCE:
489 #ifdef RTE_MBUF_REFCNT
490 case BONDING_MODE_BROADCAST:
492 for (i = 0; i < internals->slave_count; i++) {
493 if (mac_address_set(&rte_eth_devices[internals->slaves[i]],
494 bonded_eth_dev->data->mac_addrs)) {
496 "%s: Failed to update port Id %d MAC address\n",
497 __func__, internals->slaves[i]);
502 case BONDING_MODE_ACTIVE_BACKUP:
504 for (i = 0; i < internals->slave_count; i++) {
505 if (internals->slaves[i] == internals->current_primary_port) {
506 if (mac_address_set(&rte_eth_devices[internals->primary_port],
507 bonded_eth_dev->data->mac_addrs)) {
509 "%s: Failed to update port Id %d MAC address\n",
510 __func__, internals->current_primary_port);
513 struct slave_conf *conf =
514 slave_config_get(internals, internals->slaves[i]);
516 if (mac_address_set(&rte_eth_devices[internals->slaves[i]],
519 "%s: Failed to update port Id %d MAC address\n",
520 __func__, internals->slaves[i]);
532 bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode)
534 struct bond_dev_private *internals;
536 internals = eth_dev->data->dev_private;
539 case BONDING_MODE_ROUND_ROBIN:
540 eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_round_robin;
541 eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
543 case BONDING_MODE_ACTIVE_BACKUP:
544 eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_active_backup;
545 eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup;
547 case BONDING_MODE_BALANCE:
548 eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_balance;
549 eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
551 #ifdef RTE_MBUF_REFCNT
552 case BONDING_MODE_BROADCAST:
553 eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_broadcast;
554 eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
561 internals->mode = mode;
567 slave_configure(struct rte_eth_dev *bonded_eth_dev,
568 struct rte_eth_dev *slave_eth_dev)
570 struct bond_rx_queue *bd_rx_q;
571 struct bond_tx_queue *bd_tx_q;
576 rte_eth_dev_stop(slave_eth_dev->data->port_id);
578 /* Enable interrupts on slave device */
579 slave_eth_dev->data->dev_conf.intr_conf.lsc = 1;
581 if (rte_eth_dev_configure(slave_eth_dev->data->port_id,
582 bonded_eth_dev->data->nb_rx_queues,
583 bonded_eth_dev->data->nb_tx_queues,
584 &(slave_eth_dev->data->dev_conf)) != 0) {
585 RTE_LOG(ERR, PMD, "Cannot configure slave device: port=%u\n",
586 slave_eth_dev->data->port_id);
590 /* Setup Rx Queues */
591 for (q_id = 0; q_id < bonded_eth_dev->data->nb_rx_queues; q_id++) {
592 bd_rx_q = (struct bond_rx_queue *)bonded_eth_dev->data->rx_queues[q_id];
594 if (rte_eth_rx_queue_setup(slave_eth_dev->data->port_id, q_id,
596 rte_eth_dev_socket_id(slave_eth_dev->data->port_id),
597 &(bd_rx_q->rx_conf), bd_rx_q->mb_pool) != 0) {
598 RTE_LOG(ERR, PMD, "rte_eth_rx_queue_setup: port=%d queue_id %d\n",
599 slave_eth_dev->data->port_id, q_id);
604 /* Setup Tx Queues */
605 for (q_id = 0; q_id < bonded_eth_dev->data->nb_tx_queues; q_id++) {
606 bd_tx_q = (struct bond_tx_queue *)bonded_eth_dev->data->tx_queues[q_id];
608 if (rte_eth_tx_queue_setup(slave_eth_dev->data->port_id, q_id,
610 rte_eth_dev_socket_id(slave_eth_dev->data->port_id),
611 &bd_tx_q->tx_conf) != 0) {
612 RTE_LOG(ERR, PMD, "rte_eth_tx_queue_setup: port=%d queue_id %d\n",
613 slave_eth_dev->data->port_id, q_id);
619 if (rte_eth_dev_start(slave_eth_dev->data->port_id) != 0) {
620 RTE_LOG(ERR, PMD, "rte_eth_dev_start: port=%u\n",
621 slave_eth_dev->data->port_id);
629 slave_config_get(struct bond_dev_private *internals, uint8_t slave_port_id)
633 for (i = 0; i < internals->slave_count; i++) {
634 if (internals->presisted_slaves_conf[i].port_id == slave_port_id)
635 return &internals->presisted_slaves_conf[i];
641 slave_config_clear(struct bond_dev_private *internals,
642 struct rte_eth_dev *slave_eth_dev)
646 for (i = 0; i < internals->slave_count; i++) {
647 if (internals->presisted_slaves_conf[i].port_id ==
648 slave_eth_dev->data->port_id) {
650 memset(&internals->presisted_slaves_conf[i], 0,
651 sizeof(internals->presisted_slaves_conf[i]));
653 if (found && i < (internals->slave_count - 1)) {
654 memcpy(&internals->presisted_slaves_conf[i],
655 &internals->presisted_slaves_conf[i+1],
656 sizeof(internals->presisted_slaves_conf[i]));
662 slave_config_store(struct bond_dev_private *internals,
663 struct rte_eth_dev *slave_eth_dev)
665 struct slave_conf *presisted_slave_conf =
666 &internals->presisted_slaves_conf[internals->slave_count];
668 presisted_slave_conf->port_id = slave_eth_dev->data->port_id;
670 memcpy(&(presisted_slave_conf->mac_addr), slave_eth_dev->data->mac_addrs,
671 sizeof(struct ether_addr));
675 bond_ethdev_primary_set(struct bond_dev_private *internals,
676 uint8_t slave_port_id)
680 if (internals->active_slave_count < 1)
681 internals->current_primary_port = slave_port_id;
683 /* Search bonded device slave ports for new proposed primary port */
684 for (i = 0; i < internals->active_slave_count; i++) {
685 if (internals->active_slaves[i] == slave_port_id)
686 internals->current_primary_port = slave_port_id;
691 bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev);
694 bond_ethdev_start(struct rte_eth_dev *eth_dev)
696 struct bond_dev_private *internals;
699 /* slave eth dev will be started by bonded device */
700 if (valid_bonded_ethdev(eth_dev)) {
702 "%s: user tried to explicitly start a slave eth_dev (%d) of the bonded eth_dev\n",
703 __func__, eth_dev->data->port_id);
707 eth_dev->data->dev_link.link_status = 1;
708 eth_dev->data->dev_started = 1;
710 internals = eth_dev->data->dev_private;
712 if (internals->slave_count == 0) {
714 "%s: Cannot start port since there are no slave devices\n",
719 if (internals->user_defined_mac == 0) {
720 struct slave_conf *conf = slave_config_get(internals,
721 internals->primary_port);
723 if (mac_address_set(eth_dev, &(conf->mac_addr)) != 0) {
725 "bonded port (%d) failed to update mac address",
726 eth_dev->data->port_id);
731 /* Update all slave devices MACs*/
732 if (mac_address_slaves_update(eth_dev) != 0)
735 /* If bonded device is configure in promiscuous mode then re-apply config */
736 if (internals->promiscuous_en)
737 bond_ethdev_promiscuous_enable(eth_dev);
739 /* Reconfigure each slave device if starting bonded device */
740 for (i = 0; i < internals->slave_count; i++) {
741 if (slave_configure(eth_dev, &(rte_eth_devices[internals->slaves[i]]))
743 RTE_LOG(ERR, PMD, "bonded port "
744 "(%d) failed to reconfigure slave device (%d)\n)",
745 eth_dev->data->port_id, internals->slaves[i]);
750 if (internals->user_defined_primary_port)
751 bond_ethdev_primary_set(internals, internals->primary_port);
757 bond_ethdev_stop(struct rte_eth_dev *eth_dev)
759 struct bond_dev_private *internals = eth_dev->data->dev_private;
761 internals->active_slave_count = 0;
763 eth_dev->data->dev_link.link_status = 0;
764 eth_dev->data->dev_started = 0;
768 bond_ethdev_close(struct rte_eth_dev *dev __rte_unused)
772 /* forward declaration */
773 static int bond_ethdev_configure(struct rte_eth_dev *dev);
776 bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
778 dev_info->driver_name = driver_name;
779 dev_info->max_mac_addrs = 1;
781 dev_info->max_rx_pktlen = (uint32_t)2048;
783 dev_info->max_rx_queues = (uint16_t)128;
784 dev_info->max_tx_queues = (uint16_t)512;
786 dev_info->min_rx_bufsize = 0;
787 dev_info->pci_dev = dev->pci_dev;
791 bond_ethdev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
792 uint16_t nb_rx_desc, unsigned int socket_id __rte_unused,
793 const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool)
795 struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)
796 rte_zmalloc_socket(NULL, sizeof(struct bond_rx_queue),
797 0, dev->pci_dev->numa_node);
801 bd_rx_q->queue_id = rx_queue_id;
802 bd_rx_q->dev_private = dev->data->dev_private;
804 bd_rx_q->nb_rx_desc = nb_rx_desc;
806 memcpy(&(bd_rx_q->rx_conf), rx_conf, sizeof(struct rte_eth_rxconf));
807 bd_rx_q->mb_pool = mb_pool;
809 dev->data->rx_queues[rx_queue_id] = bd_rx_q;
815 bond_ethdev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
816 uint16_t nb_tx_desc, unsigned int socket_id __rte_unused,
817 const struct rte_eth_txconf *tx_conf)
819 struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)
820 rte_zmalloc_socket(NULL, sizeof(struct bond_tx_queue),
821 0, dev->pci_dev->numa_node);
826 bd_tx_q->queue_id = tx_queue_id;
827 bd_tx_q->dev_private = dev->data->dev_private;
829 bd_tx_q->nb_tx_desc = nb_tx_desc;
830 memcpy(&(bd_tx_q->tx_conf), tx_conf, sizeof(bd_tx_q->tx_conf));
832 dev->data->tx_queues[tx_queue_id] = bd_tx_q;
838 bond_ethdev_rx_queue_release(void *queue)
847 bond_ethdev_tx_queue_release(void *queue)
856 bond_ethdev_link_update(struct rte_eth_dev *bonded_eth_dev,
857 int wait_to_complete)
859 struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
861 if (!bonded_eth_dev->data->dev_started ||
862 internals->active_slave_count == 0) {
863 bonded_eth_dev->data->dev_link.link_status = 0;
866 struct rte_eth_dev *slave_eth_dev;
869 for (i = 0; i < internals->active_slave_count; i++) {
870 slave_eth_dev = &rte_eth_devices[internals->active_slaves[i]];
872 (*slave_eth_dev->dev_ops->link_update)(slave_eth_dev,
874 if (slave_eth_dev->data->dev_link.link_status == 1) {
880 bonded_eth_dev->data->dev_link.link_status = link_up;
887 bond_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
889 struct bond_dev_private *internals = dev->data->dev_private;
890 struct rte_eth_stats slave_stats;
894 /* clear bonded stats before populating from slaves */
895 memset(stats, 0, sizeof(*stats));
897 for (i = 0; i < internals->slave_count; i++) {
898 rte_eth_stats_get(internals->slaves[i], &slave_stats);
900 stats->ipackets += slave_stats.ipackets;
901 stats->opackets += slave_stats.opackets;
902 stats->ibytes += slave_stats.ibytes;
903 stats->obytes += slave_stats.obytes;
904 stats->ierrors += slave_stats.ierrors;
905 stats->oerrors += slave_stats.oerrors;
906 stats->imcasts += slave_stats.imcasts;
907 stats->rx_nombuf += slave_stats.rx_nombuf;
908 stats->fdirmatch += slave_stats.fdirmatch;
909 stats->fdirmiss += slave_stats.fdirmiss;
910 stats->tx_pause_xon += slave_stats.tx_pause_xon;
911 stats->rx_pause_xon += slave_stats.rx_pause_xon;
912 stats->tx_pause_xoff += slave_stats.tx_pause_xoff;
913 stats->rx_pause_xoff += slave_stats.rx_pause_xoff;
918 bond_ethdev_stats_reset(struct rte_eth_dev *dev)
920 struct bond_dev_private *internals = dev->data->dev_private;
923 for (i = 0; i < internals->slave_count; i++)
924 rte_eth_stats_reset(internals->slaves[i]);
928 bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
930 struct bond_dev_private *internals = eth_dev->data->dev_private;
933 internals->promiscuous_en = 1;
935 switch (internals->mode) {
936 /* Promiscuous mode is propagated to all slaves */
937 case BONDING_MODE_ROUND_ROBIN:
938 case BONDING_MODE_BALANCE:
939 #ifdef RTE_MBUF_REFCNT
940 case BONDING_MODE_BROADCAST:
942 for (i = 0; i < internals->slave_count; i++)
943 rte_eth_promiscuous_enable(internals->slaves[i]);
945 /* Promiscuous mode is propagated only to primary slave */
946 case BONDING_MODE_ACTIVE_BACKUP:
948 rte_eth_promiscuous_enable(internals->current_primary_port);
954 bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
956 struct bond_dev_private *internals = dev->data->dev_private;
959 internals->promiscuous_en = 0;
961 switch (internals->mode) {
962 /* Promiscuous mode is propagated to all slaves */
963 case BONDING_MODE_ROUND_ROBIN:
964 case BONDING_MODE_BALANCE:
965 #ifdef RTE_MBUF_REFCNT
966 case BONDING_MODE_BROADCAST:
968 for (i = 0; i < internals->slave_count; i++)
969 rte_eth_promiscuous_disable(internals->slaves[i]);
971 /* Promiscuous mode is propagated only to primary slave */
972 case BONDING_MODE_ACTIVE_BACKUP:
974 rte_eth_promiscuous_disable(internals->current_primary_port);
979 bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
982 struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev;
983 struct bond_dev_private *internals;
984 struct rte_eth_link link;
986 int i, valid_slave = 0, active_pos = -1;
987 uint8_t lsc_flag = 0;
989 if (type != RTE_ETH_EVENT_INTR_LSC || param == NULL)
992 bonded_eth_dev = &rte_eth_devices[*(uint8_t *)param];
993 slave_eth_dev = &rte_eth_devices[port_id];
995 if (valid_bonded_ethdev(bonded_eth_dev))
998 internals = bonded_eth_dev->data->dev_private;
1000 /* If the device isn't started don't handle interrupts */
1001 if (!bonded_eth_dev->data->dev_started)
1004 /* verify that port_id is a valid slave of bonded port */
1005 for (i = 0; i < internals->slave_count; i++) {
1006 if (internals->slaves[i] == port_id) {
1015 /* Search for port in active port list */
1016 for (i = 0; i < internals->active_slave_count; i++) {
1017 if (port_id == internals->active_slaves[i]) {
1023 rte_eth_link_get_nowait(port_id, &link);
1024 if (link.link_status) {
1025 if (active_pos >= 0)
1028 /* if no active slave ports then set this port to be primary port */
1029 if (internals->active_slave_count < 1) {
1030 /* If first active slave, then change link status */
1031 bonded_eth_dev->data->dev_link.link_status = 1;
1032 internals->current_primary_port = port_id;
1035 /* Inherit eth dev link properties from first active slave */
1036 link_properties_set(bonded_eth_dev,
1037 &(slave_eth_dev->data->dev_link));
1039 internals->active_slaves[internals->active_slave_count++] = port_id;
1041 /* If user has defined the primary port then default to using it */
1042 if (internals->user_defined_primary_port &&
1043 internals->primary_port == port_id)
1044 bond_ethdev_primary_set(internals, port_id);
1049 /* Remove from active slave list */
1050 for (i = active_pos; i < (internals->active_slave_count - 1); i++)
1051 internals->active_slaves[i] = internals->active_slaves[i+1];
1053 internals->active_slave_count--;
1055 /* No active slaves, change link status to down and reset other
1056 * link properties */
1057 if (internals->active_slave_count < 1) {
1059 bonded_eth_dev->data->dev_link.link_status = 0;
1061 link_properties_reset(bonded_eth_dev);
1064 /* Update primary id, take first active slave from list or if none
1065 * available set to -1 */
1066 if (port_id == internals->current_primary_port) {
1067 if (internals->active_slave_count > 0)
1068 bond_ethdev_primary_set(internals,
1069 internals->active_slaves[0]);
1071 internals->current_primary_port = internals->primary_port;
1076 _rte_eth_dev_callback_process(bonded_eth_dev, RTE_ETH_EVENT_INTR_LSC);
1079 struct eth_dev_ops default_dev_ops = {
1080 .dev_start = bond_ethdev_start,
1081 .dev_stop = bond_ethdev_stop,
1082 .dev_close = bond_ethdev_close,
1083 .dev_configure = bond_ethdev_configure,
1084 .dev_infos_get = bond_ethdev_info,
1085 .rx_queue_setup = bond_ethdev_rx_queue_setup,
1086 .tx_queue_setup = bond_ethdev_tx_queue_setup,
1087 .rx_queue_release = bond_ethdev_rx_queue_release,
1088 .tx_queue_release = bond_ethdev_tx_queue_release,
1089 .link_update = bond_ethdev_link_update,
1090 .stats_get = bond_ethdev_stats_get,
1091 .stats_reset = bond_ethdev_stats_reset,
1092 .promiscuous_enable = bond_ethdev_promiscuous_enable,
1093 .promiscuous_disable = bond_ethdev_promiscuous_disable
1097 bond_init(const char *name, const char *params)
1099 struct bond_dev_private *internals;
1100 struct rte_kvargs *kvlist;
1101 uint8_t bonding_mode, socket_id;
1102 int arg_count, port_id;
1104 RTE_LOG(INFO, EAL, "Initializing pmd_bond for %s\n", name);
1106 kvlist = rte_kvargs_parse(params, pmd_bond_init_valid_arguments);
1110 /* Parse link bonding mode */
1111 if (rte_kvargs_count(kvlist, PMD_BOND_MODE_KVARG) == 1) {
1112 if (rte_kvargs_process(kvlist, PMD_BOND_MODE_KVARG,
1113 &bond_ethdev_parse_slave_mode_kvarg, &bonding_mode) != 0) {
1114 RTE_LOG(ERR, EAL, "Invalid mode for bonded device %s\n", name);
1119 "Mode must be specified only once for bonded device %s\n",
1124 /* Parse socket id to create bonding device on */
1125 arg_count = rte_kvargs_count(kvlist, PMD_BOND_SOCKET_ID_KVARG);
1126 if (arg_count == 1) {
1127 if (rte_kvargs_process(kvlist, PMD_BOND_SOCKET_ID_KVARG,
1128 &bond_ethdev_parse_socket_id_kvarg, &socket_id) != 0) {
1130 "Invalid socket Id specified for bonded device %s\n",
1134 } else if (arg_count > 1) {
1136 "Socket Id can be specified only once for bonded device %s\n",
1140 socket_id = rte_socket_id();
1143 /* Create link bonding eth device */
1144 port_id = rte_eth_bond_create(name, bonding_mode, socket_id);
1147 "Failed to create socket %s in mode %u on socket %u.\n",
1148 name, bonding_mode, socket_id);
1151 internals = rte_eth_devices[port_id].data->dev_private;
1152 internals->kvlist = kvlist;
1155 "Create bonded device %s on port %d in mode %u on socket %u.\n",
1156 name, port_id, bonding_mode, socket_id);
1160 /* this part will resolve the slave portids after all the other pdev and vdev
1161 * have been allocated */
1163 bond_ethdev_configure(struct rte_eth_dev *dev)
1165 char *name = dev->data->name;
1166 struct bond_dev_private *internals = dev->data->dev_private;
1167 struct rte_kvargs *kvlist = internals->kvlist;
1168 int arg_count, port_id = dev - rte_eth_devices;
1171 * if no kvlist, it means that this bonded device has been created
1172 * through the bonding api.
1177 /* Parse MAC address for bonded device */
1178 arg_count = rte_kvargs_count(kvlist, PMD_BOND_MAC_ADDR_KVARG);
1179 if (arg_count == 1) {
1180 struct ether_addr bond_mac;
1182 if (rte_kvargs_process(kvlist, PMD_BOND_MAC_ADDR_KVARG,
1183 &bond_ethdev_parse_bond_mac_addr_kvarg, &bond_mac) < 0) {
1184 RTE_LOG(INFO, EAL, "Invalid mac address for bonded device %s\n",
1189 /* Set MAC address */
1190 if (rte_eth_bond_mac_address_set(port_id, &bond_mac) != 0) {
1192 "Failed to set mac address on bonded device %s\n",
1196 } else if (arg_count > 1) {
1198 "MAC address can be specified only once for bonded device %s\n",
1203 /* Parse/set balance mode transmit policy */
1204 arg_count = rte_kvargs_count(kvlist, PMD_BOND_XMIT_POLICY_KVARG);
1205 if (arg_count == 1) {
1206 uint8_t xmit_policy;
1208 if (rte_kvargs_process(kvlist, PMD_BOND_XMIT_POLICY_KVARG,
1209 &bond_ethdev_parse_balance_xmit_policy_kvarg, &xmit_policy) !=
1212 "Invalid xmit policy specified for bonded device %s\n",
1217 /* Set balance mode transmit policy*/
1218 if (rte_eth_bond_xmit_policy_set(port_id, xmit_policy) != 0) {
1220 "Failed to set balance xmit policy on bonded device %s\n",
1224 } else if (arg_count > 1) {
1226 "Transmit policy can be specified only once for bonded device %s\n",
1231 /* Parse/add slave ports to bonded device */
1232 if (rte_kvargs_count(kvlist, PMD_BOND_SLAVE_PORT_KVARG) > 0) {
1233 struct bond_ethdev_slave_ports slave_ports;
1236 memset(&slave_ports, 0, sizeof(slave_ports));
1238 if (rte_kvargs_process(kvlist, PMD_BOND_SLAVE_PORT_KVARG,
1239 &bond_ethdev_parse_slave_port_kvarg, &slave_ports) != 0) {
1241 "Failed to parse slave ports for bonded device %s\n",
1246 for (i = 0; i < slave_ports.slave_count; i++) {
1247 if (rte_eth_bond_slave_add(port_id, slave_ports.slaves[i]) != 0) {
1249 "Failed to add port %d as slave to bonded device %s\n",
1250 slave_ports.slaves[i], name);
1255 RTE_LOG(INFO, EAL, "No slaves specified for bonded device %s\n", name);
1259 /* Parse/set primary slave port id*/
1260 arg_count = rte_kvargs_count(kvlist, PMD_BOND_PRIMARY_SLAVE_KVARG);
1261 if (arg_count == 1) {
1262 uint8_t primary_slave_port_id;
1264 if (rte_kvargs_process(kvlist,
1265 PMD_BOND_PRIMARY_SLAVE_KVARG,
1266 &bond_ethdev_parse_primary_slave_port_id_kvarg,
1267 &primary_slave_port_id) < 0) {
1269 "Invalid primary slave port id specified for bonded device %s\n",
1274 /* Set balance mode transmit policy*/
1275 if (rte_eth_bond_primary_set(port_id, (uint8_t)primary_slave_port_id)
1278 "Failed to set primary slave port %d on bonded device %s\n",
1279 primary_slave_port_id, name);
1282 } else if (arg_count > 1) {
1284 "Primary slave can be specified only once for bonded device %s\n",
1292 static struct rte_driver bond_drv = {
1298 PMD_REGISTER_DRIVER(bond_drv);