Setting TOS on a net.UDPConn connection

I have a working UDP connection connection but I now need to set the TOS on a particular packet I’m sending.

I was hoping this code would do the job, but whilst I’m not getting an error, the TOS is not getting set as verified with Wireshark.

conn, err := net.ListenUDP(“udp”, addr)
if err != nil {
return err
}

err := ipv4.NewConn(conn).SetTOS(0x02)
if err != nil {
log.Debugf(“Error setting TOS: %s”, err)
}
_, err = conn.WriteToUDP(b, ip)

As far as I read the docs, ipv4.NewConn creates and returns a new Conn from the old one, and does not alter it.

The following should roughly do it, but is untested:

c := ipv4.NewConn(conn)
err := c.SetTOS(0x02)
if err != nil {
  log.Debugf(“Error setting TOS: %s”, err)
}
_, err = c.WriteToUDP(b, ip)

Does that make the old Conn no longer usable?

Also, ipv4.NewConn returns a Conn which does not have a WriteToUDP method.

The example at https://godoc.org/golang.org/x/net/ipv4#ex-Conn--MarkingTCP appears to reuse the existing connection, and I’ve tried to mimic this using the following code but it does not set the TOS:

		p := ipv4.NewConn(conn)
		if err := p.SetTOS(0x02); err != nil {
			log.Debugf("Error setting TOS: %s", err)
		}
		_, err := conn.WriteToUDP(b, ip)

Hmmm… Haven’t seen that…

Then I’m out of ideas and also can’t test it on my own right now. Not at a go and wireshark enabled machine now.

But just to make sure that we can rule out OS behaviour, on what operating system did you test? I can try to reproduce on windows or linux tomorrow.

The plot thickens. I have created the following test app, which on Windows SetTOS doesn’t have any effect but SetTTL works. On Linux, however, I get a panic!

$ go run udp_tos.go
panic: reflect: call of reflect.Value.Int on zero Value

goroutine 1 [running]:
reflect.Value.Int(0x0, 0x0, 0x0, 0x527b6d)
/usr/local/go/src/reflect/value.go:914 +0x141
golang.org/x/net/ipv4.sysfd(0x5be5e0, 0xc42000e030, 0xc420053e08, 0x4de159, 0x515760)
/home/kgolding/go/src/golang.org/x/net/ipv4/helper_unix.go:46 +0x196
golang.org/x/net/ipv4.(*genericOpt).sysfd(0xc420080190, 0xc42000e030, 0xc420080190, 0xc42000e030)
/home/kgolding/go/src/golang.org/x/net/ipv4/helper_unix.go:17 +0x57
golang.org/x/net/ipv4.(*genericOpt).SetTOS(0xc420080190, 0x2, 0xc420080190, 0xc42000e030)
/home/kgolding/go/src/golang.org/x/net/ipv4/genericopt_posix.go:29 +0x45
main.main()
/home/kgolding/Projects/golang/src/xxxxxxxxx.co.uk/_tests/udp_tos/udp_tos.go:24 +0x239
exit status 2

The app code:

package main

import (
	"log"
	"net"

	"golang.org/x/net/ipv4"
)

func main() {
	laddr, err := net.ResolveUDPAddr("udp4", "192.168.5.22:5000")
	if err != nil {
		log.Fatal(err)
	}
	raddr, err := net.ResolveUDPAddr("udp4", "192.168.5.29:5000")
	if err != nil {
		log.Fatal(err)
	}
	conn, err := net.ListenUDP("udp4", laddr)
	if err != nil {
		log.Fatal(err)
	}
	p := ipv4.NewPacketConn(conn)
	err = p.SetTOS(2) // IGNORED
	if err != nil {
		log.Fatal(err)
	}
	p.SetTTL(10) // WORKS
	if err != nil {
		log.Fatal(err)
	}

	b := []byte("HELLO")

	n, err := p.WriteTo(b, nil, raddr)
	log.Printf("Write %d bytes", n)
	if err != nil {
		log.Fatal(err)
	}

	n, err = conn.WriteToUDP(b, raddr)
	log.Printf("WriteToUDP %d bytes", n)
	if err != nil {
		log.Fatal(err)
	}
	log.Fatal("Done")
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.