bgpd: initialise nh_flag attribute#249
Conversation
This patch modifies `leak_update()` to accept a non-interned static attribute rather than requiring an already-interned one. Previously, callers such as `vpn_leak_to_vrf_update_onevrf()` and `_vpn_leak_from_vrf_update_leak_attr()` would intern the attribute prior to calling `leak_update()`. If `leak_update()` determined that the route was unchanged, it would simply unintern the attribute and continue, resulting in unnecessary memory allocation and hash table overhead. With this change, the caller passes a pointer to the static attribute, and `leak_update()` now defers calling `bgp_attr_intern()` until it actually needs to update an existing path or allocate a new one. The callers handle flushing the static attribute when done. Signed-off-by: Francois Dumontet <francois.dumontet@6wind.com>
this commit fixes an issue during new path creation: if the new leaked path is determined to have a valid nexthop, the `BGP_ATTR_NH_VALID` flag is now correctly set on the `nh_flags`. Fixes: 879bfc0 (bgpd: fix VRF leaking with 'network import-check') Signed-off-by: Francois Dumontet <francois.dumontet@6wind.com>
Greptile SummaryThis PR refactors
|
| Filename | Overview |
|---|---|
| bgpd/bgp_mplsvpn.c | Refactors leak_update to accept a non-interned static_attr and perform interning internally; fixes BGP_ATTR_NH_VALID initialization in the new-route path, but the update path still interns before the nexthop check, and the flag mutation at line 1444 relies on new->attr == static_attr as an implicit alias. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["leak_update(static_attr)"] --> B{existing bpi?}
B -- yes --> C["bgp_attr_intern(static_attr)\nbpi->attr = new_attr\n⚠ nh_flags == 0 here"]
C --> D["leak_update_nexthop_valid()"]
D -- valid --> E["bgp_path_info_set_flag VALID\n❌ BGP_ATTR_NH_VALID NOT set on bpi->attr"]
D -- invalid --> F["bgp_path_info_unset_flag VALID"]
B -- no --> G["info_make(static_attr)\nnew->attr = static_attr"]
G --> H["leak_update_nexthop_valid()"]
H -- valid --> I["bgp_path_info_set_flag VALID\nSET_FLAG(new->attr->nh_flags)\n= mutates static_attr via alias"]
H -- invalid --> J["bgp_path_info_unset_flag VALID"]
I --> K["new->attr = bgp_attr_intern(static_attr)\n✅ nh_flags encoded correctly"]
J --> K
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
bgpd/bgp_mplsvpn.c:1444-1447
**`BGP_ATTR_NH_VALID` set on wrong attr instance**
`new->attr` at line 1444 still points to `static_attr` (the raw stack pointer assigned by `info_make`), so `SET_FLAG(new->attr->nh_flags, BGP_ATTR_NH_VALID)` mutates `static_attr` directly. `bgp_attr_intern(static_attr)` then interns the modified struct, so the interned attr does end up with the flag set — but only because mutating the caller's stack variable through `new->attr` happens to work here.
The intent would be clearer and safer if the flag were set on `static_attr` explicitly before the intern:
```c
if (leak_update_nexthop_valid(to_bgp, bn, static_attr, afi, safi,
source_bpi, new, bgp_orig, p, debug)) {
bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
SET_FLAG(static_attr->nh_flags, BGP_ATTR_NH_VALID);
} else {
bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
}
new->attr = bgp_attr_intern(static_attr);
```
This makes the mutation target unambiguous and avoids relying on `new->attr == static_attr` as an implicit side-channel.
Reviews (2): Last reviewed commit: "bgpd: initialise nh_flag attribute" | Re-trigger Greptile
| SET_FLAG(new->attr->nh_flags, BGP_ATTR_NH_VALID); | ||
| } else | ||
| bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID); | ||
| new->attr = bgp_attr_intern(static_attr); |
There was a problem hiding this comment.
BGP_ATTR_NH_VALID set on wrong attr instance
new->attr at line 1444 still points to static_attr (the raw stack pointer assigned by info_make), so SET_FLAG(new->attr->nh_flags, BGP_ATTR_NH_VALID) mutates static_attr directly. bgp_attr_intern(static_attr) then interns the modified struct, so the interned attr does end up with the flag set — but only because mutating the caller's stack variable through new->attr happens to work here.
The intent would be clearer and safer if the flag were set on static_attr explicitly before the intern:
if (leak_update_nexthop_valid(to_bgp, bn, static_attr, afi, safi,
source_bpi, new, bgp_orig, p, debug)) {
bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
SET_FLAG(static_attr->nh_flags, BGP_ATTR_NH_VALID);
} else {
bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
}
new->attr = bgp_attr_intern(static_attr);This makes the mutation target unambiguous and avoids relying on new->attr == static_attr as an implicit side-channel.
Prompt To Fix With AI
This is a comment left during a code review.
Path: bgpd/bgp_mplsvpn.c
Line: 1444-1447
Comment:
**`BGP_ATTR_NH_VALID` set on wrong attr instance**
`new->attr` at line 1444 still points to `static_attr` (the raw stack pointer assigned by `info_make`), so `SET_FLAG(new->attr->nh_flags, BGP_ATTR_NH_VALID)` mutates `static_attr` directly. `bgp_attr_intern(static_attr)` then interns the modified struct, so the interned attr does end up with the flag set — but only because mutating the caller's stack variable through `new->attr` happens to work here.
The intent would be clearer and safer if the flag were set on `static_attr` explicitly before the intern:
```c
if (leak_update_nexthop_valid(to_bgp, bn, static_attr, afi, safi,
source_bpi, new, bgp_orig, p, debug)) {
bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
SET_FLAG(static_attr->nh_flags, BGP_ATTR_NH_VALID);
} else {
bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
}
new->attr = bgp_attr_intern(static_attr);
```
This makes the mutation target unambiguous and avoids relying on `new->attr == static_attr` as an implicit side-channel.
How can I resolve this? If you propose a fix, please make it concise.
in "leak_update" function
nh_flag is not initialized when nexthop is valid at route creation.
Original PR21498 by fdumontet6WIND