All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command
  2017-04-19 16:57 [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command ZhiPeng Lu
@ 2017-04-19  9:21 ` Daniel P. Berrange
  2017-04-19 11:41 ` Cornelia Huck
  2017-04-19 13:34 ` Eric Blake
  2 siblings, 0 replies; 6+ messages in thread
From: Daniel P. Berrange @ 2017-04-19  9:21 UTC (permalink / raw)
  To: ZhiPeng Lu; +Cc: mdroth, qemu-devel

On Thu, Apr 20, 2017 at 12:57:08AM +0800, ZhiPeng Lu wrote:
> we can get the  network card statistics inside  a virtual machine by
> guest-network-get-interface-stat command.
> it is very userful for us to monitor and analyze network traff.

In most cases you can already monitor guest network traffic from the
statistics on the QEMU backend device (ie tap device). The exception
is when doing PCI device assignment. Is the latter the reason why you
need to add this functionality instead of just quuerying the host
backend ?

There have been a lot of proposals for new QEMU geust agent commands in
the past few weeks

 - NIC statistics
 - Logged in users
 - Timezone offset
 - Hostname
 - OS version / product

This makes me wonder what our intended scope is for the guest agent ? Are we
happy to add arbitrary functionality to the guest agent, allowing it grow in
size & complexity without bound. Or is it better to restrict it to tasks which
are needed in order to coordinate management of the host virtualization layer
and leave general purpose guest OS management to another app.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command
  2017-04-19 16:57 [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command ZhiPeng Lu
  2017-04-19  9:21 ` Daniel P. Berrange
@ 2017-04-19 11:41 ` Cornelia Huck
  2017-04-19 11:50   ` Daniel P. Berrange
  2017-04-19 13:34 ` Eric Blake
  2 siblings, 1 reply; 6+ messages in thread
From: Cornelia Huck @ 2017-04-19 11:41 UTC (permalink / raw)
  To: ZhiPeng Lu; +Cc: mdroth, qemu-devel

On Thu, 20 Apr 2017 00:57:08 +0800
ZhiPeng Lu <lu.zhipeng@zte.com.cn> wrote:

> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> index a02dbf2..60111dc 100644
> --- a/qga/qapi-schema.json
> +++ b/qga/qapi-schema.json
> @@ -1042,3 +1042,37 @@
>    'data':    { 'path': 'str', '*arg': ['str'], '*env': ['str'],
>                 '*input-data': 'str', '*capture-output': 'bool' },
>    'returns': 'GuestExec' }
> +##
> +# @GuestNetworkInterfaceStat:
> +#
> +# @rx_bytes: received bytes of interface
> +#
> +# @rx_packets: received packets of interface
> +#
> +# @rx_errs: received error packets of interface
> +# @rx_drop: received drop packets of interface
> +#
> +# Since: 2.10
> +##
> +{ 'struct': 'GuestNetworkInterfaceStat',
> +  'data': {'rx_bytes': 'uint64',
> +            'rx_packets': 'uint64',
> +            'rx_errs': 'uint64',
> +            'rx_drop': 'uint64',
> +            'tx_bytes': 'uint64',
> +            'tx_packets': 'uint64',
> +            'tx_errs': 'uint64',
> +            'tx_drop': 'uint64'
> +           } }
> +##
> +# @guest-network-get-interface-stat:
> +#
> +# Get list of interface stat
> +#
> +# Returns: List of GuestNetworkInterfaceStat on success.
> +#
> +# Since: 2.10
> +##
> +{ 'command': 'guest-network-get-interface-stat',
> +  'data':    {'bus': 'int64', 'slot': 'int64', 'function': 'int64','netname':'str'},
> +  'returns': ['GuestNetworkInterfaceStat'] }

Disregarding the question whether this command should be added to the
guest agent (I'll leave that to others to discuss), I don't think it's
a good idea to enshrine pci identifiers here, as it means that we would
need to add a new interface for every non-pci network device.

Can you use a more general device identifier interface? It's fine to
only support pci for now (as that is likely your use case anyway), but
there should be a way to extend this in the future.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command
  2017-04-19 11:41 ` Cornelia Huck
@ 2017-04-19 11:50   ` Daniel P. Berrange
  2017-04-19 11:57     ` Cornelia Huck
  0 siblings, 1 reply; 6+ messages in thread
From: Daniel P. Berrange @ 2017-04-19 11:50 UTC (permalink / raw)
  To: Cornelia Huck; +Cc: ZhiPeng Lu, mdroth, qemu-devel

On Wed, Apr 19, 2017 at 01:41:47PM +0200, Cornelia Huck wrote:
> On Thu, 20 Apr 2017 00:57:08 +0800
> ZhiPeng Lu <lu.zhipeng@zte.com.cn> wrote:
> 
> > diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> > index a02dbf2..60111dc 100644
> > --- a/qga/qapi-schema.json
> > +++ b/qga/qapi-schema.json
> > @@ -1042,3 +1042,37 @@
> >    'data':    { 'path': 'str', '*arg': ['str'], '*env': ['str'],
> >                 '*input-data': 'str', '*capture-output': 'bool' },
> >    'returns': 'GuestExec' }
> > +##
> > +# @GuestNetworkInterfaceStat:
> > +#
> > +# @rx_bytes: received bytes of interface
> > +#
> > +# @rx_packets: received packets of interface
> > +#
> > +# @rx_errs: received error packets of interface
> > +# @rx_drop: received drop packets of interface
> > +#
> > +# Since: 2.10
> > +##
> > +{ 'struct': 'GuestNetworkInterfaceStat',
> > +  'data': {'rx_bytes': 'uint64',
> > +            'rx_packets': 'uint64',
> > +            'rx_errs': 'uint64',
> > +            'rx_drop': 'uint64',
> > +            'tx_bytes': 'uint64',
> > +            'tx_packets': 'uint64',
> > +            'tx_errs': 'uint64',
> > +            'tx_drop': 'uint64'
> > +           } }
> > +##
> > +# @guest-network-get-interface-stat:
> > +#
> > +# Get list of interface stat
> > +#
> > +# Returns: List of GuestNetworkInterfaceStat on success.
> > +#
> > +# Since: 2.10
> > +##
> > +{ 'command': 'guest-network-get-interface-stat',
> > +  'data':    {'bus': 'int64', 'slot': 'int64', 'function': 'int64','netname':'str'},
> > +  'returns': ['GuestNetworkInterfaceStat'] }
> 
> Disregarding the question whether this command should be added to the
> guest agent (I'll leave that to others to discuss), I don't think it's
> a good idea to enshrine pci identifiers here, as it means that we would
> need to add a new interface for every non-pci network device.
> 
> Can you use a more general device identifier interface? It's fine to
> only support pci for now (as that is likely your use case anyway), but
> there should be a way to extend this in the future.

It would be better to match the identification approach uses for the
existing guest-network-get-interfaces command, which is based on MAC
address. Arguably the stats data could just be added to this existnig
command instead of adding a new command.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command
  2017-04-19 11:50   ` Daniel P. Berrange
@ 2017-04-19 11:57     ` Cornelia Huck
  0 siblings, 0 replies; 6+ messages in thread
From: Cornelia Huck @ 2017-04-19 11:57 UTC (permalink / raw)
  To: Daniel P. Berrange; +Cc: ZhiPeng Lu, mdroth, qemu-devel

On Wed, 19 Apr 2017 12:50:36 +0100
"Daniel P. Berrange" <berrange@redhat.com> wrote:

> On Wed, Apr 19, 2017 at 01:41:47PM +0200, Cornelia Huck wrote:
> > On Thu, 20 Apr 2017 00:57:08 +0800
> > ZhiPeng Lu <lu.zhipeng@zte.com.cn> wrote:
> > 
> > > diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> > > index a02dbf2..60111dc 100644
> > > --- a/qga/qapi-schema.json
> > > +++ b/qga/qapi-schema.json
> > > @@ -1042,3 +1042,37 @@
> > >    'data':    { 'path': 'str', '*arg': ['str'], '*env': ['str'],
> > >                 '*input-data': 'str', '*capture-output': 'bool' },
> > >    'returns': 'GuestExec' }
> > > +##
> > > +# @GuestNetworkInterfaceStat:
> > > +#
> > > +# @rx_bytes: received bytes of interface
> > > +#
> > > +# @rx_packets: received packets of interface
> > > +#
> > > +# @rx_errs: received error packets of interface
> > > +# @rx_drop: received drop packets of interface
> > > +#
> > > +# Since: 2.10
> > > +##
> > > +{ 'struct': 'GuestNetworkInterfaceStat',
> > > +  'data': {'rx_bytes': 'uint64',
> > > +            'rx_packets': 'uint64',
> > > +            'rx_errs': 'uint64',
> > > +            'rx_drop': 'uint64',
> > > +            'tx_bytes': 'uint64',
> > > +            'tx_packets': 'uint64',
> > > +            'tx_errs': 'uint64',
> > > +            'tx_drop': 'uint64'
> > > +           } }
> > > +##
> > > +# @guest-network-get-interface-stat:
> > > +#
> > > +# Get list of interface stat
> > > +#
> > > +# Returns: List of GuestNetworkInterfaceStat on success.
> > > +#
> > > +# Since: 2.10
> > > +##
> > > +{ 'command': 'guest-network-get-interface-stat',
> > > +  'data':    {'bus': 'int64', 'slot': 'int64', 'function': 'int64','netname':'str'},
> > > +  'returns': ['GuestNetworkInterfaceStat'] }
> > 
> > Disregarding the question whether this command should be added to the
> > guest agent (I'll leave that to others to discuss), I don't think it's
> > a good idea to enshrine pci identifiers here, as it means that we would
> > need to add a new interface for every non-pci network device.
> > 
> > Can you use a more general device identifier interface? It's fine to
> > only support pci for now (as that is likely your use case anyway), but
> > there should be a way to extend this in the future.
> 
> It would be better to match the identification approach uses for the
> existing guest-network-get-interfaces command, which is based on MAC
> address. Arguably the stats data could just be added to this existnig
> command instead of adding a new command.

Agreed, that sounds like a better choice.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command
  2017-04-19 16:57 [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command ZhiPeng Lu
  2017-04-19  9:21 ` Daniel P. Berrange
  2017-04-19 11:41 ` Cornelia Huck
@ 2017-04-19 13:34 ` Eric Blake
  2 siblings, 0 replies; 6+ messages in thread
From: Eric Blake @ 2017-04-19 13:34 UTC (permalink / raw)
  To: ZhiPeng Lu, mdroth; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2069 bytes --]

On 04/19/2017 11:57 AM, ZhiPeng Lu wrote:
> we can get the  network card statistics inside  a virtual machine by guest-network-get-interface-stat command.
> it is very userful for us to monitor and analyze network traff.
> 
> Signed-off-by: ZhiPeng Lu <lu.zhipeng@zte.com.cn>
> ---

> +++ b/qga/qapi-schema.json
> @@ -1042,3 +1042,37 @@
>    'data':    { 'path': 'str', '*arg': ['str'], '*env': ['str'],
>                 '*input-data': 'str', '*capture-output': 'bool' },
>    'returns': 'GuestExec' }
> +##
> +# @GuestNetworkInterfaceStat:
> +#
> +# @rx_bytes: received bytes of interface
> +#
> +# @rx_packets: received packets of interface
> +#
> +# @rx_errs: received error packets of interface
> +# @rx_drop: received drop packets of interface

New interfaces should favor the use of '-' rather than '_', as in
'rx-bytes', 'rx-packets'...

> +#
> +# Since: 2.10
> +##
> +{ 'struct': 'GuestNetworkInterfaceStat',
> +  'data': {'rx_bytes': 'uint64',
> +            'rx_packets': 'uint64',
> +            'rx_errs': 'uint64',
> +            'rx_drop': 'uint64',
> +            'tx_bytes': 'uint64',
> +            'tx_packets': 'uint64',
> +            'tx_errs': 'uint64',
> +            'tx_drop': 'uint64'

You only documented four fields, but have a lot more in the structure.

> +           } }
> +##
> +# @guest-network-get-interface-stat:
> +#
> +# Get list of interface stat
> +#
> +# Returns: List of GuestNetworkInterfaceStat on success.
> +#
> +# Since: 2.10
> +##
> +{ 'command': 'guest-network-get-interface-stat',
> +  'data':    {'bus': 'int64', 'slot': 'int64', 'function': 'int64','netname':'str'},

Are all of these parameters requires on every invocation, or are they
optional for filtering the results but with an intent to allow them to
be omitted to get a full list at once?

Missing documentation.

> +  'returns': ['GuestNetworkInterfaceStat'] }
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command
@ 2017-04-19 16:57 ZhiPeng Lu
  2017-04-19  9:21 ` Daniel P. Berrange
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: ZhiPeng Lu @ 2017-04-19 16:57 UTC (permalink / raw)
  To: mdroth; +Cc: qemu-devel, ZhiPeng Lu

we can get the  network card statistics inside  a virtual machine by guest-network-get-interface-stat command.
it is very userful for us to monitor and analyze network traff.

Signed-off-by: ZhiPeng Lu <lu.zhipeng@zte.com.cn>
---
 qga/commands-posix.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 qga/commands-win32.c |   6 ++
 qga/qapi-schema.json |  34 +++++++++++
 3 files changed, 205 insertions(+), 1 deletion(-)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 915df9e..3166bf4 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2357,6 +2357,163 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
 
     return info;
 }
+static int ga_get_netname(int bus, int dev, int func, char *netname,
+           int name_len)
+{
+    int cnt = 0;
+    int result = -1;
+
+    FILE *pfilein = NULL;
+
+    bool findnet = false;
+    char *netpos = NULL;
+
+    char netstr[32] = {0};
+    char buffer[1024] = {0};
+
+    if (NULL == netname) {
+        return -1;
+    }
+    snprintf(netstr, 31, "%02x:%02x.%01x", bus, dev, func);
+    g_debug("qga net pci is : %s ", netstr);
+
+    pfilein = popen("ls -l /sys/class/net", "r");
+    if (NULL == pfilein) {
+        g_debug("failed to do shell command for [%s] getting net name", netstr);
+        return -1;
+    }
+
+    while (fgets(buffer, 1023, pfilein) != NULL) {
+        if (strstr(buffer, netstr)) {
+            findnet = true;
+            g_debug("find pci  [%s] net string: %s", netstr, buffer);
+            break;
+        }
+    }
+
+    result = ferror(pfilein);
+    if (pclose(pfilein) || result) {
+        g_debug("error happened while finding pci [%s] net string", netstr);
+        return -1;
+    }
+
+    if (!findnet) {
+        g_debug("didn't finding bdf [%s] block string", netstr);
+        return -1;
+    }
+
+    netpos = strrchr(buffer, '/');
+    if (NULL == netpos) {
+        g_debug("can't get net name for [%s]", netstr);
+        return -1;
+    }
+
+    netpos++;
+    if (name_len < strlen(netpos)) {
+        g_debug("net name buffer of [%s] is not enough", netstr);
+        return -1;
+    }
+
+    cnt = 0;
+    while (('\0' != *netpos) && ('\n' != *netpos)) {
+        netname[cnt] = *netpos;
+        cnt++;
+        netpos++;
+    }
+    netname[cnt] = '\0';
+
+    if ('\0' == netname[0]) {
+        g_debug("net name for pci  [%s] is invalid", netstr);
+        return -1;
+    }
+
+    g_debug("succeed to get pci [%s] actual net name: %s", netstr, netname);
+    return 0;
+}
+
+
+static int ga_get_net_stats(const char *path,
+                     GuestNetworkInterfaceStat *stats)
+{
+    int path_len;
+    FILE *fp;
+    char line[256], *colon;
+
+    fp = fopen("/proc/net/dev", "r");
+    if (!fp) {
+        slog("Could not open /proc/net/dev");
+        return -1;
+    }
+    path_len = strlen(path);
+    while (fgets(line, sizeof(line), fp)) {
+        long long dummy;
+        long long rx_bytes;
+        long long rx_packets;
+        long long rx_errs;
+        long long rx_drop;
+        long long tx_bytes;
+        long long tx_packets;
+        long long tx_errs;
+        long long tx_drop;
+
+        /* The line looks like:
+ *          *   "   eth0:..."
+ *                   * Split it at the colon.
+ *                            */
+        colon = strchr(line, ':');
+        if (!colon) {
+            continue;
+        }
+        *colon = '\0';
+        if (colon - path_len >= line && strcmp(colon - path_len, path) == 0) {
+            if (sscanf(colon + 1,
+                "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
+                &rx_bytes, &rx_packets, &rx_errs, &rx_drop,
+                &dummy, &dummy, &dummy, &dummy,
+                &tx_bytes, &tx_packets, &tx_errs, &tx_drop,
+                &dummy, &dummy, &dummy, &dummy) != 16) {
+                continue;
+            }
+            stats->rx_bytes = rx_bytes;
+            stats->rx_packets = rx_packets;
+            stats->rx_errs = rx_errs;
+            stats->rx_drop = rx_drop;
+            stats->tx_bytes = tx_bytes;
+            stats->tx_packets = tx_packets;
+            stats->tx_errs = tx_errs;
+            stats->tx_drop = tx_drop;
+            fclose(fp);
+            return 0;
+        }
+    }
+    fclose(fp);
+
+    g_debug("/proc/net/dev: Interface not found");
+    return -1;
+}
+
+GuestNetworkInterfaceStatList *qmp_guest_network_get_interface_stat(int64_t bus,
+    int64_t slot, int64_t function, const char *netname, Error **errp)
+{
+    char guestnetname[14] = {0};
+    GuestNetworkInterfaceStat *info = NULL;
+    GuestNetworkInterfaceStatList *new, *ret = NULL;
+    if (ga_get_netname(bus, slot,
+        function, guestnetname, sizeof(guestnetname))) {
+        return NULL;
+    }
+    info = g_malloc0(sizeof(*info));
+    if (ga_get_net_stats(guestnetname, info)) {
+        g_free(info);
+        return NULL;
+    }
+
+    new = g_malloc(sizeof(*ret));
+    new->value = info;
+    new->next = ret;
+    ret = new;
+    return ret;
+}
 
 #else /* defined(__linux__) */
 
@@ -2419,6 +2576,12 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
     error_setg(errp, QERR_UNSUPPORTED);
     return NULL;
 }
