Merge pull request #419 from betrusted-io/smoltcp-port

let's get it into ci, it's passing all the local tests
This commit is contained in:
bunnie 2023-10-03 19:23:06 +08:00 committed by GitHub
commit 81a8720d1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 711 additions and 594 deletions

147
Cargo.lock generated
View file

@ -74,7 +74,7 @@ dependencies = [
"aes 0.8.1",
"hex-literal",
"log",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
]
@ -264,7 +264,7 @@ dependencies = [
"num-derive",
"num-traits",
"trng",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -586,7 +586,7 @@ dependencies = [
"pddb",
"rkyv",
"trng",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -705,7 +705,7 @@ dependencies = [
"rkyv",
"trng",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -736,7 +736,7 @@ dependencies = [
"trng",
"typenum",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -793,7 +793,7 @@ dependencies = [
"graphics-server",
"log",
"rkyv",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-names",
]
@ -834,7 +834,7 @@ version = "0.1.0"
dependencies = [
"log",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -850,7 +850,7 @@ dependencies = [
"num-derive",
"num-traits",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -864,7 +864,7 @@ dependencies = [
"num-derive",
"num-traits",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -1439,7 +1439,7 @@ dependencies = [
"trng",
"userprefs",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -1464,7 +1464,7 @@ dependencies = [
"rkyv",
"spinor",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -1619,7 +1619,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -1778,7 +1778,7 @@ dependencies = [
"num-derive",
"num-traits",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -2002,7 +2002,7 @@ dependencies = [
"trng",
"tts-frontend",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -2068,7 +2068,7 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen",
"wasm-bindgen-test",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2103,7 +2103,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -2156,9 +2156,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heapless"
version = "0.7.13"
version = "0.7.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a08e755adbc0ad283725b29f4a4883deee15336f372d5f61fae59efec40f983"
checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
dependencies = [
"atomic-polyfill",
"hash32",
@ -2193,7 +2193,7 @@ dependencies = [
"num-derive",
"num-traits",
"tts-frontend",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2336,7 +2336,7 @@ dependencies = [
"rkyv",
"tts-frontend",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -2352,7 +2352,7 @@ dependencies = [
"num-derive",
"num-traits",
"rkyv",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2367,7 +2367,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -2386,7 +2386,7 @@ dependencies = [
"rkyv",
"tts-frontend",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -2496,7 +2496,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -2516,7 +2516,7 @@ version = "0.1.0"
dependencies = [
"log",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-ticktimer",
]
@ -2533,7 +2533,7 @@ dependencies = [
"rkyv",
"spinor",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -2614,7 +2614,7 @@ dependencies = [
"num-derive",
"num-traits",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -2638,7 +2638,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -2801,7 +2801,7 @@ dependencies = [
"trng",
"tts-frontend",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -2837,7 +2837,7 @@ dependencies = [
"trng",
"ureq",
"url",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -2867,7 +2867,7 @@ dependencies = [
"serde",
"trng",
"ureq",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -2907,7 +2907,7 @@ dependencies = [
"smoltcp",
"trng",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -3298,7 +3298,7 @@ dependencies = [
"trng",
"tts-frontend",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -3331,7 +3331,7 @@ version = "0.1.0"
dependencies = [
"log",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
]
[[package]]
@ -3884,7 +3884,7 @@ dependencies = [
"num-derive",
"num-traits",
"trng",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -3926,7 +3926,7 @@ dependencies = [
"spin 0.5.2",
"untrusted",
"winapi",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -4010,7 +4010,7 @@ dependencies = [
"tts-frontend",
"usb-device-xous",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -4333,7 +4333,7 @@ dependencies = [
"rkyv",
"trng",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -4427,7 +4427,7 @@ dependencies = [
"usb-device-xous",
"utralib",
"x25519-dalek",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -4465,12 +4465,14 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "smoltcp"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72165c4af59f5f19c7fb774b88b95660591b612380305b5f4503157341a9f7ee"
version = "0.10.0"
source = "git+https://github.com/smoltcp-rs/smoltcp.git?branch=main#edfdb23243a973d458397a2b4e76f527bacb1fd6"
dependencies = [
"bitflags 1.3.2",
"byteorder",
"cfg-if",
"defmt",
"heapless",
"libc",
"log",
"managed",
@ -4514,7 +4516,7 @@ dependencies = [
"rkyv",
"trng",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -4575,7 +4577,7 @@ dependencies = [
"usb-device-xous",
"userprefs",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -4762,7 +4764,7 @@ name = "ticktimer-test-client"
version = "0.1.0"
dependencies = [
"log",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
]
@ -4856,7 +4858,7 @@ dependencies = [
"sha2 0.9.8",
"webpki-roots 0.24.0",
"x509-parser",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -4973,7 +4975,7 @@ dependencies = [
"num-derive",
"num-traits",
"usb-device-xous",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4991,7 +4993,7 @@ dependencies = [
"rand_core 0.5.1",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -5009,7 +5011,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-ticktimer",
@ -5173,7 +5175,7 @@ dependencies = [
"usbd_scsi 0.1.1",
"utralib",
"vcell",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -5198,7 +5200,7 @@ dependencies = [
"usbd-human-interface-device 0.1.1",
"utralib",
"vcell",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -5261,7 +5263,7 @@ dependencies = [
"typenum",
"usb-device",
"usbd_mass_storage 0.1.0",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-ticktimer",
]
@ -5335,7 +5337,7 @@ dependencies = [
"usb-device",
"usbd_bulk_only_transport 0.1.0",
"usbd_mass_storage 0.1.0",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-ticktimer",
]
@ -5414,7 +5416,7 @@ dependencies = [
"usbd-human-interface-device 0.2.1",
"userprefs",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -5959,15 +5961,6 @@ dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "xous"
version = "0.9.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4d8c91009ed676410e747425107cfe4afc3dd9d3bf502a87542a353173b09e8"
dependencies = [
"lazy_static",
]
[[package]]
name = "xous-api-log"
version = "0.1.47"
@ -5977,7 +5970,7 @@ dependencies = [
"log",
"num-derive",
"num-traits",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -5991,7 +5984,7 @@ dependencies = [
"num-derive",
"num-traits",
"rkyv",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -6007,7 +6000,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
@ -6023,7 +6016,7 @@ dependencies = [
"num-derive",
"num-traits",
"rkyv",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -6037,7 +6030,7 @@ version = "0.9.51"
dependencies = [
"bitflags 1.3.2",
"rkyv",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
]
[[package]]
@ -6048,7 +6041,7 @@ checksum = "549eacc8d02d5e4c49559840fc3ec7f16e9a2c0a5bd27ae94da9c3e6ef9bc210"
dependencies = [
"bitflags 1.3.2",
"rkyv",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
]
[[package]]
@ -6068,7 +6061,7 @@ dependencies = [
"rand_chacha 0.3.1",
"stats_alloc",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-riscv",
]
@ -6082,7 +6075,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -6096,7 +6089,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
@ -6111,7 +6104,7 @@ dependencies = [
"pio",
"pio-proc",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
]
[[package]]
@ -6123,7 +6116,7 @@ dependencies = [
"pio",
"pio-proc",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-pio",
]
@ -6152,7 +6145,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -6169,7 +6162,7 @@ dependencies = [
"num-traits",
"rkyv",
"utralib",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-log",
"xous-api-names",
"xous-api-susres",
@ -6188,7 +6181,7 @@ dependencies = [
"num-derive",
"num-traits",
"rkyv",
"xous 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xous",
"xous-api-names",
"xous-ipc 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)",
]

View file

@ -177,8 +177,8 @@ rev="4296c2e7904898766cf7d8d589759a129794783b" # use the commitref because we're
path = "./utralib"
[patch.crates-io.svd2utra]
path = "./svd2utra"
# [patch.crates-io.xous]
# path = "./xous-rs"
[patch.crates-io.xous]
path = "./xous-rs"
# [patch.crates-io.xous-ipc]
# path = "./xous-ipc"
# [patch.crates-io.xous-api-names]

View file

@ -408,6 +408,9 @@ perform the Xous firmware upgrade. This requires running manual update commands,
## New in v0.9.15
- refresh item cache after leaving vault host readout mode
- Regressions have bee found in Rust 1.72. We suspect the llvm back-end for RV32 is emitting invalid code, see issue #416 and #417 for more details. For now, the optimization level has been set to `s` as a work-around.
- Network stack is updated to work with the `main` branch of `smoltcp`. This is not intended as a release configuration -- this note is here so that when a release is snapshotted out, we remember to pin to a particular commit (or ideally an official release, if one happens in time).
- This fixes a number of long-standing issues, including #210 and #407.
- Fairly major overhaul to the network stack. We now use mspc primitives to implement the wait/poll loop, which should make the net stack much more efficient and robust.
## Roadmap
- Lots of testing and bug fixes

View file

@ -35,11 +35,12 @@ xous-semver = "0.1.2"
[dependencies.smoltcp]
# some historical notes for development on branches in the future
# path = "../../../smoltcp"
#git = "https://github.com/smoltcp-rs/smoltcp.git"
git = "https://github.com/smoltcp-rs/smoltcp.git"
branch = "main"
#git = "https://github.com/betrusted-io/smoltcp.git"
#rev = "35c8ec3d30c846442a1faae01fb0537641aef898"
# 0.8.1 drops the rand_core dep and doesn't have the breaking IPv4 change (see issue #613)
version = "0.8.1"
# version = "0.8.1"
default-features = false
features = [
"std", "log", # needed for `cargo test --no-default-features --features default` :/

View file

@ -34,9 +34,11 @@ pub const MIN_EC_REV: SemVer = SemVer {
};
/// Dispatch opcodes to the Net crate main loop.
#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug)]
#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug, PartialEq, Eq)]
#[repr(C)]
pub(crate) enum Opcode {
SetupMpsc = 0,
SetDebug = 1,
/// Calls for UDP implementation (now deprecated to libstd)
//UdpBind = 0,
//UdpClose = 1,
@ -457,7 +459,6 @@ pub fn ipaddress_to_ipaddr(other: IpAddress) -> IpAddr {
let octets = ipv6.0;
IpAddr::V6(Ipv6Addr::from(octets))
}
_ => unimplemented!(),
}
}

View file

@ -59,9 +59,6 @@ impl From<IpAddress> for NetIpAddr {
match other {
IpAddress::Ipv4(ipv4) => NetIpAddr::Ipv4(ipv4.0),
IpAddress::Ipv6(ipv6) => NetIpAddr::Ipv6(ipv6.0),
_ => {
panic!("Invalid IpAddress")
}
}
}
}

View file

@ -1,17 +1,14 @@
use com::Com;
use com::api::NET_MTU;
use smoltcp::Result;
use smoltcp::phy::{self, DeviceCapabilities, Medium};
use smoltcp::wire::{ArpPacket, ArpRepr, ArpOperation, Ipv4Address, EthernetAddress, EthernetFrame, EthernetProtocol};
use smoltcp::phy::{self, DeviceCapabilities, Medium, ChecksumCapabilities};
use smoltcp::wire::{ArpPacket, ArpRepr, ArpOperation, Ipv4Address,
EthernetAddress, EthernetFrame, EthernetProtocol, Ipv4Packet,
Ipv4Repr, /* IpProtocol, TcpPacket, TcpRepr, IpAddress, UdpPacket, UdpRepr */};
use num_traits::*;
use std::convert::TryInto;
use smoltcp::{
time::Instant,
};
use crate::{MAC_ADDRESS_LSB, MAC_ADDRESS_MSB};
use crate::{MAC_ADDRESS_LSB, MAC_ADDRESS_MSB, IPV4_ADDRESS};
use core::sync::atomic::Ordering;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
@ -49,31 +46,55 @@ impl<'a> NetPhy {
}
}
impl<'a> phy::Device<'a> for NetPhy {
type RxToken = NetPhyRxToken<'a>;
type TxToken = NetPhyTxToken<'a>;
impl phy::Device for NetPhy {
type RxToken<'a> = NetPhyRxToken<'a>;
type TxToken<'a> = NetPhyTxToken<'a>;
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
fn receive(&mut self, _instant: smoltcp::time::Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
let csum_copy = self.capabilities().checksum.clone();
if let Some(rx_len) = self.loopback_pending.lock().unwrap().pop_front() {
log::debug!("loopback injected {} bytes", rx_len);
// loopback takes precedence
self.com.wlan_fetch_loopback_packet(&mut self.rx_buffer[..rx_len as usize]).expect("Couldn't call wlan_fetch_packet in device adapter");
Some((NetPhyRxToken{buf: &mut self.rx_buffer[..rx_len as usize]},
NetPhyTxToken{buf: &mut self.tx_buffer[..], com: & self.com, loopback_conn: self.loopback_conn, loopback_count: self.loopback_pending.clone()}))
NetPhyTxToken{
buf: &mut self.tx_buffer[..],
com: & self.com,
loopback_conn: self.loopback_conn,
loopback_count: self.loopback_pending.clone(),
caps: csum_copy
}))
} else {
if let Some(rx_len) = self.rx_avail.take() {
log::debug!("device rx of {} bytes", rx_len);
self.com.wlan_fetch_packet(&mut self.rx_buffer[..rx_len as usize]).expect("Couldn't call wlan_fetch_packet in device adapter");
Some((NetPhyRxToken{buf: &mut self.rx_buffer[..rx_len as usize]},
NetPhyTxToken{buf: &mut self.tx_buffer[..], com: & self.com, loopback_conn: self.loopback_conn, loopback_count: self.loopback_pending.clone()}))
NetPhyTxToken{
buf: &mut self.tx_buffer[..],
com: & self.com,
loopback_conn: self.loopback_conn,
loopback_count: self.loopback_pending.clone(),
caps: csum_copy
}))
} else {
log::trace!("nothing to rx");
None
}
}
}
fn transmit(&'a mut self) -> Option<Self::TxToken> {
Some(NetPhyTxToken{buf: &mut self.tx_buffer[..], com: &self.com, loopback_conn: self.loopback_conn, loopback_count: self.loopback_pending.clone()})
fn transmit(&mut self, _instant: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
let csum_copy = self.capabilities().checksum.clone();
log::debug!("device tx");
Some(NetPhyTxToken{
buf: &mut self.tx_buffer[..],
com: &self.com,
loopback_conn: self.loopback_conn,
loopback_count: self.loopback_pending.clone(),
caps: csum_copy
})
}
fn capabilities(&self) -> DeviceCapabilities {
@ -90,8 +111,8 @@ pub struct NetPhyRxToken<'a> {
}
impl<'a, 'c> phy::RxToken for NetPhyRxToken<'a> {
fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
where F: FnOnce(&mut [u8]) -> Result<R>
fn consume<R, F>(mut self, f: F) -> R
where F: FnOnce(&mut [u8]) -> R
{
let result = f(&mut self.buf);
//log::info!("rx: {:x?}", self.buf);
@ -104,10 +125,13 @@ pub struct NetPhyTxToken<'a> {
com: &'a Com,
loopback_conn: xous::CID,
loopback_count: Arc::<Mutex::<VecDeque<u16>>>,
caps: ChecksumCapabilities,
}
impl <'a> NetPhyTxToken<'a> {
/// Initiates the Rx side of things to read out the loopback packet that was queued
fn loopback_rx(&self, rxlen: usize) {
// this will initiate a target trace
// log::set_max_level(log::LevelFilter::Trace);
self.loopback_count.lock().unwrap().push_back(rxlen as u16);
xous::try_send_message(self.loopback_conn,
xous::Message::new_scalar(crate::Opcode::LoopbackRx.to_usize().unwrap(), rxlen, 0, 0, 0)
@ -152,86 +176,197 @@ impl <'a> NetPhyTxToken<'a> {
}
impl<'a> phy::TxToken for NetPhyTxToken<'a> {
fn consume<R, F>(mut self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where F: FnOnce(&mut [u8]) -> Result<R>
fn consume<R, F>(self, len: usize, f: F) -> R
where F: FnOnce(&mut [u8]) -> R
{
let result = f(&mut self.buf[..len]);
//log::info!("txlen: {}", len);
log::debug!("txlen: {}", len);
{
// this is a hack to make loopbacks work on smoltcp. Work-around taken from Redox, but tracking this issue as well:
// https://github.com/smoltcp-rs/smoltcp/issues/50 and https://github.com/smoltcp-rs/smoltcp/issues/55
// detect an outbound loopback packet, and shove it back in
let mut loopback = false;
if let Ok(mut frame) = smoltcp::wire::EthernetFrame::new_checked(&mut self.buf) {
if let Ok(mut eth_frame) = EthernetFrame::new_checked(&mut self.buf[..len]) {
let mut local_hwaddr = [0u8; 6];
local_hwaddr[2..6].copy_from_slice(&MAC_ADDRESS_LSB.load(Ordering::SeqCst).to_be_bytes());
local_hwaddr[0..2].copy_from_slice(&MAC_ADDRESS_MSB.load(Ordering::SeqCst).to_be_bytes());
if frame.dst_addr() == EthernetAddress::default() {
if eth_frame.dst_addr() == EthernetAddress::default() {
log::debug!("loopback packet redirect");
// override the destination address to be our own address
frame.set_dst_addr(smoltcp::wire::EthernetAddress(local_hwaddr));
loopback = true;
} else if frame.dst_addr().as_bytes() == local_hwaddr {
log::debug!("loopback return packet redirect");
loopback = true;
}
}
if result.is_ok() {
if loopback {
eth_frame.set_dst_addr(smoltcp::wire::EthernetAddress(local_hwaddr));
self.com.wlan_queue_loopback(&self.buf[..len]);
self.loopback_rx(len);
} else {
{
// this is a hack to make loopbacks work on smoltcp. Work-around taken from Redox, but tracking this issue as well:
// https://github.com/smoltcp-rs/smoltcp/issues/50 and https://github.com/smoltcp-rs/smoltcp/issues/55
// this part of the hack finds ARP packets to and from the local device, and responds to them with packet injections
let pkt = &self.buf[..len];
if let Ok(frame) = EthernetFrame::new_checked(pkt) {
if frame.ethertype() == EthernetProtocol::Arp {
// we're parsing packets that came from our own stack -- they better be OK!
let arp_packet = ArpPacket::new_checked(frame.payload()).unwrap();
let arp_repr = ArpRepr::parse(&arp_packet).unwrap();
match arp_repr {
ArpRepr::EthernetIpv4 {
operation, source_hardware_addr, source_protocol_addr, target_protocol_addr, ..
} => {
log::trace!("outgoing arp: {:?} {:?} {:?}", source_hardware_addr, source_protocol_addr, target_protocol_addr);
if target_protocol_addr.as_bytes() == [127, 0, 0, 1] && operation == ArpOperation::Request {
log::trace!("intercepted outgoing arp for 127.0.0.1: {:?}", pkt);
self.wlan_queue_localhost_arp(
source_hardware_addr.as_bytes().try_into().unwrap(),
source_protocol_addr,
EthernetAddress([0, 0, 0, 0, 0, 0,]),
Ipv4Address([127, 0, 0, 1]),
);
return result;
} else if source_protocol_addr.as_bytes() == [127, 0, 0, 1] && operation == ArpOperation::Request {
// reverse lookup case
log::trace!("intercepted outgoing arp for own IP: {:?} {:?}", target_protocol_addr, pkt);
self.wlan_queue_localhost_arp(
source_hardware_addr.as_bytes().try_into().unwrap(),
source_protocol_addr,
source_hardware_addr,
target_protocol_addr,
);
return result;
} else {
// don't do anything, pass it on
return result;
} else if eth_frame.dst_addr().as_bytes() == local_hwaddr {
log::debug!("loopback return packet redirect");
self.com.wlan_queue_loopback(&self.buf[..len]);
self.loopback_rx(len);
return result;
}
// make a copy of the packet so we can meet mutability requirements of the routines below...
let mut packet_clone = [0u8; NET_MTU];
let payload_len = eth_frame.payload_mut().len();
packet_clone[..payload_len].copy_from_slice(&eth_frame.payload_mut()[..payload_len]);
match eth_frame.ethertype() {
EthernetProtocol::Ipv4 => {
if let Ok(packet) = Ipv4Packet::new_checked(&packet_clone[..payload_len]) {
log::debug!("IPV4 packet checksum: {:x} ({:?})", packet.checksum(), packet.verify_checksum());
if let Ok(ipv4_parsed) = Ipv4Repr::parse(&packet, &self.caps) {
log::debug!("IPV4 parsed: {:?}", ipv4_parsed);
if ipv4_parsed.dst_addr.as_bytes() == [127, 0, 0, 1] {
log::debug!("patching destination 127.0.0.1");
// patch the destination MAC address
let mut local_hwaddr = [0u8; 6];
local_hwaddr[2..6].copy_from_slice(&MAC_ADDRESS_LSB.load(Ordering::SeqCst).to_be_bytes());
local_hwaddr[0..2].copy_from_slice(&MAC_ADDRESS_MSB.load(Ordering::SeqCst).to_be_bytes());
eth_frame.set_dst_addr(smoltcp::wire::EthernetAddress(local_hwaddr));
/* this is no longer necessary in smoltcp 0.9 or later - an interface can bind to multiple sockets, one of which being 127.0.0.1
// patch the destination IP address
let orig_dst_addr = ipv4_parsed.dst_addr;
ipv4_parsed.dst_addr = smoltcp::wire::Ipv4Address::from_bytes(&IPV4_ADDRESS.load(Ordering::SeqCst).to_be_bytes());
// extract the buffer region from the original frame and overwrite it
let payload_buf = eth_frame.payload_mut();
let mut mut_pkt = Ipv4Packet::new_unchecked(payload_buf);
// recompute inner-checksums for TCP and UDP cases...
match ipv4_parsed.next_header {
IpProtocol::Tcp => {
let tcp_packet = TcpPacket::new_unchecked(packet.payload());
if let Ok(tcp_repr) = TcpRepr::parse(
&tcp_packet,
&IpAddress::Ipv4(ipv4_parsed.src_addr),
&IpAddress::Ipv4(orig_dst_addr),
&self.caps
) {
log::trace!("tcp checksum: {:x}", tcp_packet.checksum());
let mut mut_tcp_packet = TcpPacket::new_unchecked(mut_pkt.payload_mut());
tcp_repr.emit(
&mut mut_tcp_packet,
&IpAddress::Ipv4(ipv4_parsed.src_addr),
&IpAddress::Ipv4(ipv4_parsed.dst_addr),
&self.caps
);
log::trace!("tcp new checksum: {:x}", tcp_packet.checksum());
} else {
log::error!("Transmitted TCP packet did not unpack correctly! checksum: {:?}", tcp_packet.verify_checksum(
&IpAddress::Ipv4(ipv4_parsed.src_addr), &IpAddress::Ipv4(orig_dst_addr)));
}
}
IpProtocol::Udp => {
let udp_packet = UdpPacket::new_unchecked(packet.payload());
if let Ok(udp_repr) = UdpRepr::parse(
&udp_packet,
&IpAddress::Ipv4(ipv4_parsed.src_addr),
&IpAddress::Ipv4(orig_dst_addr),
&self.caps
) {
log::debug!("udp checksum: {:x}", udp_packet.checksum());
let mut mut_udp_packet = UdpPacket::new_unchecked(mut_pkt.payload_mut());
udp_repr.emit(
&mut mut_udp_packet,
&IpAddress::Ipv4(ipv4_parsed.src_addr),
&IpAddress::Ipv4(ipv4_parsed.dst_addr),
udp_packet.len() as usize,
|buf| buf.copy_from_slice(packet.payload()),
&self.caps
);
log::debug!("udp new checksum: {:x}", udp_packet.checksum());
} else {
log::error!("Transmitted UDP packet did not unpack correctly! checksum: {:?}", udp_packet.verify_checksum(
&IpAddress::Ipv4(ipv4_parsed.src_addr), &IpAddress::Ipv4(orig_dst_addr)));
}
}
_ => {
log::warn!("Unhandled packet type in loopback! Checksum will be incorrect.");
}
}
_ => {}, // pass it on
log::trace!("checksum: {:x}", mut_pkt.checksum());
ipv4_parsed.emit(&mut mut_pkt, &self.caps);
log::trace!("new checksum: {:x}", mut_pkt.checksum());
*/
let buf_to_send = eth_frame.into_inner();
self.com.wlan_queue_loopback(buf_to_send);
/* // for double-checking the RX packet
if let Ok(check_frame) = EthernetFrame::new_checked(&buf_to_send) {
if let Ok(check_pkt) = Ipv4Packet::new_checked(&check_frame.payload()) {
if let Ok(check_parsed) = Ipv4Repr::parse(&check_pkt, &self.caps) {
log::debug!("CHECK: checksum: {:x}, valid: {:?}, patched packet: {:?}",
check_pkt.checksum(),
check_pkt.verify_checksum(),
check_parsed);
} else {
log::debug!("CHECK: FAILED - invalid IPv4 packet");
}
} else {
log::debug!("CHECK: FAILED - invalid payload");
}
} else {
log::debug!("CHECK: FAILED - invalid ethernet frame");
}
*/
self.loopback_rx(len);
// exit here without sending the packet on, because it went to Rx
return result;
}
}
}
}
// normally this would be the only line!
self.com.wlan_send_packet(&self.buf[..len]).map_err(|_| smoltcp::Error::Dropped)?;
EthernetProtocol::Arp => {
// this is a hack to make loopbacks work on smoltcp. Work-around taken from Redox, but tracking this issue as well:
// https://github.com/smoltcp-rs/smoltcp/issues/50 and https://github.com/smoltcp-rs/smoltcp/issues/55
// this part of the hack finds ARP packets to and from the local device, and responds to them with packet injections
// we're parsing packets that came from our own stack -- they better be OK!
let arp_packet = ArpPacket::new_checked(eth_frame.payload_mut()).unwrap();
let arp_repr = ArpRepr::parse(&arp_packet).unwrap();
match arp_repr {
ArpRepr::EthernetIpv4 {
operation, source_hardware_addr, source_protocol_addr, target_protocol_addr, ..
} => {
log::debug!("outgoing arp: {:?} {:?} {:?}", source_hardware_addr, source_protocol_addr, target_protocol_addr);
let local_addr = IPV4_ADDRESS.load(Ordering::SeqCst).to_be_bytes();
if (target_protocol_addr.as_bytes() == [127, 0, 0, 1]
|| target_protocol_addr.as_bytes() == local_addr)
&& operation == ArpOperation::Request {
log::debug!("intercepted outgoing arp for localhost: {:?}", arp_repr);
let mut local_hwaddr = [0u8; 6];
local_hwaddr[2..6].copy_from_slice(&MAC_ADDRESS_LSB.load(Ordering::SeqCst).to_be_bytes());
local_hwaddr[0..2].copy_from_slice(&MAC_ADDRESS_MSB.load(Ordering::SeqCst).to_be_bytes());
self.wlan_queue_localhost_arp(
source_hardware_addr.as_bytes().try_into().unwrap(),
source_protocol_addr,
EthernetAddress(local_hwaddr),
Ipv4Address(target_protocol_addr.as_bytes().try_into().unwrap()),
);
return result;
} /* else if (source_protocol_addr.as_bytes() == [127, 0, 0, 1]
|| source_protocol_addr.as_bytes() == local_addr)
&& operation == ArpOperation::Request {
// reverse lookup case
log::debug!("intercepted outgoing arp for own IP: {:?} {:?}", target_protocol_addr, arp_repr);
self.wlan_queue_localhost_arp(
source_hardware_addr.as_bytes().try_into().unwrap(),
source_protocol_addr,
source_hardware_addr,
target_protocol_addr,
);
return result;
} else {
// don't do anything, pass it on
} */
}
_ => {}, // pass it on
}
}
_ => {}
}
}
}
// forward the packet on if it's not a loopback (loopback will call return early and exit before getting to this line)
self.com.wlan_send_packet(&self.buf[..len]).expect("driver error sending WLAN packet");
result
}
}

View file

@ -59,6 +59,18 @@ impl NetManager {
wifi_state_sid: None,
}
}
pub fn set_debug_level(&self, level: log::LevelFilter) {
let code = match level {
log::LevelFilter::Info => 0,
log::LevelFilter::Debug => 1,
log::LevelFilter::Trace => 2,
_ => 0,
};
send_message(
self.netconn.conn(),
Message::new_scalar(Opcode::SetDebug.to_usize().unwrap(), code, 0, 0, 0),
).expect("couldn't set debug");
}
pub fn get_ipv4_config(&self) -> Option<Ipv4Conf> {
let storage = Some(Ipv4Conf::default().encode_u16());
let mut buf = Buffer::into_buf(storage).expect("Couldn't convert to memory structure");

File diff suppressed because it is too large Load diff

View file

@ -40,10 +40,6 @@ pub(crate) fn write_address(address: IpAddress, data: &mut [u8]) -> Option<usize
}
Some(16)
}
_ => {
*i.next()? = 0;
Some(1)
}
}
}

View file

@ -1,10 +1,11 @@
use crate::*;
use crate::device::NetPhy;
use smoltcp::wire::{IpEndpoint, IpAddress};
use smoltcp::socket::tcp;
pub(crate) fn std_tcp_listen(
mut msg: xous::MessageEnvelope,
iface: &mut Interface::<NetPhy>,
_iface: &mut Interface,
sockets: &mut SocketSet,
our_sockets: &mut Vec<Option<SocketHandle>>,
trng: &trng::Trng,
) {
@ -40,19 +41,19 @@ pub(crate) fn std_tcp_listen(
return;
}
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; TCP_BUFFER_SIZE]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; TCP_BUFFER_SIZE]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let handle = iface.add_socket(tcp_socket);
let tcp_socket = iface.get_socket::<TcpSocket>(handle);
let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; TCP_BUFFER_SIZE]);
let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; TCP_BUFFER_SIZE]);
let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
let handle = sockets.add(tcp_socket);
let tcp_socket = sockets.get_mut::<tcp::Socket>(handle);
loop {
if let Err(e) = tcp_socket
.listen(local_port)
.map_err(|e| match e {
smoltcp::Error::Illegal => NetError::SocketInUse,
smoltcp::Error::Unaddressable => NetError::Unaddressable,
_ => NetError::LibraryError,
smoltcp::socket::tcp::ListenError::InvalidState => NetError::SocketInUse,
smoltcp::socket::tcp::ListenError::Unaddressable => NetError::Unaddressable,
})
{
match e {
@ -94,7 +95,8 @@ pub(crate) fn std_tcp_listen(
pub(crate) fn std_tcp_accept(
mut msg: xous::MessageEnvelope,
iface: &mut Interface::<NetPhy>,
_iface: &mut Interface,
sockets: &mut SocketSet,
tcp_accept_waiting: &mut Vec<Option<AcceptingSocket>>,
tcp_server_remote_close_poll: &mut Vec<SocketHandle>,
our_sockets: &Vec<Option<SocketHandle>>,
@ -122,13 +124,13 @@ pub(crate) fn std_tcp_accept(
let args = unsafe { body.buf.as_slice::<u8>() };
let nonblocking = args[0] == 0;
let socket = iface.get_socket::<TcpSocket>(*handle);
let socket = sockets.get::<tcp::Socket>(*handle);
if socket.is_active() {
log::debug!("accept did not block; immediately returning TcpSocket");
let buf = unsafe { body.buf.as_slice_mut::<u8>() };
tcp_server_remote_close_poll.push(*handle);
tcp_accept_success(buf, fd as u16, socket.remote_endpoint());
tcp_accept_success(buf, fd as u16, socket.remote_endpoint().expect("TCP accept missing remote endpoint"));
return;
}
@ -170,9 +172,6 @@ pub(crate) fn tcp_accept_success(buf: &mut [u8], fd: u16, ep: IpEndpoint) {
*d = s;
}
}
_ => {
buf[3] = 0; // this is the invalid/error type
}
}
let port = ep.port.to_le_bytes();
buf[20] = port[0];

View file

@ -3,17 +3,15 @@ use ticktimer_server::Ticktimer;
use std::convert::TryInto;
use core::num::NonZeroU64;
use smoltcp::socket::{
TcpSocket, TcpSocketBuffer,
};
use smoltcp::iface::{Interface, SocketHandle};
use smoltcp::socket::tcp;
use crate::*;
use crate::device::NetPhy;
pub(crate) fn std_tcp_connect(
mut msg: xous::MessageEnvelope,
local_port: u16,
iface: &mut Interface::<NetPhy>,
iface: &mut Interface,
sockets: &mut SocketSet,
tcp_connect_waiting: &mut Vec<Option<(xous::MessageEnvelope, SocketHandle, u16, u16, u16)>>,
our_sockets: &mut Vec<Option<SocketHandle>>,
) {
@ -41,20 +39,20 @@ pub(crate) fn std_tcp_connect(
// initiates a new connection to a remote server consisting of an (Address:Port) tuple.
// multiple connections can exist to a server, and they are further differentiated by the return port
let tcp_socket = TcpSocket::new(
TcpSocketBuffer::new(vec![0; TCP_BUFFER_SIZE]),
TcpSocketBuffer::new(vec![0; TCP_BUFFER_SIZE]),
);
let handle = iface.add_socket(tcp_socket);
let (tcp_socket, cx) = iface.get_socket_and_context::<TcpSocket>(handle);
let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; TCP_BUFFER_SIZE]);
let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; TCP_BUFFER_SIZE]);
let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
let handle = sockets.add(tcp_socket);
let cx = iface.context();
let tcp_socket = sockets.get_mut::<tcp::Socket>(handle);
// Attempt to connect, returning the error if there is one
if let Err(e) = tcp_socket
.connect(cx, (address, remote_port), local_port)
.map_err(|e| match e {
smoltcp::Error::Illegal => NetError::SocketInUse,
smoltcp::Error::Unaddressable => NetError::Unaddressable,
_ => NetError::LibraryError,
smoltcp::socket::tcp::ConnectError::InvalidState => NetError::SocketInUse,
smoltcp::socket::tcp::ConnectError::Unaddressable => NetError::Unaddressable,
})
{
log::debug!("couldn't connect: {:?}", e);
@ -77,7 +75,8 @@ pub(crate) fn std_tcp_connect(
pub(crate) fn std_tcp_tx(
mut msg: xous::MessageEnvelope,
timer: &Ticktimer,
iface: &mut Interface::<NetPhy>,
_iface: &mut Interface,
sockets: &mut SocketSet,
tcp_tx_waiting: &mut Vec<Option<WaitingSocket>>,
our_sockets: &Vec<Option<SocketHandle>>,
) {
@ -98,7 +97,7 @@ pub(crate) fn std_tcp_tx(
}
};
let socket = iface.get_socket::<TcpSocket>(*handle);
let socket = sockets.get_mut::<tcp::Socket>(*handle);
// handle the case that the connection closed due to the receiver quitting
if !socket.can_send() {
log::trace!("tx can't send, will retry");
@ -150,7 +149,8 @@ pub(crate) fn std_tcp_tx(
pub(crate) fn std_tcp_rx(
mut msg: xous::MessageEnvelope,
timer: &Ticktimer,
iface: &mut Interface::<NetPhy>,
_iface: &mut Interface,
sockets: &mut SocketSet,
tcp_rx_waiting: &mut Vec<Option<WaitingSocket>>,
our_sockets: &Vec<Option<SocketHandle>>,
nonblocking: bool,
@ -178,7 +178,7 @@ pub(crate) fn std_tcp_rx(
}
};
let socket = iface.get_socket::<TcpSocket>(*handle);
let socket = sockets.get_mut::<tcp::Socket>(*handle);
if socket.can_recv() {
log::debug!("receiving data right away");
let buflen = if let Some(valid) = body.valid {
@ -227,7 +227,8 @@ pub(crate) fn std_tcp_rx(
pub(crate) fn std_tcp_peek(
mut msg: xous::MessageEnvelope,
timer: &Ticktimer,
iface: &mut Interface::<NetPhy>,
_iface: &mut Interface,
sockets: &mut SocketSet,
our_sockets: &Vec<Option<SocketHandle>>,
tcp_peek_waiting: &mut Vec<Option<WaitingSocket>>,
nonblocking: bool,
@ -255,7 +256,7 @@ pub(crate) fn std_tcp_peek(
}
};
let socket = iface.get_socket::<TcpSocket>(*handle);
let socket = sockets.get_mut::<tcp::Socket>(*handle);
if socket.can_recv() {
log::debug!("peeking data right away");
let buflen = if let Some(valid) = body.valid {

View file

@ -1,5 +1,4 @@
use crate::*;
use crate::device::NetPhy;
use smoltcp::wire::{IpEndpoint, IpAddress};
use ticktimer_server::Ticktimer;
@ -8,11 +7,10 @@ use ticktimer_server::Ticktimer;
/// Sockets are stored in the PID/SocketHandle HashMap `process_sockets` (this is shared with TCP)
/// `recv` requests create `UpdStdState` objects, that are stored in a `udp_rx` Vec.
const BUFLEN: usize = NET_MTU as usize;
pub(crate) fn std_udp_bind(
mut msg: xous::MessageEnvelope,
iface: &mut Interface::<NetPhy>,
_iface: &mut Interface,
sockets: &mut SocketSet,
our_sockets: &mut Vec<Option<SocketHandle>>,
) {
// Ignore nonblocking and scalar messages
@ -36,21 +34,24 @@ pub(crate) fn std_udp_bind(
}
};
let udp_rx_buffer =
UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; BUFLEN]);
let udp_tx_buffer =
UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; BUFLEN]);
let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
let handle = iface.add_socket(udp_socket);
let udp_socket = iface.get_socket::<UdpSocket>(handle);
let udp_rx_buffer = udp::PacketBuffer::new(
vec![udp::PacketMetadata::EMPTY, udp::PacketMetadata::EMPTY],
vec![0; 65535],
);
let udp_tx_buffer = udp::PacketBuffer::new(
vec![udp::PacketMetadata::EMPTY, udp::PacketMetadata::EMPTY],
vec![0; 65535],
);
let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
let handle = sockets.add(udp_socket);
let udp_socket = sockets.get_mut::<udp::Socket>(handle);
// Attempt to connect, returning the error if there is one
if let Err(e) = udp_socket
.bind(IpEndpoint{addr: address, port: local_port})
.map_err(|e| match e {
smoltcp::Error::Illegal => NetError::SocketInUse,
smoltcp::Error::Unaddressable => NetError::Unaddressable,
_ => NetError::LibraryError,
smoltcp::socket::udp::BindError::InvalidState => NetError::SocketInUse,
smoltcp::socket::udp::BindError::Unaddressable => NetError::Unaddressable,
})
{
log::trace!("couldn't connect: {:?}", e);
@ -71,7 +72,8 @@ pub(crate) fn std_udp_bind(
pub(crate) fn std_udp_rx(
mut msg: xous::MessageEnvelope,
timer: &Ticktimer,
iface: &mut Interface::<NetPhy>,
iface: &mut Interface,
sockets: &mut SocketSet,
udp_rx_waiting: &mut Vec<Option<UdpStdState>>,
our_sockets: &Vec<Option<SocketHandle>>,
) {
@ -116,20 +118,22 @@ pub(crate) fn std_udp_rx(
return;
}
};
let socket = iface.get_socket::<UdpSocket>(*handle);
let socket = sockets.get_mut::<udp::Socket>(*handle);
let port = socket.endpoint().port;
// TODO: comment below may be invalid after port to latest smoltcp. Error handler
// is also suspect.
//
// force the local address to correspond to our (one and only) IP address
// the underlying smoltcp library can't handle unspecified source addresses
// because the library itself works with multiple interfaces and has no default resolution mechanism
// this may eventually get fixed see https://github.com/smoltcp-rs/smoltcp/issues/599
if socket.endpoint().addr != IpAddress::Ipv4(local_addr) {
if socket.endpoint().addr.expect("UDP endpoint missing") != IpAddress::Ipv4(local_addr) {
if socket.is_open() {
socket.close();
}
if let Err(e) = socket.bind(IpEndpoint{addr: IpAddress::Ipv4(local_addr), port})
.map_err(|e| match e {
smoltcp::Error::Illegal => NetError::SocketInUse,
smoltcp::Error::Unaddressable => NetError::Unaddressable,
smoltcp::socket::udp::BindError::Unaddressable => NetError::WouldBlock,
_ => NetError::LibraryError,
}) {
std_failure(msg, e);
@ -143,7 +147,7 @@ pub(crate) fn std_udp_rx(
// difference in types means you can't do a pattern match assign to a common variable.
match socket.peek() {
Ok((data, endpoint)) => {
udp_rx_success(unsafe { body.buf.as_slice_mut() }, data, *endpoint);
udp_rx_success(unsafe { body.buf.as_slice_mut() }, data, endpoint.endpoint);
}
Err(e) => {
log::error!("unable to receive: {:?}", e);
@ -154,7 +158,7 @@ pub(crate) fn std_udp_rx(
match socket.recv() {
Ok((data, endpoint)) => {
log::debug!("immediate udp rx");
udp_rx_success(unsafe { body.buf.as_slice_mut() }, data, endpoint);
udp_rx_success(unsafe { body.buf.as_slice_mut() }, data, endpoint.endpoint);
}
Err(e) => {
log::error!("unable to receive: {:?}", e);
@ -185,7 +189,8 @@ pub(crate) fn std_udp_rx(
pub(crate) fn std_udp_tx(
mut msg: xous::MessageEnvelope,
iface: &mut Interface::<NetPhy>,
iface: &mut Interface,
sockets: &mut SocketSet,
our_sockets: &Vec<Option<SocketHandle>>,
) {
// unpack meta
@ -226,21 +231,20 @@ pub(crate) fn std_udp_tx(
return;
}
};
let socket = iface.get_socket::<UdpSocket>(*handle);
let socket = sockets.get_mut::<udp::Socket>(*handle);
let port = socket.endpoint().port;
// force the local address to correspond to our (one and only) IP address
// the underlying smoltcp library can't handle unspecified source addresses
// because the library itself works with multiple interfaces and has no default resolution mechanism
// this may eventually get fixed see https://github.com/smoltcp-rs/smoltcp/issues/599
if socket.endpoint().addr != IpAddress::Ipv4(local_addr) {
if socket.endpoint().addr.expect("UDP TX endpoint missing") != IpAddress::Ipv4(local_addr) {
if socket.is_open() {
socket.close();
}
if let Err(e) = socket.bind(IpEndpoint{addr: IpAddress::Ipv4(local_addr), port})
.map_err(|e| match e {
smoltcp::Error::Illegal => NetError::SocketInUse,
smoltcp::Error::Unaddressable => NetError::Unaddressable,
_ => NetError::LibraryError,
smoltcp::socket::udp::BindError::InvalidState => NetError::WouldBlock,
smoltcp::socket::udp::BindError::Unaddressable => NetError::Unaddressable,
}) {
std_failure(msg, e);
return;
@ -277,9 +281,6 @@ pub(crate) fn udp_rx_success(buf: &mut [u8], rx: &[u8], ep: IpEndpoint) {
*d = s;
}
}
_ => {
buf[3] = 0; // this is the invalid/error type
}
}
let port = ep.port.to_le_bytes();
buf[20] = port[0];

View file

@ -8,11 +8,12 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::atomic::{AtomicUsize, Ordering};
pub(crate) fn start_batch_tests() {
let netmgr = net::NetManager::new();
let _ = thread::spawn({
move || {
let run_passing = true;
let run_passing = false;
let tt = ticktimer_server::Ticktimer::new().unwrap();
const PRINT_DELAY: usize = 3000;
const PRINT_DELAY: usize = 2000;
if run_passing {
log::info!("################################################## bind_error");
tt.sleep_ms(PRINT_DELAY).ok();
@ -32,6 +33,18 @@ pub(crate) fn start_batch_tests() {
log::info!("################################################## read_eof");
tt.sleep_ms(PRINT_DELAY).ok();
read_eof();
// This test can fail if there is a ticktimer scheduling error:
/*
INFO:shellchat::nettests: ################################################## write_close (services\shellchat\src\nettests.rs:35)
INFO:shellchat::nettests: ++++++++++++++++++++++++++create server (services\shellchat\src\nettests.rs:252)
INFO:shellchat::nettests: ++++++++++++++++++++++++++try to establish connection (services\shellchat\src\nettests.rs:265)
INFO:shellchat::nettests: ++++++++++++++++++++++++++established (services\shellchat\src\nettests.rs:267)
INFO:shellchat::nettests: ----------------------------create and drop connection to server (services\shellchat\src\nettests.rs:257)
INFO:shellchat::nettests: ----------------------------signal that we should proceed to send the data to the closed server (services\shellchat\src\nettests.rs:262)
ERR :xous_ticktimer: requested to wake 1 entries, which is more than the current 2 waiting entries (services\xous-ticktimer\src\main.rs:429)
-- hangs here forever.
*/
log::info!("################################################## write_close");
tt.sleep_ms(PRINT_DELAY).ok();
write_close();
@ -49,9 +62,9 @@ pub(crate) fn start_batch_tests() {
tt.sleep_ms(PRINT_DELAY).ok();
write_vectored();
// This test cannot be run until issue #210 is fixed see https://github.com/betrusted-io/xous-core/issues/210
//log::info!("################################################## nodelay");
//nodelay();
log::info!("################################################## nodelay");
nodelay();
tt.sleep_ms(PRINT_DELAY).ok();
log::info!("################################################## ttl");
tt.sleep_ms(PRINT_DELAY).ok();
ttl();
@ -90,23 +103,40 @@ pub(crate) fn start_batch_tests() {
log::info!("################################################## clone_while_reading");
tt.sleep_ms(PRINT_DELAY).ok();
clone_while_reading();
// these tests fail after being called in the long series of tests, but when run on their
// own they pass...
log::info!("################################################## clone_accept_smoke");
tt.sleep_ms(PRINT_DELAY).ok();
//netmgr.set_debug_level(log::LevelFilter::Trace);
clone_accept_smoke();
//netmgr.set_debug_level(log::LevelFilter::Info);
log::info!("################################################## clone_accept_concurrent");
tt.sleep_ms(PRINT_DELAY).ok();
//netmgr.set_debug_level(log::LevelFilter::Trace);
clone_accept_concurrent();
//netmgr.set_debug_level(log::LevelFilter::Info);
}
// These tests seem to fail unless you insert some debug prints in them. This is a problem
// likely related to race conditions in condvars and ticktimers. We're going to waive this
// for now because the tests themselves are pretty synthetic, it's rare that you create
// multiple sockets simply for the purpose of abandoning them? Or at least, not when
// used as a client; perhaps in a server environment this is common, but Xous isn't targeting
// a server (yet).
log::info!("################################################## multiple_connect_serial");
tt.sleep_ms(PRINT_DELAY).ok();
multiple_connect_serial();
log::info!("################################################## multiple_connect_interleaved_greedy_schedule");
tt.sleep_ms(PRINT_DELAY).ok();
netmgr.set_debug_level(log::LevelFilter::Debug);
multiple_connect_interleaved_greedy_schedule();
netmgr.set_debug_level(log::LevelFilter::Info);
log::info!("################################################## multiple_connect_interleaved_lazy_schedule");
tt.sleep_ms(PRINT_DELAY).ok();
netmgr.set_debug_level(log::LevelFilter::Trace);
multiple_connect_interleaved_lazy_schedule();
netmgr.set_debug_level(log::LevelFilter::Info);
log::info!("################################################## FIN");
log::info!("################################################## FIN");
@ -308,6 +338,7 @@ fn multiple_connect_serial() {
fn multiple_connect_interleaved_greedy_schedule() {
const MAX: usize = 3;
each_ip(&mut |addr| {
log::info!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~bind to addr: {:?}", addr);
let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move || {
@ -315,28 +346,35 @@ fn multiple_connect_interleaved_greedy_schedule() {
for (i, stream) in acceptor.incoming().enumerate().take(MAX) {
// Start another thread to handle the connection
let _t = thread::spawn(move || {
log::info!("++++++++++++++++++++++++++++++++ start thread {}", i);
let mut stream = t!(stream);
let mut buf = [0];
t!(stream.read(&mut buf));
log::info!("++++++++++++++++++++++++++++++++ thread {} read: {:?}", i, buf);
assert!(buf[0] == i as u8);
});
}
});
connect(0, addr);
log::info!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~after connect(0)");
});
fn connect(i: usize, addr: SocketAddr) {
log::info!("******************************* connect {}", i);
if i == MAX {
return;
}
let t = thread::spawn(move || {
let mut stream = t!(TcpStream::connect(&addr));
log::info!("******************************* connect {:?}", addr);
let mut stream = t!(TcpStream::connect(&addr)); // errors out here
// Connect again before writing
connect(i + 1, addr);
log::info!("******************************* writing {:?}", i);
t!(stream.write(&[i as u8]));
});
log::info!("******************************* joining... {}", i);
t.join().ok().expect("thread panicked");
}
}
@ -580,18 +618,27 @@ fn clone_while_reading() {
fn clone_accept_smoke() {
each_ip(&mut |addr| {
log::info!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~bind to addr: {:?}", addr);
let a = t!(TcpListener::bind(&addr));
log::info!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~bind to addr clone");
let a2 = t!(a.try_clone());
let _t = thread::spawn(move || {
log::info!("++++++++++++++++++++++++++++++++connect #1");
let _ = TcpStream::connect(&addr);
log::info!("++++++++++++++++++++++++++++++++#1 connected");
});
let _t = thread::spawn(move || {
log::info!("--------------------------------connect #2");
let _ = TcpStream::connect(&addr);
log::info!("--------------------------------#2 connected");
});
log::info!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#1 accept");
t!(a.accept());
log::info!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#2 accept");
t!(a2.accept());
log::info!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~FINISH");
})
}

View file

@ -7,6 +7,7 @@ pub struct Envelope {
pub sender: MessageSender,
pub body: Message,
}
unsafe impl Send for Envelope {}
impl Envelope {
pub fn to_usize(&self) -> [usize; 7] {

View file

@ -132,6 +132,7 @@ pub enum Message {
Scalar(ScalarMessage),
BlockingScalar(ScalarMessage),
}
unsafe impl Send for Message {}
impl Message {
pub fn new_scalar(