Skip to content

Commit 3089bf8

Browse files
scottfeldmandeadprogram
authored andcommitted
net: updates/cleanup/docs for net, netdev, and netlink
1 parent 196d1dd commit 3089bf8

23 files changed

+211
-848
lines changed

README-net.md

+94-150
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
#### Table of Contents
1+
### Table of Contents
22

33
- ["net" Package](#net-package)
44
- [Using "net" Package](#using-net-package)
55
- [Using "net/http" Package](#using-nethttp-package)
66
- [Using "crypto/tls" Package](#using-cryptotls-package)
77
- [Using Sockets](#using-sockets)
8-
- [Netdev and Netlink](#netdev-and-netlink)
9-
- [Writing a New Netdev Driver](#writing-a-new-netdev-driver)
108

119
## "net" Package
1210

1311
TinyGo's "net" package is ported from Go. The port offers a subset of Go's
1412
"net" package. The subset maintains Go 1 compatiblity guarantee. A Go
1513
application that uses "net" will most-likey just work on TinyGo if the usage is
1614
within the subset offered. (There may be external constraints such as limited
17-
SRAM on embedded environment that may limit full functionality).
15+
SRAM on some targets that may limit full "net" functionality).
1816

1917
Continue below for details on using "net" and "net/http" packages.
2018

@@ -24,143 +22,140 @@ TinyGo's "net" package.
2422
## Using "net" Package
2523

2624
Ideally, TinyGo's "net" package would be Go's "net" package and applications
27-
using "net" would just work, as-is. TinyGo's net package is a partial port
28-
from Go's net package, replacing OS socket syscalls with netdev socket calls.
29-
30-
Netdev is TinyGo's network device driver model; read more about
31-
[Netdev](#netdev-and-netlink).
25+
using "net" would just work, as-is. TinyGo's net package is a partial port of
26+
Go's net package, so some things may not work because they have not been
27+
ported.
3228

3329
There are a few features excluded during the porting process, in particular:
3430

3531
- No IPv6 support
3632
- No DualStack support
3733

38-
Run ```go doc -all ./src/net``` in TinyGo repo to see full listing.
34+
Run ```go doc -all ./src/net``` in TinyGo repo to see full listing of what has
35+
been ported. Here is a list of things known to work. You can find examples
36+
of these at [examples/net](examples/net/).
3937

40-
Applications using Go's net package will need a few setup steps to work with
41-
TinyGo's net package.
38+
### What is Known to Work
4239

43-
### Step 1: Create the netdev for your target device.
40+
(These are all IPv4 only).
4441

45-
The available netdev are:
42+
- TCP client and server
43+
- UDP client
44+
- TLS client
45+
- HTTP client and server
46+
- HTTPS client
47+
- NTP client (UDP)
48+
- MQTT client (paho & natiu)
49+
- WebSocket client and server
4650

47-
- [wifinina]: ESP32 WiFi co-controller running Arduino WiFiNINA firmware
51+
Multiple sockets can be opened in a single app. For example, the app could run
52+
as an http server listen on port :80 and also use NTP to get the current time
53+
or send something over MQTT. There is a practical limit to the number of
54+
active sockets per app, around 8 or 10, so don't go crazy.
4855

49-
targets: pyportal arduino_nano33 nano_rp2040 metro_m4_airlift
50-
arduino_mkrwifi1010 matrixportal_m4
56+
Applications using Go's net package will need a few setup steps to work with
57+
TinyGo's net package. The steps are required before using "net".
5158

52-
- [rtl8720dn]: RealTek WiFi rtl8720dn co-controller
59+
### Step 1: Probe to Load Network Driver
5360

54-
targets: wioterminal
61+
Call Probe() to load the correct network driver for your target. Probe()
62+
allows the app to work on multiple targets.
5563

56-
- [espat]: ESP32/ESP8266 WiFi co-controller running Espressif AT firmware
64+
```go
65+
package main
5766

58-
targets: TBD
67+
import (
68+
"tinygo.org/x/drivers/netlink/probe"
69+
)
5970

60-
This example configures and creates a wifinina netdev using New().
71+
func main() {
6172

62-
```go
63-
import "tinygo.org/x/drivers/wifinina"
73+
// load network driver for target
74+
link, dev := probe.Probe()
6475

65-
func main() {
66-
cfg := wifinina.Config{Ssid: "foo", Passphrase: "bar"}
67-
netdev := wifinina.New(&cfg)
68-
...
76+
...
6977
}
7078
```
7179

72-
New() registers the netdev with the "net" package using net.useNetdev().
80+
Probe() will load the driver with default configuration for the target. For
81+
custom configuration, the app can open code Probe() for the target
82+
requirements.
7383

74-
The Config structure is netdev-specific; consult the specific netdev package
75-
for Config details. In this case, the WiFi credentials are passed, but other
76-
settings are typically passed such as device configuration.
84+
Probe() returns a [Netlinker](netlink/README.md) and a
85+
[Netdever](netdev/README.md), interfaces implemented by the network driver.
86+
Next, we'll use the Netlinker interface to connect the target to an IP network.
7787

7888
### Step 2: Connect to an IP Network
7989

80-
Before the net package is fully functional, connect the netdev to an underlying
81-
IP network. For example, a WiFi netdev would connect to a WiFi access point or
82-
become a WiFi access point; either way, once connected, the netdev has a
83-
station IP address and is connected on the IP network. Similarly, a LTE netdev
84-
would connect to a LTE provider, giving the device an IP address on the LTE
85-
network.
86-
87-
Using the Netlinker interface, Call netdev.NetConnect() to connect the device
88-
to an IP network. Call netdev.NetDisconnect() to disconnect. Continuing example:
90+
Before the net package is fully functional, we need to connect the target to an
91+
IP network.
8992

9093
```go
94+
package main
95+
9196
import (
92-
"tinygo.org/x/drivers/wifinina"
97+
"tinygo.org/x/drivers/netlink"
98+
"tinygo.org/x/drivers/netlink/probe"
9399
)
94100

95101
func main() {
96-
cfg := wifinina.Config{Ssid: "foo", Passphrase: "bar"}
97-
netdev := wifinina.New(&cfg)
98102

99-
netdev.NetConnect()
103+
// load network driver for target
104+
link, _ := probe.Probe()
100105

101-
// "net" package calls here
106+
// Connect target to IP network
107+
link.NetConnect(&netlink.ConnectParams{
108+
Ssid: "my SSID",
109+
Passphrase: "my passphrase",
110+
})
102111

103-
netdev.NetDisconnect()
112+
// OK to use "net" from here on
113+
...
104114
}
105115
```
106116

107117
Optionally, get notified of IP network connects and disconnects:
108118

109119
```go
110-
netdev.Notify(func(e drivers.NetlinkEvent) {
120+
link.Notify(func(e netlink.Event) {
111121
switch e {
112-
case drivers.NetlinkEventNetUp:
113-
println("Network UP")
114-
case drivers.NetlinkEventNetDown:
115-
println("Network DOWN")
122+
case netlink.EventNetUp: println("Network UP")
123+
case netlink.EventNetDown: println("Network DOWN")
116124
})
117125
```
118126
119-
Here is a simple example of an http server listening on port :8080, before and
120-
after:
127+
Here is an example of an http server listening on port :8080:
121128
122-
#### Before
123129
```go
124130
package main
125131

126132
import (
127133
"fmt"
128134
"net/http"
129-
)
130135

131-
func main() {
132-
http.HandleFunc("/", HelloServer)
133-
http.ListenAndServe(":8080", nil)
134-
}
136+
"tinygo.org/x/drivers/netlink"
137+
"tinygo.org/x/drivers/netlink/probe"
138+
)
135139

136140
func HelloServer(w http.ResponseWriter, r *http.Request) {
137141
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
138142
}
139-
```
140143

141-
#### After
142-
```go
143-
package main
144+
func main() {
144145

145-
import (
146-
"fmt"
147-
"net/http"
146+
// load network driver for target
147+
link, _ := probe.Probe()
148148

149-
"tinygo.org/x/drivers/wifinina"
150-
)
151-
152-
func main() {
153-
cfg := wifinina.Config{Ssid: "foo", Passphrase: "bar"}
154-
netdev := wifinina.New(&cfg)
155-
netdev.NetConnect()
149+
// Connect target to IP network
150+
link.NetConnect(&netlink.ConnectParams{
151+
Ssid: "my SSID",
152+
Passphrase: "my passphrase",
153+
})
156154

155+
// Serve it up
157156
http.HandleFunc("/", HelloServer)
158157
http.ListenAndServe(":8080", nil)
159158
}
160-
161-
func HelloServer(w http.ResponseWriter, r *http.Request) {
162-
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
163-
}
164159
```
165160
166161
## Using "net/http" Package
@@ -191,99 +186,48 @@ protocol. This is different from Go's crypto/tls package which handles the TLS
191186
protocol in software.
192187
193188
TinyGo's TLS support is only available for client applications. You can
194-
http.Get() to an http:// or https:// address, but you cannot
195-
http.ListenAndServeTLS() an https server.
189+
http.Get() to an https:// address, but you cannot http.ListenAndServeTLS() an
190+
https server.
196191
197192
The offloading hardware has pre-defined TLS certificates built-in.
198193
199194
## Using Sockets
200195
201-
A netdev implements a BSD socket-like interface so an application can make direct
202-
socket calls, bypassing the net package.
196+
The Netdever interface is a BSD socket-like interface so an application can make direct
197+
socket calls, bypassing the "net" package for the lowest overhead.
203198
204-
Here is a simple TCP application using direct sockets:
199+
Here is a simple TCP client application using direct sockets:
205200
206201
```go
207202
package main
208203

209204
import (
210205
"net" // only need to parse IP address
211206

212-
"tinygo.org/x/drivers"
213-
"tinygo.org/x/drivers/wifinina"
207+
"tinygo.org/x/drivers/netdev"
208+
"tinygo.org/x/drivers/netlink"
209+
"tinygo.org/x/drivers/netlink/probe"
214210
)
215211

216212
func main() {
217-
cfg := wifinina.Config{Ssid: "foo", Passphrase: "bar"}
218-
netdev := wifinina.New(&cfg)
219-
220-
// ignoring error handling
221-
222-
netdev.NetConnect()
223-
224-
sock, _ := netdev.Socket(drivers.AF_INET, drivers.SOCK_STREAM, drivers.IPPROTO_TCP)
225-
226-
netdev.Connect(sock, "", net.ParseIP("10.0.0.100"), 8080)
227-
netdev.Send(sock, []bytes("hello"), 0, 0)
228-
229-
netdev.Close(sock)
230-
}
231-
```
232213

233-
## Netdev and Netlink
214+
// load network driver for target
215+
link, dev := probe.Probe()
234216

235-
Netdev is TinyGo's network device driver model. Network drivers implement the
236-
netdever interface, providing a common network I/O interface to TinyGo's "net"
237-
package. The interface is modeled after the BSD socket interface. net.Conn
238-
implementations (TCPConn, UDPConn, and TLSConn) use the netdev interface for
239-
device I/O access. For example, net.DialTCP, which returns a net.TCPConn,
240-
calls netdev.Socket() and netdev.Connect():
217+
// Connect target to IP network
218+
link.NetConnect(&netlink.ConnectParams{
219+
Ssid: "my SSID",
220+
Passphrase: "my passphrase",
221+
})
241222

242-
```go
243-
func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error) {
223+
// omit error handling
244224

245-
fd, _ := netdev.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
225+
sock, _ := dev.Socket(netdev.AF_INET, netdev.SOCK_STREAM, netdev.IPPROTO_TCP)
246226

247-
netdev.Connect(fd, "", raddr.IP, raddr.Port)
227+
dev.Connect(sock, "", net.ParseIP("10.0.0.100"), 8080)
228+
dev.Send(sock, []bytes("hello"), 0, 0)
248229

249-
return &TCPConn{
250-
fd: fd,
251-
laddr: laddr,
252-
raddr: raddr,
253-
}, nil
230+
dev.Close(sock)
231+
link.NetDisconnect()
254232
}
255233
```
256-
257-
Network drivers also (optionally) implement the Netlinker interface. This
258-
interface is not used by TinyGo's "net" package, but rather provides the TinyGo
259-
application direct access to the network device for common settings and control
260-
that fall outside of netdev's socket interface.
261-
262-
## Writing a New Netdev Driver
263-
264-
A new netdev driver will implement the netdever and optionally the Netlinker
265-
interfaces. See the wifinina or rtl8720dn drivers for examples.
266-
267-
#### Locking
268-
269-
Multiple goroutines may invoke methods on a net.Conn simultaneously, and since
270-
the net package translates net.Conn calls into netdev socket calls, it follows
271-
that multiple goroutines may invoke socket calls, so locking is required to
272-
keep socket calls from stepping on one another.
273-
274-
Don't hold a lock while Time.Sleep()ing waiting for a hardware operation to
275-
finish. Unlocking while sleeping let's other goroutines make progress. If the
276-
sleep period is really small, then you can get away with holding the lock.
277-
278-
#### Sockfd
279-
280-
The netdev socket interface uses a socket fd (int) to represent a socket
281-
connection (end-point). Each net.Conn maps 1:1 to a fd. The number of fds
282-
available is a hardware limitation. Wifinina, for example, can hand out 10
283-
fds.
284-
285-
### Testing
286-
287-
The netdev driver should minimally run all of the example/net examples.
288-
289-
TODO: automate testing to catch regressions.

espat/espat.go

-7
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,6 @@ func (d *Device) NetNotify(cb func(netlink.Event)) {
125125
// Not supported
126126
}
127127

128-
func (d *Device) SendEth(pkt []byte) error {
129-
return netlink.ErrNotSupported
130-
}
131-
132-
func (d *Device) RecvEthFunc(cb func(pkt []byte) error) {
133-
}
134-
135128
func (d *Device) GetHostByName(name string) (net.IP, error) {
136129
ip, err := d.GetDNS(name)
137130
return net.ParseIP(ip), err

0 commit comments

Comments
 (0)