All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <lvivier@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, "Eric Blake" <eblake@redhat.com>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Daniel P. Berrangé" <berrange@redhat.com>,
	"Jason Wang" <jasowang@redhat.com>,
	"Stefano Brivio" <sbrivio@redhat.com>
Subject: Re: [RFC PATCH v3 04/11] qapi: net: add stream and dgram netdevs
Date: Mon, 20 Jun 2022 19:52:01 +0200	[thread overview]
Message-ID: <7eb9f5a3-5166-ee8d-86f8-1d05770331f6@redhat.com> (raw)
In-Reply-To: <874k0fz7gg.fsf@pond.sub.org>

On 20/06/2022 17:21, Markus Armbruster wrote:
> Laurent Vivier <lvivier@redhat.com> writes:
> 
>> Copied from socket netdev file and modified to use SocketAddress
>> to be able to introduce new features like unix socket.
>>
>> "udp" and "mcast" are squashed into dgram netdev, multicast is detected
>> according to the IP address type.
>> "listen" and "connect" modes are managed by stream netdev. An optional
>> parameter "server" defines the mode (server by default)
>>
>> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
>> Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
>> ---
>>   hmp-commands.hx |   2 +-
>>   net/clients.h   |   6 +
>>   net/dgram.c     | 630 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   net/hub.c       |   2 +
>>   net/meson.build |   2 +
>>   net/net.c       |  19 +-
>>   net/stream.c    | 425 ++++++++++++++++++++++++++++++++
>>   qapi/net.json   |  40 ++-
>>   qemu-options.hx |  12 +
>>   9 files changed, 1133 insertions(+), 5 deletions(-)
>>   create mode 100644 net/dgram.c
>>   create mode 100644 net/stream.c
>>
...
>> diff --git a/net/dgram.c b/net/dgram.c
>> new file mode 100644
>> index 000000000000..aa4240501ed0
>> --- /dev/null
>> +++ b/net/dgram.c
>> @@ -0,0 +1,630 @@
>> +/*
>> + * QEMU System Emulator
>> + *
>> + * Copyright (c) 2003-2008 Fabrice Bellard
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>> + * of this software and associated documentation files (the "Software"), to deal
>> + * in the Software without restriction, including without limitation the rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>> + * THE SOFTWARE.
>> + */
> 
> Blank line here, please.

Done

...

>> diff --git a/net/net.c b/net/net.c
>> index c337d3d753fe..440957b272ee 100644
>> --- a/net/net.c
>> +++ b/net/net.c
...
>> @@ -1612,7 +1617,19 @@ void net_init_clients(void)
>>    */
>>   static bool netdev_is_modern(const char *optarg)
>>   {
>> -    return false;
>> +    QDict *args;
>> +    const char *type;
>> +    bool is_modern;
>> +
>> +    args = keyval_parse(optarg, "type", NULL, NULL);
>> +    if (!args) {
>> +        return false;
>> +    }
>> +    type = qdict_get_try_str(args, "type");
>> +    is_modern = !g_strcmp0(type, "stream") || !g_strcmp0(type, "dgram");
>> +    qobject_unref(args);
>> +
>> +    return is_modern;
>>   }
> 
> You could use g_autoptr here:
> 
>         g_autoptr(QDict) args = NULL;
>         const char *type;
>         bool is_modern;
> 
>         args = keyval_parse(optarg, "type", NULL, NULL);
>         if (!args) {
>             return false;
>         }
>         type = qdict_get_try_str(args, "type");
>         return !g_strcmp0(type, "stream") || !g_strcmp0(type, "dgram");
> 
> Matter of taste; you decide.

Looks good. We already had some series to convert existing code to g_autoptr(), so it 
seems the way to do.

