Mgmt frontend problems in zebra#21252
Conversation
Greptile SummaryThis PR migrates five zebra configuration commands — Key findings from the review:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant VTY
participant NB as Northbound (zebra_cli.c)
participant Config as zebra_nb_config.c
participant Zebra as zebra_import_table()
User->>VTY: ip import-table 10 distance 15 route-map FOO
VTY->>NB: nb_cli_enqueue_change(NB_OP_CREATE, list-entry)
VTY->>NB: nb_cli_enqueue_change(NB_OP_MODIFY, distance=15)
VTY->>NB: nb_cli_enqueue_change(NB_OP_MODIFY, route-map=FOO)
VTY->>NB: nb_cli_apply_changes()
NB->>Config: zebra_import_kernel_table_create (NB_EV_APPLY)
Config->>Zebra: zebra_import_table(AFI_IP, SAFI_UNICAST, 10, 15, FOO, add=true)
NB->>Config: zebra_import_kernel_table_distance_modify (NB_EV_APPLY)
Config->>Zebra: zebra_import_table(AFI_IP, SAFI_UNICAST, 10, 15, FOO, add=true)
NB->>Config: zebra_import_kernel_table_route_map_modify (NB_EV_APPLY)
Config->>Zebra: zebra_import_table(AFI_IP, SAFI_UNICAST, 10, 15, FOO, add=true)
Note over NB,Zebra: zebra_import_table called 3× (same args)
User->>VTY: no ip import-table 10
VTY->>NB: nb_cli_enqueue_change(NB_OP_DESTROY, list-entry)
VTY->>NB: nb_cli_apply_changes()
NB->>Config: zebra_import_kernel_table_destroy (NB_EV_APPLY)
Config->>Zebra: zebra_import_table(AFI_IP, SAFI_UNICAST, 10, 0, NULL, add=false)
|
| int zebra_import_kernel_table_route_map_destroy(struct nb_cb_destroy_args *args) | ||
| { | ||
| switch (args->event) { | ||
| case NB_EV_VALIDATE: | ||
| case NB_EV_PREPARE: | ||
| case NB_EV_ABORT: | ||
| case NB_EV_APPLY: | ||
| /* TODO: implement me. */ | ||
| break; | ||
| } | ||
| const struct lyd_node *dnode = | ||
| (const struct lyd_node *)args->dnode->parent; | ||
|
|
||
| if (args->event != NB_EV_APPLY) | ||
| return NB_OK; | ||
|
|
||
| if (zebra_import_kernel_table_apply(dnode, true) < 0) | ||
| return NB_ERR; | ||
|
|
||
| return NB_OK; | ||
| } |
There was a problem hiding this comment.
route_map_destroy re-applies with stale route-map data
In FRR's northbound framework, args->dnode for a destroy callback points to the old (pre-deletion) diff node. Therefore args->dnode->parent is the list entry as it existed before the change, meaning the route-map leaf is still present as a child. As a result, yang_dnode_exists(dnode, "route-map") returns true and the old route-map name is read, so zebra_import_kernel_table_apply(dnode, true) re-applies the import table with the route-map still in effect instead of removing it.
This path is not exercised by the CLI (no ip import-table / no ipv6 import-table always destroys the entire list entry via NB_OP_DESTROY on the entry xpath, triggering zebra_import_kernel_table_destroy), but it is reachable via direct YANG/mgmtd operations that delete only the route-map leaf while keeping the list entry.
The callback needs to call zebra_import_table explicitly with rmap = NULL to apply the updated state without the route-map:
int zebra_import_kernel_table_route_map_destroy(struct nb_cb_destroy_args *args)
{
const struct lyd_node *dnode =
(const struct lyd_node *)args->dnode->parent;
const char *afi_safi = yang_dnode_get_string(dnode, "afi-safi");
uint32_t table_id = yang_dnode_get_uint32(dnode, "table-id");
uint32_t distance = yang_dnode_get_uint32(dnode, "distance");
afi_t afi;
safi_t safi;
if (args->event != NB_EV_APPLY)
return NB_OK;
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
/* Re-apply without the route-map since it is being removed */
if (zebra_import_table(afi, safi, VRF_DEFAULT, table_id, distance,
NULL, true) < 0)
return NB_ERR;
return NB_OK;
}Prompt To Fix With AI
This is a comment left during a code review.
Path: zebra/zebra_nb_config.c
Line: 239-251
Comment:
**`route_map_destroy` re-applies with stale route-map data**
In FRR's northbound framework, `args->dnode` for a destroy callback points to the **old** (pre-deletion) diff node. Therefore `args->dnode->parent` is the list entry as it existed before the change, meaning the route-map leaf is still present as a child. As a result, `yang_dnode_exists(dnode, "route-map")` returns `true` and the old route-map name is read, so `zebra_import_kernel_table_apply(dnode, true)` re-applies the import table *with the route-map still in effect* instead of removing it.
This path is not exercised by the CLI (`no ip import-table` / `no ipv6 import-table` always destroys the entire list entry via `NB_OP_DESTROY` on the entry xpath, triggering `zebra_import_kernel_table_destroy`), but it is reachable via direct YANG/mgmtd operations that delete only the route-map leaf while keeping the list entry.
The callback needs to call `zebra_import_table` explicitly with `rmap = NULL` to apply the updated state without the route-map:
```c
int zebra_import_kernel_table_route_map_destroy(struct nb_cb_destroy_args *args)
{
const struct lyd_node *dnode =
(const struct lyd_node *)args->dnode->parent;
const char *afi_safi = yang_dnode_get_string(dnode, "afi-safi");
uint32_t table_id = yang_dnode_get_uint32(dnode, "table-id");
uint32_t distance = yang_dnode_get_uint32(dnode, "distance");
afi_t afi;
safi_t safi;
if (args->event != NB_EV_APPLY)
return NB_OK;
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
/* Re-apply without the route-map since it is being removed */
if (zebra_import_table(afi, safi, VRF_DEFAULT, table_id, distance,
NULL, true) < 0)
return NB_ERR;
return NB_OK;
}
```
How can I resolve this? If you propose a fix, please make it concise.|
@choppsv1 -> I need some advice here on what you think is best to do. For the |
I'm going through the changes now, then I'll check out greptile's suggestions again. |
|
I think the simple solution to the multiple calls to |
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
Route the `zebra dplane limit` CLI through the mgmt-fronted zebra NB path and implement the existing dplane queue limit NB apply callback so the command keeps its behavior after the move. Signed-off-by: Donald Sharp <[email protected]>
Move the `zebra zapi-packets` command to fully use the mgmt frontend. Signed-off-by: Donald Sharp <[email protected]>
Reroute the `zebra work-queue` commands to actually be on the mgmt frontend side instead of the zebra side. Signed-off-by: Donald Sharp <[email protected]>
The `ip import-table ...` commands were not on the mgmt front end side. Move them to it. Signed-off-by: Donald Sharp <[email protected]>
Better test: a) ip import table b) allow-external.... c) packet read in values for zebra Signed-off-by: Donald Sharp <[email protected]>
f60bc5b to
242e105
Compare
See individual commits for more detail:
Move
ip import-table,zebra work-queue,zebra zapi-packets,zebra dplane limitandallow-external-route-updateto their appropriate place in the mgmt frontend.Add tests to show things are working better.