+GuestNetworkInterfaceStatList *qmp_guest_network_get_interface_stat(int64_t bus,
+   int64_t slot, int64_t function, const char *netname, Error **errp)
+{
+    error_setg(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
 
 #endif
 
@@ -2480,7 +2643,8 @@ GList *ga_command_blacklist_init(GList *blacklist)
             "guest-suspend-hybrid", "guest-network-get-interfaces",
             "guest-get-vcpus", "guest-set-vcpus",
             "guest-get-memory-blocks", "guest-set-memory-blocks",
-            "guest-get-memory-block-size", NULL};
+            "guest-get-memory-block-size",
+            "guest-network-get-interfaces-stat", NULL};
         char **p = (char **)list;
 
         while (*p) {
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 19d72b2..dee939c 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -1497,6 +1497,12 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
     error_setg(errp, QERR_UNSUPPORTED);
     return NULL;
 }
+GuestNetworkInterfaceStatList *qmp_guest_network_get_interface_stat(int64_t bus,
+   int64_t slot, int64_t function, const char *netname, Error **errp)
+{
+    error_setg(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
 
 /* add unsupported commands to the blacklist */
 GList *ga_command_blacklist_init(GList *blacklist)
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index a02dbf2..60111dc 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1042,3 +1042,37 @@
   'data':    { 'path': 'str', '*arg': ['str'], '*env': ['str'],
                '*input-data': 'str', '*capture-output': 'bool' },
   'returns': 'GuestExec' }
+##
+# @GuestNetworkInterfaceStat:
+#
+# @rx_bytes: received bytes of interface
+#
+# @rx_packets: received packets of interface
+#
+# @rx_errs: received error packets of interface
+# @rx_drop: received drop packets of interface
+#
+# Since: 2.10
+##
+{ 'struct': 'GuestNetworkInterfaceStat',
+  'data': {'rx_bytes': 'uint64',
+            'rx_packets': 'uint64',
+            'rx_errs': 'uint64',
+            'rx_drop': 'uint64',
+            'tx_bytes': 'uint64',
+            'tx_packets': 'uint64',
+            'tx_errs': 'uint64',
+            'tx_drop': 'uint64'
+           } }
+##
+# @guest-network-get-interface-stat:
+#
+# Get list of interface stat
+#
+# Returns: List of GuestNetworkInterfaceStat on success.
+#
+# Since: 2.10
+##
+{ 'command': 'guest-network-get-interface-stat',
+  'data':    {'bus': 'int64', 'slot': 'int64', 'function': 'int64','netname':'str'},
+  'returns': ['GuestNetworkInterfaceStat'] }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-04-19 13:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-19 16:57 [Qemu-devel] [PATCH] qemu-ga: add guest-network-get-interface-stat command ZhiPeng Lu
2017-04-19  9:21 ` Daniel P. Berrange
2017-04-19 11:41 ` Cornelia Huck
2017-04-19 11:50   ` Daniel P. Berrange
2017-04-19 11:57     ` Cornelia Huck
2017-04-19 13:34 ` Eric Blake

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.