[dpdk-dev] [PATCH v5 1/5] net/virtio: add initial RSS support
Andrew Rybchenko
andrew.rybchenko at oktetlabs.ru
Tue Oct 19 11:37:43 CEST 2021
Hi Maxime,
On 10/19/21 12:22 PM, Maxime Coquelin wrote:
> Hi Andrew,
>
> On 10/19/21 09:30, Andrew Rybchenko wrote:
>> On 10/18/21 1:20 PM, Maxime Coquelin wrote:
>>> Provide the capability to update the hash key, hash types
>>> and RETA table on the fly (without needing to stop/start
>>> the device). However, the key length and the number of RETA
>>> entries are fixed to 40B and 128 entries respectively. This
>>> is done in order to simplify the design, but may be
>>> revisited later as the Virtio spec provides this
>>> flexibility.
>>>
>>> Note that only VIRTIO_NET_F_RSS support is implemented,
>>> VIRTIO_NET_F_HASH_REPORT, which would enable reporting the
>>> packet RSS hash calculated by the device into mbuf.rss, is
>>> not yet supported.
>>>
>>> Regarding the default RSS configuration, it has been
>>> chosen to use the default Intel ixgbe key as default key,
>>> and default RETA is a simple modulo between the hash and
>>> the number of Rx queues.
>>>
>>> Signed-off-by: Maxime Coquelin <maxime.coquelin at redhat.com>
[snip]
>>> + rss.unclassified_queue = 0;
>>> + memcpy(rss.indirection_table, hw->rss_reta,
>>> VIRTIO_NET_RSS_RETA_SIZE * sizeof(uint16_t));
>>> + rss.max_tx_vq = nb_queues;
>>
>> Is it guaranteed that driver is configured with equal number
>> of Rx and Tx queues? Or is it not a problem otherwise?
>
> Virtio networking devices works with queue pairs.
But it seems to me that I still can configure just 1 Rx queue
and many Tx queues. Basically just non equal.
The line is suspicious since I'd expect nb_queues to be
a number of Rx queues in the function, but we set max_tx_vq
count here.
>>> +static int
>>> +virtio_dev_rss_init(struct rte_eth_dev *eth_dev)
>>> +{
>>> + struct virtio_hw *hw = eth_dev->data->dev_private;
>>> + uint16_t nb_rx_queues = eth_dev->data->nb_rx_queues;
>>> + struct rte_eth_rss_conf *rss_conf;
>>> + int ret, i;
>>> +
>>> + rss_conf = ð_dev->data->dev_conf.rx_adv_conf.rss_conf;
>>> +
>>> + ret = virtio_dev_get_rss_config(hw, &hw->rss_hash_types);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + if (rss_conf->rss_hf) {
>>> + /* Ensure requested hash types are supported by the device */
>>> + if (rss_conf->rss_hf &
>>> ~virtio_to_ethdev_rss_offloads(hw->rss_hash_types))
>>> + return -EINVAL;
>>> +
>>> + hw->rss_hash_types =
>>> ethdev_to_virtio_rss_offloads(rss_conf->rss_hf);
>>> + }
>>> +
>>> + if (!hw->rss_key) {
>>> + /* Setup default RSS key if not already setup by the user */
>>> + hw->rss_key = rte_malloc_socket("rss_key",
>>> + VIRTIO_NET_RSS_KEY_SIZE, 0,
>>> + eth_dev->device->numa_node);
>>> + if (!hw->rss_key) {
>>> + PMD_INIT_LOG(ERR, "Failed to allocate RSS key");
>>> + return -1;
>>> + }
>>> +
>>> + if (rss_conf->rss_key && rss_conf->rss_key_len) {
>>> + if (rss_conf->rss_key_len != VIRTIO_NET_RSS_KEY_SIZE) {
>>> + PMD_INIT_LOG(ERR, "Driver only supports %u RSS key
>>> length",
>>> + VIRTIO_NET_RSS_KEY_SIZE);
>>> + return -EINVAL;
>>> + }
>>> + memcpy(hw->rss_key, rss_conf->rss_key,
>>> VIRTIO_NET_RSS_KEY_SIZE);
>>> + } else {
>>> + memcpy(hw->rss_key, rss_intel_key,
>>> VIRTIO_NET_RSS_KEY_SIZE);
>>> + }
>>
>> Above if should work in the case of reconfigure as well when
>> array is already allocated.
>
> I'm not sure, because rte_eth_dev_rss_hash_update() API does not update
> eth_dev->data->dev_conf.rx_adv_conf.rss_conf, so we may lose the RSS key
> the user would have updated using this API. What do you think?
I think, but I think it should be used correctly by the
application. I.e. if application does reconfigure and
provides same or new key, does not matter, it should be
applied. Key could be a part of configure request and we
should not ignore it in the case of reconfigure.
Yes, I agree that it is a bit tricky, but still right
logic.
>>> + }
>>> +
>>> + if (!hw->rss_reta) {
>>> + /* Setup default RSS reta if not already setup by the user */
>>> + hw->rss_reta = rte_malloc_socket("rss_reta",
>>> + VIRTIO_NET_RSS_RETA_SIZE * sizeof(uint16_t), 0,
>>> + eth_dev->device->numa_node);
>>> + if (!hw->rss_reta) {
>>> + PMD_INIT_LOG(ERR, "Failed to allocate RSS reta");
>>> + return -1;
>>> + }
>>> + for (i = 0; i < VIRTIO_NET_RSS_RETA_SIZE; i++)
>>> + hw->rss_reta[i] = i % nb_rx_queues;
>>
>> How should it work in the case of reconfigure if a nubmer of Rx
>> queue changes?
>
> Hmm, good catch! I did not think about this, and so did not test it.
>
> Not to lose user-provisionned reta in case of unrelated change, maybe I
> should save the number of Rx queues when setting the reta (here and in
> virtio_dev_rss_reta_update), and perform a re-initialization if it is
> different?
Yes, it is much harder than RSS key case since the data are not
provided in dev_conf explicitly. So, we should guess here what
to do. The simple solution is to reinitialize if number of RxQs
change. I'd go this way.
>> Also I'm wondering how it works...
>> virtio_dev_rss_init() is called from eth_virtio_dev_init() as
>> well when a number of Rx queues is zero. I guess the reason is
>> VIRTIO_PMD_DEFAULT_GUEST_FEATURES, but it looks very fragile.
>
> Yes, we only add VIRTIO_NET_F_RSS to the supported features in
> virtio_dev_configure(), if Rx MQ mode is RSS. So virtio_dev_rss_init()
> will never be called from eth_virtio_dev_init().
>
> If I'm not mistaken, rte_eth_dev_configure() must be called it is stated
> in the API documentation, so it will be negotiated if conditions are
> met.
As far as I know we can configure ethdev with zero number of
RxQs, but non-zero number of Tx queues. E.g. traffic generator
usecase.
Division by zero is a guaranteed crash, so, I'd care
about it explicitly in any case. Just do not try to rely
on other checks faraway.
Andrew.
More information about the dev
mailing list