hv_netvsc: Mark VF as slave before exposing it to user-mode
Commit Message
From: Long Li <longli@microsoft.com>
When a VF is being exposed form the kernel, it should be marked as "slave"
before exposing to the user-mode. The VF is not usable without netvsc running
as master. The user-mode should never see a VF without the "slave" flag.
This commit moves the code of setting the slave flag to the time before VF is
exposed to user-mode.
Signed-off-by: Long Li <longli@microsoft.com>
---
drivers/net/hyperv/netvsc_drv.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
Comments
On Wed, 25 Oct 2023 15:50:50 -0700
longli@linuxonhyperv.com wrote:
> list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
> ndev = hv_get_drvdata(ndev_ctx->device_ctx);
> - if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr)) {
> - netdev_notice(vf_netdev,
> - "falling back to mac addr based matching\n");
> + if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr) ||
> + ether_addr_equal(vf_netdev->dev_addr, ndev->perm_addr))
This part looks like unrelated change.
The VF mac address shouldn't change, but if it did don't look at i.
On Wed, 25 Oct 2023 15:50:50 -0700
longli@linuxonhyperv.com wrote:
> @@ -2347,6 +2342,12 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
> if (!ndev)
> return NOTIFY_DONE;
>
> + if (event == NETDEV_POST_INIT) {
> + /* set slave flag before open to prevent IPv6 addrconf */
> + vf_netdev->flags |= IFF_SLAVE;
> + return NOTIFY_DONE;
> + }
> +
> net_device_ctx = netdev_priv(ndev);
> netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
> if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
> @@ -2753,8 +2754,9 @@ static int netvsc_netdev_event(struct notifier_block *this,
> return NOTIFY_DONE;
>
> switch (event) {
> + case NETDEV_POST_INIT:
> case NETDEV_REGISTER:
> - return netvsc_register_vf(event_dev);
> + return netvsc_register_vf(event_dev, event);
Although correct, this is an awkward way to write this.
There are two events which call register_vf() but the post init
one short circuits and doesn't really register the VF.
The code is clearer if flag is set in switch statement.
@@ -2206,9 +2206,6 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
goto upper_link_failed;
}
- /* set slave flag before open to prevent IPv6 addrconf */
- vf_netdev->flags |= IFF_SLAVE;
-
schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
@@ -2753,6 +2750,10 @@ static int netvsc_netdev_event(struct notifier_block *this,
return NOTIFY_DONE;
switch (event) {
+ case NETDEV_POST_INIT:
+ /* set slave flag before open to prevent IPv6 addrconf */
+ vf_netdev->flags |= IFF_SLAVE;
+ return NOTIFY_DONE;
case NETDEV_REGISTER:
return netvsc_register_vf(event_dev);
case NETDEV_UNREGISTER:
> Subject: Re: [PATCH] hv_netvsc: Mark VF as slave before exposing it to user-mode
>
> On Wed, 25 Oct 2023 15:50:50 -0700
> longli@linuxonhyperv.com wrote:
>
> > list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
> > ndev = hv_get_drvdata(ndev_ctx->device_ctx);
> > - if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr))
> {
> > - netdev_notice(vf_netdev,
> > - "falling back to mac addr based
> matching\n");
> > + if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr)
> ||
> > + ether_addr_equal(vf_netdev->dev_addr, ndev->perm_addr))
>
> This part looks like unrelated change.
> The VF mac address shouldn't change, but if it did don't look at i.
At the time of NETDEV_POST_INIT, the perm_addr is not assigned yet (last it was copied from dev_addr when device is registered).
> Subject: Re: [PATCH] hv_netvsc: Mark VF as slave before exposing it to user-mode
>
> On Wed, 25 Oct 2023 15:50:50 -0700
> longli@linuxonhyperv.com wrote:
>
> > @@ -2347,6 +2342,12 @@ static int netvsc_register_vf(struct net_device
> *vf_netdev)
> > if (!ndev)
> > return NOTIFY_DONE;
> >
> > + if (event == NETDEV_POST_INIT) {
> > + /* set slave flag before open to prevent IPv6 addrconf */
> > + vf_netdev->flags |= IFF_SLAVE;
> > + return NOTIFY_DONE;
> > + }
> > +
> > net_device_ctx = netdev_priv(ndev);
> > netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
> > if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
> > @@ -2753,8 +2754,9 @@ static int netvsc_netdev_event(struct notifier_block
> *this,
> > return NOTIFY_DONE;
> >
> > switch (event) {
> > + case NETDEV_POST_INIT:
> > case NETDEV_REGISTER:
> > - return netvsc_register_vf(event_dev);
> > + return netvsc_register_vf(event_dev, event);
>
> Although correct, this is an awkward way to write this.
> There are two events which call register_vf() but the post init one short circuits
> and doesn't really register the VF.
>
> The code is clearer if flag is set in switch statement.
>
I will add a dedicated function to handle NETDEV_POST_INIT.
Thanks,
Long
@@ -2206,9 +2206,6 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
goto upper_link_failed;
}
- /* set slave flag before open to prevent IPv6 addrconf */
- vf_netdev->flags |= IFF_SLAVE;
-
schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
@@ -2320,11 +2317,9 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
*/
list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
ndev = hv_get_drvdata(ndev_ctx->device_ctx);
- if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr)) {
- netdev_notice(vf_netdev,
- "falling back to mac addr based matching\n");
+ if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr) ||
+ ether_addr_equal(vf_netdev->dev_addr, ndev->perm_addr))
return ndev;
- }
}
netdev_notice(vf_netdev,
@@ -2332,7 +2327,7 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
return NULL;
}
-static int netvsc_register_vf(struct net_device *vf_netdev)
+static int netvsc_register_vf(struct net_device *vf_netdev, unsigned long event)
{
struct net_device_context *net_device_ctx;
struct netvsc_device *netvsc_dev;
@@ -2347,6 +2342,12 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
if (!ndev)
return NOTIFY_DONE;
+ if (event == NETDEV_POST_INIT) {
+ /* set slave flag before open to prevent IPv6 addrconf */
+ vf_netdev->flags |= IFF_SLAVE;
+ return NOTIFY_DONE;
+ }
+
net_device_ctx = netdev_priv(ndev);
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
@@ -2753,8 +2754,9 @@ static int netvsc_netdev_event(struct notifier_block *this,
return NOTIFY_DONE;
switch (event) {
+ case NETDEV_POST_INIT:
case NETDEV_REGISTER:
- return netvsc_register_vf(event_dev);
+ return netvsc_register_vf(event_dev, event);
case NETDEV_UNREGISTER:
return netvsc_unregister_vf(event_dev);
case NETDEV_UP: