Repository: vinc/moros (language: rust)

Issue:
Bump smoltcp from 0.8.2 to 0.9.1
Bumps [smoltcp](https://github.com/smoltcp-rs/smoltcp) from 0.8.2 to 0.9.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/smoltcp-rs/smoltcp/blob/master/CHANGELOG.md">smoltcp's changelog</a>.</em></p>
<blockquote>
<h2>[0.9.1] - 2023-02-08</h2>
<ul>
<li>iface: make MulticastError public. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/747">#747</a>)</li>
<li>Fix parsing of ieee802154 link layer address for NDISC options (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/746">#746</a>)</li>
</ul>
<h2>[0.9.0] - 2023-02-06</h2>
<ul>
<li>Minimum Supported Rust Version (MSRV) <strong>bumped</strong> from 1.56 to 1.65</li>
<li>Added DNS client support.
<ul>
<li>Add DnsSocket (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/465">#465</a>)</li>
<li>Add support for one-shot mDNS resolution (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/669">#669</a>)</li>
</ul>
</li>
<li>Added support for packet fragmentation and reassembly, both for IPv4 and 6LoWPAN. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/591">#591</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/580">#580</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/624">#624</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/634">#634</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/645">#645</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/653">#653</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/684">#684</a>)</li>
<li>Major error handling overhaul.
<ul>
<li>Previously, <em>smoltcp</em> had a single <code>Error</code> enum that all methods returned. Now methods that can fail have their own error enums, with only the actual errors they can return. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/617">#617</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/667">#667</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/730">#730</a>)</li>
<li>Consuming <code>phy::Device</code> tokens is now infallible.
<ul>
<li>In the case of &quot;buffer full&quot;, <code>phy::Device</code> implementations must return <code>None</code> from the <code>transmit</code>/<code>receive</code> methods. (Previously, they could either do that, or return tokens and then return <code>Error::Exhausted</code> when consuming them. The latter wasted computation since it'd make <em>smoltcp</em> pointlessly spend effort preparing the packet, and is now disallowed).</li>
<li>For all other phy errors, <code>phy::Device</code> implementations should drop the packet and handle the error themselves. (Either log it and forget it, or buffer/count it and offer methods to let the user retrieve the error queue/counts.) Returning the error to have it bubble up to <code>Interface::poll()</code> is no longer supported.</li>
</ul>
</li>
</ul>
</li>
<li>phy: the <code>trait Device</code> now uses Generic Associated Types (GAT) for the TX and RX tokens. The main impact of this is <code>Device</code> impls can now borrow data (because previously, the<code>for&lt;'a&gt; T: Device&lt;'a&gt;</code> bounds required to workaround the lack of GATs essentially implied <code>T: 'static</code>.) (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/572">#572</a>)</li>
<li>iface: The <code>Interface</code> API has been significantly simplified and cleaned up.
<ul>
<li>The builder has been removed (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/736">#736</a>)</li>
<li>SocketSet and Device are now borrowed in methods that need them, instead of owning them. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/619">#619</a>)</li>
<li><code>Interface</code> now owns the list of addresses (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/719">#719</a>), routes, neighbor cache (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/722">#722</a>), 6LoWPAN address contexts, and fragmentation buffers (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/736">#736</a>) instead of borrowing them with <code>managed</code>.</li>
<li>A new compile-time configuration mechanism has been added, to configure the size of the (now owned) buffers (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/742">#742</a>)</li>
</ul>
</li>
<li>iface: Change neighbor discovery timeout from 3s to 1s, to match Linux's behavior. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/620">#620</a>)</li>
<li>iface: Remove implicit sized bound on device generics (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/679">#679</a>)</li>
<li>iface/6lowpan: Add address context information for resolving 6LoWPAN addresses (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/687">#687</a>)</li>
<li>iface/6lowpan: fix incorrect SAM value in IPHC when address is not compressed (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/630">#630</a>)</li>
<li>iface/6lowpan: packet parsing fuzz fixes (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/636">#636</a>)</li>
<li>socket: Add send_with to udp, raw, and icmp sockets. These methods enable reserving a packet buffer with a greater size than you need, and then shrinking the size once you know it. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/625">#625</a>)</li>
<li>socket: Make <code>trait AnySocket</code> object-safe (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/718">#718</a>)</li>
<li>socket/dhcpv4: add waker support (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/623">#623</a>)</li>
<li>socket/dhcpv4: indicate new config if there's a packet buffer provided (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/685">#685</a>)</li>
<li>socket/dhcpv4: Use renewal time from DHCP server ACK, if given (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/683">#683</a>)</li>
<li>socket/dhcpv4: allow for extra configuration
<ul>
<li>setting arbitrary options in the request. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/650">#650</a>)</li>
<li>retrieving arbitrary options from the response. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/650">#650</a>)</li>
<li>setting custom parameter request list. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/650">#650</a>)</li>
<li>setting custom timing for retries. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/650">#650</a>)</li>
<li>Allow specifying different server/client DHCP ports (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/738">#738</a>)</li>
</ul>
</li>
<li>socket/raw: Add <code>peek</code> and <code>peek_slice</code> methods (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/734">#734</a>)</li>
<li>socket/raw: When sending packets, send the source IP address unmodified (it was previously replaced with the interface's address if it was unspecified). (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/616">#616</a>)</li>
<li>socket/tcp: Do not reset socket-level settings, such as keepalive, on reset (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/603">#603</a>)</li>
<li>socket/tcp: ensure we always accept the segment at offset=0 even if the assembler is full. (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/735">#735</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/452">#452</a>)</li>
<li>socket/tcp: Refactored assembler, now more robust and faster (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/726">#726</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/735">#735</a>)</li>
<li>socket/udp: accept packets with checksum field set to <code>0</code>, since that means the checksum is not computed (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/632">#632</a>)</li>
<li>wire: make many functions const (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/693">#693</a>)</li>
<li>wire/dhcpv4: remove Option enum (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/656">#656</a>)</li>
<li>wire/dhcpv4: use heapless Vec for DNS server list (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/678">#678</a>)</li>
<li>wire/icmpv4: add support for TimeExceeded packets (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/609">#609</a>)</li>
<li>wire/ip: Remove <code>IpRepr::Unspecified</code>, <code>IpVersion::Unspecified</code>, <code>IpAddress::Unspecified</code> (<a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/579">#579</a>, <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/616">#616</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/9027825c16c9c3fbadb7663e56d64b590fc95d5a"><code>9027825</code></a> Release v0.9.1</li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/c92439385664f7e267c01389e4e6e747064affc9"><code>c924393</code></a> Merge <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/747">#747</a></li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/51af32ebd1f63f61d917c16810a742568c0072af"><code>51af32e</code></a> iface: make MulticastError public.</li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/c978b36749af7e50fa254948195265807356f78d"><code>c978b36</code></a> Merge <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/746">#746</a></li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/46cca501d7e1c8dc920ba36bb78351e01f8fb8ec"><code>46cca50</code></a> Fix parsing of link layer address for ndiscoptions</li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/20e545507693ff2f012ac8de3fdb7dd6299ae502"><code>20e5455</code></a> Release v0.9.0</li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/739e7a58a9a41ce027eaf1e8857dc507b70f4756"><code>739e7a5</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/742">#742</a> from smoltcp-rs/size-configs</li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/b047cbeade409203b0d0eaffb4dfe55bdd5dc8fc"><code>b047cbe</code></a> Add compile-time configuration options for counts and buffer sizes.</li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/3fbef82cbec5f23f38e1d1339be0fd5889a1c184"><code>3fbef82</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/smoltcp-rs/smoltcp/issues/740">#740</a> from smoltcp-rs/fragmentation-unify</li>
<li><a href="https://github.com/smoltcp-rs/smoltcp/commit/a656ab0c08c3cb6d4bdf214873469d629d156b5d"><code>a656ab0</code></a> iface: use reassembly timeout setting for both ipv4 and 6lowpan.</li>
<li>Additional commits viewable in <a href="https://github.com/smoltcp-rs/smoltcp/compare/v0.8.2...v0.9.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=smoltcp&package-manager=cargo&previous-version=0.8.2&new-version=0.9.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

You can trigger a rebase of this PR by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>> **Note**
> Automatic rebases have been disabled on this pull request as it has been open for over 30 days.



Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4cd21b36..4905adc7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,8 @@
 # Changelog
 
 ## Unreleased
+- Upgrade smoltcp from 0.8.2 to 0.9.1 (#484)
+- Update rust to nightly-2022-12-21 (#485)
 - Fix RTL8139 driver issues (#483)
 - Improve help system (#481)
 - Refactor lisp functions (#478)
diff --git a/Cargo.lock b/Cargo.lock
index fad139be..156f1841 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,6 +32,15 @@ version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
 
+[[package]]
+name = "atomic-polyfill"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
+dependencies = [
+ "critical-section",
+]
+
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -110,6 +119,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "critical-section"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
+
 [[package]]
 name = "crypto-common"
 version = "0.1.6"
@@ -120,6 +135,38 @@ dependencies = [
  "typenum",
 ]
 
+[[package]]
+name = "defmt"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "956673bd3cb347512bf988d1e8d89ac9a82b64f6eec54d3c01c3529dac019882"
+dependencies = [
+ "bitflags",
+ "defmt-macros",
+]
+
+[[package]]
+name = "defmt-macros"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4abc4821bd84d3d8f49945ddb24d029be9385ed9b77c99bf2f6296847a6a9f0"
+dependencies = [
+ "defmt-parser",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "defmt-parser"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "269924c02afd7f94bc4cecbfa5c379f6ffcf9766b3408fe63d22c728654eccd0"
+dependencies = [
+ "thiserror",
+]
+
 [[package]]
 name = "digest"
 version = "0.10.6"
@@ -147,6 +194,28 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "hash32"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "heapless"
+version = "0.7.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
+dependencies = [
+ "atomic-polyfill",
+ "hash32",
+ "rustc_version",
+ "spin 0.9.8",
+ "stable_deref_trait",
+]
+
 [[package]]
 name = "hmac"
 version = "0.12.1"
@@ -353,6 +422,30 @@ version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
 [[package]]
 name = "proc-macro-hack"
 version = "0.5.20+deprecated"
@@ -470,6 +563,15 @@ dependencies = [
  "log",
 ]
 
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
 [[package]]
 name = "rustversion"
 version = "1.0.12"
@@ -482,6 +584,12 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
+[[package]]
+name = "semver"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+
 [[package]]
 name = "sha2"
 version = "0.10.6"
@@ -495,12 +603,15 @@ dependencies = [
 
 [[package]]
 name = "smoltcp"
-version = "0.8.2"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee34c1e1bfc7e9206cc0fb8030a90129b4e319ab53856249bb27642cab914fb3"
+checksum = "7e9786ac45091b96f946693e05bfa4d8ca93e2d3341237d97a380107a6b38dea"
 dependencies = [
  "bitflags",
  "byteorder",
+ "cfg-if",
+ "defmt",
+ "heapless",
  "managed",
 ]
 
@@ -528,6 +639,12 @@ dependencies = [
  "lock_api",
 ]
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
 [[package]]
 name = "standback"
 version = "0.2.17"
@@ -554,12 +671,43 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "syn"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
 [[package]]
 name = "tap"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
 
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
 [[package]]
 name = "time"
 version = "0.2.27"
@@ -592,7 +740,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "standback",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index fbf23981..d88b6d42 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -35,7 +35,7 @@ rand = { version = "0.8.5", default-features = false }
 rand_hc = "0.3.1"
 raw-cpuid = "10.7.0"
 sha2 = { version = "0.10.6", default-features = false, features = ["force-soft"] }
-smoltcp = { version = "0.8.2", default-features = false, features = ["alloc", "medium-ethernet", "socket-tcp", "socket-udp", "socket-dhcpv4", "proto-ipv4", "proto-dhcpv4"] }
+smoltcp = { version = "0.9.1", default-features = false, features = ["alloc", "medium-ethernet", "socket-tcp", "socket-udp", "socket-dhcpv4", "proto-ipv4", "proto-dhcpv4"] }
 spin = "0.9.8"
 time = { version = "0.2.27", default-features = false }
 uart_16550 = "0.2.18"
diff --git a/src/sys/net/mod.rs b/src/sys/net/mod.rs
index 78d0369c..62d22e1f 100644
--- a/src/sys/net/mod.rs
+++ b/src/sys/net/mod.rs
@@ -1,23 +1,17 @@
 use crate::{sys, usr};
 
-use alloc::collections::BTreeMap;
 use alloc::sync::Arc;
 use alloc::vec::Vec;
-use alloc::vec;
 use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
-use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
+use smoltcp::iface::Interface;
 use smoltcp::phy::DeviceCapabilities;
-use smoltcp::phy::{Device, Medium};
-use smoltcp::time::Instant;
-use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address};
+use smoltcp::wire::EthernetAddress;
 use spin::Mutex;
 
 mod rtl8139;
 mod pcnet;
 
-pub type Interface = smoltcp::iface::Interface<'static, EthernetDevice>;
-
-pub static IFACE: Mutex<Option<Interface>> = Mutex::new(None);
+pub static NET: Mutex<Option<(Interface, EthernetDevice)>> = Mutex::new(None);
 
 #[derive(Clone)]
 pub enum EthernetDevice {
@@ -72,9 +66,9 @@ impl EthernetDeviceIO for EthernetDevice {
     }
 }
 
-impl<'a> smoltcp::phy::Device<'a> for EthernetDevice {
-    type RxToken = RxToken;
-    type TxToken = TxToken;
+impl<'a> smoltcp::phy::Device for EthernetDevice {
+    type RxToken<'b> = RxToken where Self: 'b;
+    type TxToken<'b> = TxToken where Self: 'b;
 
     fn capabilities(&self) -> DeviceCapabilities {
         let mut caps = DeviceCapabilities::default();
@@ -83,7 +77,7 @@ impl<'a> smoltcp::phy::Device<'a> for EthernetDevice {
         caps
     }
 
-    fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
+    fn receive(&mut self, _instant: smoltcp::time::Instant) -> Option<(Self::RxToken<'a>, Self::TxToken<'a>)> {
         if let Some(buffer) = self.receive_packet() {
             if self.config().is_debug_enabled() {
                 debug!("NET Packet Received");
@@ -98,7 +92,7 @@ impl<'a> smoltcp::phy::Device<'a> for EthernetDevice {
         }
     }
 
-    fn transmit(&'a mut self) -> Option<Self::TxToken> {
+    fn transmit(&mut self, _instant: smoltcp::time::Instant) -> Option<Self::TxToken<'a>> {
         let tx = TxToken { device: self.clone() };
         Some(tx)
     }
@@ -110,7 +104,7 @@ pub struct RxToken {
 }
 
 impl smoltcp::phy::RxToken for RxToken {
-     fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> smoltcp::Result<R> where F: FnOnce(&mut [u8]) -> smoltcp::Result<R> {
+     fn consume<R, F>(mut self, f: F) -> R where F: FnOnce(&mut [u8]) -> R {
         f(&mut self.buffer)
     }
 }
@@ -120,18 +114,16 @@ pub struct TxToken {
     device: EthernetDevice,
 }
 impl smoltcp::phy::TxToken for TxToken {
-    fn consume<R, F>(mut self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result<R> where F: FnOnce(&mut [u8]) -> smoltcp::Result<R> {
+    fn consume<R, F>(mut self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R {
         let config = self.device.config();
         let buf = self.device.next_tx_buffer(len);
-        let res = f(buf);
-        if res.is_ok() {
-            if config.is_debug_enabled() {
-                debug!("NET Packet Transmitted");
-                usr::hex::print_hex(buf);
-            }
-            self.device.transmit_packet(len);
-            self.device.stats().tx_add(len as u64);
+        if config.is_debug_enabled() {
+            debug!("NET Packet Transmitted");
+            usr::hex::print_hex(buf);
         }
+        let res = f(buf);
+        self.device.transmit_packet(len);
+        self.device.stats().tx_add(len as u64);
         res
     }
 }
@@ -225,25 +217,21 @@ fn find_pci_io_base(vendor_id: u16, device_id: u16) -> Option<u16> {
 }
 
 pub fn init() {
-    let add_interface = |device: EthernetDevice, name| {
+    let add = |mut device: EthernetDevice, name| {
         if let Some(mac) = device.config().mac() {
             log!("NET {} MAC {}\n", name, mac);
-            let neighbor_cache = NeighborCache::new(BTreeMap::new());
-            let routes = Routes::new(BTreeMap::new());
-            let ip_addrs = [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)];
-            let medium = device.capabilities().medium;
-            let mut builder = InterfaceBuilder::new(device, vec![]).ip_addrs(ip_addrs).routes(routes);
-            if medium == Medium::Ethernet {
-                builder = builder.hardware_addr(mac.into()).neighbor_cache(neighbor_cache);
-            }
-            let iface = builder.finalize();
-            *IFACE.lock() = Some(iface);
+
+            let mut config = smoltcp::iface::Config::new();
+            config.hardware_addr = Some(mac.into());
+            let iface = Interface::new(config, &mut device);
+
+            *NET.lock() = Some((iface, device));
         }
     };
     if let Some(io_base) = find_pci_io_base(0x10EC, 0x8139) {
-        add_interface(EthernetDevice::RTL8139(rtl8139::Device::new(io_base)), "RTL8139");
+        add(EthernetDevice::RTL8139(rtl8139::Device::new(io_base)), "RTL8139");
     }
     if let Some(io_base) = find_pci_io_base(0x1022, 0x2000) {
-        add_interface(EthernetDevice::PCNET(pcnet::Device::new(io_base)), "PCNET");
+        add(EthernetDevice::PCNET(pcnet::Device::new(io_base)), "PCNET");
     }
 }
diff --git a/src/usr/dhcp.rs b/src/usr/dhcp.rs
index 4017728e..9aaf0f4d 100644
--- a/src/usr/dhcp.rs
+++ b/src/usr/dhcp.rs
@@ -7,7 +7,9 @@ use crate::api::syscall;
 use alloc::format;
 use alloc::string::ToString;
 use alloc::vec::Vec;
-use smoltcp::socket::{Dhcpv4Event, Dhcpv4Socket};
+use alloc::vec;
+use smoltcp::iface::SocketSet;
+use smoltcp::socket::dhcpv4;
 use smoltcp::time::Instant;
 
 pub fn main(args: &[&str]) -> Result<(), ExitCode> {
@@ -22,9 +24,10 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
         }
     }
 
-    if let Some(ref mut iface) = *sys::net::IFACE.lock() {
-        let dhcp_socket = Dhcpv4Socket::new();
-        let dhcp_handle = iface.add_socket(dhcp_socket);
+    if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() {
+        let dhcp_socket = dhcpv4::Socket::new();
+        let mut sockets = SocketSet::new(vec![]);
+        let dhcp_handle = sockets.add(dhcp_socket);
         if verbose {
             debug!("DHCP Discover transmitted");
         }
@@ -33,36 +36,31 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
         loop {
             if clock::realtime() - started > timeout {
                 error!("Timeout reached");
-                iface.remove_socket(dhcp_handle);
                 return Err(ExitCode::Failure);
             }
             if sys::console::end_of_text() || sys::console::end_of_transmission() {
                 eprintln!();
-                iface.remove_socket(dhcp_handle);
                 return Err(ExitCode::Failure);
             }
 
             let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
-            if let Err(e) = iface.poll(timestamp) {
-                error!("Network Error: {}", e);
-            }
+            iface.poll(timestamp, device, &mut sockets);
+            let event = sockets.get_mut::<dhcpv4::Socket>(dhcp_handle).poll();
 
-            let event = iface.get_socket::<Dhcpv4Socket>(dhcp_handle).poll();
             match event {
                 None => {}
-                Some(Dhcpv4Event::Configured(config)) => {
-                    dhcp_config = Some(config);
+                Some(dhcpv4::Event::Configured(config)) => {
+                    dhcp_config = Some((config.address, config.router, config.dns_servers));
                     if verbose {
                         debug!("DHCP Offer received");
                     }
-                    iface.remove_socket(dhcp_handle);
                     break;
                 }
-                Some(Dhcpv4Event::Deconfigured) => {
+                Some(dhcpv4::Event::Deconfigured) => {
                 }
             }
 
-            if let Some(wait_duration) = iface.poll_delay(timestamp) {
+            if let Some(wait_duration) = iface.poll_delay(timestamp, &sockets) {
                 syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
             }
         }
@@ -71,19 +69,18 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
         return Err(ExitCode::Failure);
     }
 
-    if let Some(config) = dhcp_config {
-        //debug!("{:#?}", config);
-        usr::shell::exec(&format!("net config ip {}", config.address)).ok();
+    if let Some((address, router, dns_servers)) = dhcp_config {
+        usr::shell::exec(&format!("net config ip {}", address)).ok();
         usr::shell::exec("net config ip").ok();
 
-        if let Some(router) = config.router {
+        if let Some(router) = router {
             usr::shell::exec(&format!("net config gw {}", router)).ok();
         } else {
             usr::shell::exec("net config gw 0.0.0.0").ok();
         }
         usr::shell::exec("net config gw").ok();
 
-        let dns: Vec<_> = config.dns_servers.iter().filter_map(|s| *s).map(|s| s.to_string()).collect();
+        let dns: Vec<_> = dns_servers.iter().map(|s| s.to_string()).collect();
         if !dns.is_empty() {
             usr::shell::exec(&format!("net config dns {}", dns.join(","))).ok();
         }
diff --git a/src/usr/host.rs b/src/usr/host.rs
index 604afd42..64579dd7 100644
--- a/src/usr/host.rs
+++ b/src/usr/host.rs
@@ -10,9 +10,10 @@ use bit_field::BitField;
 use core::convert::TryInto;
 use core::str;
 use core::str::FromStr;
-use smoltcp::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
+use smoltcp::iface::SocketSet;
+use smoltcp::socket::udp;
 use smoltcp::time::Instant;
-use smoltcp::wire::{IpAddress, IpEndpoint, Ipv4Address};
+use smoltcp::wire::{IpAddress, IpEndpoint, IpListenEndpoint, Ipv4Address};
 
 // See RFC 1035 for implementation details
 
@@ -141,21 +142,24 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
     let server = IpEndpoint::new(dns_address, dns_port);
 
     let local_port = 49152 + random::get_u16() % 16384;
-    let client = IpEndpoint::new(IpAddress::Unspecified, local_port);
+    let client = IpListenEndpoint::from(local_port);
 
     let qname = name;
     let qtype = QueryType::A;
     let qclass = QueryClass::IN;
     let query = Message::query(qname, qtype, qclass);
 
-    let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 1024]);
-    let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 1024]);
-    let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
-
     #[derive(Debug)]
     enum State { Bind, Query, Response }
     let mut state = State::Bind;
-    if let Some(ref mut iface) = *sys::net::IFACE.lock() {
+
+    if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() {
+        let mut sockets = SocketSet::new(vec![]);
+        let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 1024]);
+        let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 1024]);
+        let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
+        let udp_handle = sockets.add(udp_socket);
+
         match iface.ipv4_addr() {
             None => {
                 return Err(ResponseCode::NetworkError);
@@ -166,21 +170,16 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
             _ => {}
         }
 
-        let udp_handle = iface.add_socket(udp_socket);
-
         let timeout = 5.0;
         let started = clock::realtime();
         loop {
             if clock::realtime() - started > timeout {
-                iface.remove_socket(udp_handle);
                 return Err(ResponseCode::NetworkError);
             }
-            let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
-            if let Err(e) = iface.poll(timestamp) {
-                error!("Network Error: {}", e);
-            }
 
-            let socket = iface.get_socket::<UdpSocket>(udp_handle);
+            let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
+            iface.poll(timestamp, device, &mut sockets);
+            let socket = sockets.get_mut::<udp::Socket>(udp_handle);
 
             state = match state {
                 State::Bind if !socket.is_open() => {
@@ -195,7 +194,6 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
                     let (data, _) = socket.recv().expect("cannot receive");
                     let message = Message::from(data);
                     if message.id() == query.id() && message.is_response() {
-                        iface.remove_socket(udp_handle);
                         return match message.rcode() {
                             ResponseCode::NoError => {
                                 // TODO: Parse the datagram instead of
@@ -216,7 +214,7 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
                 _ => state
             };
 
-            if let Some(wait_duration) = iface.poll_delay(timestamp) {
+            if let Some(wait_duration) = iface.poll_delay(timestamp, &sockets) {
                 syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
 
             }
diff --git a/src/usr/http.rs b/src/usr/http.rs
index 3b968d9b..ae217af3 100644
--- a/src/usr/http.rs
+++ b/src/usr/http.rs
@@ -7,7 +7,8 @@ use crate::api::syscall;
 use alloc::string::{String, ToString};
 use alloc::vec;
 use core::str::{self, FromStr};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::iface::SocketSet;
+use smoltcp::socket::tcp;
 use smoltcp::time::Instant;
 use smoltcp::wire::IpAddress;
 
@@ -117,33 +118,31 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
         }
     };
 
-    let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
-
     let mut session_state = SessionState::Connect;
 
-    if let Some(ref mut iface) = *sys::net::IFACE.lock() {
-        let tcp_handle = iface.add_socket(tcp_socket);
+    if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() {
+        let mut sockets = SocketSet::new(vec![]);
+        let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+        let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+        let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
+        let tcp_handle = sockets.add(tcp_socket);
+
         let mut last_received_at = clock::realtime();
         let mut response_state = ResponseState::Headers;
         loop {
             if clock::realtime() - last_received_at > timeout {
                 error!("Timeout reached");
-                iface.remove_socket(tcp_handle);
                 return Err(ExitCode::Failure);
             }
             if sys::console::end_of_text() || sys::console::end_of_transmission() {
                 eprintln!();
-                iface.remove_socket(tcp_handle);
                 return Err(ExitCode::Failure);
             }
-            let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
-            if let Err(e) = iface.poll(timestamp) {
-                error!("Network Error: {}", e);
-            }
 
-            let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle);
+            let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
+            iface.poll(timestamp, device, &mut sockets);
+            let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
+            let cx = iface.context();
 
             session_state = match session_state {
                 SessionState::Connect if !socket.is_active() => {
@@ -155,7 +154,6 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
                     }
                     if socket.connect(cx, (address, url.port), local_port).is_err() {
                         error!("Could not connect to {}:{}", address, url.port);
-                        iface.remove_socket(tcp_handle);
                         return Err(ExitCode::Failure);
                     }
                     SessionState::Request
@@ -227,11 +225,10 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
                 _ => session_state
             };
 
-            if let Some(wait_duration) = iface.poll_delay(timestamp) {
+            if let Some(wait_duration) = iface.poll_delay(timestamp, &sockets) {
                 syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
             }
         }
-        iface.remove_socket(tcp_handle);
         Ok(())
     } else {
         Err(ExitCode::Failure)
diff --git a/src/usr/httpd.rs b/src/usr/httpd.rs
index 75c00a16..68fe21e5 100644
--- a/src/usr/httpd.rs
+++ b/src/usr/httpd.rs
@@ -14,7 +14,8 @@ use alloc::string::{String, ToString};
 use alloc::vec;
 use alloc::vec::Vec;
 use core::fmt;
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::iface::SocketSet;
+use smoltcp::socket::tcp;
 use smoltcp::time::Instant;
 use smoltcp::phy::Device;
 use smoltcp::wire::IpAddress;
@@ -32,9 +33,9 @@ struct Request {
 }
 
 impl Request {
-    pub fn new() -> Self {
+    pub fn new(addr: IpAddress) -> Self {
         Self {
-            addr: IpAddress::default(),
+            addr,
             verb: String::new(),
             path: String::new(),
             body: Vec::new(),
@@ -43,10 +44,9 @@ impl Request {
     }
 
     pub fn from(addr: IpAddress, buf: &[u8]) -> Option<Self> {
-        let mut req = Request::new();
         let msg = String::from_utf8_lossy(buf);
         if !msg.is_empty() {
-            req.addr = addr;
+            let mut req = Request::new(addr);
             let mut is_header = true;
             for (i, line) in msg.lines().enumerate() {
                 if i == 0 { // Request line
@@ -85,12 +85,12 @@ struct Response {
 }
 
 impl Response {
-    pub fn new() -> Self {
+    pub fn new(req: Request) -> Self {
         let mut headers = BTreeMap::new();
         headers.insert("Date".to_string(), time::now_utc().format("%a, %d %b %Y %H:%M:%S GMT"));
         headers.insert("Server".to_string(), format!("MOROS/{}", env!("CARGO_PKG_VERSION")));
         Self {
-            req: Request::new(),
+            req,
             buf: Vec::new(),
             mime: String::new(),
             time: time::now().format(DATE_TIME_ZONE),
@@ -206,47 +206,48 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
         i += 1;
     }
 
-    if let Some(ref mut iface) = *sys::net::IFACE.lock() {
-        println!("{}HTTP Server listening on 0.0.0.0:{}{}", csi_color, port, csi_reset);
+    if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() {
+        let mut sockets = SocketSet::new(vec![]);
 
-        let mtu = iface.device().capabilities().max_transmission_unit;
+        let mtu = device.capabilities().max_transmission_unit;
         let buf_len = mtu - 14 - 20 - 20; // ETH+TCP+IP headers
         let mut connections = Vec::new();
         for _ in 0..MAX_CONNECTIONS {
-            let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; buf_len]);
-            let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; buf_len]);
-            let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
-            let tcp_handle = iface.add_socket(tcp_socket);
+            let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; buf_len]);
+            let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; buf_len]);
+            let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
+            let tcp_handle = sockets.add(tcp_socket);
+
             let send_queue: VecDeque<Vec<u8>> = VecDeque::new();
-            connections.push((tcp_handle, send_queue));
+            let keep_alive = true;
+            connections.push((tcp_handle, send_queue, keep_alive));
         }
 
+        println!("{}HTTP Server listening on 0.0.0.0:{}{}", csi_color, port, csi_reset);
+
         loop {
             if sys::console::end_of_text() || sys::console::end_of_transmission() {
-                for (tcp_handle, _) in &connections {
-                    iface.remove_socket(*tcp_handle);
-                }
                 println!();
                 return Ok(());
             }
 
             let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
-            if let Err(e) = iface.poll(timestamp) {
-                error!("Network Error: {}", e);
-            }
+            iface.poll(timestamp, device, &mut sockets);
 
-            for (tcp_handle, send_queue) in &mut connections {
-                let socket = iface.get_socket::<TcpSocket>(*tcp_handle);
+            for (tcp_handle, send_queue, keep_alive) in &mut connections {
+                let socket = sockets.get_mut::<tcp::Socket>(*tcp_handle);
 
                 if !socket.is_open() {
                     socket.listen(port).unwrap();
                 }
-                let addr = socket.remote_endpoint().addr;
+                let endpoint = match socket.remote_endpoint() {
+                    Some(endpoint) => endpoint,
+                    None => continue,
+                };
                 if socket.may_recv() {
                     let res = socket.recv(|buffer| {
-                        let mut res = Response::new();
-                        if let Some(req) = Request::from(addr, buffer) {
-                            res.req = req.clone();
+                        if let Some(req) = Request::from(endpoint.addr, buffer) {
+                            let mut res = Response::new(req.clone());
                             let sep = if req.path == "/" { "" } else { "/" };
                             let real_path = format!("{}{}{}", dir, sep, req.path.strip_suffix('/').unwrap_or(&req.path)).replace("//", "/");
 
@@ -337,11 +338,16 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
                             }
                             res.end();
                             println!("{}", res);
+                            (buffer.len(), Some(res))
+                        } else {
+                            (0, None)
+                        }
+                    });
+                    if let Ok(Some(res)) = res {
+                        *keep_alive = res.is_persistent();
+                        for chunk in res.buf.chunks(buf_len) {
+                            send_queue.push_back(chunk.to_vec());
                         }
-                        (buffer.len(), res)
-                    }).unwrap();
-                    for chunk in res.buf.chunks(buf_len) {
-                        send_queue.push_back(chunk.to_vec());
                     }
                     if socket.can_send() {
                         if let Some(chunk) = send_queue.pop_front() {
@@ -349,7 +355,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
                             debug_assert!(sent == chunk.len());
                         }
                     }
-                    if send_queue.is_empty() && !res.is_persistent() {
+                    if send_queue.is_empty() && !*keep_alive {
                         socket.close();
                     }
                 } else if socket.may_send() {
@@ -357,7 +363,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
                     send_queue.clear();
                 }
             }
-            if let Some(wait_duration) = iface.poll_delay(timestamp) {
+            if let Some(wait_duration) = iface.poll_delay(timestamp, &sockets) {
                 let t = wait_duration.total_micros() / POLL_DELAY_DIV as u64;
                 if t > 0 {
                     syscall::sleep((t as f64) / 1000000.0);
diff --git a/src/usr/net.rs b/src/usr/net.rs
index 098422f4..d8e7f2d2 100644
--- a/src/usr/net.rs
+++ b/src/usr/net.rs
@@ -13,9 +13,10 @@ use alloc::string::String;
 use alloc::vec;
 use core::str::FromStr;
 use smoltcp::wire::{EthernetFrame, PrettyPrinter, IpCidr, Ipv4Address};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::socket::tcp;
 use smoltcp::time::Instant;
 use smoltcp::phy::Device;
+use smoltcp::iface::SocketSet;
 
 pub fn main(args: &[&str]) -> Result<(), ExitCode> {
     match *args.get(1).unwrap_or(&"") {
@@ -39,8 +40,8 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
             }
         }
         "s" | "stat" => {
-            if let Some(ref mut iface) = *sys::net::IFACE.lock() {
-                let stats = iface.device().stats();
+            if let Some((_, ref mut device)) = *sys::net::NET.lock() {
+                let stats = device.stats();
                 let csi_color = Style::color("LightCyan");
                 let csi_reset = Style::reset();
                 println!("{}rx:{} {} packets ({} bytes)", csi_color, csi_reset, stats.rx_packets_count(), stats.rx_bytes_count());
@@ -50,29 +51,26 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
             }
         }
         "m" | "monitor" => {
-            if let Some(ref mut iface) = *sys::net::IFACE.lock() {
-                iface.device_mut().config().enable_debug();
+            if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() {
+                device.config().enable_debug();
 
-                let mtu = iface.device().capabilities().max_transmission_unit;
-                let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
-                let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
-                let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
-                let tcp_handle = iface.add_socket(tcp_socket);
+                let mtu = device.capabilities().max_transmission_unit;
+                let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; mtu]);
+                let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; mtu]);
+                let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
+                let mut sockets = SocketSet::new(vec![]);
+                let tcp_handle = sockets.add(tcp_socket);
 
                 loop {
                     if sys::console::end_of_text() || sys::console::end_of_transmission() {
                         println!();
-                        iface.remove_socket(tcp_handle);
                         return Ok(());
                     }
                     syscall::sleep(0.1);
 
                     let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
-                    if let Err(e) = iface.poll(timestamp) {
-                        error!("Network Error: {}", e);
-                    }
-
-                    let socket = iface.get_socket::<TcpSocket>(tcp_handle);
+                    iface.poll(timestamp, device, &mut sockets);
+                    let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
                     if socket.may_recv() {
                         socket.recv(|buffer| {
                             let recvd_len = buffer.len();
@@ -133,7 +131,7 @@ const DNS_FILE: &str = "/ini/dns";
 pub fn get_config(attribute: &str) -> Option<String> {
     match attribute {
         "mac" => {
-            if let Some(ref mut iface) = *sys::net::IFACE.lock() {
+            if let Some((ref mut iface, _)) = *sys::net::NET.lock() {
                 return Some(iface.hardware_addr().to_string());
             } else {
                 error!("Network error");
@@ -141,7 +139,7 @@ pub fn get_config(attribute: &str) -> Option<String> {
             None
         }
         "ip" => {
-            if let Some(ref mut iface) = *sys::net::IFACE.lock() {
+            if let Some((ref mut iface, _)) = *sys::net::NET.lock() {
                 if let Some(ip_cidr) = iface.ip_addrs().iter().next() {
                     return Some(format!("{}/{}", ip_cidr.address(), ip_cidr.prefix_len()));
                 }
@@ -152,9 +150,9 @@ pub fn get_config(attribute: &str) -> Option<String> {
         }
         "gw" => {
             let mut res = None;
-            if let Some(ref mut iface) = *sys::net::IFACE.lock() {
+            if let Some((ref mut iface, _)) = *sys::net::NET.lock() {
                 iface.routes_mut().update(|storage| {
-                    if let Some((_, route)) = storage.iter().next() {
+                    if let Some(route) = storage.iter().next() {
                         res = Some(route.via_router.to_string());
                     }
                 });
@@ -187,10 +185,10 @@ pub fn get_config(attribute: &str) -> Option<String> {
 pub fn set_config(attribute: &str, value: &str) {
     match attribute {
         "debug" => {
-            if let Some(ref mut iface) = *sys::net::IFACE.lock() {
+            if let Some((_, ref mut device)) = *sys::net::NET.lock() {
                 match value {
-                    "1" | "true" => iface.device_mut().config().enable_debug(),
-                    "0" | "false" => iface.device_mut().config().disable_debug(),
+                    "1" | "true" => device.config().enable_debug(),
+                    "0" | "false" => device.config().disable_debug(),
                     _ => error!("Invalid config value"),
                 }
             } else {
@@ -198,12 +196,11 @@ pub fn set_config(attribute: &str, value: &str) {
             }
         }
         "ip" => {
-            if let Ok(ip) = IpCidr::from_str(value) {
-                if let Some(ref mut iface) = *sys::net::IFACE.lock() {
+            if let Ok(addr) = IpCidr::from_str(value) {
+                if let Some((ref mut iface, _)) = *sys::net::NET.lock() {
                     iface.update_ip_addrs(|addrs| {
-                        if let Some(addr) = addrs.iter_mut().next() {
-                            *addr = ip;
-                        }
+                        addrs.clear();
+                        addrs.push(addr).unwrap();
                     });
                 } else {
                     error!("Network error");
@@ -213,7 +210,7 @@ pub fn set_config(attribute: &str, value: &str) {
             }
         }
         "gw" => {
-            if let Some(ref mut iface) = *sys::net::IFACE.lock() {
+            if let Some((ref mut iface, _)) = *sys::net::NET.lock() {
                 if value == "0.0.0.0" {
                     iface.routes_mut().remove_default_ipv4_route();
                 } else if let Ok(ip) = Ipv4Address::from_str(value) {
diff --git a/src/usr/shell.rs b/src/usr/shell.rs
index a14c7368..aaf63c8d 100644
--- a/src/usr/shell.rs
+++ b/src/usr/shell.rs
@@ -7,6 +7,7 @@ use crate::api::regex::Regex;
 use crate::api::syscall;
 use crate::sys::fs::FileType;
 
+use core::sync::atomic::{fence, Ordering};
 use alloc::collections::btree_map::BTreeMap;
 use alloc::format;
 use alloc::vec::Vec;
@@ -360,9 +361,6 @@ fn cmd_version(_args: &[&str]) -> Result<(), ExitCode> {
 }
 
 fn exec_with_config(cmd: &str, config: &mut Config) -> Result<(), ExitCode> {
-    #[cfg(test)] // FIXME: tests with `print foo => /bar` are failing without that
-    sys::console::print_fmt(format_args!(""));
-
     let cmd = variables_expansion(cmd, config);
 
     let mut args = split_args(&cmd.trim());
@@ -467,6 +465,7 @@ fn exec_with_config(cmd: &str, config: &mut Config) -> Result<(), ExitCode> {
         }
     }
 
+    fence(Ordering::SeqCst);
     let res = match args[0] {
         ""         => Ok(()),
         "2048"     => usr::pow::main(&args),
diff --git a/src/usr/socket.rs b/src/usr/socket.rs
index d281a416..0370f1d6 100644
--- a/src/usr/socket.rs
+++ b/src/usr/socket.rs
@@ -11,7 +11,8 @@ use alloc::string::String;
 use alloc::vec;
 use alloc::vec::Vec;
 use core::str::{self, FromStr};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer, TcpState};
+use smoltcp::iface::SocketSet;
+use smoltcp::socket::tcp;
 use smoltcp::time::Instant;
 use smoltcp::wire::IpAddress;
 
@@ -92,29 +93,28 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
         }
     };
 
-    let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
-
     #[derive(Debug)]
     enum State { Connecting, Sending, Receiving }
     let mut state = State::Connecting;
 
-    if let Some(ref mut iface) = *sys::net::IFACE.lock() {
-        let tcp_handle = iface.add_socket(tcp_socket);
+    if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() {
+        let mut sockets = SocketSet::new(vec![]);
+        let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+        let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+        let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
+        let tcp_handle = sockets.add(tcp_socket);
 
         loop {
             if sys::console::end_of_text() || sys::console::end_of_transmission() {
                 eprintln!();
-                iface.remove_socket(tcp_handle);
                 return Err(ExitCode::Failure);
             }
+
             let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
-            if let Err(e) = iface.poll(timestamp) {
-                error!("Network Error: {}", e);
-            }
+            iface.poll(timestamp, device, &mut sockets);
+            let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
+            let cx = iface.context();
 
-            let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle);
             if verbose {
                 debug!("*********************************");
                 debug!("APP State: {:?}", state);
@@ -184,7 +184,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
                     }).unwrap();
                     State::Receiving
                 }
-                _ if socket.state() == TcpState::SynSent || socket.state() == TcpState::SynReceived => {
+                _ if socket.state() == tcp::State::SynSent || socket.state() == tcp::State::SynReceived => {
                     state
                 }
                 State::Receiving if !socket.may_recv() && !listen => {
@@ -211,11 +211,10 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
             if interval > 0.0 {
                 syscall::sleep(interval);
             }
-            if let Some(wait_duration) = iface.poll_delay(timestamp) {
+            if let Some(wait_duration) = iface.poll_delay(timestamp, &sockets) {
                 syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
             }
         }
-        iface.remove_socket(tcp_handle);
         Ok(())
     } else {
         Err(ExitCode::Failure)
diff --git a/src/usr/tcp.rs b/src/usr/tcp.rs
index ac74bc97..b8d65996 100644
--- a/src/usr/tcp.rs
+++ b/src/usr/tcp.rs
@@ -9,7 +9,8 @@ use alloc::string::String;
 use alloc::vec;
 use alloc::vec::Vec;
 use core::str::{self, FromStr};
-use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::iface::SocketSet;
+use smoltcp::socket::tcp;
 use smoltcp::time::Instant;
 use smoltcp::wire::IpAddress;
 
@@ -59,35 +60,32 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
         }
     };
 
-    let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
-    let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
-
     enum State { Connect, Request, Response }
     let mut state = State::Connect;
 
-    if let Some(ref mut iface) = *sys::net::IFACE.lock() {
-        let tcp_handle = iface.add_socket(tcp_socket);
+    if let Some((ref mut iface, ref mut device)) = *sys::net::NET.lock() {
+        let mut sockets = SocketSet::new(vec![]);
+        let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+        let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
+        let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
+        let tcp_handle = sockets.add(tcp_socket);
 
         let timeout = 5.0;
         let started = clock::realtime();
         loop {
             if clock::realtime() - started > timeout {
                 error!("Timeout reached");
-                iface.remove_socket(tcp_handle);
                 return Err(ExitCode::Failure);
             }
             if sys::console::end_of_text() || sys::console::end_of_transmission() {
                 eprintln!();
-                iface.remove_socket(tcp_handle);
                 return Err(ExitCode::Failure);
             }
-            let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
-            if let Err(e) = iface.poll(timestamp) {
-                error!("Network Error: {}", e);
-            }
 
-            let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle);
+            let timestamp = Instant::from_micros((clock::realtime() * 1000000.0) as i64);
+            iface.poll(timestamp, device, &mut sockets);
+            let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
+            let cx = iface.context();
 
             state = match state {
                 State::Connect if !socket.is_active() => {
@@ -123,11 +121,10 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
                 _ => state
             };
 
-            if let Some(wait_duration) = iface.poll_delay(timestamp) {
+            if let Some(wait_duration) = iface.poll_delay(timestamp, &sockets) {
                 syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
             }
         }
-        iface.remove_socket(tcp_handle);
         Ok(())
     } else {
         Err(ExitCode::Failure)


Test patch: