diff mbox series

[v2,2/2] net: Drop the NetLegacy structure, always use Netdev instead

Message ID 20200512123149.30207-3-thuth@redhat.com (mailing list archive)
State New, archived
Headers show
Series net: Drop legacy "name" from -net and remove NetLegacy | expand

Commit Message

Thomas Huth May 12, 2020, 12:31 p.m. UTC
Now that the "name" parameter is gone, there is hardly any difference
between NetLegacy and Netdev anymore. Drop NetLegacy and always use
Netdev to simplify the code quite a bit.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 net/net.c     | 74 ++++++++-------------------------------------------
 qapi/net.json | 48 +--------------------------------
 2 files changed, 12 insertions(+), 110 deletions(-)

Comments

Eric Blake May 12, 2020, 2:32 p.m. UTC | #1
On 5/12/20 7:31 AM, Thomas Huth wrote:
> Now that the "name" parameter is gone, there is hardly any difference
> between NetLegacy and Netdev anymore. Drop NetLegacy and always use
> Netdev to simplify the code quite a bit.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---

> +++ b/net/net.c
> @@ -967,13 +967,14 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
>   
>   static int net_client_init1(const void *object, bool is_netdev, Error **errp)

Why do we still need the 'is_netdev' parameter?  If all callers are 
passing in a netdev, then either this parameter needs to be renamed to 
capture the actual difference between callers, or it can be dropped 
altogether.

>   {
> -    Netdev legacy = {0};
> -    const Netdev *netdev;
> +    const Netdev *netdev = object;
>       NetClientState *peer = NULL;
>   
>       if (is_netdev) {
> -        netdev = object;
> -
> +        if (!netdev->has_id) {
> +            error_setg(errp, QERR_MISSING_PARAMETER, "id");
> +            return -1;
> +        }

You wouldn't need this if 'id' remained mandatory.

> @@ -981,56 +982,11 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
>               return -1;
>           }
>       } else {
> -        const NetLegacy *net = object;
> -        const NetLegacyOptions *opts = net->opts;
> -        legacy.id = net->id;
> -        netdev = &legacy;
> -
> -        /* Map the old options to the new flat type */
> -        switch (opts->type) {
> -        case NET_LEGACY_OPTIONS_TYPE_NONE:
> +        if (netdev->type == NET_CLIENT_DRIVER_NONE) {
>               return 0; /* nothing to do */


> -
> -        if (!net_client_init_fun[netdev->type]) {
> +        if (netdev->type == NET_CLIENT_DRIVER_HUBPORT ||
> +            !net_client_init_fun[netdev->type]) {
>               error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
>                          "a net backend type (maybe it is not compiled "
>                          "into this binary)");

So maybe we still want this legacy-handling code, but renaming 
'is_netdev' to 'legacy_handling' may make more sense.

> @@ -1039,7 +995,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
>   
>           /* Do not add to a hub if it's a nic with a netdev= parameter. */
>           if (netdev->type != NET_CLIENT_DRIVER_NIC ||
> -            !opts->u.nic.has_netdev) {
> +            !netdev->u.nic.has_netdev) {
>               peer = net_hub_add_port(0, NULL, NULL);
>           }
>       }
> @@ -1143,21 +1099,13 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
>           }
>       }
>   
> -    if (is_netdev) {
> -        visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
> -    } else {
> -        visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
> -    }
> +    visit_type_Netdev(v, NULL, (Netdev **)&object, &err);

Why do we need to cast?  If all callers are passing a Netdev, can't we 
just give 'object' the correct type to begin with?


> +++ b/qapi/net.json
> @@ -453,7 +453,7 @@
>   #        'l2tpv3' - since 2.1
>   ##
>   { 'union': 'Netdev',
> -  'base': { 'id': 'str', 'type': 'NetClientDriver' },
> +  'base': { '*id': 'str', 'type': 'NetClientDriver' },

I don't think we need to make 'id' optional.

>     'discriminator': 'type',
>     'data': {
>       'nic':      'NetLegacyNicOptions',
> @@ -467,52 +467,6 @@
>       'netmap':   'NetdevNetmapOptions',
>       'vhost-user': 'NetdevVhostUserOptions' } }
>   
> -##
> -# @NetLegacy:
> -#
> -# Captures the configuration of a network device; legacy.
> -#
> -# @id: identifier for monitor commands
> -#
> -# @opts: device type specific properties (legacy)
> -#
> -# Since: 1.2
> -##
> -{ 'struct': 'NetLegacy',
> -  'data': {
> -    '*id':   'str',
> -    'opts':  'NetLegacyOptions' } }
> -
> -##
> -# @NetLegacyOptionsType:
> -#
> -# Since: 1.2
> -##
> -{ 'enum': 'NetLegacyOptionsType',
> -  'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
> -           'bridge', 'netmap', 'vhost-user'] }

