stats: fix collector updates of symlinks 46/36146/3
authorArthur de Kerhor <arthurdekerhor@gmail.com>
Mon, 16 May 2022 17:46:22 +0000 (19:46 +0200)
committerDamjan Marion <dmarion@me.com>
Thu, 19 May 2022 12:30:58 +0000 (12:30 +0000)
A node name is not bound to a node index. For example, if an interface
is deleted and re-added, the indexes of its nodes "<itfc_name>-tx"
and "<itfc_name>-output" may change. Thus, when the collector updates
the nodes stats, it should first delete all the symlinks for nodes that
have changed their names before adding new symlinks. Otherwise, it
could attempt to add already existing symlinks or delete valid ones.

Example of a series of command that triggers a crash in the assert
`ASSERT (node_data[i].symlinks[j] != CLIB_U32_MAX);`:

```
create loopback interface
create loopback interface
```
Wait for the nodes stats to update, then:
```
delete loopback interface intfc loop0
delete loopback interface intfc loop1
create loopback interface
create loopback interface
```

Type: fix

Change-Id: Ief8e7135e5c02dc6bc64dc94b76cff21ea9ab3a9
Signed-off-by: Arthur de Kerhor <arthurdekerhor@gmail.com>
src/vlib/stats/collector.c

index 36d54a4..c27d2fc 100644 (file)
@@ -61,15 +61,21 @@ update_node_counters (vlib_stats_segment_t *sm)
       vlib_stats_segment_lock ();
       clib_bitmap_foreach (i, bmp)
        {
-         vlib_node_t *n = node_dups[0][i];
          if (node_data[i].name)
            {
              vec_free (node_data[i].name);
              for (j = 0; j < ARRAY_LEN (node_data->symlinks); j++)
                vlib_stats_remove_entry (node_data[i].symlinks[j]);
            }
-
-         node_data[i].name = vec_dup (node_dups[0][i]->name);
+       }
+      /* We can't merge the loops because a node index corresponding to a given
+       * node name can change between 2 updates. Otherwise, we could add
+       * already existing symlinks or delete valid ones.
+       */
+      clib_bitmap_foreach (i, bmp)
+       {
+         vlib_node_t *n = node_dups[0][i];
+         node_data[i].name = vec_dup (n->name);
          vlib_stats_set_string_vector (&node_names, n->index, "%v", n->name);
 
          for (int j = 0; j < ARRAY_LEN (node_counters); j++)