* [PATCH 8/9] perf, bpf: enable annotation of bpf program
From: Song Liu @ 2019-02-09 1:21 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, kernel-team, peterz, acme, Song Liu
In-Reply-To: <20190209012142.2177204-1-songliubraving@fb.com>
This patch enables the annotation of bpf program.
A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
calls into a new function symbol__disassemble_bpf(), where annotation
line information is filled based bpf_prog_info and btf saved in given
perf_env.
symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
tools/perf/Makefile.config | 2 +-
tools/perf/util/annotate.c | 149 +++++++++++++++++++++++++++++++++++-
tools/perf/util/bpf-event.c | 48 ++++++++++++
tools/perf/util/bpf-event.h | 4 +
tools/perf/util/dso.c | 1 +
tools/perf/util/dso.h | 33 +++++---
tools/perf/util/symbol.c | 1 +
7 files changed, 225 insertions(+), 13 deletions(-)
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index b441c88cafa1..e0bafbc273af 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -701,7 +701,7 @@ else
endif
ifeq ($(feature-libbfd), 1)
- EXTLIBS += -lbfd
+ EXTLIBS += -lbfd -lopcodes
else
# we are on a system that requires -liberty and (maybe) -lz
# to link against -lbfd; test each case individually here
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 70de8f6b3aee..078017d31ca9 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -22,6 +22,7 @@
#include "annotate.h"
#include "evsel.h"
#include "evlist.h"
+#include "bpf-event.h"
#include "block-range.h"
#include "string2.h"
#include "arch/common.h"
@@ -29,6 +30,9 @@
#include <pthread.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
+#include <bfd.h>
+#include <dis-asm.h>
+#include <bpf/libbpf.h>
/* FIXME: For the HE_COLORSET */
#include "ui/browser.h"
@@ -1672,6 +1676,147 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
return 0;
}
+static void get_exec_path(char *tpath, size_t size)
+{
+ const char *path = "/proc/self/exe";
+ ssize_t len;
+
+ len = readlink(path, tpath, size - 1);
+ assert(len > 0);
+ tpath[len] = 0;
+}
+
+static int symbol__disassemble_bpf(struct symbol *sym,
+ struct annotate_args *args)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ struct annotation_options *opts = args->options;
+ struct bpf_prog_info_linear *info_linear;
+ struct bpf_prog_linfo *prog_linfo = NULL;
+ struct bpf_prog_info_node *info_node;
+ int len = sym->end - sym->start;
+ disassembler_ftype disassemble;
+ struct map *map = args->ms.map;
+ struct disassemble_info info;
+ struct dso *dso = map->dso;
+ int pc = 0, count, sub_id;
+ struct btf *btf = NULL;
+ char tpath[PATH_MAX];
+ size_t buf_size;
+ int nr_skip = 0;
+ __u64 arrays;
+ char *buf;
+ bfd *bfdf;
+ FILE *s;
+
+ if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
+ return -1;
+
+ pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
+ sym->name, sym->start, sym->end - sym->start);
+
+ memset(tpath, 0, sizeof(tpath));
+ get_exec_path(tpath, sizeof(tpath));
+
+ bfdf = bfd_openr(tpath, NULL);
+ assert(bfdf);
+ assert(bfd_check_format(bfdf, bfd_object));
+
+ s = open_memstream(&buf, &buf_size);
+ init_disassemble_info(&info, s,
+ (fprintf_ftype) fprintf);
+
+ info.arch = bfd_get_arch(bfdf);
+ info.mach = bfd_get_mach(bfdf);
+
+ arrays = 1UL << BPF_PROG_INFO_JITED_INSNS;
+ arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS;
+ arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
+ arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
+
+ info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
+ dso->bpf_prog.id);
+ if (!info_node)
+ return -1;
+ info_linear = info_node->info_linear;
+ sub_id = dso->bpf_prog.sub_id;
+
+ info.buffer = (void *)(info_linear->info.jited_prog_insns);
+ info.buffer_length = info_linear->info.jited_prog_len;
+
+ if (info_linear->info.nr_line_info)
+ prog_linfo = bpf_prog_linfo__new(&info_linear->info);
+ prog_linfo = prog_linfo;
+
+ if (info_linear->info.btf_id) {
+ struct btf_node *node;
+
+ node = perf_env__find_btf(dso->bpf_prog.env,
+ info_linear->info.btf_id);
+ if (node)
+ btf = btf__new((__u8 *)(node->data),
+ node->data_size);
+ }
+
+ disassemble_init_for_target(&info);
+
+#ifdef DISASM_FOUR_ARGS_SIGNATURE
+ disassemble = disassembler(info.arch,
+ bfd_big_endian(bfdf),
+ info.mach,
+ bfdf);
+#else
+ disassemble = disassembler(bfdf);
+#endif
+ assert(disassemble);
+
+ fflush(s);
+ do {
+ const struct bpf_line_info *linfo = NULL;
+ struct disasm_line *dl;
+ size_t prev_buf_size;
+ const char *srcline;
+ u64 addr;
+
+ addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
+ count = disassemble(pc, &info);
+
+ linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo, addr, sub_id,
+ nr_skip);
+
+ if (linfo) {
+ srcline = btf__name_by_offset(btf, linfo->line_off);
+ nr_skip++;
+ } else
+ srcline = NULL;
+
+ fprintf(s, "\n");
+ prev_buf_size = buf_size;
+ fflush(s);
+
+ if (!opts->hide_src_code && srcline) {
+ args->offset = -1;
+ args->line = strdup(srcline);
+ args->line_nr = 0;
+ args->ms.sym = sym;
+ dl = disasm_line__new(args);
+ annotation_line__add(&dl->al, ¬es->src->source);
+ }
+
+ args->offset = pc;
+ args->line = buf + prev_buf_size;
+ args->line_nr = 0;
+ args->ms.sym = sym;
+ dl = disasm_line__new(args);
+ annotation_line__add(&dl->al, ¬es->src->source);
+
+ pc += count;
+ } while (count > 0 && pc < len);
+
+ bfd_close(bfdf);
+ return 0;
+}
+
static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
{
struct annotation_options *opts = args->options;
@@ -1699,7 +1844,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
pr_debug("annotating [%p] %30s : [%p] %30s\n",
dso, dso->long_name, sym, sym->name);
- if (dso__is_kcore(dso)) {
+ if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
+ return symbol__disassemble_bpf(sym, args);
+ } else if (dso__is_kcore(dso)) {
kce.kcore_filename = symfs_filename;
kce.addr = map__rip_2objdump(map, sym->start);
kce.offs = sym->start;
diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
index 37a5b8134e00..4f347d61ed96 100644
--- a/tools/perf/util/bpf-event.c
+++ b/tools/perf/util/bpf-event.c
@@ -21,12 +21,60 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len)
return ret;
}
+static int machine__process_bpf_event_load(struct machine *machine __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample __maybe_unused)
+{
+ struct bpf_prog_info_linear *info_linear;
+ struct bpf_prog_info_node *info_node;
+ struct perf_env *env = machine->env;
+ int id = event->bpf_event.id;
+ unsigned int i;
+
+ /* perf-record, no need to handle bpf-event */
+ if (env == NULL)
+ return 0;
+
+ info_node = perf_env__find_bpf_prog_info(env, id);
+ if (!info_node)
+ return 0;
+ info_linear = info_node->info_linear;
+
+ for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) {
+ u64 *addrs = (u64 *)(info_linear->info.jited_ksyms);
+ u64 addr = addrs[i];
+ struct map *map;
+
+ map = map_groups__find(&machine->kmaps, addr);
+
+ if (map) {
+ map->dso->binary_type = DSO_BINARY_TYPE__BPF_PROG_INFO;
+ map->dso->bpf_prog.id = id;
+ map->dso->bpf_prog.sub_id = i;
+ map->dso->bpf_prog.env = env;
+ }
+ }
+ return 0;
+}
+
int machine__process_bpf_event(struct machine *machine __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused)
{
if (dump_trace)
perf_event__fprintf_bpf_event(event, stdout);
+
+ switch (event->bpf_event.type) {
+ case PERF_BPF_EVENT_PROG_LOAD:
+ return machine__process_bpf_event_load(machine, event, sample);
+
+ case PERF_BPF_EVENT_PROG_UNLOAD:
+ break;
+ default:
+ pr_debug("unexpected bpf_event type of %d\n",
+ event->bpf_event.type);
+ break;
+ }
return 0;
}
diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h
index 60ce24e4e5c6..c4f0f1395ea5 100644
--- a/tools/perf/util/bpf-event.h
+++ b/tools/perf/util/bpf-event.h
@@ -2,6 +2,10 @@
#ifndef __PERF_BPF_EVENT_H
#define __PERF_BPF_EVENT_H
+#include <bpf/bpf.h>
+#include <bpf/btf.h>
+#include <bpf/libbpf.h>
+#include <linux/btf.h>
#include <linux/compiler.h>
#include <bpf/bpf.h>
#include <bpf/btf.h>
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 62c8cf622607..1798192bf0f9 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -181,6 +181,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
case DSO_BINARY_TYPE__KALLSYMS:
case DSO_BINARY_TYPE__GUEST_KALLSYMS:
case DSO_BINARY_TYPE__JAVA_JIT:
+ case DSO_BINARY_TYPE__BPF_PROG_INFO:
case DSO_BINARY_TYPE__NOT_FOUND:
ret = -1;
break;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 8c8a7abe809d..f20d319463f1 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -14,6 +14,8 @@
#include "namespaces.h"
#include "build-id.h"
+struct perf_env;
+
enum dso_binary_type {
DSO_BINARY_TYPE__KALLSYMS = 0,
DSO_BINARY_TYPE__GUEST_KALLSYMS,
@@ -34,6 +36,7 @@ enum dso_binary_type {
DSO_BINARY_TYPE__KCORE,
DSO_BINARY_TYPE__GUEST_KCORE,
DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+ DSO_BINARY_TYPE__BPF_PROG_INFO,
DSO_BINARY_TYPE__NOT_FOUND,
};
@@ -177,17 +180,25 @@ struct dso {
struct auxtrace_cache *auxtrace_cache;
int comp;
- /* dso data file */
- struct {
- struct rb_root cache;
- int fd;
- int status;
- u32 status_seen;
- size_t file_size;
- struct list_head open_entry;
- u64 debug_frame_offset;
- u64 eh_frame_hdr_offset;
- } data;
+ union {
+ /* dso data file */
+ struct {
+ struct rb_root cache;
+ int fd;
+ int status;
+ u32 status_seen;
+ size_t file_size;
+ struct list_head open_entry;
+ u64 debug_frame_offset;
+ u64 eh_frame_hdr_offset;
+ } data;
+ /* bpf prog information */
+ struct {
+ u32 id;
+ u32 sub_id;
+ struct perf_env *env;
+ } bpf_prog;
+ };
union { /* Tool specific area */
void *priv;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 48efad6d0f90..33ae59e89da2 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1441,6 +1441,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
return true;
+ case DSO_BINARY_TYPE__BPF_PROG_INFO:
case DSO_BINARY_TYPE__NOT_FOUND:
default:
return false;
--
2.17.1
^ permalink raw reply related
* Re: [PATCH net-next v5 12/12] sock: Add SO_RCVTIMEO_NEW and SO_SNDTIMEO_NEW
From: Deepa Dinamani @ 2019-02-09 1:44 UTC (permalink / raw)
To: Michael Ellerman
Cc: David S. Miller, Linux Kernel Mailing List,
Linux Network Devel Mailing List, Arnd Bergmann,
y2038 Mailman List, ccaulfie, Helge Deller, Paul Mackerras,
Ralf Baechle, Richard Henderson, cluster-devel, linuxppc-dev,
linux-alpha, linux-arch, linux-mips, Parisc List, sparclinux
In-Reply-To: <87r2clku4j.fsf@concordia.ellerman.id.au>
> You touched powerpc in the previous patch but not this one.
>
> That's because we use the asm-generic version I assume.
That is correct.
> Would be good to mention in the change log though to avoid any confusion.
I'm not sure how to do that now. It looks like the series has already
been applied to net-next with a couple of merge conflicts fixed.
-Deepa
^ permalink raw reply
* Re: Resource management for ndo_xdp_xmit (Was: [PATCH net] virtio_net: Account for tx bytes and packets on sending xdp_frames)
From: Jakub Kicinski @ 2019-02-09 2:05 UTC (permalink / raw)
To: Saeed Mahameed
Cc: brouer@redhat.com, thoiland@redhat.com, hawk@kernel.org,
virtualization@lists.linux-foundation.org, borkmann@iogearbox.net,
Tariq Toukan, toke@toke.dk, john.fastabend@gmail.com,
mst@redhat.com, dsahern@gmail.com, netdev@vger.kernel.org,
jasowang@redhat.com, davem@davemloft.net,
makita.toshiaki@lab.ntt.co.jp
In-Reply-To: <b4eb9dd1c7aaa3215ade8d3d17f397588a519ca3.camel@mellanox.com>
On Sat, 9 Feb 2019 00:18:31 +0000, Saeed Mahameed wrote:
> On Fri, 2019-02-08 at 15:17 -0800, Saeed Mahameed wrote:
> > On Thu, 2019-02-07 at 19:08 +0000, Saeed Mahameed wrote:
> > >
> > > So
> > > 1) on dev_map_update_elem() we will call
> > > dev->dev->ndo_bpf() to notify the device on the intention to
> > > start/stop
> > > redirect, and wait for it to create/destroy the HW resources
> > > before/after actually updating the map
> > >
> >
> > silly me, dev_map_update_elem must be atomic, we can't hook driver
> > resource allocation to it, it must come as a separate request
> > (syscall)
> > from user space to request to create XDP redirect resources.
> >
>
> Well, it is possible to render dev_map_update_elem non-atomic and fail
> BPF programs who try to update it in the verifier
> check_map_func_compatibility.
>
> if you know of any case where devmap needs to be updated from the BPF
> program please let me know.
Did we find a solution to non-map redirect?
Sorry if I missed the discussion, I couldn't make the iovisor call this
week due to travel.
^ permalink raw reply
* [PATCH net-next 0/4] devlink: minor tweaks to reported device info
From: Jakub Kicinski @ 2019-02-09 3:16 UTC (permalink / raw)
To: davem; +Cc: jiri, netdev, oss-drivers, Jakub Kicinski
Hi!
This series contains two minor touch ups for devlink code. First
|| is corrected to && in the ethtool compat code. Next patch
decreases the stack allocation size.
On the nfp side after further discussions with the manufacturing
team we decided to realign the serial number contents slightly and
rename one of the other fields from "vendor" to "mfr", short for
"manufacture".
Jakub Kicinski (4):
devlink: fix condition for compat device info
devlink: don't allocate attrs on the stack
nfp: devlink: rename vendor to manufacture
nfp: devlink: include vendor/product info in serial number
.../net/ethernet/netronome/nfp/nfp_devlink.c | 23 +++++++++++++++----
net/core/devlink.c | 15 ++++++++----
2 files changed, 29 insertions(+), 9 deletions(-)
--
2.19.2
^ permalink raw reply
* [PATCH net-next 1/4] devlink: fix condition for compat device info
From: Jakub Kicinski @ 2019-02-09 3:16 UTC (permalink / raw)
To: davem; +Cc: jiri, netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20190209031611.1102-1-jakub.kicinski@netronome.com>
We need the port to be both ethernet and have the rigth netdev,
not one or the other.
Fixes: ddb6e99e2db1 ("ethtool: add compat for devlink info")
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
net/core/devlink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/core/devlink.c b/net/core/devlink.c
index e6a015b8ac9b..cf0f511bc56c 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -6385,7 +6385,7 @@ void devlink_compat_running_version(struct net_device *dev,
list_for_each_entry(devlink, &devlink_list, list) {
mutex_lock(&devlink->lock);
list_for_each_entry(devlink_port, &devlink->port_list, list) {
- if (devlink_port->type == DEVLINK_PORT_TYPE_ETH ||
+ if (devlink_port->type == DEVLINK_PORT_TYPE_ETH &&
devlink_port->type_dev == dev) {
__devlink_compat_running_version(devlink,
buf, len);
--
2.19.2
^ permalink raw reply related
* [PATCH net-next 4/4] nfp: devlink: include vendor/product info in serial number
From: Jakub Kicinski @ 2019-02-09 3:16 UTC (permalink / raw)
To: davem; +Cc: jiri, netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20190209031611.1102-1-jakub.kicinski@netronome.com>
The manufacturing team requests we include vendor and product
in the serial number field, as the serial number itself is not
unique across manufacturing facilities and products.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
---
.../net/ethernet/netronome/nfp/nfp_devlink.c | 21 ++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
index 6e15e216732a..5fa11a27d640 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
@@ -258,18 +258,33 @@ nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
struct netlink_ext_ack *extack)
{
struct nfp_pf *pf = devlink_priv(devlink);
+ const char *sn, *vendor, *part;
struct nfp_nsp *nsp;
char *buf = NULL;
- const char *sn;
int err;
err = devlink_info_driver_name_put(req, "nfp");
if (err)
return err;
+ vendor = nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor");
+ part = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno");
sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial");
- if (sn) {
- err = devlink_info_serial_number_put(req, sn);
+ if (vendor && part && sn) {
+ char *buf;
+
+ buf = kmalloc(strlen(vendor) + strlen(part) + strlen(sn) + 1,
+ GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf[0] = '\0';
+ strcat(buf, vendor);
+ strcat(buf, part);
+ strcat(buf, sn);
+
+ err = devlink_info_serial_number_put(req, buf);
+ kfree(buf);
if (err)
return err;
}
--
2.19.2
^ permalink raw reply related
* [PATCH net-next 2/4] devlink: don't allocate attrs on the stack
From: Jakub Kicinski @ 2019-02-09 3:16 UTC (permalink / raw)
To: davem; +Cc: jiri, netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20190209031611.1102-1-jakub.kicinski@netronome.com>
Number of devlink attributes has grown over 128, causing the
following warning:
../net/core/devlink.c: In function ‘devlink_nl_cmd_region_read_dumpit’:
../net/core/devlink.c:3740:1: warning: the frame size of 1064 bytes is larger than 1024 bytes [-Wframe-larger-than=]
}
^
Since the number of attributes is only going to grow allocate
the array dynamically.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
net/core/devlink.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/net/core/devlink.c b/net/core/devlink.c
index cf0f511bc56c..46c468a1f3dc 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -3629,26 +3629,30 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
struct netlink_callback *cb)
{
u64 ret_offset, start_offset, end_offset = 0;
- struct nlattr *attrs[DEVLINK_ATTR_MAX + 1];
const struct genl_ops *ops = cb->data;
struct devlink_region *region;
struct nlattr *chunks_attr;
const char *region_name;
struct devlink *devlink;
+ struct nlattr **attrs;
bool dump = true;
void *hdr;
int err;
start_offset = *((u64 *)&cb->args[0]);
+ attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + devlink_nl_family.hdrsize,
attrs, DEVLINK_ATTR_MAX, ops->policy, cb->extack);
if (err)
- goto out;
+ goto out_free;
devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
if (IS_ERR(devlink))
- goto out;
+ goto out_free;
mutex_lock(&devlink_mutex);
mutex_lock(&devlink->lock);
@@ -3710,6 +3714,7 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
genlmsg_end(skb, hdr);
mutex_unlock(&devlink->lock);
mutex_unlock(&devlink_mutex);
+ kfree(attrs);
return skb->len;
@@ -3718,7 +3723,8 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
out_unlock:
mutex_unlock(&devlink->lock);
mutex_unlock(&devlink_mutex);
-out:
+out_free:
+ kfree(attrs);
return 0;
}
--
2.19.2
^ permalink raw reply related
* [PATCH net-next 3/4] nfp: devlink: rename vendor to manufacture
From: Jakub Kicinski @ 2019-02-09 3:16 UTC (permalink / raw)
To: davem; +Cc: jiri, netdev, oss-drivers, Jakub Kicinski
In-Reply-To: <20190209031611.1102-1-jakub.kicinski@netronome.com>
Vendor may sound ambiguous, let's rename the fab string to
"board.manufacture".
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
index dddbb0575be9..6e15e216732a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
@@ -178,7 +178,7 @@ static const struct nfp_devlink_versions_simple {
} nfp_devlink_versions_hwinfo[] = {
{ DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, "assembly.partno", },
{ DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, "assembly.revision", },
- { "board.vendor", /* fab */ "assembly.vendor", },
+ { "board.manufacture", "assembly.vendor", },
{ "board.model", /* code name */ "assembly.model", },
};
--
2.19.2
^ permalink raw reply related
* Re: [PATCH] net: hso: do not unregister if not registered
From: David Miller @ 2019-02-09 3:40 UTC (permalink / raw)
To: tuba; +Cc: netdev
In-Reply-To: <1549670577031.62975@ece.ufl.edu>
From: "Yavuz, Tuba" <tuba@ece.ufl.edu>
Date: Sat, 9 Feb 2019 00:02:56 +0000
> I just resubmitted the patch and made sure to send it in
> plaintext. Hopefully, it will work this time.
That's not the problem.
It's still corrupted.
Your email client is formatting the text, and this makes the
patch unusable. Specifically, the last line of the patch
should have just a single space, but your mail client remove
that space and turned it into an empty line.
Please read the Documentation/email-clients.txt file, and it
should be able to show you how to do this properly.
Thank you.
^ permalink raw reply
* Re: [PATCH net] net: ipv4: use a dedicated counter for icmp_v4 redirect packets
From: David Miller @ 2019-02-09 5:50 UTC (permalink / raw)
To: lorenzo.bianconi; +Cc: netdev
In-Reply-To: <5896f41165a82acf6e31f76562448de29940611b.1549476789.git.lorenzo.bianconi@redhat.com>
From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Date: Wed, 6 Feb 2019 19:18:04 +0100
> According to the algorithm described in the comment block at the
> beginning of ip_rt_send_redirect, the host should try to send
> 'ip_rt_redirect_number' ICMP redirect packets with an exponential
> backoff and then stop sending them at all assuming that the destination
> ignores redirects.
> If the device has previously sent some ICMP error packets that are
> rate-limited (e.g TTL expired) and continues to receive traffic,
> the redirect packets will never be transmitted. This happens since
> peer->rate_tokens will be typically greater than 'ip_rt_redirect_number'
> and so it will never be reset even if the redirect silence timeout
> (ip_rt_redirect_silence) has elapsed without receiving any packet
> requiring redirects.
>
> Fix it by using a dedicated counter for the number of ICMP redirect
> packets that has been sent by the host
>
> I have not been able to identify a given commit that introduced the
> issue since ip_rt_send_redirect implements the same rate-limiting
> algorithm from commit 1da177e4c3f4 ("Linux-2.6.12-rc2")
>
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH net-next] net: phy: consider latched link-down status in polling mode
From: David Miller @ 2019-02-09 6:09 UTC (permalink / raw)
To: hkallweit1; +Cc: andrew, f.fainelli, netdev, linux
In-Reply-To: <7180c54c-34b2-0a36-97ff-bbda302eb427@gmail.com>
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Wed, 6 Feb 2019 19:39:52 +0100
> The link status value latches link-down events. To get the current
> status we read the register twice in genphy_update_link(). There's
> a potential risk that we miss a link-down event in polling mode.
> This may cause issues if the user e.g. connects his machine to a
> different network.
>
> On the other hand reading the latched value may cause issues in
> interrupt mode. Following scenario:
>
> - After boot link goes up
> - phy_start() is called triggering an aneg restart, hence link goes
> down and link-down info is latched.
> - After aneg has finished link goes up and triggers an interrupt.
> Interrupt handler reads link status, means it reads the latched
> "link is down" info. But there won't be another interrupt as long
> as link stays up, therefore phylib will never recognize that link
> is up.
>
> Deal with both scenarios by reading the register twice in interrupt
> mode only.
>
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-next 0/4] net: dsa: bcm_sf2: Add support for CFP statistics
From: David Miller @ 2019-02-09 6:11 UTC (permalink / raw)
To: f.fainelli; +Cc: netdev, cphealy, vivien.didelot
In-Reply-To: <20190206204600.24109-1-f.fainelli@gmail.com>
From: Florian Fainelli <f.fainelli@gmail.com>
Date: Wed, 6 Feb 2019 12:45:56 -0800
> The Broadcom SF2 switch has a Compact Field Processor (CFP) which not
> only can perform matching + action, but also counts the number of times
> a rule has been hit. This is invaluable while debugging when/if rules
> are not matched.
Series applied, thanks Florian.
^ permalink raw reply
* [PATCH bpf] bpf: Fix narrow load on a bpf_sock returned from sk_lookup()
From: Martin KaFai Lau @ 2019-02-09 6:25 UTC (permalink / raw)
To: netdev; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team, Joe Stringer
By adding this test to test_verifier:
{
"reference tracking: access sk->src_ip4 (narrow load)",
.insns = {
BPF_SK_LOOKUP,
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
BPF_LDX_MEM(BPF_H, BPF_REG_2, BPF_REG_0, offsetof(struct bpf_sock, src_ip4) + 2),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
BPF_EMIT_CALL(BPF_FUNC_sk_release),
BPF_EXIT_INSN(),
},
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.result = ACCEPT,
},
The above test loads 2 bytes from sk->src_ip4 where
sk is obtained by bpf_sk_lookup_tcp().
It hits an internal verifier error from convert_ctx_accesses():
[root@arch-fb-vm1 bpf]# ./test_verifier 665 665
Failed to load prog 'Invalid argument'!
0: (b7) r2 = 0
1: (63) *(u32 *)(r10 -8) = r2
2: (7b) *(u64 *)(r10 -16) = r2
3: (7b) *(u64 *)(r10 -24) = r2
4: (7b) *(u64 *)(r10 -32) = r2
5: (7b) *(u64 *)(r10 -40) = r2
6: (7b) *(u64 *)(r10 -48) = r2
7: (bf) r2 = r10
8: (07) r2 += -48
9: (b7) r3 = 36
10: (b7) r4 = 0
11: (b7) r5 = 0
12: (85) call bpf_sk_lookup_tcp#84
13: (bf) r6 = r0
14: (15) if r0 == 0x0 goto pc+3
R0=sock(id=1,off=0,imm=0) R6=sock(id=1,off=0,imm=0) R10=fp0,call_-1 fp-8=????0000 fp-16=0000mmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm refs=1
15: (69) r2 = *(u16 *)(r0 +26)
16: (bf) r1 = r6
17: (85) call bpf_sk_release#86
18: (95) exit
from 14 to 18: safe
processed 20 insns (limit 131072), stack depth 48
bpf verifier is misconfigured
Summary: 0 PASSED, 0 SKIPPED, 1 FAILED
The bpf_sock_is_valid_access() is expecting src_ip4 can be narrowly
loaded (meaning load any 1 or 2 bytes of the src_ip4) by
marking info->ctx_field_size. However, this marked
ctx_field_size is not used. This patch fixes it.
Due to the recent refactoring in test_verifier,
this new test will be added to the bpf-next branch
(together with the bpf_tcp_sock patchset)
to avoid merge conflict.
Fixes: c64b7983288e ("bpf: Add PTR_TO_SOCKET verifier type")
Cc: Joe Stringer <joe@wand.net.nz>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
kernel/bpf/verifier.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 56674a7c3778..8f295b790297 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1617,12 +1617,13 @@ static int check_flow_keys_access(struct bpf_verifier_env *env, int off,
return 0;
}
-static int check_sock_access(struct bpf_verifier_env *env, u32 regno, int off,
- int size, enum bpf_access_type t)
+static int check_sock_access(struct bpf_verifier_env *env, int insn_idx,
+ u32 regno, int off, int size,
+ enum bpf_access_type t)
{
struct bpf_reg_state *regs = cur_regs(env);
struct bpf_reg_state *reg = ®s[regno];
- struct bpf_insn_access_aux info;
+ struct bpf_insn_access_aux info = {};
if (reg->smin_value < 0) {
verbose(env, "R%d min value is negative, either use unsigned index or do a if (index >=0) check.\n",
@@ -1636,6 +1637,8 @@ static int check_sock_access(struct bpf_verifier_env *env, u32 regno, int off,
return -EACCES;
}
+ env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
+
return 0;
}
@@ -2032,7 +2035,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
verbose(env, "cannot write into socket\n");
return -EACCES;
}
- err = check_sock_access(env, regno, off, size, t);
+ err = check_sock_access(env, insn_idx, regno, off, size, t);
if (!err && value_regno >= 0)
mark_reg_unknown(env, regs, value_regno);
} else {
--
2.17.1
^ permalink raw reply related
* Re: [PATCH net] vsock: cope with memory allocation failure at socket creation time
From: David Miller @ 2019-02-09 6:32 UTC (permalink / raw)
To: pabeni; +Cc: netdev, jhansen, sgarzare
In-Reply-To: <9ad578fedcc2888319e4ec222d11f6fe51afd613.1549545195.git.pabeni@redhat.com>
From: Paolo Abeni <pabeni@redhat.com>
Date: Thu, 7 Feb 2019 14:13:18 +0100
> In the unlikely event that the kmalloc call in vmci_transport_socket_init()
> fails, we end-up calling vmci_transport_destruct() with a NULL vmci_trans()
> and oopsing.
>
> This change addresses the above explicitly checking for zero vmci_trans()
> at destruction time.
>
> Reported-by: Xiumei Mu <xmu@redhat.com>
> Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [EXT] Re: [PATCH net-next 0/2] qed*: SmartAN query support
From: David Miller @ 2019-02-09 6:55 UTC (permalink / raw)
To: jakub.kicinski; +Cc: skalluru, netdev, aelior, mkalderon, mkubecek
In-Reply-To: <20190208080429.0411ea05@cakuba.netronome.com>
From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Fri, 8 Feb 2019 08:04:29 -0800
> Thanks! Yes, that's exactly the same thing. In a nutshell trying
> different serdes and FEC speeds. I guess I'll just put adding an API
> for this down as a TODO, and add it once we have ethtool netlink. And
> keep IOCTL ethtool frozen until then.
>
> So I think the priv flag is fine for now.
Series applied to net-next.
^ permalink raw reply
* Re: [PATCH net-next] bridge: use struct_size() helper
From: David Miller @ 2019-02-09 6:57 UTC (permalink / raw)
To: gustavo; +Cc: roopa, nikolay, bridge, netdev, linux-kernel
In-Reply-To: <20190208005856.GA16642@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 18:58:56 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> struct boo entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(struct boo);
> instance = alloc(size, GFP_KERNEL)
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> size = struct_size(instance, entry, count);
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net/sched: use struct_size() helper
From: David Miller @ 2019-02-09 6:57 UTC (permalink / raw)
To: gustavo; +Cc: jhs, xiyou.wangcong, jiri, netdev, linux-kernel
In-Reply-To: <20190208010252.GA24824@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 19:02:52 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> struct boo entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(struct boo);
> instance = alloc(size, GFP_KERNEL)
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> size = struct_size(instance, entry, count);
> instance = alloc(size, GFP_KERNEL)
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] mpls_iptunnel: use struct_size() helper
From: David Miller @ 2019-02-09 6:57 UTC (permalink / raw)
To: gustavo; +Cc: netdev, linux-kernel
In-Reply-To: <20190208011052.GA646@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 19:10:52 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> struct boo entry[];
> };
>
> instance = alloc(sizeof(struct foo) + count * sizeof(struct boo));
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> instance = alloc(struct_size(instance, entry, count));
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net: dsa: use struct_size() in devm_kzalloc()
From: David Miller @ 2019-02-09 6:58 UTC (permalink / raw)
To: gustavo; +Cc: andrew, vivien.didelot, f.fainelli, netdev, linux-kernel
In-Reply-To: <20190208011603.GA927@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 19:16:03 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> struct boo entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(struct boo);
> instance = alloc(size, GFP_KERNEL)
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> instance = alloc(struct_size(instance, entry, count), GFP_KERNEL)
>
> Notice that, in this case, variable size is not necessary, hence it is
> removed.
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net: usb: cdc-phonet: use struct_size() in alloc_netdev()
From: David Miller @ 2019-02-09 6:58 UTC (permalink / raw)
To: gustavo; +Cc: linux-usb, netdev, linux-kernel
In-Reply-To: <20190208031313.GA2848@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 21:13:13 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> void *entry[];
> };
>
> instance = alloc(sizeof(struct foo) + count * sizeof(void *));
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> instance = alloc(struct_size(instance, entry, count));
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] wan: wanxl: use struct_size() in kzalloc()
From: David Miller @ 2019-02-09 6:58 UTC (permalink / raw)
To: gustavo; +Cc: khc, netdev, linux-kernel
In-Reply-To: <20190208031648.GA3022@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 21:16:48 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> struct boo entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(struct boo);
> instance = alloc(size, GFP_KERNEL)
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> instance = alloc(struct_size(instance, entry, count), GFP_KERNEL)
>
> Notice that, in this case, variable alloc_size is not necessary, hence
> it is removed.
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] wimax/i2400m: use struct_size() helper
From: David Miller @ 2019-02-09 6:58 UTC (permalink / raw)
To: gustavo; +Cc: inaky.perez-gonzalez, linux-wimax, netdev, linux-kernel
In-Reply-To: <20190208032217.GA3232@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 21:22:17 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> void *entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(void *);
> instance = alloc(size, GFP_KERNEL);
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> size = struct_size(instance, entry, count);
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] bnx2x: Use struct_size() in kzalloc()
From: David Miller @ 2019-02-09 6:58 UTC (permalink / raw)
To: gustavo; +Cc: aelior, skalluru, GR-everest-linux-l2, netdev, linux-kernel
In-Reply-To: <20190208032910.GA3436@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 21:29:10 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> struct boo entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(struct boo);
> instance = kzalloc(size, GFP_KERNEL)
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL)
>
> Notice that, in this case, variable fsz is not necessary, hence
> it is removed.
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] mlxsw: spectrum_router: Use struct_size() in kzalloc()
From: David Miller @ 2019-02-09 6:58 UTC (permalink / raw)
To: gustavo; +Cc: jiri, idosch, netdev, linux-kernel
In-Reply-To: <20190208034241.GA11858@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 21:42:41 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> struct boo entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(struct boo);
> instance = kzalloc(size, GFP_KERNEL)
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL)
>
> Notice that, in this case, variable alloc_size is not necessary, hence
> it is removed.
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] nfp: flower: cmsg: use struct_size() helper
From: David Miller @ 2019-02-09 6:58 UTC (permalink / raw)
To: gustavo; +Cc: jakub.kicinski, oss-drivers, netdev, linux-kernel
In-Reply-To: <20190208034725.GA12043@embeddedor>
From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Date: Thu, 7 Feb 2019 21:47:25 -0600
> One of the more common cases of allocation size calculations is finding
> the size of a structure that has a zero-sized array at the end, along
> with memory for some number of elements for that array. For example:
>
> struct foo {
> int stuff;
> void *entry[];
> };
>
> size = sizeof(struct foo) + count * sizeof(void *);
> instance = alloc(size, GFP_KERNEL);
>
> Instead of leaving these open-coded and prone to type mistakes, we can
> now use the new struct_size() helper:
>
> instance = alloc(struct_size(instance, entry, count), GFP_KERNEL);
>
> Notice that, in this case, variable size is not necessary, hence
> it is removed.
>
> This code was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Applied.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox