Add support to allow users to specify the ring_cookie as a VF/queue value, ie: '0/25' means direct to the physical function queue 25, while '3/10' means to direct to VF id 3, queue 10. It is driver dependent to determine what the VF id is, excepting that 0 indicates the physical function. This allows the user to more easily specify the matching notation as it is understood by the kernel and some drivers. Since no driver exists today with over 2,147,483,647 queues, this notation will simply fail on drivers which don't recognize the new partitioning.
Signed-off-by: Jacob Keller <jacob.e.kel...@intel.com> --- ethtool.8.in | 3 ++- rxclass.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/ethtool.8.in b/ethtool.8.in index 5c36c06385f6..cb165fa4c77a 100644 --- a/ethtool.8.in +++ b/ethtool.8.in @@ -826,7 +826,8 @@ Specifies the Rx queue to send packets to, or some other action. nokeep; lB l. -1 Drop the matched flow -0 or higher Rx queue to route the flow +0 or higher Route flow to specific Rx queue on the physical function +N/M Route flow to Rx queue M of specific virtual function N (0 indicates the physical function) .TE .TP .BI loc \ N diff --git a/rxclass.c b/rxclass.c index 7f0e765d3b47..de25550529b4 100644 --- a/rxclass.c +++ b/rxclass.c @@ -614,6 +614,7 @@ typedef enum { OPT_IP4, OPT_IP6, OPT_MAC, + OPT_ACTION, } rule_opt_type_t; #define NFC_FLAG_RING 0x001 @@ -654,7 +655,7 @@ static const struct rule_opts rule_nfc_tcp_ip4[] = { { "dst-port", OPT_BE16, NFC_FLAG_DPORT, offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip4_spec.pdst), offsetof(struct ethtool_rx_flow_spec, m_u.tcp_ip4_spec.pdst) }, - { "action", OPT_U64, NFC_FLAG_RING, + { "action", OPT_ACTION, NFC_FLAG_RING, offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, { "loc", OPT_U32, NFC_FLAG_LOC, offsetof(struct ethtool_rx_flow_spec, location), -1 }, @@ -685,7 +686,7 @@ static const struct rule_opts rule_nfc_esp_ip4[] = { { "spi", OPT_BE32, NFC_FLAG_SPI, offsetof(struct ethtool_rx_flow_spec, h_u.esp_ip4_spec.spi), offsetof(struct ethtool_rx_flow_spec, m_u.esp_ip4_spec.spi) }, - { "action", OPT_U64, NFC_FLAG_RING, + { "action", OPT_ACTION, NFC_FLAG_RING, offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, { "loc", OPT_U32, NFC_FLAG_LOC, offsetof(struct ethtool_rx_flow_spec, location), -1 }, @@ -728,7 +729,7 @@ static const struct rule_opts rule_nfc_usr_ip4[] = { { "dst-port", OPT_BE16, NFC_FLAG_DPORT, offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip4_spec.l4_4_bytes) + 2, offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip4_spec.l4_4_bytes) + 2 }, - { "action", OPT_U64, NFC_FLAG_RING, + { "action", OPT_ACTION, NFC_FLAG_RING, offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, { "loc", OPT_U32, NFC_FLAG_LOC, offsetof(struct ethtool_rx_flow_spec, location), -1 }, @@ -762,7 +763,7 @@ static const struct rule_opts rule_nfc_tcp_ip6[] = { { "dst-port", OPT_BE16, NFC_FLAG_DPORT, offsetof(struct ethtool_rx_flow_spec, h_u.tcp_ip6_spec.pdst), offsetof(struct ethtool_rx_flow_spec, m_u.tcp_ip6_spec.pdst) }, - { "action", OPT_U64, NFC_FLAG_RING, + { "action", OPT_ACTION, NFC_FLAG_RING, offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, { "loc", OPT_U32, NFC_FLAG_LOC, offsetof(struct ethtool_rx_flow_spec, location), -1 }, @@ -793,7 +794,7 @@ static const struct rule_opts rule_nfc_esp_ip6[] = { { "spi", OPT_BE32, NFC_FLAG_SPI, offsetof(struct ethtool_rx_flow_spec, h_u.esp_ip6_spec.spi), offsetof(struct ethtool_rx_flow_spec, m_u.esp_ip6_spec.spi) }, - { "action", OPT_U64, NFC_FLAG_RING, + { "action", OPT_ACTION, NFC_FLAG_RING, offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, { "loc", OPT_U32, NFC_FLAG_LOC, offsetof(struct ethtool_rx_flow_spec, location), -1 }, @@ -836,7 +837,7 @@ static const struct rule_opts rule_nfc_usr_ip6[] = { { "dst-port", OPT_BE16, NFC_FLAG_DPORT, offsetof(struct ethtool_rx_flow_spec, h_u.usr_ip6_spec.l4_4_bytes) + 2, offsetof(struct ethtool_rx_flow_spec, m_u.usr_ip6_spec.l4_4_bytes) + 2 }, - { "action", OPT_U64, NFC_FLAG_RING, + { "action", OPT_ACTION, NFC_FLAG_RING, offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, { "loc", OPT_U32, NFC_FLAG_LOC, offsetof(struct ethtool_rx_flow_spec, location), -1 }, @@ -864,7 +865,7 @@ static const struct rule_opts rule_nfc_ether[] = { { "proto", OPT_BE16, NFC_FLAG_PROTO, offsetof(struct ethtool_rx_flow_spec, h_u.ether_spec.h_proto), offsetof(struct ethtool_rx_flow_spec, m_u.ether_spec.h_proto) }, - { "action", OPT_U64, NFC_FLAG_RING, + { "action", OPT_ACTION, NFC_FLAG_RING, offsetof(struct ethtool_rx_flow_spec, ring_cookie), -1 }, { "loc", OPT_U32, NFC_FLAG_LOC, offsetof(struct ethtool_rx_flow_spec, location), -1 }, @@ -948,6 +949,40 @@ static int rxclass_get_ether(char *str, unsigned char *val) return 0; } +static int rxclass_get_action(char *str, unsigned long long *val) +{ + const long long max_queue = ~0ULL >> 32; + const long long max_vf = ~0ULL >> 8; + char *end_vf, *end_queue; + unsigned long long queue, vf; + + /* If there is no '/' just read the full value like a u64 */ + if (!strchr(str, '/')) + return rxclass_get_ulong(str, val, 64); + + errno = 0; + + vf = strtoull(str, &end_vf, 0); + + /* + * Ensure that we consume everything up to the slash, and that there + * is more than the empty string following the slash. + */ + if ((*end_vf != '/') || !(*(end_vf + 1)) || errno || (vf > max_vf)) + return -1; + + errno = 0; + + queue = strtoull(end_vf + 1, &end_queue, 0); + + if (*end_queue || errno || (queue > max_queue)) + return -1; + + *val = (vf << ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF) | queue; + + return 0; +} + static int rxclass_get_val(char *str, unsigned char *p, u32 *flags, const struct rule_opts *opt) { @@ -1070,6 +1105,14 @@ static int rxclass_get_val(char *str, unsigned char *p, u32 *flags, memcpy(&p[opt->moffset], &mask, ETH_ALEN); break; } + case OPT_ACTION: { + unsigned long long val; + err = rxclass_get_action(str, &val); + if (err) + return -1; + *(u64 *)&p[opt->offset] = (u64)val; + break; + } case OPT_NONE: default: return -1; @@ -1183,6 +1226,7 @@ static int rxclass_get_mask(char *str, unsigned char *p, memcpy(&p[opt->moffset], val, ETH_ALEN); break; } + case OPT_ACTION: case OPT_NONE: default: return -1; -- 2.11.0.rc2.152.g4d04e67