Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
dynamo
Commits
9b8b35a8
Unverified
Commit
9b8b35a8
authored
Jan 20, 2026
by
ishandhanani
Committed by
GitHub
Jan 20, 2026
Browse files
fix: ipv6 support for sglang disaggregation (#5521)
Co-authored-by:
Claude Opus 4.5
<
noreply@anthropic.com
>
parent
2e8c4447
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
90 additions
and
9 deletions
+90
-9
components/src/dynamo/sglang/register.py
components/src/dynamo/sglang/register.py
+47
-3
lib/runtime/src/utils/ip_resolver.rs
lib/runtime/src/utils/ip_resolver.rs
+43
-6
No files found.
components/src/dynamo/sglang/register.py
View file @
9b8b35a8
...
...
@@ -88,11 +88,55 @@ def _get_bootstrap_info_for_config(
return
None
,
None
if
inner_tm
.
server_args
.
dist_init_addr
:
bootstrap_host
=
socket
.
gethostbyname
(
inner_tm
.
server_args
.
dist_init_addr
.
split
(
":"
)[
0
]
# IPv6-ready host extraction and resolution:
# 1) Extract raw host from "host:port" or "[IPv6]:port"/"[IPv6]".
# 2) Resolve via AF_UNSPEC to accept A/AAAA and literals.
# 3) Bracket-wrap IPv6 for safe "{host}:{port}" URL formatting.
addr
=
inner_tm
.
server_args
.
dist_init_addr
.
strip
()
if
addr
.
startswith
(
"["
):
end
=
addr
.
find
(
"]"
)
host_core
=
addr
[
1
:
end
]
if
end
!=
-
1
else
addr
.
strip
(
"[]"
)
else
:
# Only treat single ':' with numeric suffix as host:port; otherwise it's an IPv6/FQDN host.
if
addr
.
count
(
":"
)
==
1
:
host_candidate
,
maybe_port
=
addr
.
rsplit
(
":"
,
1
)
host_core
=
host_candidate
if
maybe_port
.
isdigit
()
else
addr
else
:
host_core
=
addr
try
:
infos
=
socket
.
getaddrinfo
(
host_core
,
None
,
family
=
socket
.
AF_UNSPEC
,
type
=
socket
.
SOCK_STREAM
,
)
resolved
=
infos
[
0
][
4
][
0
]
# let OS policy pick v4/v6
bootstrap_host
=
resolved
addr_family
=
infos
[
0
][
0
]
logging
.
info
(
f
"Resolved bootstrap host '
{
host_core
}
' -> '
{
resolved
}
' "
f
"(
{
'IPv6'
if
addr_family
==
socket
.
AF_INET6
else
'IPv4'
}
)"
)
except
socket
.
gaierror
as
e
:
# Fallback: keep literal/FQDN as-is (still wrap IPv6 below)
bootstrap_host
=
host_core
logging
.
warning
(
f
"Failed to resolve bootstrap host '
{
host_core
}
':
{
e
}
, using as-is"
)
else
:
# get_local_ip_auto() tries IPv4 first, then IPv6. For explicit control,
# set SGLANG_HOST_IP env var (use bracketed format for IPv6: [addr])
bootstrap_host
=
get_local_ip_auto
()
is_ipv6
=
":"
in
bootstrap_host
logging
.
info
(
f
"Using auto-detected local IP:
{
bootstrap_host
}
"
f
"(
{
'IPv6'
if
is_ipv6
else
'IPv4'
}
)"
)
# Wrap IPv6 literal with brackets so f"{host}:{port}" stays valid.
if
":"
in
bootstrap_host
and
not
bootstrap_host
.
startswith
(
"["
):
bootstrap_host
=
f
"[
{
bootstrap_host
}
]"
logging
.
info
(
f
"Wrapped IPv6 address with brackets:
{
bootstrap_host
}
"
)
return
bootstrap_host
,
bootstrap_port
except
Exception
as
e
:
...
...
lib/runtime/src/utils/ip_resolver.rs
View file @
9b8b35a8
...
...
@@ -12,23 +12,31 @@ use std::net::IpAddr;
/// This function attempts to resolve the local IP address using the provided resolver.
/// If resolution fails, it falls back to 127.0.0.1 (localhost).
///
/// IPv6 addresses are wrapped with brackets for safe URL construction (e.g., `[::1]`).
///
/// # Arguments
/// * `resolver` - An implementation of IpResolver trait for getting local IP addresses
///
/// # Returns
/// A string representation of the resolved IP address
/// A string representation of the resolved IP address
(IPv6 addresses are bracketed)
pub
fn
get_http_rpc_host_with_resolver
<
R
:
IpResolver
>
(
resolver
:
R
)
->
String
{
let
resolved_ip
=
resolver
.local_ip
()
.or_else
(|
err
|
match
err
{
Error
::
LocalIpAddressNotFound
=>
resolver
.local_ipv6
(),
_
=>
Err
(
err
),
});
match
resolved_ip
{
let
addr
=
match
resolved_ip
{
Ok
(
addr
)
=>
addr
,
Err
(
Error
::
LocalIpAddressNotFound
)
=>
IpAddr
::
from
([
127
,
0
,
0
,
1
]),
Err
(
_
)
=>
IpAddr
::
from
([
127
,
0
,
0
,
1
]),
// Fallback for any other error
};
// Wrap IPv6 addresses with brackets for safe URL construction
// e.g., "2001:db8::1" becomes "[2001:db8::1]" so that "{host}:{port}" is valid
match
addr
{
IpAddr
::
V6
(
_
)
=>
format!
(
"[{}]"
,
addr
),
IpAddr
::
V4
(
_
)
=>
addr
.to_string
(),
}
.to_string
()
}
/// Get the local IP address for HTTP RPC host binding using the default resolver
...
...
@@ -112,7 +120,8 @@ mod tests {
};
let
result
=
get_http_rpc_host_with_resolver
(
resolver
);
assert_eq!
(
result
,
"2001:db8::1"
);
// IPv6 addresses should be bracketed for safe URL construction
assert_eq!
(
result
,
"[2001:db8::1]"
);
}
#[test]
...
...
@@ -151,7 +160,35 @@ mod tests {
// Should return some IP address (either resolved or fallback)
assert
!
(
!
result
.is_empty
());
// Should be a valid IP address
let
_
:
IpAddr
=
result
.parse
()
.expect
(
"Should be a valid IP address"
);
// Should be a valid IP address (strip brackets for IPv6 before parsing)
let
ip_str
=
result
.trim_start_matches
(
'['
)
.trim_end_matches
(
']'
);
let
_
:
IpAddr
=
ip_str
.parse
()
.expect
(
"Should be a valid IP address"
);
}
#[test]
fn
test_ipv6_address_is_bracketed
()
{
let
resolver
=
MockIpResolver
{
ipv4_result
:
Err
(
Error
::
LocalIpAddressNotFound
),
ipv6_result
:
Ok
(
IpAddr
::
from
([
0xfd00
,
0xdead
,
0xbeef
,
0
,
0
,
0
,
0
,
2
])),
};
let
result
=
get_http_rpc_host_with_resolver
(
resolver
);
// IPv6 must be bracketed for URLs like http://{host}:{port}/path
assert
!
(
result
.starts_with
(
'['
),
"IPv6 should start with '['"
);
assert
!
(
result
.ends_with
(
']'
),
"IPv6 should end with ']'"
);
assert_eq!
(
result
,
"[fd00:dead:beef::2]"
);
}
#[test]
fn
test_ipv4_address_not_bracketed
()
{
let
resolver
=
MockIpResolver
{
ipv4_result
:
Ok
(
IpAddr
::
from
([
10
,
0
,
0
,
1
])),
ipv6_result
:
Err
(
Error
::
LocalIpAddressNotFound
),
};
let
result
=
get_http_rpc_host_with_resolver
(
resolver
);
// IPv4 should NOT be bracketed
assert
!
(
!
result
.contains
(
'['
),
"IPv4 should not contain '['"
);
assert_eq!
(
result
,
"10.0.0.1"
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment