tstest/natlab: bit more of in-memory network testing package

Pairing with @danderson
This commit is contained in:
Brad Fitzpatrick 2020-07-02 13:02:13 -07:00
parent 23c93da942
commit bb1a9e4700
1 changed files with 64 additions and 4 deletions

View File

@ -30,16 +30,39 @@ type PacketConner interface {
}
type Network struct {
name string
dhcpPool netaddr.IPPrefix
alloced map[netaddr.IP]bool
pushRoute netaddr.IPPrefix
}
func (n *Network) write(p []byte, dst, src netaddr.IPPort) (num int, err error) {
panic("TODO")
}
type iface struct {
net *Network
up bool
ips []netaddr.IP
name string // optional
ips []netaddr.IP // static; not mutated once created
}
func (f *iface) String() string {
// TODO: make this all better
if f.name != "" {
return f.name
}
return fmt.Sprintf("unamed-interface-on-network-%p", f.net)
}
// Contains reports whether f contains ip as an IP.
func (f *iface) Contains(ip netaddr.IP) bool {
for _, v := range f.ips {
if ip == v {
return true
}
}
return false
}
type routeEntry struct {
@ -57,6 +80,39 @@ type Machine struct {
conns map[netaddr.IPPort]*conn
}
var (
v4unspec = netaddr.IPv4(0, 0, 0, 0)
v6unspec = netaddr.IPv6Unspecified()
)
func (m *Machine) writePacket(p []byte, dst, src netaddr.IPPort) (n int, err error) {
iface, err := m.interfaceForIP(dst.IP)
if err != nil {
return 0, err
}
unspec := src.IP == v4unspec || src.IP == v6unspec
if unspec {
// TODO: pick a src IP
} else {
if !iface.Contains(src.IP) {
return 0, fmt.Errorf("can't send to %v with src %v on interface %v", dst.IP, src.IP, iface)
}
}
return iface.net.write(p, dst, src)
}
func (m *Machine) interfaceForIP(ip netaddr.IP) (*iface, error) {
m.mu.Lock()
defer m.mu.Unlock()
for _, re := range m.routes {
if re.prefix.Contains(ip) {
return re.iface, nil
}
}
return nil, fmt.Errorf("no route found to %v", ip)
}
func (m *Machine) hasv6() bool {
m.mu.Lock()
defer m.mu.Unlock()
@ -213,7 +269,11 @@ func (c *conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
}
func (c *conn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
panic("TODO")
ipp, err := netaddr.ParseIPPort(addr.String())
if err != nil {
return 0, fmt.Errorf("bogus addr %T %q", addr, addr.String())
}
return c.m.writePacket(p, ipp, c.ipp)
}
func (c *conn) SetDeadline(t time.Time) error {