fix:修改默认网路只有5G模组问题

This commit is contained in:
nnbcccscdscdsc
2026-04-13 17:22:18 +08:00
parent 7dc47d310d
commit 2f507a7546
7 changed files with 148 additions and 6 deletions

3
.gitignore vendored
View File

@@ -22,3 +22,6 @@ c/bin
/.venv /.venv
**/build/ **/build/
ros-control-py/install
ros-control-py/log

View File

@@ -7,6 +7,22 @@ source "${SCRIPT_DIR}/common.sh"
STEP="5g-dial" STEP="5g-dial"
append_route_targets() {
local raw_list="$1"
local target
if [[ -z "${raw_list}" ]]; then
return 0
fi
for target in ${raw_list//,/ }; do
if [[ -z "${target}" ]]; then
continue
fi
dial_cmd+=(--route-target "${target}")
done
}
read_detected_interface() { read_detected_interface() {
local info_json="$1" local info_json="$1"
@@ -135,6 +151,12 @@ case "${BLITZ_5G_SKIP_DHCP:-0}" in
dial_cmd+=(--skip-dhcp) dial_cmd+=(--skip-dhcp)
;; ;;
esac esac
case "${BLITZ_5G_REMOVE_DEFAULT_ROUTE:-1}" in
1|true|TRUE|yes|YES)
dial_cmd+=(--remove-default-route --gateway "${BLITZ_5G_GATEWAY}" --route-target "${BLITZ_TIME_SERVER_IP}")
append_route_targets "${BLITZ_5G_ROUTE_TARGETS:-}"
;;
esac
pushd "${BLITZ_5G_DIAL_DIR}" >/dev/null pushd "${BLITZ_5G_DIAL_DIR}" >/dev/null
blitz_run "${STEP}" "dial" "${dial_cmd[@]}" blitz_run "${STEP}" "dial" "${dial_cmd[@]}"

View File

@@ -66,7 +66,7 @@ timestamp | step | action | result | details | exit_code
- `robot-boot.env.local`:本机覆盖配置,建议把你自己的配置写这里 - `robot-boot.env.local`:本机覆盖配置,建议把你自己的配置写这里
- `common.sh`:公共环境加载和统一日志函数 - `common.sh`:公共环境加载和统一日志函数
- `boot-gate.sh`:启动闸门,当前逻辑是固定等待 30 秒 - `boot-gate.sh`:启动闸门,当前逻辑是固定等待 30 秒
- `5g-dial.sh`:等待 5G 串口出现,执行 `rndis_dial.py`检查路由是否真的起来 - `5g-dial.sh`:等待 5G 串口出现,执行 `rndis_dial.py`删除 5G 默认路由并补齐目标主机路由,然后检查路由是否真的起来
- `time-sync.sh`:把 `chrony` 指向白名单服务器 IP 和端口,并执行一次同步 - `time-sync.sh`:把 `chrony` 指向白名单服务器 IP 和端口,并执行一次同步
- `start-ros-receiver-service.sh`:开机版 ROS receiver 启动包装 - `start-ros-receiver-service.sh`:开机版 ROS receiver 启动包装
- `wait-for-unix-socket.sh`:等待 ROS receiver 建好本地 unix socket - `wait-for-unix-socket.sh`:等待 ROS receiver 建好本地 unix socket
@@ -178,6 +178,9 @@ BLITZ_LOG_FILE="/var/log/blitz-robot/startup.log"
BLITZ_5G_DIAL_DIR="/home/nvidia/5g-test/5G" BLITZ_5G_DIAL_DIR="/home/nvidia/5g-test/5G"
BLITZ_5G_SERIAL_PORT="/dev/ttyUSB7" BLITZ_5G_SERIAL_PORT="/dev/ttyUSB7"
BLITZ_5G_GATEWAY="192.168.225.1"
BLITZ_5G_REMOVE_DEFAULT_ROUTE="1"
BLITZ_5G_ROUTE_TARGETS="106.55.173.235"
BLITZ_TIME_SERVER_IP="你的白名单云服务器IP" BLITZ_TIME_SERVER_IP="你的白名单云服务器IP"
BLITZ_TIME_SERVER_PORT="10910" BLITZ_TIME_SERVER_PORT="10910"
@@ -187,6 +190,8 @@ BLITZ_ROS_USER="nvidia"
如果 `BLITZ_TIME_SERVER_IP` 留空,脚本会自动回退到 `ROBOT_SIDE_OMNISOCKET_SERVER_ADDR` 的 IP 部分。 如果 `BLITZ_TIME_SERVER_IP` 留空,脚本会自动回退到 `ROBOT_SIDE_OMNISOCKET_SERVER_ADDR` 的 IP 部分。
`BLITZ_5G_REMOVE_DEFAULT_ROUTE="1"` 时,脚本会在 5G 拨号完成后删除该接口上的默认路由,避免整机默认出口切到 5G。此时 `BLITZ_TIME_SERVER_IP``BLITZ_5G_ROUTE_TARGETS` 中的目标 IP 会显式走 5G其它流量继续走有线或 Wi-Fi 的默认路由。
## 如何安装和使用 ## 如何安装和使用
下面假设你当前目录就在 `OmniSocketGo` 仓库根目录。 下面假设你当前目录就在 `OmniSocketGo` 仓库根目录。
@@ -272,7 +277,8 @@ systemctl status blitz-b-side-omnid.service
```bash ```bash
journalctl -u blitz-robot.target -u blitz-boot-gate.service -u blitz-5g-dial.service \ journalctl -u blitz-robot.target -u blitz-boot-gate.service -u blitz-5g-dial.service \
-u blitz-time-sync.service -u blitz-ros-receiver.service -u blitz-b-side-omnid.service -f -u blitz-time-sync.service -u blitz-ros-receiver.service \
-u blitz-b-side-omnid.service -f
``` ```
## 当前时钟同步会做什么 ## 当前时钟同步会做什么

View File

@@ -56,7 +56,10 @@ blitz_load_boot_env() {
export BLITZ_5G_SERIAL_PORT="${BLITZ_5G_SERIAL_PORT:-/dev/ttyUSB7}" export BLITZ_5G_SERIAL_PORT="${BLITZ_5G_SERIAL_PORT:-/dev/ttyUSB7}"
export BLITZ_5G_INTERFACE="${BLITZ_5G_INTERFACE:-}" export BLITZ_5G_INTERFACE="${BLITZ_5G_INTERFACE:-}"
export BLITZ_5G_MODEM_SUBNET="${BLITZ_5G_MODEM_SUBNET:-192.168.224.0/22}" export BLITZ_5G_MODEM_SUBNET="${BLITZ_5G_MODEM_SUBNET:-192.168.224.0/22}"
export BLITZ_5G_GATEWAY="${BLITZ_5G_GATEWAY:-192.168.225.1}"
export BLITZ_5G_SKIP_DHCP="${BLITZ_5G_SKIP_DHCP:-0}" export BLITZ_5G_SKIP_DHCP="${BLITZ_5G_SKIP_DHCP:-0}"
export BLITZ_5G_REMOVE_DEFAULT_ROUTE="${BLITZ_5G_REMOVE_DEFAULT_ROUTE:-1}"
export BLITZ_5G_ROUTE_TARGETS="${BLITZ_5G_ROUTE_TARGETS:-106.55.173.235}"
export BLITZ_5G_INFO_JSON="${BLITZ_5G_INFO_JSON:-${BLITZ_5G_DIAL_DIR}/modem_network_info.json}" export BLITZ_5G_INFO_JSON="${BLITZ_5G_INFO_JSON:-${BLITZ_5G_DIAL_DIR}/modem_network_info.json}"
export BLITZ_5G_DISABLE_INTERFACES="${BLITZ_5G_DISABLE_INTERFACES:-}" export BLITZ_5G_DISABLE_INTERFACES="${BLITZ_5G_DISABLE_INTERFACES:-}"
export BLITZ_5G_SERIAL_WAIT_SEC="${BLITZ_5G_SERIAL_WAIT_SEC:-60}" export BLITZ_5G_SERIAL_WAIT_SEC="${BLITZ_5G_SERIAL_WAIT_SEC:-60}"

View File

@@ -1,9 +1,9 @@
{ {
"interface": "enx8c5508fedec7", "interface": "enx78886c7fbd46",
"ipv4": [ "ipv4": [
"192.168.225.74/22" "192.168.225.62/22"
], ],
"ipv6": [ "ipv6": [
"fe80::e1ff:36e7:82eb:438c/64" "fe80::a335:b50d:622d:92e8/64"
] ]
} }

View File

@@ -76,6 +76,24 @@ def format_shell_cmd(cmd):
return " ".join(shlex.quote(part) for part in cmd) return " ".join(shlex.quote(part) for part in cmd)
def parse_ipv4_address(value):
try:
return str(ipaddress.IPv4Address(value))
except ipaddress.AddressValueError as exc:
raise argparse.ArgumentTypeError(f"无效的 IPv4 地址: {value}") from exc
def dedupe_keep_order(values):
seen = set()
result = []
for value in values:
if value in seen:
continue
seen.add(value)
result.append(value)
return result
def require_root(): def require_root():
if os.geteuid() != 0: if os.geteuid() != 0:
print("[FAIL] 请使用 sudo 运行此脚本") print("[FAIL] 请使用 sudo 运行此脚本")
@@ -513,6 +531,70 @@ def renew_dhcp(iface):
return False, "系统中未找到 dhclient 或 udhcpc" return False, "系统中未找到 dhclient 或 udhcpc"
def get_default_routes(iface):
code, output = run_cmd(["ip", "-o", "route", "show", "default", "dev", iface], timeout=10)
if code != 0:
return []
return [line.strip() for line in output.splitlines() if line.strip()]
def resolve_gateway(iface, fallback_gateway):
for route in get_default_routes(iface):
tokens = route.split()
for index, token in enumerate(tokens[:-1]):
if token == "via":
gateway = tokens[index + 1]
print(f"[INFO] 从默认路由检测到 {iface} 网关: {gateway}")
return gateway
print(f"[INFO] 未从默认路由检测到 {iface} 网关,回退到 {fallback_gateway}")
return fallback_gateway
def delete_default_routes(iface):
removed = 0
while True:
routes = get_default_routes(iface)
if not routes:
return removed
deleted_this_round = False
for route in routes:
cmd = ["ip", "route", "del", *route.split()]
code, output = run_cmd(cmd, timeout=10)
if code != 0:
code, output = run_cmd(["ip", "route", "del", "default", "dev", iface], timeout=10)
if code != 0:
raise RuntimeError(f"删除默认路由失败: {iface}\n{output}")
removed += 1
deleted_this_round = True
if not deleted_this_round:
raise RuntimeError(f"未能删除 {iface} 的默认路由")
def install_host_routes(iface, gateway, targets):
for target in dedupe_keep_order(targets):
cmd = ["ip", "route", "replace", f"{target}/32", "via", gateway, "dev", iface]
code, output = run_cmd(cmd, timeout=10)
if code != 0:
raise RuntimeError(f"添加主机路由失败: {target} via {gateway} dev {iface}\n{output}")
print(f"[OK] 已添加主机路由: {target}/32 via {gateway} dev {iface}")
def enforce_route_policy(iface, fallback_gateway, route_targets):
gateway = resolve_gateway(iface, fallback_gateway)
removed = delete_default_routes(iface)
print(f"[OK] 已删除 {iface} 上的 {removed} 条默认路由")
if route_targets:
install_host_routes(iface, gateway, route_targets)
else:
print(f"[WARN] {iface} 未配置任何主机路由目标5G 将不再承载公网流量")
def ensure_ipv4(iface): def ensure_ipv4(iface):
"""为指定接口申请 IPv4 地址。""" """为指定接口申请 IPv4 地址。"""
ipv4_addrs = get_ipv4_addrs().get(iface, []) ipv4_addrs = get_ipv4_addrs().get(iface, [])
@@ -659,11 +741,29 @@ def parse_args():
default=DEFAULT_MODEM_SUBNET, default=DEFAULT_MODEM_SUBNET,
help=f"拨号成功后用于识别模组接口的 IPv4 网段,默认 {DEFAULT_MODEM_SUBNET}", help=f"拨号成功后用于识别模组接口的 IPv4 网段,默认 {DEFAULT_MODEM_SUBNET}",
) )
parser.add_argument(
"--gateway",
type=parse_ipv4_address,
default=DEFAULT_MODEM_GATEWAY,
help=f"5G 模组网关地址,默认 {DEFAULT_MODEM_GATEWAY}",
)
parser.add_argument( parser.add_argument(
"--skip-dhcp", "--skip-dhcp",
action="store_true", action="store_true",
help="只等待 USB 网卡出现,不主动申请 IPv4", help="只等待 USB 网卡出现,不主动申请 IPv4",
) )
parser.add_argument(
"--remove-default-route",
action="store_true",
help="拨号成功后删除 5G 接口上的默认路由,只保留显式主机路由",
)
parser.add_argument(
"--route-target",
action="append",
default=[],
type=parse_ipv4_address,
help="拨号完成后通过 5G 接口保留的 IPv4 主机路由目标,可重复传入",
)
return parser.parse_args() return parser.parse_args()
@@ -733,7 +833,12 @@ def main():
for addr in ipv4_addrs: for addr in ipv4_addrs:
print(f"[OK] {iface} 已获取 IPv4: {addr}") print(f"[OK] {iface} 已获取 IPv4: {addr}")
save_interface_info(iface) save_interface_info(iface)
ping_via_interface(iface) route_targets = dedupe_keep_order(args.route_target)
if args.remove_default_route:
enforce_route_policy(iface, args.gateway, route_targets)
connectivity_targets = route_targets or list(DEFAULT_PUBLIC_TARGETS)
ping_via_interface(iface, targets=connectivity_targets)
print(f"[DONE] RNDIS 拨号完成,可执行: sudo python3 speed_test.py {iface}") print(f"[DONE] RNDIS 拨号完成,可执行: sudo python3 speed_test.py {iface}")
return return

View File

@@ -8,7 +8,10 @@ BLITZ_5G_DIAL_DIR="${OMNISOCKETGO_ROOT}/scripts/boot"
BLITZ_5G_SERIAL_PORT="/dev/ttyUSB2" BLITZ_5G_SERIAL_PORT="/dev/ttyUSB2"
BLITZ_5G_INTERFACE="" BLITZ_5G_INTERFACE=""
BLITZ_5G_MODEM_SUBNET="192.168.224.0/22" BLITZ_5G_MODEM_SUBNET="192.168.224.0/22"
BLITZ_5G_GATEWAY="192.168.225.1"
BLITZ_5G_SKIP_DHCP="0" BLITZ_5G_SKIP_DHCP="0"
BLITZ_5G_REMOVE_DEFAULT_ROUTE="1"
BLITZ_5G_ROUTE_TARGETS="106.55.173.235"
BLITZ_5G_INFO_JSON="${OMNISOCKETGO_ROOT}/scripts/boot/modem_network_info.json" BLITZ_5G_INFO_JSON="${OMNISOCKETGO_ROOT}/scripts/boot/modem_network_info.json"
BLITZ_5G_SERIAL_WAIT_SEC="60" BLITZ_5G_SERIAL_WAIT_SEC="60"
BLITZ_5G_ROUTE_WAIT_SEC="30" BLITZ_5G_ROUTE_WAIT_SEC="30"