diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0e7ec41..544a047 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -143,6 +143,12 @@ jobs: - uses: actions/setup-go@v6 with: go-version: "1.26" + # Needed because a build command in memci.json names tinygo. Keep the two + # versions in step: TinyGo 0.42 builds with Go 1.25 through 1.27 and + # refuses to run outside that window, in either direction. + - uses: acifani/setup-tinygo@v2 + with: + tinygo-version: "0.42.0" - uses: soypat/memci@main with: args: -kind package diff --git a/.github/workflows/memci-comment.yml b/.github/workflows/memci-comment.yml index e725a95..a618e1e 100644 --- a/.github/workflows/memci-comment.yml +++ b/.github/workflows/memci-comment.yml @@ -6,7 +6,7 @@ name: memci comment on: workflow_run: - workflows: [memci] + workflows: [CI] types: [completed] permissions: read-all diff --git a/.github/workflows/memci.json b/.github/workflows/memci.json index 06f5fca..a20041e 100644 --- a/.github/workflows/memci.json +++ b/.github/workflows/memci.json @@ -3,5 +3,11 @@ "name":"Stack MWE", "build":"go build -o=mwe.elf -tags=noslog ./examples/min-working-example", "elf":"mwe.elf" + }, + { + "name":"Stack MWE pico", + "build":"tinygo build -o=mwe-pico.elf -target=pico -tags=noslog -panic=trap ./examples/min-working-example", + "elf":"mwe-pico.elf", + "mem":true } -] \ No newline at end of file +] diff --git a/arp/frame.go b/arp/frame.go index c52113d..1089bad 100644 --- a/arp/frame.go +++ b/arp/frame.go @@ -5,6 +5,7 @@ import ( "github.com/soypat/lneto" "github.com/soypat/lneto/ethernet" + "github.com/soypat/lneto/internal" ) // NewFrame returns a Frame with data set to buf. @@ -142,10 +143,24 @@ func (afrm Frame) ValidateSize(v *lneto.Validator) { } } +// String returns a basic human readable represetation of ARP frame. func (afrm Frame) String() string { opstr := afrm.Operation().String() - var rawbuf [11]byte + rawbuf := make([]byte, 0, 128) b := append(rawbuf[:0], "ARP "...) b = append(b, opstr...) - return string(rawbuf[:len(b)]) + htyp, hlen := afrm.Hardware() + b = internal.AppendStrDecimal(b, " htyp=", int64(htyp)) + b = internal.AppendStrDecimal(b, " hlen=", int64(hlen)) + ptyp, plen := afrm.Protocol() + b = internal.AppendStrDecimal(b, " plen=", int64(plen)) + b = append(b, " proto="...) + b = append(b, ptyp.String()...) + hw, proto := afrm.Target() + b = internal.AppendStrHexData(b, " htgt=", hw...) + b = internal.AppendStrHexData(b, " ptgt=", proto...) + hw, proto = afrm.Sender() + b = internal.AppendStrHexData(b, " hsnd=", hw...) + b = internal.AppendStrHexData(b, " psnd=", proto...) + return string(b) } diff --git a/internal/strconv.go b/internal/strconv.go index 9beb838..4584646 100644 --- a/internal/strconv.go +++ b/internal/strconv.go @@ -1,6 +1,9 @@ package internal -import "strconv" +import ( + "encoding/hex" + "strconv" +) // AppendStrDecimal appends pfx followed by value in base 10 to dst and returns // the resulting slice. It condenses the prefixed-number pattern common to @@ -10,6 +13,14 @@ func AppendStrDecimal(dst []byte, pfx string, value int64) []byte { return strconv.AppendInt(dst, value, 10) } +// AppendStrHexData appends pfx followed by data as hexadecimaldata. +// +// dst = internal.AppendStrHexData(dst, "data=0x", data...) // data=0xdeadbeef +func AppendStrHexData(dst []byte, pfx string, data ...byte) []byte { + dst = append(dst, pfx...) + return hex.AppendEncode(dst, data) +} + // IntLen returns the number of bytes [strconv.AppendInt] emits for value in the // given base, including a leading minus sign for negatives. Lets callers size a // buffer, or test whether a value fits an existing slot, before writing a byte. diff --git a/ipv4/frame.go b/ipv4/frame.go index 6d9f038..8730422 100644 --- a/ipv4/frame.go +++ b/ipv4/frame.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "github.com/soypat/lneto" + "github.com/soypat/lneto/internal" ) // NewFrame returns a new [Frame] with data set to buf. @@ -237,9 +238,17 @@ func (ifrm Frame) ValidateExceptCRC(v *lneto.Validator) { func (ifrm Frame) String() string { proto := ifrm.Protocol().String() - b := make([]byte, 0, 5+len(proto)) + b := make([]byte, 0, 91+len(proto)) b = append(b, "IP ("...) b = append(b, proto...) - b = append(b, ')') + b = append(b, ") src="...) + b = AppendFormatAddr(b, *ifrm.SourceAddr()) + b = append(b, " dst="...) + b = AppendFormatAddr(b, *ifrm.DestinationAddr()) + b = internal.AppendStrDecimal(b, " len=", int64(ifrm.TotalLength())) + b = internal.AppendStrDecimal(b, " opt=", int64(ifrm.HeaderLength()-20)) + b = internal.AppendStrDecimal(b, " ttl=", int64(ifrm.TTL())) + b = internal.AppendStrDecimal(b, " id=", int64(ifrm.ID())) + b = internal.AppendStrHexData(b, " tos=0x", byte(ifrm.ToS())) return string(b) }