hook: accept interface names in ifindex= option#508
hook: accept interface names in ifindex= option#508Bodlux wants to merge 1 commit intofacebook:mainfrom
Conversation
|
Hi @Bodlux! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
|
Hi, thanks for your first contribution! |
qdeslandes
left a comment
There was a problem hiding this comment.
Repeating my comment:
Hi, thanks for your first contribution! ifindex is more suited for an interface index (number). I would suggest introducing iface= which would allow either an interface index or an interface name.
Also, could you get rid of the comment to trigger the CLA check.
|
Thanks for the suggestion. I've renamed the option from ifindex= to iface= so it accepts either an interface name or index. |
qdeslandes
left a comment
There was a problem hiding this comment.
This change is incomplete, as it's only modifying the code and not the doc. Additionally, renaming an existing option will break use cases. An alternative would be to create a new iface option which handles interface index and interface name, then make ifindex as deprecated in the doc.
8d8081d to
55647eb
Compare
|
Thanks for the detailed feedback, @qdeslandes. I've reworked the PR along the lines you suggested and force-pushed a single, clean commit. Summary of the new approach:
Let me know if you'd like any further adjustments. |
qdeslandes
left a comment
There was a problem hiding this comment.
Small changes, otherwise LGTM.
| /* Alias table: alternative names that map to an existing bf_hookopts_type but | ||
| * use a different parser. The `type` field determines which bit in `used_opts` | ||
| * is set, so aliases share duplicate-detection and flavor | ||
| * requirement/support checks with their primary entry. */ | ||
| static struct bf_hookopts_ops _bf_hookopts_alias_ops[] = { | ||
| {.name = "iface", | ||
| .type = BF_HOOKOPTS_IFINDEX, | ||
| .required_by = 0, | ||
| .supported_by = BF_FLAGS(BF_FLAVOR_XDP, BF_FLAVOR_TC), | ||
| .parse = _bf_hookopts_iface_parse, | ||
| .dump = _bf_hookopts_ifindex_dump}, | ||
| }; |
There was a problem hiding this comment.
No need for a dedicated table here, this entry should be in _bf_hookopts_ops, and you should add a check for incompatibility in their respective parsers:
_bf_hookopts_iface_parse: error ififindexis defined, and error ififaceis already defined_bf_hookopts_ifindex_parse: error ififaceis defined, and error ififindexis already defined
55647eb to
85b9f30
Compare
|
Thanks for the review. Pushed a force-update with the requested changes:
The msgpack key is still |
85b9f30 to
ef4d564
Compare
|
@claude review |
Claude review of PR #508 (ef4d564)Must fix
Suggestions
Nits
|
| - Supported by | ||
| - Notes | ||
| * - ``ifindex=$IFINDEX`` | ||
| * - ``iface=$INTERFACE`` |
There was a problem hiding this comment.
Claude: must-fix: The "Required by" and "Supported by" columns are swapped for both iface= and ifindex=.
In the code, iface= has .required_by = 0 and .supported_by = BF_FLAGS(BF_FLAVOR_XDP, BF_FLAVOR_TC), but this row lists BF_HOOK_XDP, BF_HOOK_TC under "Required by" (unchanged context lines 385-386 inherited from the old ifindex= row).
Conversely, the new ifindex= entry (line 389-390) shows "Required by: N/A" and "Supported by: BF_HOOK_XDP, BF_HOOK_TC", but the code retains .required_by = BF_FLAGS(BF_FLAVOR_XDP, BF_FLAVOR_TC) and .supported_by = 0.
Fix: iface= should show "Required by: N/A" / "Supported by: BF_HOOK_XDP, BF_HOOK_TC". ifindex= should show "Required by: BF_HOOK_XDP, BF_HOOK_TC" / "Supported by: N/A".
| if (r) | ||
| return bf_err_r(r, "failed to parse iface from '%s'", raw_opt); | ||
|
|
||
| hookopts->ifindex = (int)ifindex; |
There was a problem hiding this comment.
Claude: suggestion: Missing INT_MAX bounds check before the uint32_t -> int narrowing cast. bf_if_index_from_str() accepts values up to UINT32_MAX (see if.c:62), and the cast (int)ifindex is implementation-defined for values exceeding INT_MAX. The sibling _bf_hookopts_ifindex_parse has an explicit guard at line 216:
if (ifindex > INT_MAX)
return bf_err_r(-E2BIG, ...);Consider adding the same check here for consistency.
|
|
||
| hookopts->ifindex = (int)ifindex; | ||
| hookopts->used_opts |= BF_FLAG(BF_HOOKOPTS_IFACE); | ||
| hookopts->used_opts |= BF_FLAG(BF_HOOKOPTS_IFINDEX); |
There was a problem hiding this comment.
Claude: suggestion: Setting both BF_HOOKOPTS_IFACE and BF_HOOKOPTS_IFINDEX is a pragmatic workaround to satisfy the required_by validation for XDP/TC, but it has two side effects:
bfcli/print.c:112only checksBF_HOOKOPTS_IFINDEXand will outputifindex=Neven when the user specifiediface=eth0— the round-trip uses the deprecated keyword.bf_hookopts_dumpiterates all entries, so both_bf_hookopts_iface_dumpand_bf_hookopts_ifindex_dumpwill fire, printing bothiface: Nandifindex: Nfor the same value.
Consider updating print.c to check BF_HOOKOPTS_IFACE first (printing iface= when set), and having one of the dump functions skip output when the other flag is also set.
|
|
||
| enum bf_hookopts_type | ||
| { | ||
| BF_HOOKOPTS_IFACE, |
There was a problem hiding this comment.
Claude: suggestion: Inserting BF_HOOKOPTS_IFACE before BF_HOOKOPTS_IFINDEX shifts the numeric values of all existing enum members (BF_HOOKOPTS_IFINDEX changes from 0 to 1, BF_HOOKOPTS_CGPATH from 1 to 2, etc.). Since these values are used as bit positions via BF_FLAG(), any external code compiled against the old header will silently misinterpret bitmasks.
At SOVERSION 0.0.0 this may be acceptable, but appending BF_HOOKOPTS_IFACE just before _BF_HOOKOPTS_MAX would avoid shifting existing values with no functional downside.
| (! ${BFCLI} ruleset set --dry-run --from-str "chain ifindex BF_HOOK_XDP{ifindex=2,ifindex=3} ACCEPT") | ||
| (! ${BFCLI} ruleset set --dry-run --from-str "chain iface BF_HOOK_XDP{iface=lo,iface=lo} ACCEPT") | ||
| (! ${BFCLI} ruleset set --dry-run --from-str "chain iface_ifindex BF_HOOK_XDP{ifindex=2,iface=lo} ACCEPT") | ||
| (! ${BFCLI} ruleset set --dry-run --from-str "chain ifindex_iface BF_HOOK_XDP{iface=lo,ifindex=2} ACCEPT") |
There was a problem hiding this comment.
Claude: nit: The file lacks a trailing newline (pre-existing, visible as \ No newline at end of file in the diff). Since this file is being modified, consider adding one to satisfy POSIX text file conventions.
Add a new hook option `iface=` that accepts either an interface name (resolved via `if_nametoindex`) or a numeric interface index. The existing `ifindex=` option is kept for backward compatibility but is now marked as deprecated: it continues to accept numeric indices only, and emits a runtime warning pointing users to `iface=`. `iface=` is added as its own `BF_HOOKOPTS_IFACE` entry in `_bf_hookopts_ops`, alongside `BF_HOOKOPTS_IFINDEX`. Each parser cross-checks the other slot's bit and rejects any combination of `iface=` and `ifindex=` in the same chain (in either order, or repeated). When `iface=` succeeds it sets both bits, so the XDP/TC `ifindex` requirement is satisfied. The on-wire (msgpack) serialization key remains `ifindex`, so existing serialized chains continue to load unchanged. Docs, unit tests and e2e duplicate-detection tests are updated. Relates to facebook#409.
ef4d564 to
556179e
Compare
|
Thanks for the bot review @qdeslandes. Pushed a force-update addressing all five points and rebased onto current
|
Use bf_if_index_from_str() to parse the ifindex= hook option value, which accepts both numeric indices and interface names (e.g. eth0). This is consistent with how the REDIRECT verdict already resolves interface references.
Closes #409