NetLegacyOptionsType differs from NetClientDriver only by missing 
'hubport', which your code above special-cased, so on that front, the 
simplification makes sense.
Thomas Huth May 12, 2020, 3:13 p.m. UTC | #2
On 12/05/2020 16.32, Eric Blake wrote:
> On 5/12/20 7:31 AM, Thomas Huth wrote:
>> Now that the "name" parameter is gone, there is hardly any difference
>> between NetLegacy and Netdev anymore. Drop NetLegacy and always use
>> Netdev to simplify the code quite a bit.
>>
>> Signed-off-by: Thomas Huth <thuth@redhat.com>
>> ---
> 
>> +++ b/net/net.c
>> @@ -967,13 +967,14 @@ static int (* const
>> net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
>>     static int net_client_init1(const void *object, bool is_netdev,
>> Error **errp)
> 
> Why do we still need the 'is_netdev' parameter?

Yes. See net_init_client(), it uses "false" here.

>  If all callers are
> passing in a netdev, then either this parameter needs to be renamed to
> capture the actual difference between callers, or it can be dropped
> altogether.

Don't think of the "Netdev" structure when you're looking at
"is_netdev", rather think about the "-netdev" comand line parameter.
"is_netdev" is used to distinguish between "-netdev" and "-net".

>>   {
>> -    Netdev legacy = {0};
>> -    const Netdev *netdev;
>> +    const Netdev *netdev = object;
>>       NetClientState *peer = NULL;
>>         if (is_netdev) {
>> -        netdev = object;
>> -
>> +        if (!netdev->has_id) {
>> +            error_setg(errp, QERR_MISSING_PARAMETER, "id");
>> +            return -1;
>> +        }
> 
> You wouldn't need this if 'id' remained mandatory.

It's still required for "-net" - see my reply to patch 1/2.

>> @@ -981,56 +982,11 @@ static int net_client_init1(const void *object,
>> bool is_netdev, Error **errp)
>>               return -1;
>>           }
>>       } else {
>> -        const NetLegacy *net = object;
>> -        const NetLegacyOptions *opts = net->opts;
>> -        legacy.id = net->id;
>> -        netdev = &legacy;
>> -
>> -        /* Map the old options to the new flat type */
>> -        switch (opts->type) {
>> -        case NET_LEGACY_OPTIONS_TYPE_NONE:
>> +        if (netdev->type == NET_CLIENT_DRIVER_NONE) {
>>               return 0; /* nothing to do */
> 
> 
>> -
>> -        if (!net_client_init_fun[netdev->type]) {
>> +        if (netdev->type == NET_CLIENT_DRIVER_HUBPORT ||
>> +            !net_client_init_fun[netdev->type]) {
>>               error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
>>                          "a net backend type (maybe it is not compiled "
>>                          "into this binary)");
> 
> So maybe we still want this legacy-handling code, but renaming
> 'is_netdev' to 'legacy_handling' may make more sense.

Hmm, maybe renaming would be good indeed to avoid confusion here... I'll
think about it.

>> @@ -1039,7 +995,7 @@ static int net_client_init1(const void *object,
>> bool is_netdev, Error **errp)
>>             /* Do not add to a hub if it's a nic with a netdev=
>> parameter. */
>>           if (netdev->type != NET_CLIENT_DRIVER_NIC ||
>> -            !opts->u.nic.has_netdev) {
>> +            !netdev->u.nic.has_netdev) {
>>               peer = net_hub_add_port(0, NULL, NULL);
>>           }
>>       }
>> @@ -1143,21 +1099,13 @@ static int net_client_init(QemuOpts *opts,
>> bool is_netdev, Error **errp)
>>           }
>>       }
>>   -    if (is_netdev) {
>> -        visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
>> -    } else {
>> -        visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
>> -    }
>> +    visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
> 
> Why do we need to cast?  If all callers are passing a Netdev, can't we
> just give 'object' the correct type to begin with?

Agreed, it should be possible to use Netdev* instead of void* for
"object" now. I'll change that in v3.

>> +++ b/qapi/net.json
>> @@ -453,7 +453,7 @@
>>   #        'l2tpv3' - since 2.1
>>   ##
>>   { 'union': 'Netdev',
>> -  'base': { 'id': 'str', 'type': 'NetClientDriver' },
>> +  'base': { '*id': 'str', 'type': 'NetClientDriver' },
> 
> I don't think we need to make 'id' optional.

It's required for "-net" now.

>>     'discriminator': 'type',
>>     'data': {
>>       'nic':      'NetLegacyNicOptions',
>> @@ -467,52 +467,6 @@
>>       'netmap':   'NetdevNetmapOptions',
>>       'vhost-user': 'NetdevVhostUserOptions' } }
>>   -##
>> -# @NetLegacy:
>> -#
>> -# Captures the configuration of a network device; legacy.
>> -#
>> -# @id: identifier for monitor commands
>> -#
>> -# @opts: device type specific properties (legacy)
>> -#
>> -# Since: 1.2
>> -##
>> -{ 'struct': 'NetLegacy',
>> -  'data': {
>> -    '*id':   'str',
>> -    'opts':  'NetLegacyOptions' } }
>> -
>> -##
>> -# @NetLegacyOptionsType:
>> -#
>> -# Since: 1.2
>> -##
>> -{ 'enum': 'NetLegacyOptionsType',
>> -  'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
>> -           'bridge', 'netmap', 'vhost-user'] }
> 
> NetLegacyOptionsType differs from NetClientDriver only by missing
> 'hubport', which your code above special-cased, so on that front, the
> simplification makes sense.

Thanks for your review!

 Thomas
Eric Blake May 12, 2020, 3:51 p.m. UTC | #3
On 5/12/20 10:13 AM, Thomas Huth wrote:

>>> +++ b/qapi/net.json
>>> @@ -453,7 +453,7 @@
>>>    #        'l2tpv3' - since 2.1
>>>    ##
>>>    { 'union': 'Netdev',
>>> -  'base': { 'id': 'str', 'type': 'NetClientDriver' },
>>> +  'base': { '*id': 'str', 'type': 'NetClientDriver' },
>>
>> I don't think we need to make 'id' optional.
> 
> It's required for "-net" now.

But does -net generate it's own id if one is not provided?  Can it still 
be mandatory in the QAPI type, and just figure out how to guarantee that 
the CLI parsing of -net provides a name early enough in the cycle to use 
the QAPI type without making the member optional there?
Thomas Huth May 13, 2020, 8:40 a.m. UTC | #4
On 12/05/2020 17.51, Eric Blake wrote:
> On 5/12/20 10:13 AM, Thomas Huth wrote:
> 
>>>> +++ b/qapi/net.json
>>>> @@ -453,7 +453,7 @@
>>>>    #        'l2tpv3' - since 2.1
>>>>    ##
>>>>    { 'union': 'Netdev',
>>>> -  'base': { 'id': 'str', 'type': 'NetClientDriver' },
>>>> +  'base': { '*id': 'str', 'type': 'NetClientDriver' },
>>>
>>> I don't think we need to make 'id' optional.
>>
>> It's required for "-net" now.
> 
> But does -net generate it's own id if one is not provided?  Can it still
> be mandatory in the QAPI type, and just figure out how to guarantee that
> the CLI parsing of -net provides a name early enough in the cycle to use
> the QAPI type without making the member optional there?

I guess it could be done - but we'd need to change the internal naming
scheme for this. Currently, the internal id / name is created with
assign_name() during qemu_net_client_setup() - which is the function
that is called from the individual network backends via
qemu_new_net_client() with a "model" string, e.g. net/slirp.c calls it
with model="user", net/tap.c calls it with model="bridge" etc.
The model string is then used in assign_name() to create the internal id
(aka. name in the NetClientState).

If we want to keep the "id" mandatory in the QAPI type, we have to
create the internal id before calling visit_type_Netdev() in
net_client_init(). But the "model" string information is not available
here yet, since this takes place before the init function of the backend
is called. Thus we'd need to come up with a different internal id string
here, e.g. something like "__org.qemu.net-xyz" like it is done in
net_param_nic() already. Do you think it is ok to change the internal
name / id here? I think it should be ok - if the users care about the id
of the netdevs, they should specify the ids on the command line and not
rely on some internal naming schemes... do you agree?

 Thomas
diff mbox series

Patch

diff --git a/net/net.c b/net/net.c
index a24da66e66..4177224939 100644
--- a/net/net.c
+++ b/net/net.c
@@ -967,13 +967,14 @@  static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
 
 static int net_client_init1(const void *object, bool is_netdev, Error **errp)
 {
-    Netdev legacy = {0};
-    const Netdev *netdev;
+    const Netdev *netdev = object;
     NetClientState *peer = NULL;
 
     if (is_netdev) {
-        netdev = object;
-
+        if (!netdev->has_id) {
+            error_setg(errp, QERR_MISSING_PARAMETER, "id");
+            return -1;
+        }
         if (netdev->type == NET_CLIENT_DRIVER_NIC ||
             !net_client_init_fun[netdev->type]) {
             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
@@ -981,56 +982,11 @@  static int net_client_init1(const void *object, bool is_netdev, Error **errp)
             return -1;
         }
     } else {
-        const NetLegacy *net = object;
-        const NetLegacyOptions *opts = net->opts;
-        legacy.id = net->id;
-        netdev = &legacy;
-
-        /* Map the old options to the new flat type */
-        switch (opts->type) {
-        case NET_LEGACY_OPTIONS_TYPE_NONE:
+        if (netdev->type == NET_CLIENT_DRIVER_NONE) {
             return 0; /* nothing to do */
-        case NET_LEGACY_OPTIONS_TYPE_NIC:
-            legacy.type = NET_CLIENT_DRIVER_NIC;
-            legacy.u.nic = opts->u.nic;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_USER:
-            legacy.type = NET_CLIENT_DRIVER_USER;
-            legacy.u.user = opts->u.user;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_TAP:
-            legacy.type = NET_CLIENT_DRIVER_TAP;
-            legacy.u.tap = opts->u.tap;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_L2TPV3:
-            legacy.type = NET_CLIENT_DRIVER_L2TPV3;
-            legacy.u.l2tpv3 = opts->u.l2tpv3;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_SOCKET:
-            legacy.type = NET_CLIENT_DRIVER_SOCKET;
-            legacy.u.socket = opts->u.socket;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_VDE:
-            legacy.type = NET_CLIENT_DRIVER_VDE;
-            legacy.u.vde = opts->u.vde;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_BRIDGE:
-            legacy.type = NET_CLIENT_DRIVER_BRIDGE;
-            legacy.u.bridge = opts->u.bridge;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_NETMAP:
-            legacy.type = NET_CLIENT_DRIVER_NETMAP;
-            legacy.u.netmap = opts->u.netmap;
-            break;
-        case NET_LEGACY_OPTIONS_TYPE_VHOST_USER:
-            legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
-            legacy.u.vhost_user = opts->u.vhost_user;
-            break;
-        default:
-            abort();
         }
-
-        if (!net_client_init_fun[netdev->type]) {
+        if (netdev->type == NET_CLIENT_DRIVER_HUBPORT ||
+            !net_client_init_fun[netdev->type]) {
             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
                        "a net backend type (maybe it is not compiled "
                        "into this binary)");
@@ -1039,7 +995,7 @@  static int net_client_init1(const void *object, bool is_netdev, Error **errp)
 
         /* Do not add to a hub if it's a nic with a netdev= parameter. */
         if (netdev->type != NET_CLIENT_DRIVER_NIC ||
-            !opts->u.nic.has_netdev) {
+            !netdev->u.nic.has_netdev) {
             peer = net_hub_add_port(0, NULL, NULL);
         }
     }
@@ -1143,21 +1099,13 @@  static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
         }
     }
 
-    if (is_netdev) {
-        visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
-    } else {
-        visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
-    }
+    visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
 
     if (!err) {
         ret = net_client_init1(object, is_netdev, &err);
     }
 
-    if (is_netdev) {
-        qapi_free_Netdev(object);
-    } else {
-        qapi_free_NetLegacy(object);
-    }
+    qapi_free_Netdev(object);
 
 out:
     error_propagate(errp, err);
diff --git a/qapi/net.json b/qapi/net.json
index fc7c95f6d8..e344825c43 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -453,7 +453,7 @@ 
 #        'l2tpv3' - since 2.1
 ##
 { 'union': 'Netdev',
-  'base': { 'id': 'str', 'type': 'NetClientDriver' },
+  'base': { '*id': 'str', 'type': 'NetClientDriver' },
   'discriminator': 'type',
   'data': {
     'nic':      'NetLegacyNicOptions',
@@ -467,52 +467,6 @@ 
     'netmap':   'NetdevNetmapOptions',
     'vhost-user': 'NetdevVhostUserOptions' } }
 
-##
-# @NetLegacy:
-#
-# Captures the configuration of a network device; legacy.
-#
-# @id: identifier for monitor commands
-#
-# @opts: device type specific properties (legacy)
-#
-# Since: 1.2
-##
-{ 'struct': 'NetLegacy',
-  'data': {
-    '*id':   'str',
-    'opts':  'NetLegacyOptions' } }
-
-##
-# @NetLegacyOptionsType:
-#
-# Since: 1.2
-##
-{ 'enum': 'NetLegacyOptionsType',
-  'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
-           'bridge', 'netmap', 'vhost-user'] }
-
-##
-# @NetLegacyOptions:
-#
-# Like Netdev, but for use only by the legacy command line options
-#
-# Since: 1.2
-##
-{ 'union': 'NetLegacyOptions',
-  'base': { 'type': 'NetLegacyOptionsType' },
-  'discriminator': 'type',
-  'data': {
-    'nic':      'NetLegacyNicOptions',
-    'user':     'NetdevUserOptions',
-    'tap':      'NetdevTapOptions',
-    'l2tpv3':   'NetdevL2TPv3Options',
-    'socket':   'NetdevSocketOptions',
-    'vde':      'NetdevVdeOptions',
-    'bridge':   'NetdevBridgeOptions',
-    'netmap':   'NetdevNetmapOptions',
-    'vhost-user': 'NetdevVhostUserOptions' } }
-
 ##
 # @NetFilterDirection:
 #