[dhcpmon] Validate DHCPv6 relay transformations - #101
Conversation
|
/azp run |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR disables the DHCPv6 “same-message-type relay-disparity” positive health signal in dhcpmon by making the DHCPv6 positive-health check return DHCP_MON_STATUS_INDETERMINATE, reflecting that DHCPv6 message types legitimately change across the relay boundary.
Changes:
- Updated the DHCPv6 positive-health check to always return
INDETERMINATEinstead of comparing RX/TX counters. - Added an in-code rationale noting DHCPv6 client vs relay message-type differences across the relay boundary.
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/dhcp_device.cpp:122
- The Doxygen
@codeexample showsdhcp_device_check_positive_health_v6()with no arguments, but the function still takes aconst std::string¶meter and is called withifnameelsewhere in this file. This mismatch can confuse readers and break generated docs.
/**
* @code dhcp_device_check_positive_health_v6();
* @brief Same-message-type RX/TX comparison is not valid across the DHCPv6 relay boundary.
* @return DHCP_MON_STATUS_INDETERMINATE
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/dhcp_device.cpp:124
- The Doxygen block documents
dhcp_device_check_positive_health_v6()as parameterless, but the function still takes aconst std::string&and is called withifnamelater in this file. This makes the docs misleading and the signature (unnamed parameter) harder to understand; it can also trigger Doxygen@code/signature mismatches. Consider naming the parameter, documenting it as unused, and explicitly marking it unused in the body to avoid compiler warnings.
* @code dhcp_device_check_positive_health_v6();
* @brief Same-message-type RX/TX comparison is not valid across the DHCPv6 relay boundary.
* @return DHCP_MON_STATUS_INDETERMINATE
*/
static dhcp_mon_status_t dhcp_device_check_positive_health_v6(const std::string &)
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
7ca314f to
d9ace6d
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/dhcp_devman.h:148
- The updated Doxygen for
dhcp_devman_get_device_context()no longer documents that the function can return NULL when an interface is unmapped, but the implementation still returns NULL in that case (e.g., when no parent mapping exists or whenMAX_CONTEXT_DEPTHis exceeded). This can mislead callers and generates inaccurate API docs.
* @brief find the tracked input interface that owns an interface.
*
* @param ifname interface name
*
* @return The interface's tracked context; a tracked input interface returns its own context
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/dhcp_device.cpp:125
- get_counter_delta() subtracts unsigned uint64_t counters directly. If counters ever reset/are cleared between snapshots (e.g. via counter-clear / DB sync), this underflows and produces a huge “delta”, causing false positives in check_counter_increased() and DHCPv6 relay/aggregate health decisions. Use a saturating delta (0 when current < snapshot) to preserve the previous “only count increases” semantics.
static uint64_t get_counter_delta(const std::string &ifname, int sock, int msg_type)
{
const sock_info_t &sock_info = sock_mgr_get_sock_info(sock);
return sock_info.all_counters.at(ifname).at(msg_type) -
sock_info.all_counters_snapshot.at(ifname).at(msg_type);
src/health_check.cpp:31
- relay_disparity_error says “none transmitted”, but the underlying positive checks mark UNHEALTHY when expected relay output is missing (same-type for v4; relay-forward / advertise-reply transformations for v6). It can be triggered even when some TX traffic exists, which makes this error message misleading for operators.
static const char relay_disparity_error[] =
"dhcpmon detected DHCPv4/v6 packets received but none transmitted for intf: %s. Duration: %d (sec)";
6c40cf3 to
cf8c659
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Bound each raw-socket callback to 64 packets and reset the recvfrom address length for every receive attempt. Rename three file-scope helpers that begin with underscores because C++ reserves those identifiers in the global namespace; static linkage already marks them as internal. Replace four nullptr comparisons with NULL to match the daemon's established style. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 39f979be-d826-4d5c-949a-f20abb58bb83 Signed-off-by: Xichen96 <lukelin0907@gmail.com>
Preserve VLAN and PortChannel membership so a physical member resolves through its immediate PortChannel parent to the monitored VLAN context. Keep direct VLAN-member precedence, bound hierarchy traversal, ignore self-references, and centralize parent, context, and aggregate-name lookup. Aggregate only to the immediate parent so pre-VLAN observations are not rolled into the root VLAN counter and misreported as relay loss. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 39f979be-d826-4d5c-949a-f20abb58bb83 Signed-off-by: Xichen96 <lukelin0907@gmail.com>
Populate one state per discovered VLAN or PortChannel check, derive aggregate ratios from topology, and format aggregate disparity errors with the interface and duration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 39f979be-d826-4d5c-949a-f20abb58bb83 Signed-off-by: Xichen96 <lukelin0907@gmail.com>
Replace invalid same-message-type DHCPv6 disparity checks with relay-aware activity checks. Require RX Solicit, Request, or Relay-Forward activity to produce TX Relay-Forward activity, and RX Relay-Reply activity to produce TX Advertise, Reply, or Relay-Reply activity. Keep direct lookups for the single Relay-Forward and Relay-Reply counters and compare activity rather than magnitude so multiple configured servers remain valid. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 39f979be-d826-4d5c-949a-f20abb58bb83 Signed-off-by: Xichen96 <lukelin0907@gmail.com>
cf8c659 to
95df31b
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/dhcp_device.cpp:237
- check_counters_delta_expected() (used by the aggregate disparity checks) still derives deltas via unsigned subtraction inside its loop. If counters ever decrease (e.g., after a COUNTERS_DB sync/clear), those subtractions underflow and can produce false disparities. Use a safe delta (clamp negative to 0), ideally by reusing get_counter_delta().
static bool check_counters_delta_expected(const std::string &ifname, const std::string &other_ifname, int sock,
size_t ratio, const int *monitored_msgs, size_t monitored_msg_cnt)
{
const sock_info_t &sock_info = sock_mgr_get_sock_info(sock);
const counter_t &counters = sock_info.all_counters.at(ifname);
src/dhcp_device.cpp:126
- get_counter_delta() subtracts the snapshot from the current counter without guarding against counter resets/DB resync. Cache counters can be rewritten from COUNTERS_DB (see update_cache_counter_callback) without updating snapshots, so current may be less than snapshot and this subtraction will underflow, producing a huge delta and false health-check results. Clamp negative deltas to 0 (or update snapshots when syncing).
This issue also appears on line 233 of the same file.
static uint64_t get_counter_delta(const std::string &ifname, int sock, int msg_type)
{
const sock_info_t &sock_info = sock_mgr_get_sock_info(sock);
return sock_info.all_counters.at(ifname).at(msg_type) -
sock_info.all_counters_snapshot.at(ifname).at(msg_type);
}
Description of PR
Replace the invalid DHCPv6 same-message-type disparity check with relay-aware
forward and return-path validation.
Work item tracking
Type of change
Approach
DHCPv6 transforms client messages at the relay boundary: for example, Solicit
becomes Relay-Forward and Relay-Reply becomes Advertise/Reply. Comparing the
same message type on RX and TX cannot reliably indicate relay loss.
The positive DHCPv6 relay-health check now validates:
The check compares activity rather than magnitude so multiple configured DHCPv6
servers remain valid. Configured-server fan-out validation is intentionally
separate. DHCPv6 counters and interface-hierarchy checks remain unchanged.
Stack
Depends on #100. Review the final commit only:
95df31b [dhcpmon]: Validate DHCPv6 relay transformationsVerification
No local compilation was used. Azure PR CI will validate the updated branch.
Back port request
None. This targets master only.