Skip to content

Commit faa9181

Browse files
authoredApr 30, 2024··
add dhcp.ClientState (#20)
1 parent 60c7db9 commit faa9181

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed
 

‎eth/dhcp/clientstate_string.go

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎eth/dhcp/dhcp.go

+29
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,35 @@ const (
2323
DefaultServerPort = 67
2424
)
2525

26+
// ClientState represents the state of a DHCP client.
27+
// Below is a state diagram of a DHCP client.
28+
type ClientState uint8
29+
30+
// IsValid returns true if the state is within the valid range.
31+
func (s ClientState) IsValid() bool {
32+
return s > 0 || s < ClientState(s)
33+
}
34+
35+
// install stringer with `go install golang.org/x/tools/cmd/stringer@latest`
36+
//
37+
//go:generate stringer -type=ClientState -trimprefix=State
38+
const (
39+
_ ClientState = iota
40+
// On clean slate boot, abort, NAK or decline enter the INIT state.
41+
StateInit
42+
// After sending out a Discover enter SELECTING.
43+
StateSelecting
44+
// After receiving a worthy offer enter REQUESTING.
45+
StateRequesting
46+
// On reboot enter INIT-REBOOT state.
47+
// StateInitReboot
48+
// On sending out a Request enter REBOOTING.
49+
// StateRebooting
50+
// On ACK to Request enter BOUND.
51+
StateBound
52+
numStates uint8 = iota
53+
)
54+
2655
type Option struct {
2756
Num OptNum
2857
Data []byte

‎eth/dns/types.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const (
6262
// An RCode is a DNS response status code.
6363
type RCode uint16
6464

65-
//go:generate stringer -type=RCode -trimprefix=RCode -output=rcode_string.go
65+
// /go:generate stringer -type=RCode -trimprefix=RCode -output=rcode_string.go
6666
const (
6767
RCodeSuccess RCode = 0 // No error condition.
6868
RCodeFormatError RCode = 1 // Format error - The name server was unable to interpret the query.

‎stacks/dhcp_client.go

+20
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,30 @@ func (d *DHCPClient) BeginRequest(cfg DHCPRequestConfig) error {
120120
return d.stack.FlagPendingUDP(d.port)
121121
}
122122

123+
// IsDone
124+
//
125+
// Deprecated: Use d.State()==dhcp.StateBound instead.
123126
func (d *DHCPClient) IsDone() bool {
124127
return d.state == dhcpStateDone || d.state == dhcpStateNaked
125128
}
126129

130+
// State returns the current state of the DHCP client.
131+
func (d *DHCPClient) State() dhcp.ClientState {
132+
switch d.state {
133+
case dhcpStateNone:
134+
return dhcp.StateInit
135+
case dhcpStateWaitOffer, dhcpStateGotOffer:
136+
return dhcp.StateSelecting
137+
case dhcpStateWaitAck:
138+
return dhcp.StateRequesting
139+
case dhcpStateDone:
140+
return dhcp.StateBound
141+
case dhcpStateNaked:
142+
return dhcp.StateInit
143+
}
144+
return 0
145+
}
146+
127147
// DHCPServer IP address field of the DHCP packet. Is the siaddr field of the DHCP packet, which can be overriden with the Server IP option.
128148
func (d *DHCPClient) DHCPServer() netip.Addr {
129149
return ipv4orInvalid(d.svip)

‎stacks/stacks_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/soypat/seqs"
1616
"github.com/soypat/seqs/eth"
17+
"github.com/soypat/seqs/eth/dhcp"
1718
"github.com/soypat/seqs/eth/dns"
1819
"github.com/soypat/seqs/stacks"
1920
)
@@ -89,6 +90,13 @@ func TestDHCP(t *testing.T) {
8990
}
9091

9192
func testDHCP(t *testing.T, cl *stacks.DHCPClient, sv *stacks.DHCPServer) {
93+
checkClientState := func(t *testing.T, want dhcp.ClientState) {
94+
t.Helper()
95+
if cl.State() != want {
96+
t.Fatalf("client state=%s want=%s", cl.State().String(), want.String())
97+
}
98+
}
99+
checkClientState(t, dhcp.StateInit)
92100
var requestedIP = netip.AddrFrom4([4]byte{192, 168, 1, 69})
93101
cstack := cl.PortStack()
94102
sstack := sv.PortStack()
@@ -103,6 +111,7 @@ func testDHCP(t *testing.T, cl *stacks.DHCPClient, sv *stacks.DHCPServer) {
103111
if err != nil {
104112
t.Fatal(err)
105113
}
114+
106115
checkClientNotDone := func(msg string) {
107116
t.Helper()
108117
if cl.IsDone() {
@@ -116,6 +125,7 @@ func testDHCP(t *testing.T, cl *stacks.DHCPClient, sv *stacks.DHCPServer) {
116125
if n < minDHCPSize {
117126
t.Errorf("ex[%d] sent=%d want>=%d", ex, n, minDHCPSize)
118127
}
128+
checkClientState(t, dhcp.StateSelecting)
119129
checkNoMoreDataSent(t, "after cl DISCOVER send", egr)
120130
checkClientNotDone("after DISCOVER send")
121131
egr.HandleRx(t)
@@ -125,6 +135,7 @@ func testDHCP(t *testing.T, cl *stacks.DHCPClient, sv *stacks.DHCPServer) {
125135
if n < minDHCPSize {
126136
t.Errorf("ex[%d] sent=%d want>=%d", ex, n, minDHCPSize)
127137
}
138+
checkClientState(t, dhcp.StateSelecting)
128139
checkNoMoreDataSent(t, "after sv OFFER send", egr)
129140
egr.HandleRx(t) // Client receives OFFER.
130141
checkClientNotDone("after OFFER recv")
@@ -134,6 +145,7 @@ func testDHCP(t *testing.T, cl *stacks.DHCPClient, sv *stacks.DHCPServer) {
134145
if n < minDHCPSize {
135146
t.Errorf("ex[%d] sent=%d want>=%d", ex, n, minDHCPSize)
136147
}
148+
checkClientState(t, dhcp.StateRequesting)
137149
checkNoMoreDataSent(t, "after client REQUEST send", egr)
138150
checkClientNotDone("after REQUEST send")
139151
egr.HandleRx(t) // Server receives REQUEST.
@@ -148,6 +160,7 @@ func testDHCP(t *testing.T, cl *stacks.DHCPClient, sv *stacks.DHCPServer) {
148160
if !cl.IsDone() {
149161
t.Fatal("client not processed ACK yet")
150162
}
163+
checkClientState(t, dhcp.StateBound)
151164
}
152165

153166
func TestARP(t *testing.T) {

0 commit comments

Comments
 (0)
Please sign in to comment.