|
52 | 52 | #include <sys/types.h> |
53 | 53 | #include <unistd.h> |
54 | 54 |
|
| 55 | +#include <ynl.h> |
| 56 | +#include "ethtool-user.h" |
| 57 | + |
55 | 58 | #include "../../../kselftest.h" |
56 | 59 | #include "../../../net/lib/ksft.h" |
57 | 60 |
|
|
65 | 68 | #define FOUR_TUPLE_MAX_LEN ((sizeof(struct in6_addr) * 2) + (sizeof(uint16_t) * 2)) |
66 | 69 |
|
67 | 70 | #define RSS_MAX_CPUS (1 << 16) /* real constraint is PACKET_FANOUT_MAX */ |
| 71 | +#define RSS_MAX_INDIR (1 << 16) |
68 | 72 |
|
69 | 73 | #define RPS_MAX_CPUS 16UL /* must be a power of 2 */ |
70 | 74 |
|
@@ -102,6 +106,8 @@ struct ring_state { |
102 | 106 | static unsigned int rx_irq_cpus[RSS_MAX_CPUS]; /* map from rxq to cpu */ |
103 | 107 | static int rps_silo_to_cpu[RPS_MAX_CPUS]; |
104 | 108 | static unsigned char toeplitz_key[TOEPLITZ_KEY_MAX_LEN]; |
| 109 | +static unsigned int rss_indir_tbl[RSS_MAX_INDIR]; |
| 110 | +static unsigned int rss_indir_tbl_size; |
105 | 111 | static struct ring_state rings[RSS_MAX_CPUS]; |
106 | 112 |
|
107 | 113 | static inline uint32_t toeplitz(const unsigned char *four_tuple, |
@@ -130,7 +136,12 @@ static inline uint32_t toeplitz(const unsigned char *four_tuple, |
130 | 136 | /* Compare computed cpu with arrival cpu from packet_fanout_cpu */ |
131 | 137 | static void verify_rss(uint32_t rx_hash, int cpu) |
132 | 138 | { |
133 | | - int queue = rx_hash % cfg_num_queues; |
| 139 | + int queue; |
| 140 | + |
| 141 | + if (rss_indir_tbl_size) |
| 142 | + queue = rss_indir_tbl[rx_hash % rss_indir_tbl_size]; |
| 143 | + else |
| 144 | + queue = rx_hash % cfg_num_queues; |
134 | 145 |
|
135 | 146 | log_verbose(" rxq %d (cpu %d)", queue, rx_irq_cpus[queue]); |
136 | 147 | if (rx_irq_cpus[queue] != cpu) { |
@@ -483,6 +494,56 @@ static void parse_rps_bitmap(const char *arg) |
483 | 494 | rps_silo_to_cpu[cfg_num_rps_cpus++] = i; |
484 | 495 | } |
485 | 496 |
|
| 497 | +static void read_rss_dev_info_ynl(void) |
| 498 | +{ |
| 499 | + struct ethtool_rss_get_req *req; |
| 500 | + struct ethtool_rss_get_rsp *rsp; |
| 501 | + struct ynl_sock *ys; |
| 502 | + |
| 503 | + ys = ynl_sock_create(&ynl_ethtool_family, NULL); |
| 504 | + if (!ys) |
| 505 | + error(1, errno, "ynl_sock_create failed"); |
| 506 | + |
| 507 | + req = ethtool_rss_get_req_alloc(); |
| 508 | + if (!req) |
| 509 | + error(1, errno, "ethtool_rss_get_req_alloc failed"); |
| 510 | + |
| 511 | + ethtool_rss_get_req_set_header_dev_name(req, cfg_ifname); |
| 512 | + |
| 513 | + rsp = ethtool_rss_get(ys, req); |
| 514 | + if (!rsp) |
| 515 | + error(1, ys->err.code, "YNL: %s", ys->err.msg); |
| 516 | + |
| 517 | + if (!rsp->_len.hkey) |
| 518 | + error(1, 0, "RSS key not available for %s", cfg_ifname); |
| 519 | + |
| 520 | + if (rsp->_len.hkey < TOEPLITZ_KEY_MIN_LEN || |
| 521 | + rsp->_len.hkey > TOEPLITZ_KEY_MAX_LEN) |
| 522 | + error(1, 0, "RSS key length %u out of bounds [%u, %u]", |
| 523 | + rsp->_len.hkey, TOEPLITZ_KEY_MIN_LEN, |
| 524 | + TOEPLITZ_KEY_MAX_LEN); |
| 525 | + |
| 526 | + memcpy(toeplitz_key, rsp->hkey, rsp->_len.hkey); |
| 527 | + |
| 528 | + if (rsp->_count.indir > RSS_MAX_INDIR) |
| 529 | + error(1, 0, "RSS indirection table too large (%u > %u)", |
| 530 | + rsp->_count.indir, RSS_MAX_INDIR); |
| 531 | + |
| 532 | + /* If indir table not available we'll fallback to simple modulo math */ |
| 533 | + if (rsp->_count.indir) { |
| 534 | + memcpy(rss_indir_tbl, rsp->indir, |
| 535 | + rsp->_count.indir * sizeof(rss_indir_tbl[0])); |
| 536 | + rss_indir_tbl_size = rsp->_count.indir; |
| 537 | + |
| 538 | + log_verbose("RSS indirection table size: %u\n", |
| 539 | + rss_indir_tbl_size); |
| 540 | + } |
| 541 | + |
| 542 | + ethtool_rss_get_rsp_free(rsp); |
| 543 | + ethtool_rss_get_req_free(req); |
| 544 | + ynl_sock_destroy(ys); |
| 545 | +} |
| 546 | + |
486 | 547 | static void parse_opts(int argc, char **argv) |
487 | 548 | { |
488 | 549 | static struct option long_options[] = { |
@@ -551,7 +612,7 @@ static void parse_opts(int argc, char **argv) |
551 | 612 | } |
552 | 613 |
|
553 | 614 | if (!have_toeplitz) |
554 | | - error(1, 0, "Must supply rss key ('-k')"); |
| 615 | + read_rss_dev_info_ynl(); |
555 | 616 |
|
556 | 617 | num_cpus = get_nprocs(); |
557 | 618 | if (num_cpus > RSS_MAX_CPUS) |
|
0 commit comments