ospfd: Implement rfc4222 Recommendation 1 and 2#20936
ospfd: Implement rfc4222 Recommendation 1 and 2#20936dfedyk wants to merge 6 commits intoFRRouting:masterfrom
Conversation
Greptile SummaryThis PR implements RFC 4222 Recommendation 1 (per-packet-type DSCP marking via
Confidence Score: 4/5Safe to merge after fixing the missing sleep in test_ospf_dead_timer; core C implementation is correct. One P1 finding remains: the inactive-timer topotest will be flaky in CI because it checks the reset counter without sleeping after flooding routes. The C implementation itself (DSCP marking, inactivity timer restart, byte-order handling) is correct. The P2 default-branch inconsistency in ospf_tos_for_type is a minor architectural nit that will not affect currently deployed packet types. tests/topotests/ospf_rfc4222_inactive_tmr/test_ospf_rfc4222_inactive_tmr.py — missing sleep before counter assertion Important Files Changed
|
85dbd8b to
9130018
Compare
riw777
left a comment
There was a problem hiding this comment.
looks good ... it doesn't look like the lint errors are in the changed code (?)
/*
<stdin>:359: trailing whitespace.
/*
<stdin>:371: trailing whitespace.
/*
<stdin>:383: trailing whitespace.
/*
warning: 4 lines add whitespace errors.
Report for ospf_packet.c | 10 issues
===============================================
< WARNING: Block comments use * on subsequent lines
< #422: FILE: /tmp/f1-1891220/ospf_packet.c:422:
< ERROR: trailing whitespace
< #1301: FILE: /tmp/f1-1891220/ospf_packet.c:1301:
< ERROR: trailing whitespace
< #1552: FILE: /tmp/f1-1891220/ospf_packet.c:1552:
< ERROR: trailing whitespace
< #1800: FILE: /tmp/f1-1891220/ospf_packet.c:1800:
< ERROR: trailing whitespace
< #2194: FILE: /tmp/f1-1891220/ospf_packet.c:2194:\nDetails at [https://ci1.netdef.org/browse/FRR-PULLREQ3-CHECKOUT-14881](https://ci1.netdef.org/browse/FRR-PULLREQ3-CHECKOUT-14881)```
|
@dfedyk can you fix the lint stuff here? |
9429ebf to
9fc5690
Compare
|
Sorry for delay I had some vacation and STDs meetings back now. |
9fc5690 to
fab2a7b
Compare
|
FYI, the linter looks wrong on the one remaining suggested change ... |
fab2a7b to
a2afe17
Compare
|
@greptile review |
ac108f2 to
3d4b8e9
Compare
1ad96ce to
6cfe883
Compare
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
RFC 4222 Recommendation 2: When packet prioritization isn’t feasible, refresh the OSPF neighbor inactivity timer upon receipt of any valid OSPF unicast packet, or any OSPF packet sent to AllSPFRouters on a point-to-point link (not just Hellos), to avoid unnecessary adjacency drops under congestion. This extends the adjacency on low-speed links where Hellos might be delayed or blocked by other control traffic. Signed-off-by: Don Fedyk <dfedyk@labn.net>
6cfe883 to
e3695c0
Compare
|
@greptile review |
e3695c0 to
8599a3e
Compare
|
@greptile review |
| static inline uint8_t ospf_tos_for_type(struct ospf_interface *oi, uint8_t type) | ||
| { | ||
| uint8_t dscp; | ||
|
|
||
| switch (type) { | ||
| case OSPF_MSG_HELLO: | ||
| case OSPF_MSG_LS_ACK: | ||
| /* Always highest priority */ | ||
| dscp = OSPF_IF_PARAM(oi, dscp_ospf_all); | ||
| break; | ||
|
|
||
| case OSPF_MSG_DB_DESC: | ||
| case OSPF_MSG_LS_REQ: | ||
| case OSPF_MSG_LS_UPD: | ||
| /* Bulk control traffic: low control */ | ||
| dscp = OSPF_IF_PARAM(oi, dscp_low_control); | ||
| break; | ||
|
|
||
| default: | ||
| dscp = OSPF_IF_PARAM(oi, dscp_low_control); | ||
| break; | ||
| } | ||
|
|
||
| dscp &= 0x3f; /* clamp to 6 bits */ | ||
| return (uint8_t)(dscp << 2); /* DSCP in bits 7..2, ECN = 0 */ | ||
| } |
There was a problem hiding this comment.
dscp_ospf_all never applied to bulk traffic despite documentation claiming it does
The command help text for ip ospf dscp all (line 3399 in ospf_vty.c) explicitly states: "DSCP used for all OSPF control packets (Hellos, Acks, and others when low-control not set)". However, ospf_tos_for_type hardwires DB-Desc, LS-Req, and LS-Upd to always read dscp_low_control, regardless of whether dscp_low_control was explicitly configured.
With the defaults both at IPTOS_PREC_INTERNETCONTROL >> 2 (CS6 = 48), an operator who runs only ip ospf dscp all 46 will get Hello/Ack at DSCP 46 while bulk traffic continues to use DSCP 48 — a higher precedence class, which inverts the QoS priority the RFC is designed to achieve. The bulk-traffic path should fall back to dscp_ospf_all when dscp_low_control is not explicitly configured:
case OSPF_MSG_DB_DESC:
case OSPF_MSG_LS_REQ:
case OSPF_MSG_LS_UPD:
default:
/* Fall back to dscp_ospf_all when low-control is not explicitly set */
if (OSPF_IF_PARAM_CONFIGURED(oi->params, dscp_low_control) ||
OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), dscp_low_control))
dscp = OSPF_IF_PARAM(oi, dscp_low_control);
else
dscp = OSPF_IF_PARAM(oi, dscp_ospf_all);
break;The existing test_ospf_dscp_all_and_low_control test always configures both parameters together (all=46 and low-control=40), so it does not exercise or catch this gap.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ospfd/ospf_packet.c
Line: 419-444
Comment:
**`dscp_ospf_all` never applied to bulk traffic despite documentation claiming it does**
The command help text for `ip ospf dscp all` (line 3399 in `ospf_vty.c`) explicitly states: *"DSCP used for all OSPF control packets (Hellos, Acks, **and others when low-control not set**)"*. However, `ospf_tos_for_type` hardwires DB-Desc, LS-Req, and LS-Upd to always read `dscp_low_control`, regardless of whether `dscp_low_control` was explicitly configured.
With the defaults both at `IPTOS_PREC_INTERNETCONTROL >> 2` (CS6 = 48), an operator who runs only `ip ospf dscp all 46` will get Hello/Ack at DSCP 46 while bulk traffic continues to use DSCP 48 — a **higher** precedence class, which inverts the QoS priority the RFC is designed to achieve. The bulk-traffic path should fall back to `dscp_ospf_all` when `dscp_low_control` is not explicitly configured:
```c
case OSPF_MSG_DB_DESC:
case OSPF_MSG_LS_REQ:
case OSPF_MSG_LS_UPD:
default:
/* Fall back to dscp_ospf_all when low-control is not explicitly set */
if (OSPF_IF_PARAM_CONFIGURED(oi->params, dscp_low_control) ||
OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), dscp_low_control))
dscp = OSPF_IF_PARAM(oi, dscp_low_control);
else
dscp = OSPF_IF_PARAM(oi, dscp_ospf_all);
break;
```
The existing `test_ospf_dscp_all_and_low_control` test always configures **both** parameters together (all=46 *and* low-control=40), so it does not exercise or catch this gap.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
This is currently design is intent- do not couple value to precedence meaning since a higher DSCP value does not always mean a higher precedence. This is basically a user beware configuration and you should know what you are doing. If we think the documentation needs to be more explicit then I would rather update the documentation than make a change where the system forces a value which would not allow flexibility through all values. If we implement this it would prevent users setting to some DSCP values which could have local meaning. There are DSCP values are available for local/experimental use for example (e.g., 1–7, 9, 11, 13, 15, 17, .).
There was a problem hiding this comment.
@greptile, look at the reply above
There was a problem hiding this comment.
Fair point — you're right that coupling the fallback logic to a precedence assumption would be wrong. DSCP is just a 6-bit marking; its meaning is locally defined, and forcing dscp_ospf_all as a fallback would break operators using local/experimental codepoints for bulk traffic.
The documentation wording "and others when low-control not set" is the real issue here. If the help text were updated to say something like "DSCP used for Hello and LS-Ack packets" (without implying a fallback), the behavior and docs would be consistent and no code change is needed.
Tip: You can give me more context with [.greptile/rules](https://www.greptile.com/docs/code-review/custom-standards) so I get this right next time.
There was a problem hiding this comment.
I will review and update the documentation.
There was a problem hiding this comment.
I have found a side effect and I am updating the operational display to clear up the confusion.
8599a3e to
02fcc94
Compare
|
@greptile review |
Topotest for RFC 4222 Rec 2 any ospf control resets dead interval Signed-off-by: Don Fedyk <dfedyk@labn.net>
Add user documentation for OSPF interface: ip ospf dead-timer-reset any-control This command implements RFC 4222 Recommendation 2 dead timer reset behavior. Signed-off-by: Don Fedyk <dfedyk@labn.net>
Implement RFC 4222 Rec 1: classify OSPF packets into high-priority (Hellos, LSA Acks) and low-priority classes, and prioritize high-priority processing to maintain critical control packet handling during congestion. All control packet can have a DSCP value set, or explicitly low control can have a different DSCP value. Signed-off-by: Don Fedyk <dfedyk@labn.net>
This test sets up two nodes and changes the DSCP then checks the resulting message dscp. Signed-off-by: Don Fedyk <dfedyk@labn.net>
Add the ip ospf dscp (all|low-control) (0-63) interface command to the OSPF user documentation. This command allows operators to set DSCP values for OSPF control packets to support QoS prioritization. Signed-off-by: Don Fedyk <dfedyk@labn.net>
02fcc94 to
d184f17
Compare
Implement RFC 4222 Recommendation 1 and Recommendation 2 includes documentation and topotests for each. See documentation for more details.