* [dpdk-dev] [PATCH] pipeline: add support for LPM lookup
@ 2021-07-07 20:48 Cristian Dumitrescu
2021-07-08 10:11 ` [dpdk-dev] [PATCH V2] " Cristian Dumitrescu
0 siblings, 1 reply; 5+ messages in thread
From: Cristian Dumitrescu @ 2021-07-07 20:48 UTC (permalink / raw)
To: dev; +Cc: Churchill Khangar
Add support for the Longest Prefix Match (LPM) lookup to the SWX
pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Churchill Khangar <churchill.khangar@intel.com>
---
lib/pipeline/rte_swx_ctl.c | 99 ++++++++++++++++++++++-----------
lib/pipeline/rte_swx_pipeline.c | 78 +++++++++-----------------
2 files changed, 93 insertions(+), 84 deletions(-)
diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c
index 4ee47df10..f1480bc27 100644
--- a/lib/pipeline/rte_swx_ctl.c
+++ b/lib/pipeline/rte_swx_ctl.c
@@ -218,9 +218,6 @@ table_params_get(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id)
if (n_match_fields_em == table->info.n_match_fields)
match_type = RTE_SWX_TABLE_MATCH_EXACT;
- else if ((n_match_fields_em == table->info.n_match_fields - 1) &&
- (last->match_type == RTE_SWX_TABLE_MATCH_LPM))
- match_type = RTE_SWX_TABLE_MATCH_LPM;
/* key_offset. */
key_offset = first->offset / 8;
@@ -347,35 +344,15 @@ table_entry_check(struct rte_swx_ctl_pipeline *ctl,
CHECK(entry, EINVAL);
- if (key_check) {
- if (table->is_stub) {
- /* key. */
- CHECK(!entry->key, EINVAL);
-
- /* key_mask. */
- CHECK(!entry->key_mask, EINVAL);
- } else {
- /* key. */
- CHECK(entry->key, EINVAL);
-
- /* key_mask. */
- switch (table->params.match_type) {
- case RTE_SWX_TABLE_MATCH_WILDCARD:
- break;
-
- case RTE_SWX_TABLE_MATCH_LPM:
- /* TBD Check that key mask is prefix. */
- break;
-
- case RTE_SWX_TABLE_MATCH_EXACT:
- status = table_entry_key_check_em(table, entry);
- if (status)
- return status;
- break;
+ if (key_check && !table->is_stub) {
+ /* key. */
+ CHECK(entry->key, EINVAL);
- default:
- CHECK(0, EINVAL);
- }
+ /* key_mask. */
+ if (table->params.match_type == RTE_SWX_TABLE_MATCH_EXACT) {
+ status = table_entry_key_check_em(table, entry);
+ if (status)
+ return status;
}
}
@@ -2207,6 +2184,45 @@ rte_swx_ctl_pipeline_abort(struct rte_swx_ctl_pipeline *ctl)
selector_abort(ctl, i);
}
+static int
+mask_to_prefix(uint64_t mask, uint32_t mask_length, uint32_t *prefix_length)
+{
+ uint32_t n_trailing_zeros = 0, n_ones = 0, i;
+
+ if (!mask) {
+ *prefix_length = 0;
+ return 0;
+ }
+
+ /* Count trailing zero bits. */
+ for (i = 0; i < 64; i++) {
+ if (mask & (1LLU << i))
+ break;
+
+ n_trailing_zeros++;
+ }
+
+ /* Count the one bits that follow. */
+ for ( ; i < 64; i++) {
+ if (!(mask & (1LLU << i)))
+ break;
+
+ n_ones++;
+ }
+
+ /* Check that no more one bits are present */
+ for ( ; i < 64; i++)
+ if (mask & (1LLU << i))
+ return -EINVAL;
+
+ /* Check that the input mask is a prefix or the right length. */
+ if (n_ones + n_trailing_zeros != mask_length)
+ return -EINVAL;
+
+ *prefix_length = n_ones;
+ return 0;
+}
+
static int
token_is_comment(const char *token)
{
@@ -2231,8 +2247,8 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
struct action *action;
struct rte_swx_table_entry *entry = NULL;
char *s0 = NULL, *s;
- uint32_t n_tokens = 0, arg_offset = 0, i;
- int blank_or_comment = 0;
+ uint32_t n_tokens = 0, arg_offset = 0, lpm_prefix_length_max = 0, lpm_prefix_length = 0, i;
+ int lpm = 0, blank_or_comment = 0;
/* Check input arguments. */
if (!ctl)
@@ -2307,6 +2323,19 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
if (mf_mask[0])
goto error;
+ /* LPM. */
+ if (mf->match_type == RTE_SWX_TABLE_MATCH_LPM) {
+ int status;
+
+ lpm = 1;
+
+ lpm_prefix_length_max = mf->n_bits;
+
+ status = mask_to_prefix(mask, mf->n_bits, &lpm_prefix_length);
+ if (status)
+ goto error;
+ }
+
/* Endianness conversion. */
if (mf->is_header)
mask = field_hton(mask, mf->n_bits);
@@ -2361,6 +2390,10 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
n_tokens -= 2;
}
+ /* LPM. */
+ if (lpm)
+ entry->key_priority = lpm_prefix_length_max - lpm_prefix_length;
+
/*
* Action.
*/
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 22c860f28..85db45d48 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -9199,37 +9199,42 @@ rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
return 0;
}
-static enum rte_swx_table_match_type
+static int
table_match_type_resolve(struct rte_swx_match_field_params *fields,
uint32_t n_fields,
- uint32_t max_offset_field_id)
+ enum rte_swx_table_match_type *match_type)
{
- uint32_t n_fields_em = 0, i;
+ uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
+
+ for (i = 0; i < n_fields; i++) {
+ struct rte_swx_match_field_params *f = &fields[i];
- for (i = 0; i < n_fields; i++)
- if (fields[i].match_type == RTE_SWX_TABLE_MATCH_EXACT)
+ if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
n_fields_em++;
- if (n_fields_em == n_fields)
- return RTE_SWX_TABLE_MATCH_EXACT;
+ if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
+ n_fields_lpm++;
+ }
+
+ if ((n_fields_lpm > 1) ||
+ (n_fields_lpm && (n_fields_em != n_fields - 1)))
+ return -EINVAL;
- if ((n_fields_em == n_fields - 1) &&
- (fields[max_offset_field_id].match_type == RTE_SWX_TABLE_MATCH_LPM))
- return RTE_SWX_TABLE_MATCH_LPM;
+ *match_type = (n_fields_em == n_fields) ?
+ RTE_SWX_TABLE_MATCH_EXACT :
+ RTE_SWX_TABLE_MATCH_WILDCARD;
- return RTE_SWX_TABLE_MATCH_WILDCARD;
+ return 0;
}
static int
table_match_fields_check(struct rte_swx_pipeline *p,
struct rte_swx_pipeline_table_params *params,
- struct header **header,
- uint32_t *min_offset_field_id,
- uint32_t *max_offset_field_id)
+ struct header **header)
{
struct header *h0 = NULL;
struct field *hf, *mf;
- uint32_t *offset = NULL, min_offset, max_offset, min_offset_pos, max_offset_pos, i;
+ uint32_t *offset = NULL, i;
int status = 0;
/* Return if no match fields. */
@@ -9293,34 +9298,10 @@ table_match_fields_check(struct rte_swx_pipeline *p,
}
}
- /* Find the min and max offset fields. */
- min_offset = offset[0];
- max_offset = offset[0];
- min_offset_pos = 0;
- max_offset_pos = 0;
-
- for (i = 1; i < params->n_fields; i++) {
- if (offset[i] < min_offset) {
- min_offset = offset[i];
- min_offset_pos = i;
- }
-
- if (offset[i] > max_offset) {
- max_offset = offset[i];
- max_offset_pos = i;
- }
- }
-
/* Return. */
if (header)
*header = h0;
- if (min_offset_field_id)
- *min_offset_field_id = min_offset_pos;
-
- if (max_offset_field_id)
- *max_offset_field_id = max_offset_pos;
-
end:
free(offset);
return status;
@@ -9338,7 +9319,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
struct table *t;
struct action *default_action;
struct header *header = NULL;
- uint32_t action_data_size_max = 0, min_offset_field_id = 0, max_offset_field_id = 0, i;
+ uint32_t action_data_size_max = 0, i;
int status = 0;
CHECK(p, EINVAL);
@@ -9350,11 +9331,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
CHECK(params, EINVAL);
/* Match checks. */
- status = table_match_fields_check(p,
- params,
- &header,
- &min_offset_field_id,
- &max_offset_field_id);
+ status = table_match_fields_check(p, params, &header);
if (status)
return status;
@@ -9393,12 +9370,11 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
if (params->n_fields) {
enum rte_swx_table_match_type match_type;
- match_type = table_match_type_resolve(params->fields,
- params->n_fields,
- max_offset_field_id);
- type = table_type_resolve(p,
- recommended_table_type_name,
- match_type);
+ status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
+ if (status)
+ return status;
+
+ type = table_type_resolve(p, recommended_table_type_name, match_type);
CHECK(type, EINVAL);
} else {
type = NULL;
--
2.17.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [dpdk-dev] [PATCH V2] pipeline: add support for LPM lookup
2021-07-07 20:48 [dpdk-dev] [PATCH] pipeline: add support for LPM lookup Cristian Dumitrescu
@ 2021-07-08 10:11 ` Cristian Dumitrescu
2021-07-09 21:41 ` Thomas Monjalon
0 siblings, 1 reply; 5+ messages in thread
From: Cristian Dumitrescu @ 2021-07-08 10:11 UTC (permalink / raw)
To: dev; +Cc: Churchill Khangar
Add support for the Longest Prefix Match (LPM) lookup to the SWX
pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Churchill Khangar <churchill.khangar@intel.com>
---
Depends-on: series-17609 ("examples/pipeline: improve table update CLI commands")
Depends-on: patch-17642 ("[V2] pipeline: fix table entry read")
lib/pipeline/rte_swx_ctl.c | 99 ++++++++++++++++++++++-----------
lib/pipeline/rte_swx_pipeline.c | 78 +++++++++-----------------
2 files changed, 93 insertions(+), 84 deletions(-)
diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c
index 4ee47df10..f1480bc27 100644
--- a/lib/pipeline/rte_swx_ctl.c
+++ b/lib/pipeline/rte_swx_ctl.c
@@ -218,9 +218,6 @@ table_params_get(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id)
if (n_match_fields_em == table->info.n_match_fields)
match_type = RTE_SWX_TABLE_MATCH_EXACT;
- else if ((n_match_fields_em == table->info.n_match_fields - 1) &&
- (last->match_type == RTE_SWX_TABLE_MATCH_LPM))
- match_type = RTE_SWX_TABLE_MATCH_LPM;
/* key_offset. */
key_offset = first->offset / 8;
@@ -347,35 +344,15 @@ table_entry_check(struct rte_swx_ctl_pipeline *ctl,
CHECK(entry, EINVAL);
- if (key_check) {
- if (table->is_stub) {
- /* key. */
- CHECK(!entry->key, EINVAL);
-
- /* key_mask. */
- CHECK(!entry->key_mask, EINVAL);
- } else {
- /* key. */
- CHECK(entry->key, EINVAL);
-
- /* key_mask. */
- switch (table->params.match_type) {
- case RTE_SWX_TABLE_MATCH_WILDCARD:
- break;
-
- case RTE_SWX_TABLE_MATCH_LPM:
- /* TBD Check that key mask is prefix. */
- break;
-
- case RTE_SWX_TABLE_MATCH_EXACT:
- status = table_entry_key_check_em(table, entry);
- if (status)
- return status;
- break;
+ if (key_check && !table->is_stub) {
+ /* key. */
+ CHECK(entry->key, EINVAL);
- default:
- CHECK(0, EINVAL);
- }
+ /* key_mask. */
+ if (table->params.match_type == RTE_SWX_TABLE_MATCH_EXACT) {
+ status = table_entry_key_check_em(table, entry);
+ if (status)
+ return status;
}
}
@@ -2207,6 +2184,45 @@ rte_swx_ctl_pipeline_abort(struct rte_swx_ctl_pipeline *ctl)
selector_abort(ctl, i);
}
+static int
+mask_to_prefix(uint64_t mask, uint32_t mask_length, uint32_t *prefix_length)
+{
+ uint32_t n_trailing_zeros = 0, n_ones = 0, i;
+
+ if (!mask) {
+ *prefix_length = 0;
+ return 0;
+ }
+
+ /* Count trailing zero bits. */
+ for (i = 0; i < 64; i++) {
+ if (mask & (1LLU << i))
+ break;
+
+ n_trailing_zeros++;
+ }
+
+ /* Count the one bits that follow. */
+ for ( ; i < 64; i++) {
+ if (!(mask & (1LLU << i)))
+ break;
+
+ n_ones++;
+ }
+
+ /* Check that no more one bits are present */
+ for ( ; i < 64; i++)
+ if (mask & (1LLU << i))
+ return -EINVAL;
+
+ /* Check that the input mask is a prefix or the right length. */
+ if (n_ones + n_trailing_zeros != mask_length)
+ return -EINVAL;
+
+ *prefix_length = n_ones;
+ return 0;
+}
+
static int
token_is_comment(const char *token)
{
@@ -2231,8 +2247,8 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
struct action *action;
struct rte_swx_table_entry *entry = NULL;
char *s0 = NULL, *s;
- uint32_t n_tokens = 0, arg_offset = 0, i;
- int blank_or_comment = 0;
+ uint32_t n_tokens = 0, arg_offset = 0, lpm_prefix_length_max = 0, lpm_prefix_length = 0, i;
+ int lpm = 0, blank_or_comment = 0;
/* Check input arguments. */
if (!ctl)
@@ -2307,6 +2323,19 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
if (mf_mask[0])
goto error;
+ /* LPM. */
+ if (mf->match_type == RTE_SWX_TABLE_MATCH_LPM) {
+ int status;
+
+ lpm = 1;
+
+ lpm_prefix_length_max = mf->n_bits;
+
+ status = mask_to_prefix(mask, mf->n_bits, &lpm_prefix_length);
+ if (status)
+ goto error;
+ }
+
/* Endianness conversion. */
if (mf->is_header)
mask = field_hton(mask, mf->n_bits);
@@ -2361,6 +2390,10 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
n_tokens -= 2;
}
+ /* LPM. */
+ if (lpm)
+ entry->key_priority = lpm_prefix_length_max - lpm_prefix_length;
+
/*
* Action.
*/
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 22c860f28..85db45d48 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -9199,37 +9199,42 @@ rte_swx_pipeline_table_type_register(struct rte_swx_pipeline *p,
return 0;
}
-static enum rte_swx_table_match_type
+static int
table_match_type_resolve(struct rte_swx_match_field_params *fields,
uint32_t n_fields,
- uint32_t max_offset_field_id)
+ enum rte_swx_table_match_type *match_type)
{
- uint32_t n_fields_em = 0, i;
+ uint32_t n_fields_em = 0, n_fields_lpm = 0, i;
+
+ for (i = 0; i < n_fields; i++) {
+ struct rte_swx_match_field_params *f = &fields[i];
- for (i = 0; i < n_fields; i++)
- if (fields[i].match_type == RTE_SWX_TABLE_MATCH_EXACT)
+ if (f->match_type == RTE_SWX_TABLE_MATCH_EXACT)
n_fields_em++;
- if (n_fields_em == n_fields)
- return RTE_SWX_TABLE_MATCH_EXACT;
+ if (f->match_type == RTE_SWX_TABLE_MATCH_LPM)
+ n_fields_lpm++;
+ }
+
+ if ((n_fields_lpm > 1) ||
+ (n_fields_lpm && (n_fields_em != n_fields - 1)))
+ return -EINVAL;
- if ((n_fields_em == n_fields - 1) &&
- (fields[max_offset_field_id].match_type == RTE_SWX_TABLE_MATCH_LPM))
- return RTE_SWX_TABLE_MATCH_LPM;
+ *match_type = (n_fields_em == n_fields) ?
+ RTE_SWX_TABLE_MATCH_EXACT :
+ RTE_SWX_TABLE_MATCH_WILDCARD;
- return RTE_SWX_TABLE_MATCH_WILDCARD;
+ return 0;
}
static int
table_match_fields_check(struct rte_swx_pipeline *p,
struct rte_swx_pipeline_table_params *params,
- struct header **header,
- uint32_t *min_offset_field_id,
- uint32_t *max_offset_field_id)
+ struct header **header)
{
struct header *h0 = NULL;
struct field *hf, *mf;
- uint32_t *offset = NULL, min_offset, max_offset, min_offset_pos, max_offset_pos, i;
+ uint32_t *offset = NULL, i;
int status = 0;
/* Return if no match fields. */
@@ -9293,34 +9298,10 @@ table_match_fields_check(struct rte_swx_pipeline *p,
}
}
- /* Find the min and max offset fields. */
- min_offset = offset[0];
- max_offset = offset[0];
- min_offset_pos = 0;
- max_offset_pos = 0;
-
- for (i = 1; i < params->n_fields; i++) {
- if (offset[i] < min_offset) {
- min_offset = offset[i];
- min_offset_pos = i;
- }
-
- if (offset[i] > max_offset) {
- max_offset = offset[i];
- max_offset_pos = i;
- }
- }
-
/* Return. */
if (header)
*header = h0;
- if (min_offset_field_id)
- *min_offset_field_id = min_offset_pos;
-
- if (max_offset_field_id)
- *max_offset_field_id = max_offset_pos;
-
end:
free(offset);
return status;
@@ -9338,7 +9319,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
struct table *t;
struct action *default_action;
struct header *header = NULL;
- uint32_t action_data_size_max = 0, min_offset_field_id = 0, max_offset_field_id = 0, i;
+ uint32_t action_data_size_max = 0, i;
int status = 0;
CHECK(p, EINVAL);
@@ -9350,11 +9331,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
CHECK(params, EINVAL);
/* Match checks. */
- status = table_match_fields_check(p,
- params,
- &header,
- &min_offset_field_id,
- &max_offset_field_id);
+ status = table_match_fields_check(p, params, &header);
if (status)
return status;
@@ -9393,12 +9370,11 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
if (params->n_fields) {
enum rte_swx_table_match_type match_type;
- match_type = table_match_type_resolve(params->fields,
- params->n_fields,
- max_offset_field_id);
- type = table_type_resolve(p,
- recommended_table_type_name,
- match_type);
+ status = table_match_type_resolve(params->fields, params->n_fields, &match_type);
+ if (status)
+ return status;
+
+ type = table_type_resolve(p, recommended_table_type_name, match_type);
CHECK(type, EINVAL);
} else {
type = NULL;
--
2.17.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [dpdk-dev] [PATCH V2] pipeline: add support for LPM lookup
2021-07-08 10:11 ` [dpdk-dev] [PATCH V2] " Cristian Dumitrescu
@ 2021-07-09 21:41 ` Thomas Monjalon
2021-07-09 22:13 ` Thomas Monjalon
0 siblings, 1 reply; 5+ messages in thread
From: Thomas Monjalon @ 2021-07-09 21:41 UTC (permalink / raw)
To: Cristian Dumitrescu; +Cc: dev, Churchill Khangar
08/07/2021 12:11, Cristian Dumitrescu:
> Add support for the Longest Prefix Match (LPM) lookup to the SWX
> pipeline.
>
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> Signed-off-by: Churchill Khangar <churchill.khangar@intel.com>
Applied, thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [dpdk-dev] [PATCH V2] pipeline: add support for LPM lookup
2021-07-09 21:41 ` Thomas Monjalon
@ 2021-07-09 22:13 ` Thomas Monjalon
2021-07-10 6:32 ` Thomas Monjalon
0 siblings, 1 reply; 5+ messages in thread
From: Thomas Monjalon @ 2021-07-09 22:13 UTC (permalink / raw)
To: Cristian Dumitrescu; +Cc: dev, Churchill Khangar
09/07/2021 23:41, Thomas Monjalon:
> 08/07/2021 12:11, Cristian Dumitrescu:
> > Add support for the Longest Prefix Match (LPM) lookup to the SWX
> > pipeline.
> >
> > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > Signed-off-by: Churchill Khangar <churchill.khangar@intel.com>
>
> Applied, thanks.
Sorry, no it cannot be in 21.08-rc1 because the series "selector table"
fails to compile on 32-bit target.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [dpdk-dev] [PATCH V2] pipeline: add support for LPM lookup
2021-07-09 22:13 ` Thomas Monjalon
@ 2021-07-10 6:32 ` Thomas Monjalon
0 siblings, 0 replies; 5+ messages in thread
From: Thomas Monjalon @ 2021-07-10 6:32 UTC (permalink / raw)
To: Cristian Dumitrescu; +Cc: dev, Churchill Khangar
10/07/2021 00:13, Thomas Monjalon:
> 09/07/2021 23:41, Thomas Monjalon:
> > 08/07/2021 12:11, Cristian Dumitrescu:
> > > Add support for the Longest Prefix Match (LPM) lookup to the SWX
> > > pipeline.
> > >
> > > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > > Signed-off-by: Churchill Khangar <churchill.khangar@intel.com>
> >
> > Applied, thanks.
>
> Sorry, no it cannot be in 21.08-rc1 because the series "selector table"
> fails to compile on 32-bit target.
It's OK now with the v4 of the dependency.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2021-07-10 6:32 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-07 20:48 [dpdk-dev] [PATCH] pipeline: add support for LPM lookup Cristian Dumitrescu
2021-07-08 10:11 ` [dpdk-dev] [PATCH V2] " Cristian Dumitrescu
2021-07-09 21:41 ` Thomas Monjalon
2021-07-09 22:13 ` Thomas Monjalon
2021-07-10 6:32 ` Thomas Monjalon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).