Skip to content

Commit

Permalink
Fetch all ip addresses in a single stdlib call (#246)
Browse files Browse the repository at this point in the history
When fetching ip addresses for the host, we fetch all the network
interfaces, and then ip addresses for each interface. The latter call is
surprisingly expensive on unix, as it involves opening a netlink socket,
sending a request for routing information, and receiving and parsing the
response. If the host has a lot of network interfaces, this can eat
surprising amounts of memory - I got in the order of 10 MB on a
Kubernetes Node with 100 Pods. See
elastic/elastic-agent#5835 (comment)
for some heap profiles from elastic-agent.

Instead, get all the addresses in a single stdlib call. We don't
actually care about which interface each ip address is attached to, we
just want all of them.

I've tested this in the real world scenario discussed in
elastic/elastic-agent#5835, not sure how to
include a self-contained test in this repo.
  • Loading branch information
swiatekm authored Oct 29, 2024
1 parent b4a498b commit 750e2c7
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .changelog/246.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
Fetch all IP addresses in a single stdlib call
```
21 changes: 12 additions & 9 deletions providers/shared/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,20 @@ func Network() (ips, macs []string, err error) {
return nil, nil, err
}

ips = make([]string, 0, len(ifcs))
// This function fetches all the addresses in a single syscall. Fetching addresses individually for each interface
// can be expensive when the host has a lot of interfaces. This usually happens when the host is doing virtualized
// networking for guests, in Kubernetes for example.
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, nil, err
}
ips = make([]string, 0, len(addrs))
for _, addr := range addrs {
ips = append(ips, addr.String())
}

macs = make([]string, 0, len(ifcs))
for _, ifc := range ifcs {
addrs, err := ifc.Addrs()
if err != nil {
return nil, nil, err
}
for _, addr := range addrs {
ips = append(ips, addr.String())
}

mac := ifc.HardwareAddr.String()
if mac != "" {
macs = append(macs, mac)
Expand Down

0 comments on commit 750e2c7

Please sign in to comment.