On 17 Jun 2026, at 22:46, Timothy Redaelli via dev wrote:

> When --format json is passed to ovs-appctl, fdb/stats-show returns a
> JSON object keyed by bridge name.  Each bridge contains two sub-objects:
> "entries" (with "current", "maximum", and "static" counts) and "events"
> (with "evicted", "expired", "learned", and "moved" counters).
>
> The implementation is split into separate text and JSON helper functions
> to keep the main handler simple.
>
> Example output:
>   {"br0": {"entries": {"current": 17, "maximum": 8192, "static": 17},
>            "events":  {"evicted": 0, "expired": 0,
>                        "learned": 17, "moved": 0}}}
>
> Reported-at: https://issues.redhat.com/browse/FDP-2444
> Signed-off-by: Timothy Redaelli <[email protected]>

Thanks Timothy for sending out the v3. I have some small comments below.

Cheers,

Eelco

> ---
>  ofproto/ofproto-dpif.c | 87 ++++++++++++++++++++++++++++++++----------
>  tests/ofproto-dpif.at  | 15 ++++++++
>  2 files changed, 81 insertions(+), 21 deletions(-)
>
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index c40da62cf..d6f07a220 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -6369,11 +6369,67 @@ ofproto_unixctl_fdb_stats_clear(struct unixctl_conn 
> *conn, int argc,
>      unixctl_command_reply(conn, "statistics successfully cleared");
>  }
>
> +static struct json *
> +ofproto_unixctl_fdb_stats_show_json(const struct ofproto_dpif *ofproto,
> +                                    const char *bridge_name)

We do not need to pass in the bridge_name, is also here: ofproto->up.name
> +{
> +    struct json *entries = json_object_create();
> +    struct json *events = json_object_create();
> +    struct json *bridge = json_object_create();
> +    struct json *json = json_object_create();
> +

I would add the lock here.

> +    json_object_put(entries, "current",
> +                    json_integer_create(hmap_count(&ofproto->ml->table)));
> +    json_object_put(entries, "maximum",
> +                    json_integer_create(ofproto->ml->max_entries));
> +    json_object_put(entries, "static",
> +                    json_integer_create(ofproto->ml->static_entries));
> +    json_object_put(bridge, "entries", entries);
> +
> +    json_object_put(events, "evicted",
> +                    json_integer_create(ofproto->ml->total_evicted));
> +    json_object_put(events, "expired",
> +                    json_integer_create(ofproto->ml->total_expired));
> +    json_object_put(events, "learned",
> +                    json_integer_create(ofproto->ml->total_learned));
> +    json_object_put(events, "moved",
> +                    json_integer_create(ofproto->ml->total_moved));
> +    json_object_put(bridge, "events", events);
> +
> +    json_object_put(json, bridge_name, bridge);

Unlock here.

> +    return json;
> +}
> +
> +static void
> +ofproto_unixctl_fdb_stats_show_text(const struct ofproto_dpif *ofproto,
> +                                    const char *bridge_name, struct ds *ds)

See above about bridge name.

> +{

I would add the lock here.

> +    ds_put_format(ds, "Statistics for bridge \"%s\":\n", bridge_name);
> +    ds_put_format(ds, "  Current/maximum MAC entries in the table: %"
> +                  PRIuSIZE"/%"PRIuSIZE"\n",
> +                  hmap_count(&ofproto->ml->table),
> +                  ofproto->ml->max_entries);
> +    ds_put_format(ds,
> +                  "  Current static MAC entries in the table : %"
> +                  PRIuSIZE"\n", ofproto->ml->static_entries);
> +    ds_put_format(ds,
> +                  "  Total number of learned MAC entries     : %"
> +                  PRIu64"\n", ofproto->ml->total_learned);
> +    ds_put_format(ds,
> +                  "  Total number of expired MAC entries     : %"
> +                  PRIu64"\n", ofproto->ml->total_expired);
> +    ds_put_format(ds,
> +                  "  Total number of evicted MAC entries     : %"
> +                  PRIu64"\n", ofproto->ml->total_evicted);
> +    ds_put_format(ds,
> +                  "  Total number of port moved MAC entries  : %"
> +                  PRIu64"\n", ofproto->ml->total_moved);

Unlock here.
> +}
> +
>  static void
>  ofproto_unixctl_fdb_stats_show(struct unixctl_conn *conn, int argc 
> OVS_UNUSED,
>                                 const char *argv[], void *aux OVS_UNUSED)
>  {
> -    struct ds ds = DS_EMPTY_INITIALIZER;
>      const struct ofproto_dpif *ofproto;

Can you add a new line here?
We should have one between the declarations and the actual code.

>      ofproto = ofproto_dpif_lookup_by_name(argv[1]);
>      if (!ofproto) {
> @@ -6381,28 +6437,17 @@ ofproto_unixctl_fdb_stats_show(struct unixctl_conn 
> *conn, int argc OVS_UNUSED,
>          return;
>      }
>
> -    ds_put_format(&ds, "Statistics for bridge \"%s\":\n", argv[1]);
>      ovs_rwlock_rdlock(&ofproto->ml->rwlock);
> +    if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) {
> +        struct json *json = ofproto_unixctl_fdb_stats_show_json(ofproto,
> +                                                                argv[1]);
> +        ovs_rwlock_unlock(&ofproto->ml->rwlock);
> +        unixctl_command_reply_json(conn, json);
> +        return;
> +    }

A single unlock might look better, something like:

    ovs_rwlock_rdlock(&ofproto->ml->rwlock);
    if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) {
        struct json *json = ofproto_unixctl_fdb_stats_show_json(ofproto,
                                                                argv[1]);
        unixctl_command_reply_json(conn, json);
    } else {
        struct ds ds = DS_EMPTY_INITIALIZER;

        ofproto_unixctl_fdb_stats_show_text(ofproto, argv[1], &ds);
        unixctl_command_reply(conn, ds_cstr(&ds));
        ds_destroy(&ds);
    }
    ovs_rwlock_unlock(&ofproto->ml->rwlock);

In general, I would move the locking to the specific show function, but keep
the if/else here.

> -    ds_put_format(&ds, "  Current/maximum MAC entries in the table: %"
> -                  PRIuSIZE"/%"PRIuSIZE"\n",
> -                  hmap_count(&ofproto->ml->table), ofproto->ml->max_entries);
> -    ds_put_format(&ds,
> -                  "  Current static MAC entries in the table : 
> %"PRIuSIZE"\n",
> -                  ofproto->ml->static_entries);
> -    ds_put_format(&ds,
> -                  "  Total number of learned MAC entries     : %"PRIu64"\n",
> -                  ofproto->ml->total_learned);
> -    ds_put_format(&ds,
> -                  "  Total number of expired MAC entries     : %"PRIu64"\n",
> -                  ofproto->ml->total_expired);
> -    ds_put_format(&ds,
> -                  "  Total number of evicted MAC entries     : %"PRIu64"\n",
> -                  ofproto->ml->total_evicted);
> -    ds_put_format(&ds,
> -                  "  Total number of port moved MAC entries  : %"PRIu64"\n",
> -                  ofproto->ml->total_moved);
> -
> +    struct ds ds = DS_EMPTY_INITIALIZER;

New line.

> +    ofproto_unixctl_fdb_stats_show_text(ofproto, argv[1], &ds);
>      ovs_rwlock_unlock(&ofproto->ml->rwlock);
>      unixctl_command_reply(conn, ds_cstr(&ds));
>      ds_destroy(&ds);
> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> index 9e64e8ee4..b5df060b0 100644
> --- a/tests/ofproto-dpif.at
> +++ b/tests/ofproto-dpif.at
> @@ -8247,6 +8247,21 @@ AT_CHECK_UNQUOTED([ovs-appctl fdb/stats-show br0 | 
> grep static], [0], [dnl
>    Current static MAC entries in the table : 17
>  ])
>
> +dnl Check JSON output.
> +AT_CHECK([ovs-appctl --format json --pretty fdb/stats-show br0], [0], [dnl
> +{
> +  "br0": {
> +    "entries": {
> +      "current": 17,
> +      "maximum": 8192,
> +      "static": 17},
> +    "events": {
> +      "evicted": 0,
> +      "expired": 0,
> +      "learned": 18,
> +      "moved": 0}}}
> +])
> +
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
>
> -- 
> 2.54.0
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to