Skip to content

[components][net][lwip-nat] Fix translated port allocation and adapt … - #11831

Open
2027636040 wants to merge 1 commit into
RT-Thread:masterfrom
2027636040:fix/lwip-nat-lwip21-and-port
Open

2027636040 wants to merge 1 commit into
RT-Thread:masterfrom
2027636040:fix/lwip-nat-lwip21-and-port

Conversation

@2027636040

Copy link
Copy Markdown

Fix the translated source port allocation in the lwIP NAT component and make
the file build against lwIP 2.1.

Why to submit this PR (why to submit this PR)

Every newly created NAT mapping was assigned the same translated port:
ip_nat_udp_lookup_outgoing() / ip_nat_tcp_lookup_outgoing() store the free
slot index in "last_free" but compute the port from the loop counter "i".
When the allocation path is taken the loop has run to completion, so
i == LWIP_NAT_DEFAULT_STATE_TABLES_UDP/TCP and every new entry got
LWIP_NAT_DEFAULT_*_SOURCE_PORT + 32. Concurrent flows therefore shared one
translated port, and the incoming lookup could match the return traffic to
the wrong (first matching) entry, which breaks NAT as soon as more than one
session is active.

What is your solution

  • Use the free slot index for the translated port:
    nport = htons(LWIP_NAT_DEFAULT_UDP_SOURCE_PORT + last_free) (same for TCP).
    The port is then unique per table slot, consistent with the incoming
    lookup which matches on nport.
  • Adapt the file to lwIP 2.1: lwip/tcp_impl.h is lwip/prot/tcp.h and
    lwip/timers.h is lwip/timeouts.h there. Without this the component does
    not compile at all when it is built with lwIP 2.1.
  • Two behaviour changes in the same file: NAT is applied only when both the
    source and the destination network match the configured rule
    (ip_nat_shallnat), and when the ICMP table is full the oldest entry (LRU)
    is evicted and reused instead of dropping the new echo request.

Verified bsp and config

  • BSP: not an upstream bsp - verified on a SiFli SF32LB52x based USB dongle
    (USB RNDIS host from a phone with USB tethering on one side, BT PAN on the
    other, lwIP 2.1.2, NAT in ip4_forward path). Concurrency was the failing
    case before the fix (several sessions from the PAN side at the same time).
  • .config: RT_USING_LWIP=y, lwIP 2.1.2 selected, LWIP_USING_NAT=y
    (+ RT_LWIP_IP_FORWARD=y for the forwarding path).
  • action: not triggered, the change is component level and the same file is
    already in use in our product tree.

Note on the extra behaviour changes: they are part of what we carry downstream
today, but they are not required for the port fix above. If you prefer to take
only the port allocation fix (and/or the lwIP 2.1 headers) I'm happy to split
this PR - just say which part you want.

…to lwIP 2.1

Allocate the translated port from the free slot index instead of the scan counter:
  the loop counter equals the table size once the allocation path is taken, so
  every new mapping got the same port (base + table size) and concurrent UDP/TCP
  sessions collided, return traffic could be matched to the wrong entry.

Adapt the file to lwIP 2.1 as well: lwip/tcp_impl.h is lwip/prot/tcp.h and
  lwip/timers.h is lwip/timeouts.h now.  Two behaviour changes come with it:
  NAT is applied only when both the source and the destination network match the
  rule, and the oldest ICMP entry (LRU) is evicted instead of dropping new echo
  requests when the ICMP table is full.

Signed-off-by: zelong_666 <2027636040@qq.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions

Copy link
Copy Markdown

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • Use workflow from 保持默认分支(通常为 master)
    Keep the default branch (usually master) in Use workflow from
  • 在 branch 输入框填写 PR 分支 fix/lwip-nat-lwip21-and-port
    Enter PR branch fix/lwip-nat-lwip21-and-port in the branch field
  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将作为独立提交推送至你的分支。
    The formatting changes will be pushed to your branch as a separate commit.

完成后,提交将自动更新至 fix/lwip-nat-lwip21-and-port 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the fix/lwip-nat-lwip21-and-port branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@github-actions

Copy link
Copy Markdown

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: @Maihuanyi

Changed Files (Click to expand)
  • components/net/lwip-nat/ipv4_nat.c

📊 Current Review Status (Last Updated: 2026-09-24 14:15 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants