Skip to content

[dhcpmon] Validate DHCPv6 relay transformations - #101

Draft
Xichen96 wants to merge 4 commits into
sonic-net:masterfrom
Xichen96:dev/xichenlin/disable-invalid-v6-disparity
Draft

[dhcpmon] Validate DHCPv6 relay transformations#101
Xichen96 wants to merge 4 commits into
sonic-net:masterfrom
Xichen96:dev/xichenlin/disable-invalid-v6-disparity

Conversation

@Xichen96

@Xichen96 Xichen96 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Description of PR

Replace the invalid DHCPv6 same-message-type disparity check with relay-aware
forward and return-path validation.

Work item tracking
  • Microsoft ADO (number only): 38615655

Type of change

  • Bug fix

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:

  • RX Solicit, Request, or Relay-Forward produces at least one TX Relay-Forward.
  • RX Relay-Reply produces at least one TX Advertise, Reply, or Relay-Reply.

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 transformations

Verification

No local compilation was used. Azure PR CI will validate the updated branch.

Back port request

None. This targets master only.

Copilot AI review requested due to automatic review settings July 26, 2026 06:46
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 INDETERMINATE instead of comparing RX/TX counters.
  • Added an in-code rationale noting DHCPv6 client vs relay message-type differences across the relay boundary.

Comment thread src/dhcp_device.cpp Outdated
Copilot AI review requested due to automatic review settings July 26, 2026 07:29
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 @code example shows dhcp_device_check_positive_health_v6() with no arguments, but the function still takes a const std::string& parameter and is called with ifname elsewhere 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

@Xichen96 Xichen96 changed the title [dhcpmon] Disable invalid DHCPv6 disparity check [dhcpmon] Remove invalid DHCPv6 RX/TX disparity check Jul 27, 2026
Copilot AI review requested due to automatic review settings July 28, 2026 06:06
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 a const std::string& and is called with ifname later 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 &)

Copilot AI review requested due to automatic review settings July 28, 2026 11:35
@Xichen96 Xichen96 changed the title [dhcpmon] Remove invalid DHCPv6 RX/TX disparity check [dhcpmon] Validate DHCPv6 relay transformations Jul 28, 2026
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 28, 2026 13:34
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@Xichen96
Xichen96 force-pushed the dev/xichenlin/disable-invalid-v6-disparity branch from 7ca314f to d9ace6d Compare July 28, 2026 16:12
Copilot AI review requested due to automatic review settings July 28, 2026 16:12
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 when MAX_CONTEXT_DEPTH is 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

Copilot AI review requested due to automatic review settings July 28, 2026 17:01
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)";

@Xichen96
Xichen96 force-pushed the dev/xichenlin/disable-invalid-v6-disparity branch from 6c40cf3 to cf8c659 Compare July 31, 2026 17:57
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Xichen96 and others added 4 commits August 1, 2026 05:01
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>
@Xichen96
Xichen96 force-pushed the dev/xichenlin/disable-invalid-v6-disparity branch from cf8c659 to 95df31b Compare July 31, 2026 19:20
Copilot AI review requested due to automatic review settings July 31, 2026 19:20
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants