On 2023/7/5 14:40, Eugenio Perez Martin wrote: > On Wed, Jul 5, 2023 at 4:09 AM Hawkins Jiawei <yin31...@gmail.com> wrote: >> >> On 2023/7/4 23:39, Eugenio Perez Martin wrote: >>> On Thu, Jun 29, 2023 at 5:26 PM Hawkins Jiawei <yin31...@gmail.com> wrote: >>>> >>>> This patch introduces vhost_vdpa_net_load_rx_mode() >>>> and vhost_vdpa_net_load_rx() to restore the packet >>>> receive filtering state in relation to >>>> VIRTIO_NET_F_CTRL_RX feature at device's startup. >>>> >>>> Signed-off-by: Hawkins Jiawei <yin31...@gmail.com> >>>> --- >>>> v2: >>>> - avoid sending CVQ command in default state suggested by Eugenio >>>> >>>> v1: >>>> https://lore.kernel.org/all/86eeddcd6f6b04e5c1e44e901ddea3b1b8b6c183.1687402580.git.yin31...@gmail.com/ >>>> >>>> net/vhost-vdpa.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++ >>>> 1 file changed, 104 insertions(+) >>>> >>>> diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c >>>> index cb45c84c88..9d5d88756c 100644 >>>> --- a/net/vhost-vdpa.c >>>> +++ b/net/vhost-vdpa.c >>>> @@ -792,6 +792,106 @@ static int >>>> vhost_vdpa_net_load_offloads(VhostVDPAState *s, >>>> return 0; >>>> } >>>> >>>> +static int vhost_vdpa_net_load_rx_mode(VhostVDPAState *s, >>>> + uint8_t cmd, >>>> + uint8_t on) >>>> +{ >>>> + ssize_t dev_written; >>>> + const struct iovec data = { >>>> + .iov_base = &on, >>>> + .iov_len = sizeof(on), >>>> + }; >>>> + dev_written = vhost_vdpa_net_load_cmd(s, VIRTIO_NET_CTRL_RX, >>>> + cmd, &data, 1); >>>> + if (unlikely(dev_written < 0)) { >>>> + return dev_written; >>>> + } >>>> + if (*s->status != VIRTIO_NET_OK) { >>>> + return -EINVAL; >>>> + } >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +static int vhost_vdpa_net_load_rx(VhostVDPAState *s, >>>> + const VirtIONet *n) >>>> +{ >>>> + uint8_t on; >>>> + int r; >>>> + >>>> + if (virtio_vdev_has_feature(&n->parent_obj, VIRTIO_NET_F_CTRL_RX)) { >>> >>> Also suggesting early returns here. >> >> So, for CVQ commands related to VIRTIO_NET_F_CTRL_EXTRA_RX, would it be >> more appropriate to create a new function, maybe >> vhost_vdpa_net_load_rx_extra, to handle them instead of sending those >> CVQ commands within this function, if we choose to return early? >> > > My understanding is that VIRTIO_NET_F_CTRL_RX_EXTRA depends on > VIRTIO_NET_F_CTRL_RX, so we can do: > > if (!virtio_vdev_has_feature(&n->parent_obj, VIRTIO_NET_F_CTRL_RX)) { > return; > } > > // Process CTRL_RX commands > > if (!virtio_vdev_has_feature(&n->parent_obj, VIRTIO_NET_F_CTRL_RX)) { > return; > } > > // process CTRL_RX_EXTRA commands
Thanks for your explanation, it makes sense. I will send the v3 patch based on your suggestion. Thanks! > >>> >>>> + /* Load the promiscous mode */ >>>> + if (n->mac_table.uni_overflow) { >>>> + /* >>>> + * According to VirtIO standard, "Since there are no >>>> guarantees, >>>> + * it can use a hash filter or silently switch to >>>> + * allmulti or promiscuous mode if it is given too many >>>> addresses." >>>> + * >>>> + * QEMU ignores non-multicast(unicast) MAC addresses and >>>> + * marks `uni_overflow` for the device internal state >>>> + * if guest sets too many non-multicast(unicast) MAC >>>> addresses. >>>> + * Therefore, we should turn promiscous mode on in this case. >>>> + */ >>>> + on = 1; >>>> + } else { >>>> + on = n->promisc; >>>> + } >>> >>> I think we can remove the "on" variable and just do: >>> >>> /* >>> * According to ... >>> */ >>> if (n->mac_table.uni_overflow || n->promisc) { >>> r = vhost_vdpa_net_load_rx_mode(s, VIRTIO_NET_CTRL_RX_PROMISC, on); >>> if (r < 0) { >>> return r; >>> } >>> --- >>> >>> And the equivalent for multicast. >>> >>> Would that make sense? >> >> Yes, I will refactor these according to your suggestion. >> >> Thanks! >> >> >>> >>> Thanks! >>> >>>> + if (on != 1) { >>>> + /* >>>> + * According to virtio_net_reset(), device turns promiscuous >>>> mode on >>>> + * by default. >>>> + * >>>> + * Therefore, there is no need to send this CVQ command if the >>>> + * driver also sets promiscuous mode on, which aligns with >>>> + * the device's defaults. >>>> + * >>>> + * Note that the device's defaults can mismatch the driver's >>>> + * configuration only at live migration. >>>> + */ >>>> + r = vhost_vdpa_net_load_rx_mode(s, >>>> VIRTIO_NET_CTRL_RX_PROMISC, on); >>>> + if (r < 0) { >>>> + return r; >>>> + } >>>> + } >>>> + >>>> + /* Load the all-multicast mode */ >>>> + if (n->mac_table.multi_overflow) { >>>> + /* >>>> + * According to VirtIO standard, "Since there are no >>>> guarantees, >>>> + * it can use a hash filter or silently switch to >>>> + * allmulti or promiscuous mode if it is given too many >>>> addresses." >>>> + * >>>> + * QEMU ignores multicast MAC addresses and >>>> + * marks `multi_overflow` for the device internal state >>>> + * if guest sets too many multicast MAC addresses. >>>> + * Therefore, we should turn all-multicast mode on in this >>>> case. >>>> + */ >>>> + on = 1; >>>> + } else { >>>> + on = n->allmulti; >>>> + } >>>> + if (on != 0) { >>>> + /* >>>> + * According to virtio_net_reset(), device turns >>>> all-multicast mode >>>> + * off by default. >>>> + * >>>> + * Therefore, there is no need to send this CVQ command if the >>>> + * driver also sets all-multicast mode off, which aligns with >>>> + * the device's defaults. >>>> + * >>>> + * Note that the device's defaults can mismatch the driver's >>>> + * configuration only at live migration. >>>> + */ >>>> + r = vhost_vdpa_net_load_rx_mode(s, >>>> VIRTIO_NET_CTRL_RX_ALLMULTI, on); >>>> + if (r < 0) { >>>> + return r; >>>> + } >>>> + } >>>> + } >>>> + >>>> + return 0; >>>> +} >>>> + >>>> static int vhost_vdpa_net_load(NetClientState *nc) >>>> { >>>> VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); >>>> @@ -818,6 +918,10 @@ static int vhost_vdpa_net_load(NetClientState *nc) >>>> if (unlikely(r)) { >>>> return r; >>>> } >>>> + r = vhost_vdpa_net_load_rx(s, n); >>>> + if (unlikely(r)) { >>>> + return r; >>>> + } >>>> >>>> return 0; >>>> } >>>> -- >>>> 2.25.1 >>>> >>> >> >