Skip to content

Conversation

@trvon
Copy link

@trvon trvon commented Oct 7, 2025

In one of my research experiments, recirculated GTP-U packets triggered the PacketTooShort error. I assumed this was because the parser’s bounds were still compared against Packet::get_ingress_length(), even after the INT shim/BeamSec insertion increased the buffer size. During the second-pass parsing, this stale length caused the deparser to emit only the original payload, resulting in the omission of telemetry headers.

To address this issue, I updated all parser bounds checks (VL extracts, fixed extracts, shift/advance operations) to rely on Packet::get_data_size(), which provides the current length of the live buffer. This change ensures that the parser logic accurately reflects the real payload and only raises an error when the buffer itself is insufficient in size. I also added unit tests that simulate ingress_length < actual buffer.

Copilot AI review requested due to automatic review settings October 7, 2025 20:30
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Updates the parser to use the live buffer size instead of the original ingress length, ensuring parsing operations account for added headers (e.g., GTP-U/INT) during recirculation.

  • Replace get_ingress_length() with get_data_size() in VL extracts and shift/advance operations.
  • Add unit tests to validate parsing when data_size > ingress_length for shift, advance, and VL extract.

Reviewed Changes

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

File Description
src/bm_sim/parser.cpp Switch bounds checks from ingress_length to data_size across extract_VL and shift/advance operations.
tests/test_parser.cpp Add tests ensuring shift, advance, and VL extract succeed when the live buffer is larger than ingress_length.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

auto bytes_to_extract = static_cast<size_t>(
hdr->get_nbytes_packet() + nbits / 8);
if (pkt->get_ingress_length() - *bytes_parsed < bytes_to_extract)
if (pkt->get_data_size() - *bytes_parsed < bytes_to_extract)
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

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

This subtraction can underflow if *bytes_parsed exceeds pkt->get_data_size(), yielding a large size_t and bypassing the bounds check. Consider guarding against underflow explicitly, e.g., first check if (*bytes_parsed > pkt->get_data_size()) or use a two-part condition: (*bytes_parsed > pkt->get_data_size()) || (pkt->get_data_size() - *bytes_parsed < bytes_to_extract).

Suggested change
if (pkt->get_data_size() - *bytes_parsed < bytes_to_extract)
if (*bytes_parsed > pkt->get_data_size() ||
pkt->get_data_size() - *bytes_parsed < bytes_to_extract)

Copilot uses AI. Check for mistakes.
size_t *bytes_parsed) const override {
(void) data;
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes)
if (pkt->get_data_size() - *bytes_parsed < shift_bytes)
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

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

Potential unsigned underflow in the subtraction if *bytes_parsed > pkt->get_data_size(). Use a defensive check to prevent underflow, e.g., (*bytes_parsed > pkt->get_data_size()) || (pkt->get_data_size() - *bytes_parsed < shift_bytes).

Suggested change
if (pkt->get_data_size() - *bytes_parsed < shift_bytes)
if ((*bytes_parsed > pkt->get_data_size()) ||
(pkt->get_data_size() - *bytes_parsed < shift_bytes))

Copilot uses AI. Check for mistakes.
const auto shift_bytes_uint = shift_bits_uint / 8;
BMLOG_DEBUG_PKT(*pkt, "Advancing by {} bytes", shift_bytes_uint);
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes_uint)
if (pkt->get_data_size() - *bytes_parsed < shift_bytes_uint)
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

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

Potential unsigned underflow on size_t subtraction if *bytes_parsed exceeds pkt->get_data_size(). Prefer a two-part guard: (*bytes_parsed > pkt->get_data_size()) || (pkt->get_data_size() - *bytes_parsed < shift_bytes_uint).

Copilot uses AI. Check for mistakes.
const auto shift_bytes_uint = shift_bits_uint / 8;
BMLOG_DEBUG_PKT(*pkt, "Advancing by {} bytes", shift_bytes_uint);
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes_uint)
if (pkt->get_data_size() - *bytes_parsed < shift_bytes_uint)
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

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

Same unsigned underflow risk as elsewhere; subtracting before the comparison can wrap if *bytes_parsed > pkt->get_data_size(). Add an explicit pre-check for (*bytes_parsed > pkt->get_data_size()) or use a two-part condition that avoids underflow.

Copilot uses AI. Check for mistakes.
const auto shift_bytes_uint = shift_bits_uint / 8;
BMLOG_DEBUG_PKT(*pkt, "Advancing by {} bytes", shift_bytes_uint);
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes_uint)
if (pkt->get_data_size() - *bytes_parsed < shift_bytes_uint)
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

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

Unsigned underflow risk on the subtraction; guard with an explicit check for (*bytes_parsed > pkt->get_data_size()) before subtracting, or combine as: (*bytes_parsed > pkt->get_data_size()) || (pkt->get_data_size() - *bytes_parsed < shift_bytes_uint).

Suggested change
if (pkt->get_data_size() - *bytes_parsed < shift_bytes_uint)
if ((*bytes_parsed > pkt->get_data_size()) ||
(pkt->get_data_size() - *bytes_parsed < shift_bytes_uint))

Copilot uses AI. Check for mistakes.
Copy link
Member

@antoninbas antoninbas left a comment

Choose a reason for hiding this comment

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

It's not clear to me what the issue is based on this PR description.
As far as I can tell, the ingress_length is set correctly (based on what was produced by the deparser) for recirculated packets:

packet_copy->set_ingress_length(packet_size);

It would be helpful to clarify this, as well as provide a P4 program to reproduce the issue. Adding @jafingerhut in case he has some time to help reproduce the issue / review the patch.

@trvon
Copy link
Author

trvon commented Oct 8, 2025

I do not have a clean way to share my p4 code, but I will reply with artifacts after I can reproduce the issue with a smaller p4 program and ptf test.

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.

2 participants