> 
> Now recall how this function is used: it decides whether to parse the
> modern way (with qobject_input_visitor_new_str()) or the traditional way
> (with qemu_opts_parse_noisily()).
> 
> qemu_opts_parse_noisily() parses into a QemuOpts, for later use with the
> opts visitor.
> 
> qobject_input_visitor_new_str() supports both dotted keys and JSON.  The
> former is parsed with keyval_parse(), the latter with
> qobject_from_json().  It returns the resulting parse tree wrapped in a
> suitable QAPI input visitor.
> 
> Issue 1: since we get there only when keyval_parse() succeeds, JSON is
> unreachable.  Reproducer:
> 
>      $ qemu-system-x86_64 -netdev '{"id":"foo"}'
>      upstream-qemu: -netdev {"id":"foo"}: Parameter 'id' is missing
> 
> This is parsed with qemu_opts_parse_noisily(), resulting in a QemuOpts
> with a single option 'type' with value '{"id":"foo"}'.  The error
> message comes from the opts visitor.
> 
> To fix this, make netdev_is_modern() return true when optarg[0] == '{'.
> This matches how qobject_input_visitor_new_str() recognizes JSON.

OK

> 
> Issue 2: when keyval_parse() detects an error, we throw it away and fall
> back to QemuOpts.  This is commonly what we want.  But not always.  For
> instance:
> 
>      $ qemu-system-x86_64 -netdev 'type=stream,id=foo,addr.type=inet,addr.host=localhost,addr.port=1234,addr.ipv4-off'
> 
> Note the typo "ipv4-off" instead of ipv4=off.  The error reporting is crap:
> 
>      qemu-system-x86_64: -netdev type=stream,id=foo,addr.type=inet,addr.host=localhost,addr.port=1234,addr.ipv4-off: warning: short-form boolean option 'addr.ipv4-off' deprecated
>      Please use addr.ipv4-off=on instead
>      qemu-system-x86_64: -netdev type=stream,id=foo,addr.type=inet,addr.host=localhost,addr.port=1234,addr.ipv4-off: Parameter 'type' is missing
> 
> We get this because netdev_is_modern() guesses wrongly: keyval_parse()
> fails with the perfectly reasonable error message "Expected '=' after
> parameter 'addr.ipv4-off'", but netdev_is_modern() ignores the error,
> and fails.  We fall back to QemuOpts, and confusion ensues.
> 
> I'm not sure we can do much better with reasonable effort.  If we decide
> to accept this behavior, it should be documented at least in the source
> code.

What about using modern syntax by default?

     args = keyval_parse(optarg, "type", NULL, NULL);
     if (!args) {
         /* cannot detect the syntax, use new style syntax */
         return true;
     }

>>   
>>   /*
>> diff --git a/net/stream.c b/net/stream.c
>> new file mode 100644
>> index 000000000000..fdc97ee43a56
>> --- /dev/null
>> +++ b/net/stream.c
>> @@ -0,0 +1,425 @@
>> +/*
>> + * QEMU System Emulator
>> + *
>> + * Copyright (c) 2003-2008 Fabrice Bellard
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>> + * of this software and associated documentation files (the "Software"), to deal
>> + * in the Software without restriction, including without limitation the rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>> + * THE SOFTWARE.
>> + */
> 
> Blank line here, please.

Done

...
>> diff --git a/qapi/net.json b/qapi/net.json
>> index d6f7cfd4d656..5f72995b1d24 100644
>> --- a/qapi/net.json
>> +++ b/qapi/net.json
...
>> @@ -566,6 +567,37 @@
>>       '*isolated':  'bool' },
>>     'if': 'CONFIG_VMNET' }
>>   
>> +##
>> +# @NetdevStreamOptions:
>> +#
>> +# Configuration info for stream socket netdev
>> +#
>> +# @addr: socket address to listen on (server=true)
>> +#        or connect to (server=false)
>> +# @server: create server socket (default: true)
>> +#
>> +# Since: 7.1
>> +##
>> +{ 'struct': 'NetdevStreamOptions',
>> +  'data': {
>> +    'addr':   'SocketAddress',
>> +    '*server': 'bool' } }
>> +
>> +##
>> +# @NetdevDgramOptions:
>> +#
>> +# Configuration info for datagram socket netdev.
>> +#
>> +# @remote: remote address
>> +# @local: local address
>> +#
>> +# Since: 7.1
>> +##
>> +{ 'struct': 'NetdevDgramOptions',
>> +  'data': {
>> +    '*local':  'SocketAddress',
>> +    '*remote': 'SocketAddress' } }
> 
> In review of v2, I inquired about behavior when members are absent.
> You wrote:
> 
>      The code checks there is at least one of these options and reports an error if not.
> 
>      if remote address is present and it's a multicast address, local address is optional.
> 
>      otherwise local address is required and remote address is optional.
> 
> Please work that into the doc comment.

OK

> 
>> +
>>   ##
>>   # @NetClientDriver:
>>   #
>> @@ -579,9 +611,9 @@
>>   #        @vmnet-bridged since 7.1
>>   ##
>>   { 'enum': 'NetClientDriver',
>> -  'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
>> -            'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa',
>> -            { 'name': 'vmnet-host', 'if': 'CONFIG_VMNET' },
>> +  'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'stream',
>> +            'dgram', 'vde', 'bridge', 'hubport', 'netmap', 'vhost-user',
>> +            'vhost-vdpa', { 'name': 'vmnet-host', 'if': 'CONFIG_VMNET' },
>>               { 'name': 'vmnet-shared', 'if': 'CONFIG_VMNET' },
>>               { 'name': 'vmnet-bridged', 'if': 'CONFIG_VMNET' }] }
> 
> Opportunity to put vmnet-host on its own line for readability.
> 

OK

Thanks,
Laurent



  reply	other threads:[~2022-06-20 17:55 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-20 10:18 [RFC PATCH v3 00/11] qapi: net: add unix socket type support to netdev backend Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 01/11] net: introduce convert_host_port() Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 02/11] net: remove the @errp argument of net_client_inits() Laurent Vivier
2022-06-20 11:39   ` Markus Armbruster
2022-06-20 10:18 ` [RFC PATCH v3 03/11] qapi: net: introduce a way to bypass qemu_opts_parse_noisily() Laurent Vivier
2022-06-20 12:43   ` Markus Armbruster
2022-06-20 13:46     ` Laurent Vivier
2022-06-22  8:00   ` Markus Armbruster
2022-06-20 10:18 ` [RFC PATCH v3 04/11] qapi: net: add stream and dgram netdevs Laurent Vivier
2022-06-20 15:21   ` Markus Armbruster
2022-06-20 17:52     ` Laurent Vivier [this message]
2022-06-21  8:49       ` Markus Armbruster
2022-06-21 19:27         ` Laurent Vivier
2022-06-22 11:47           ` Markus Armbruster
2022-06-22 16:18             ` Laurent Vivier
2022-06-23 12:49               ` Markus Armbruster
2022-06-20 10:18 ` [RFC PATCH v3 05/11] net: stream: Don't ignore EINVAL on netdev socket connection Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 06/11] net: stream: add unix socket Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 07/11] net: dgram: make dgram_dst generic Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 08/11] net: dgram: move mcast specific code from net_socket_fd_init_dgram() Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 09/11] net: dgram: add unix socket Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 10/11] qemu-sockets: introduce socket_uri() Laurent Vivier
2022-06-20 10:18 ` [RFC PATCH v3 11/11] net: stream: move to QIO Laurent Vivier
2022-06-20 18:24 ` [RFC PATCH v3 00/11] qapi: net: add unix socket type support to netdev backend Dr. David Alan Gilbert
2022-06-21  9:51   ` Laurent Vivier
2022-06-21 10:31     ` Dr. David Alan Gilbert
2022-06-21 10:54       ` Daniel P. Berrangé
2022-06-21 12:16         ` Dr. David Alan Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7eb9f5a3-5166-ee8d-86f8-1d05770331f6@redhat.com \
    --to=lvivier@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=eblake@redhat.com \
    --cc=jasowang@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.