Skip to content

Commit

Permalink
feat: Obtain info via routing sockets (#29)
Browse files Browse the repository at this point in the history
* feat: Obtain info via routing sockets

WIP

This avoids the need to mess around with sockets.

* Fixes

* Fixes

* Linux

* Windows

* Fixes

* Clippy

* Clippy

* Update src/bsd.rs

Co-authored-by: Martin Thomson <[email protected]>

* Try and fix sanitizer issue

* Rearrange Windows code

* Fixes

* Fixes

* Omit win_bindings.rs from codecov (again)

* Update docs

* Read all socket responses to allow socket reuse

* Update README

* Add .clippy.toml

* Update src/windows/mod.rs

Co-authored-by: Max Inden <[email protected]>

* Drop neli

* Cleanups

* Nit

* Fixes

* Fix

* Fix

* Simplify

* Also install llvm-symbolizer for the sanitizer runs

* Fixes

* Fixes

* README

* clippy

* Tweaks

* Misc improvements

* ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1

* Suppress

* LSAN_OPTIONS

* llvm

* path

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Again

* Update src/linux.rs

Co-authored-by: Max Inden <[email protected]>

* Use `OwnedFd`

* Address code review

* BSDs and Windows

* ifconfig

* env

* rmx_filler

* Debug

* Debug

* send

* recv

* Again

* Again

* Again

* mtu

* Fix cloudflare.com v6 address

* Undo

* rt_metrics

* More BSD

* RTAX_IFA

* All the BSDs are different, sigh

* More

* codecov

* Again

* binstall

* cargo-llvm-cov

* Again

* llvm

* Minimize conversions

* More

* Again

* Again

* Again

* Again

* Again

* More

* Again

* Again

* Linux fix

* More

* stable

* Simplify

* More comments

* Use bindgen

* Address code review

* Iterator

* Final fixes

* Install llvm

* Workflow fixes

* Hack

* Fix?

* CI

* llvm-16.0.6p30

* netbsd

* netbsd

* clang

* Remove unused code.

* More helpers

* Tweaks

* Fix

* Address code review

* Update .github/workflows/check.yml

Co-authored-by: Martin Thomson <[email protected]>

* Update .github/workflows/check.yml

Co-authored-by: Martin Thomson <[email protected]>

* Update .github/workflows/check.yml

Co-authored-by: Martin Thomson <[email protected]>

* Update src/bsd.rs

Co-authored-by: Martin Thomson <[email protected]>

* Update src/linux.rs

Co-authored-by: Martin Thomson <[email protected]>

* Address first batch of comments from @martinthomson

* Suppress shellcheck warning

* More suggestions from @martinthomson

* Use `std::io::Result`

* clippy

* Nits

* Suggestions from @martinthomson

* Fix

* Macro

* Not Windows

---------

Co-authored-by: Martin Thomson <[email protected]>
Co-authored-by: Max Inden <[email protected]>
  • Loading branch information
3 people authored Nov 21, 2024
1 parent 14356bf commit 926a014
Show file tree
Hide file tree
Showing 12 changed files with 1,159 additions and 973 deletions.
1 change: 0 additions & 1 deletion .codecov.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ignore:
- "src/win_bindings.rs"

# Do not notify until at least three results have been uploaded from the CI pipeline.
# (This corresponds to the three main platforms we support: Linux, macOS, and Windows.)
Expand Down
128 changes: 96 additions & 32 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,34 @@ concurrency:
permissions:
contents: read

defaults:
run:
shell: bash

jobs:
toolchains:
runs-on: ubuntu-latest
outputs:
toolchains: ${{ steps.toolchains.outputs.toolchains }}
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
with:
sparse-checkout: Cargo.toml
- id: toolchains
run: |
msrv="$(grep rust-version Cargo.toml | tr -d '"' | cut -f3 -d\ )"
echo "toolchains=[\"$msrv\", \"stable\", \"nightly\"]" >> "$GITHUB_OUTPUT"
check:
needs: toolchains
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# Keep low end in sync with Cargo.toml
rust-toolchain: [1.76.0, stable, nightly]
rust-toolchain: ${{ fromJSON(needs.toolchains.outputs.toolchains) }}
type: [debug]
include:
# Also do some release builds on the latest OS versions.
- os: ubuntu-latest
rust-toolchain: stable
type: release
Expand All @@ -37,6 +55,7 @@ jobs:
- os: windows-latest
rust-toolchain: stable
type: release
# Also do some debug builds on the oldest OS versions.
- os: ubuntu-20.04
rust-toolchain: stable
type: debug
Expand All @@ -49,9 +68,6 @@ jobs:
env:
BUILD_TYPE: ${{ matrix.type == 'release' && '--release' || '' }}
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
Expand All @@ -65,30 +81,37 @@ jobs:
- uses: ./neqo/.github/actions/rust
with:
version: ${{ matrix.rust-toolchain }}
components: ${{ matrix.rust-toolchain == 'stable' && 'llvm-tools-preview' || '' }} ${{ matrix.rust-toolchain == 'nightly' && 'rust-src' || '' }}
components: ${{ matrix.rust-toolchain == 'stable' && 'llvm-tools' || '' }} ${{ matrix.rust-toolchain == 'nightly' && 'rust-src' || '' }}
tools: ${{ matrix.rust-toolchain == 'stable' && 'cargo-llvm-cov, ' || '' }}
token: ${{ secrets.GITHUB_TOKEN }}

- name: Check
run: |
# shellcheck disable=SC2086
cargo +${{ matrix.rust-toolchain }} check $BUILD_TYPE --all-targets
OPTIONS=(--all-targets)
if [ "$BUILD_TYPE" ]; then
OPTIONS+=("$BUILD_TYPE")
fi
cargo +${{ matrix.rust-toolchain }} check "${OPTIONS[@]}"
- name: Run tests and determine coverage
env:
RUST_LOG: trace
run: |
# shellcheck disable=SC2086
OPTIONS=(--no-fail-fast)
if [ "$BUILD_TYPE" ]; then
OPTIONS+=("$BUILD_TYPE")
fi
if [ "${{ matrix.rust-toolchain }}" == "stable" ] && [ "${{ matrix.type }}" == "debug" ] && [ "${{endsWith(matrix.os, '-latest') && 'latest' || '' }}" == "latest" ]; then
cargo +${{ matrix.rust-toolchain }} llvm-cov test $BUILD_TYPE --no-fail-fast --lcov --output-path lcov.info
cargo +${{ matrix.rust-toolchain }} llvm-cov test "${OPTIONS[@]}" --lcov --output-path lcov.info
else
if [ "${{ startsWith(matrix.os, 'windows') && 'windows' || '' }}" == "windows" ]; then
# The codegen_windows_bindings test only succeeds when run via llvm-cov?!
export FILTER="-- --skip codegen_windows_bindings"
OPTIONS+=(-- --skip codegen_windows_bindings)
fi
cargo +${{ matrix.rust-toolchain }} test $BUILD_TYPE --no-fail-fast $FILTER
cargo +${{ matrix.rust-toolchain }} test "${OPTIONS[@]}"
fi
cargo +${{ matrix.rust-toolchain }} bench --no-run
- uses: codecov/codecov-action@5c47607acb93fed5485fdbf7232e8a31425f672a # v5.0.2
with:
files: lcov.info
Expand All @@ -103,18 +126,30 @@ jobs:
if: (matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest') && matrix.rust-toolchain == 'nightly'
env:
RUST_LOG: trace
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
run: |
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
sudo apt-get install -y --no-install-recommends llvm
TARGET="x86_64-unknown-linux-gnu"
SANITIZERS="address thread leak memory"
elif [ "${{ matrix.os }}" = "macos-latest" ]; then
# llvm-symbolizer (as part of llvm) is installed by default on macOS runners
TARGET="aarch64-apple-darwin"
# no memory and leak sanitizer support yet
SANITIZERS="address thread"
# Suppress non-mtu leaks on macOS. TODO: Check occasionally if these are still needed.
{
echo "leak:dyld4::RuntimeState"
echo "leak:fetchInitializingClassList"
} > suppressions.txt
# shellcheck disable=SC2155
export LSAN_OPTIONS="suppressions=$(pwd)/suppressions.txt"
fi
for sanitizer in $SANITIZERS; do
echo "Running tests with $sanitizer sanitizer..."
RUSTFLAGS="-Z sanitizer=$sanitizer" RUSTDOCFLAGS="-Z sanitizer=$sanitizer" cargo +nightly test -Z build-std --target "$TARGET"
export RUSTFLAGS="-Z sanitizer=$sanitizer"
export RUSTDOCFLAGS="$RUSTFLAGS"
cargo +nightly test -Z build-std --target "$TARGET"
done
clippy:
Expand All @@ -123,9 +158,6 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
Expand Down Expand Up @@ -226,50 +258,82 @@ jobs:

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- run: curl -o rustup.sh --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs

- if: matrix.os == 'freebsd'
uses: vmactions/freebsd-vm@debf37ca7b7fa40e19c542ef7ba30d6054a706a4
with:
usesh: true
copyback: false
envs: "CARGO_TERM_COLOR RUST_BACKTRACE GITHUB_ACTIONS"
prepare: |
mkdir -p /usr/local/etc/pkg/repos
sed 's/quarterly/latest/' /etc/pkg/FreeBSD.conf > /usr/local/etc/pkg/repos/FreeBSD.conf
pkg update
pkg install -y rust
pkg install -y curl llvm
run: |
sh rustup.sh --default-toolchain stable --component llvm-tools -y
. "$HOME/.cargo/env"
export RUST_LOG=trace
cargo install cargo-llvm-cov --locked
cargo check --all-targets
RUST_LOG=trace cargo test --no-fail-fast
cargo clippy
cargo llvm-cov test --no-fail-fast --lcov --output-path lcov.info
cargo test --no-fail-fast --release
- if: matrix.os == 'openbsd'
uses: vmactions/openbsd-vm@0cfe06e734a0ea3a546fca7ebf200b984b94d58a
with:
usesh: true
copyback: false
envs: "CARGO_TERM_COLOR RUST_BACKTRACE GITHUB_ACTIONS"
prepare: |
pkg_add rust
pkg_add rust llvm-16.0.6p30 # rustup doesn't support OpenBSD at all
run: |
export LIBCLANG_PATH=/usr/local/llvm16/lib
export RUST_LOG=trace
cargo check --all-targets
RUST_LOG=trace cargo test --no-fail-fast
cargo clippy
cargo test --no-fail-fast
cargo test --no-fail-fast --release
- if: matrix.os == 'netbsd'
uses: vmactions/netbsd-vm@7c9086fdb4cc1aa814cda6e305390c2b966551a9
with:
usesh: true
copyback: false
envs: "CARGO_TERM_COLOR RUST_BACKTRACE GITHUB_ACTIONS"
prepare: |
/usr/sbin/pkg_add rust
/usr/sbin/pkg_add pkgin
pkgin -y install curl clang
run: |
sh rustup.sh --default-toolchain stable --component llvm-tools -y
. "$HOME/.cargo/env"
export LIBCLANG_PATH=/usr/pkg/lib
export RUST_LOG=trace
cargo install cargo-llvm-cov --locked
cargo check --all-targets
RUST_LOG=trace cargo test --no-fail-fast
cargo clippy
cargo test --no-fail-fast
# FIXME: error[E0463]: can't find crate for `profiler_builtins`,
# so don't fail the workflow when that happens.
cargo llvm-cov test --no-fail-fast --lcov --output-path lcov.info || true
cargo test --no-fail-fast --release
- if: matrix.os == 'solaris'
uses: vmactions/solaris-vm@a89b9438868c70db27e41625f0a5de6ff5e90809
with:
usesh: true
copyback: false
prepare: |
pkg install cargo
envs: "CARGO_TERM_COLOR RUST_BACKTRACE GITHUB_ACTIONS"
run: |
sh rustup.sh --default-toolchain stable --component llvm-tools -y
. "$HOME/.cargo/env"
export RUST_LOG=trace
cargo install cargo-llvm-cov --locked
cargo check --all-targets
RUST_LOG=trace cargo test --no-fail-fast
cargo clippy
cargo llvm-cov test --no-fail-fast --lcov --output-path lcov.info
cargo test --no-fail-fast --release
- uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
with:
file: lcov.info
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
19 changes: 11 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ edition = "2021"
license = "MIT OR Apache-2.0"
# Don't increase beyond what Firefox is currently using:
# https://searchfox.org/mozilla-central/search?q=MINIMUM_RUST_VERSION&path=python/mozboot/mozboot/util.py
# Also keep in sync with .github/workflows/check.yml
rust-version = "1.76.0"

[badges]
Expand All @@ -23,18 +22,22 @@ maintenance = { status = "actively-developed", branch = "main" }

[dependencies]
# Don't increase beyond what Firefox is currently using: https://searchfox.org/mozilla-central/source/Cargo.lock
libc = { version = "0.2", default-features = false }
libc = { version = ">=0.2.161", default-features = false }
static_assertions = { version = "1.1", default-features = false }

[dev-dependencies]
rand = { version = "0.8", default-features = false, features = ["std", "std_rng"] }

[target."cfg(windows)".dependencies]
[target.'cfg(windows)'.dependencies]
# Don't increase beyond what Firefox is currently using: https://searchfox.org/mozilla-central/source/Cargo.lock
windows-core = "0.58"
windows-targets = "0.52"

[target."cfg(windows)".dev-dependencies]
windows-bindgen = { version = "0.58" } # MSRV is 1.70
[build-dependencies]
cfg_aliases = "0.2"

[target.'cfg(not(windows))'.build-dependencies]
bindgen = { version = "0.69.5" }

[target.'cfg(windows)'.build-dependencies]
windows-bindgen = { version = "0.58" }

[lints.clippy]
cargo = { level = "warn", priority = -1 }
Expand Down
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@ towards a given destination `SocketAddr`, optionally from a given local `SocketA

## Usage

This crate exports a single function `interface_and_mtu` that, given a pair of local and remote `SocketAddr`s, returns the name and [maximum transmission unit (MTU)](https://en.wikipedia.org/wiki/Maximum_transmission_unit) of the local network interface used by a socket bound to the local address and connected towards the remote destination.

If the local address is `None`, the function will let the operating system choose the local
address based on the given remote address. If the remote address is `None`, the function will
return the name and MTU of the local network interface with the given local address.
This crate exports a single function `interface_and_mtu` that returns the name and
[maximum transmission unit (MTU)](https://en.wikipedia.org/wiki/Maximum_transmission_unit)
of the outgoing network interface towards a remote destination identified by an `IpAddr`.

## Example

```rust
let saddr = "127.0.0.1:443".parse().unwrap();
let (name, mtu) = mtu::interface_and_mtu(&(None, saddr)).unwrap();
println!("MTU for {saddr:?} is {mtu} on {name}");
let destination = IpAddr::V4(Ipv4Addr::LOCALHOST);
let (name, mtu): (String, usize) = mtu::interface_and_mtu(destination).unwrap();
println!("MTU towards {destination} is {mtu} on {name}");
```

## Supported Platforms
Expand Down
Loading

0 comments on commit 926a014

Please sign in to comment.