Skip to content

Commit

Permalink
netstack: make tcpip.Address an opaque type
Browse files Browse the repository at this point in the history
The important change here is in tcpip/tcpip.go, where tcpip.Address is defined.
The rest is updating uses of tcpip.Address.

This is preparation for netip.Addr or []byte based addresses, which should save
us a bunch of allocations. Currently, we allocate every time we want to, say,
get a tcpip.Address from a header. This is because the header is a byte slice,
but Address is a string. Strings are immutable, so Go allocates and copies.

PiperOrigin-RevId: 532284732
  • Loading branch information
kevinGC authored and gvisor-bot committed May 16, 2023
1 parent 83f4f48 commit 64268c8
Show file tree
Hide file tree
Showing 110 changed files with 1,400 additions and 1,122 deletions.
10 changes: 5 additions & 5 deletions pkg/sentry/socket/hostinet/netlink.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,21 +284,21 @@ func doNetlinkInterfaceRequest(typ, flags uint16, idx uint32, addr inet.Interfac
Flags: addr.Flags,
}
// Local address.
localAddr := tcpip.Address(addr.Addr)
localAddr := tcpip.AddrFromSlice(addr.Addr)
if addr.Family == linux.AF_INET {
localAddr = localAddr.To4()
}
rtLocal := linux.RtAttr{
Len: linux.SizeOfRtAttr + uint16(len(localAddr)),
Len: linux.SizeOfRtAttr + uint16(localAddr.Len()),
Type: linux.IFA_LOCAL,
}
localAddrBs := primitive.ByteSlice(localAddr)
localAddrBs := primitive.ByteSlice(localAddr.AsSlice())
// Peer is always the local address for us.
rtPeer := linux.RtAttr{
Len: linux.SizeOfRtAttr + uint16(len(localAddr)),
Len: linux.SizeOfRtAttr + uint16(localAddr.Len()),
Type: linux.IFA_ADDRESS,
}
peerAddrBs := primitive.ByteSlice(localAddr)
peerAddrBs := primitive.ByteSlice(localAddr.AsSlice())

msgs := []marshal.Marshallable{
&hdr,
Expand Down
24 changes: 12 additions & 12 deletions pkg/sentry/socket/netfilter/ipv4.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ import (
// emptyIPv4Filter is for comparison with a rule's filters to determine whether
// it is also empty. It is immutable.
var emptyIPv4Filter = stack.IPHeaderFilter{
Dst: "\x00\x00\x00\x00",
DstMask: "\x00\x00\x00\x00",
Src: "\x00\x00\x00\x00",
SrcMask: "\x00\x00\x00\x00",
Dst: tcpip.AddrFrom4([4]byte{0x00, 0x00, 0x00, 0x00}),
DstMask: tcpip.AddrFrom4([4]byte{0x00, 0x00, 0x00, 0x00}),
Src: tcpip.AddrFrom4([4]byte{0x00, 0x00, 0x00, 0x00}),
SrcMask: tcpip.AddrFrom4([4]byte{0x00, 0x00, 0x00, 0x00}),
}

// convertNetstackToBinary4 converts the iptables as stored in netstack to the
Expand Down Expand Up @@ -75,10 +75,10 @@ func getEntries4(table stack.Table, tablename linux.TableName) (linux.KernelIPTG
TargetOffset: linux.SizeOfIPTEntry,
},
}
copy(entry.Entry.IP.Dst[:], rule.Filter.Dst)
copy(entry.Entry.IP.DstMask[:], rule.Filter.DstMask)
copy(entry.Entry.IP.Src[:], rule.Filter.Src)
copy(entry.Entry.IP.SrcMask[:], rule.Filter.SrcMask)
copy(entry.Entry.IP.Dst[:], rule.Filter.Dst.AsSlice())
copy(entry.Entry.IP.DstMask[:], rule.Filter.DstMask.AsSlice())
copy(entry.Entry.IP.Src[:], rule.Filter.Src.AsSlice())
copy(entry.Entry.IP.SrcMask[:], rule.Filter.SrcMask.AsSlice())
copy(entry.Entry.IP.OutputInterface[:], rule.Filter.OutputInterface)
copy(entry.Entry.IP.OutputInterfaceMask[:], rule.Filter.OutputInterfaceMask)
copy(entry.Entry.IP.InputInterface[:], rule.Filter.InputInterface)
Expand Down Expand Up @@ -218,11 +218,11 @@ func filterFromIPTIP(iptip linux.IPTIP) (stack.IPHeaderFilter, error) {
Protocol: tcpip.TransportProtocolNumber(iptip.Protocol),
// A Protocol value of 0 indicates all protocols match.
CheckProtocol: iptip.Protocol != 0,
Dst: tcpip.Address(iptip.Dst[:]),
DstMask: tcpip.Address(iptip.DstMask[:]),
Dst: tcpip.AddrFrom4(iptip.Dst),
DstMask: tcpip.AddrFrom4(iptip.DstMask),
DstInvert: iptip.InverseFlags&linux.IPT_INV_DSTIP != 0,
Src: tcpip.Address(iptip.Src[:]),
SrcMask: tcpip.Address(iptip.SrcMask[:]),
Src: tcpip.AddrFrom4(iptip.Src),
SrcMask: tcpip.AddrFrom4(iptip.SrcMask),
SrcInvert: iptip.InverseFlags&linux.IPT_INV_SRCIP != 0,
InputInterface: string(trimNullBytes(iptip.InputInterface[:])),
InputInterfaceMask: string(trimNullBytes(iptip.InputInterfaceMask[:])),
Expand Down
24 changes: 12 additions & 12 deletions pkg/sentry/socket/netfilter/ipv6.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ import (
// emptyIPv6Filter is for comparison with a rule's filters to determine whether
// it is also empty. It is immutable.
var emptyIPv6Filter = stack.IPHeaderFilter{
Dst: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
DstMask: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
Src: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
SrcMask: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
Dst: tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
DstMask: tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
Src: tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
SrcMask: tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
}

// convertNetstackToBinary6 converts the ip6tables as stored in netstack to the
Expand Down Expand Up @@ -75,10 +75,10 @@ func getEntries6(table stack.Table, tablename linux.TableName) (linux.KernelIP6T
TargetOffset: linux.SizeOfIP6TEntry,
},
}
copy(entry.Entry.IPv6.Dst[:], rule.Filter.Dst)
copy(entry.Entry.IPv6.DstMask[:], rule.Filter.DstMask)
copy(entry.Entry.IPv6.Src[:], rule.Filter.Src)
copy(entry.Entry.IPv6.SrcMask[:], rule.Filter.SrcMask)
copy(entry.Entry.IPv6.Dst[:], rule.Filter.Dst.AsSlice())
copy(entry.Entry.IPv6.DstMask[:], rule.Filter.DstMask.AsSlice())
copy(entry.Entry.IPv6.Src[:], rule.Filter.Src.AsSlice())
copy(entry.Entry.IPv6.SrcMask[:], rule.Filter.SrcMask.AsSlice())
copy(entry.Entry.IPv6.OutputInterface[:], rule.Filter.OutputInterface)
copy(entry.Entry.IPv6.OutputInterfaceMask[:], rule.Filter.OutputInterfaceMask)
copy(entry.Entry.IPv6.InputInterface[:], rule.Filter.InputInterface)
Expand Down Expand Up @@ -221,11 +221,11 @@ func filterFromIP6TIP(iptip linux.IP6TIP) (stack.IPHeaderFilter, error) {
Protocol: tcpip.TransportProtocolNumber(iptip.Protocol),
// In ip6tables a flag controls whether to check the protocol.
CheckProtocol: iptip.Flags&linux.IP6T_F_PROTO != 0,
Dst: tcpip.Address(iptip.Dst[:]),
DstMask: tcpip.Address(iptip.DstMask[:]),
Dst: tcpip.AddrFrom16(iptip.Dst),
DstMask: tcpip.AddrFrom16(iptip.DstMask),
DstInvert: iptip.InverseFlags&linux.IP6T_INV_DSTIP != 0,
Src: tcpip.Address(iptip.Src[:]),
SrcMask: tcpip.Address(iptip.SrcMask[:]),
Src: tcpip.AddrFrom16(iptip.Src),
SrcMask: tcpip.AddrFrom16(iptip.SrcMask),
SrcInvert: iptip.InverseFlags&linux.IP6T_INV_SRCIP != 0,
InputInterface: string(trimNullBytes(iptip.InputInterface[:])),
InputInterfaceMask: string(trimNullBytes(iptip.InputInterfaceMask[:])),
Expand Down
20 changes: 10 additions & 10 deletions pkg/sentry/socket/netfilter/targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ func (*redirectTargetMaker) unmarshal(buf []byte, filter stack.IPHeaderFilter) (
return nil, syserr.ErrInvalidArgument
}

target.addr = tcpip.Address(nfRange.RangeIPV4.MinIP[:])
target.addr = tcpip.AddrFrom4(nfRange.RangeIPV4.MinIP)
target.Port = ntohs(nfRange.RangeIPV4.MinPort)

return &target, nil
Expand Down Expand Up @@ -382,8 +382,8 @@ func (*nfNATTargetMaker) marshal(target target) []byte {
},
}
copy(nt.Target.Name[:], RedirectTargetName)
copy(nt.Range.MinAddr[:], rt.addr)
copy(nt.Range.MaxAddr[:], rt.addr)
copy(nt.Range.MinAddr[:], rt.addr.AsSlice())
copy(nt.Range.MaxAddr[:], rt.addr.AsSlice())

nt.Range.MinProto = htons(rt.Port)
nt.Range.MaxProto = nt.Range.MinProto
Expand Down Expand Up @@ -426,7 +426,7 @@ func (*nfNATTargetMaker) unmarshal(buf []byte, filter stack.IPHeaderFilter) (tar
NetworkProtocol: filter.NetworkProtocol(),
Port: ntohs(natRange.MinProto),
},
addr: tcpip.Address(natRange.MinAddr[:]),
addr: tcpip.AddrFrom16(natRange.MinAddr),
}

return &target, nil
Expand Down Expand Up @@ -457,8 +457,8 @@ func (*snatTargetMakerV4) marshal(target target) []byte {
xt.NfRange.RangeIPV4.Flags |= linux.NF_NAT_RANGE_MAP_IPS | linux.NF_NAT_RANGE_PROTO_SPECIFIED
xt.NfRange.RangeIPV4.MinPort = htons(st.Port)
xt.NfRange.RangeIPV4.MaxPort = xt.NfRange.RangeIPV4.MinPort
copy(xt.NfRange.RangeIPV4.MinIP[:], st.Addr)
copy(xt.NfRange.RangeIPV4.MaxIP[:], st.Addr)
copy(xt.NfRange.RangeIPV4.MinIP[:], st.Addr.AsSlice())
copy(xt.NfRange.RangeIPV4.MaxIP[:], st.Addr.AsSlice())
return marshal.Marshal(&xt)
}

Expand Down Expand Up @@ -504,7 +504,7 @@ func (*snatTargetMakerV4) unmarshal(buf []byte, filter stack.IPHeaderFilter) (ta
return nil, syserr.ErrInvalidArgument
}

target.Addr = tcpip.Address(nfRange.RangeIPV4.MinIP[:])
target.Addr = tcpip.AddrFrom4(nfRange.RangeIPV4.MinIP)
target.Port = ntohs(nfRange.RangeIPV4.MinPort)

return &target, nil
Expand Down Expand Up @@ -533,8 +533,8 @@ func (*snatTargetMakerV6) marshal(target target) []byte {
},
}
copy(nt.Target.Name[:], SNATTargetName)
copy(nt.Range.MinAddr[:], st.Addr)
copy(nt.Range.MaxAddr[:], st.Addr)
copy(nt.Range.MinAddr[:], st.Addr.AsSlice())
copy(nt.Range.MaxAddr[:], st.Addr.AsSlice())
nt.Range.MinProto = htons(st.Port)
nt.Range.MaxProto = nt.Range.MinProto

Expand Down Expand Up @@ -574,7 +574,7 @@ func (*snatTargetMakerV6) unmarshal(buf []byte, filter stack.IPHeaderFilter) (ta
target := snatTarget{
SNATTarget: stack.SNATTarget{
NetworkProtocol: filter.NetworkProtocol(),
Addr: tcpip.Address(natRange.MinAddr[:]),
Addr: tcpip.AddrFrom16(natRange.MinAddr),
Port: ntohs(natRange.MinProto),
},
}
Expand Down
23 changes: 13 additions & 10 deletions pkg/sentry/socket/netstack/netstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,8 +666,8 @@ func (s *sock) checkFamily(family uint16, exact bool) bool {
//
// TODO(gvisor.dev/issue/1556): remove this function.
func (s *sock) mapFamily(addr tcpip.FullAddress, family uint16) tcpip.FullAddress {
if len(addr.Addr) == 0 && s.family == linux.AF_INET6 && family == linux.AF_INET {
addr.Addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00"
if addr.Addr.BitLen() == 0 && s.family == linux.AF_INET6 && family == linux.AF_INET {
addr.Addr = tcpip.AddrFrom16([16]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00})
}
return addr
}
Expand Down Expand Up @@ -748,8 +748,11 @@ func (s *sock) Bind(_ *kernel.Task, sockaddr []byte) *syserr.Error {
a.UnmarshalBytes(sockaddr)

addr = tcpip.FullAddress{
NIC: tcpip.NICID(a.InterfaceIndex),
Addr: tcpip.Address(a.HardwareAddr[:header.EthernetAddressSize]),
NIC: tcpip.NICID(a.InterfaceIndex),
Addr: tcpip.AddrFrom16Slice(append(
a.HardwareAddr[:header.EthernetAddressSize],
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}...,
)),
Port: socket.Ntohs(a.Protocol),
}
} else {
Expand Down Expand Up @@ -2181,7 +2184,7 @@ func setSockOptIPv6(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int

return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.AddMembershipOption{
NIC: tcpip.NICID(req.InterfaceIndex),
MulticastAddr: tcpip.Address(req.MulticastAddr[:]),
MulticastAddr: tcpip.AddrFrom16(req.MulticastAddr),
}))

case linux.IPV6_DROP_MEMBERSHIP:
Expand All @@ -2192,7 +2195,7 @@ func setSockOptIPv6(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int

return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.RemoveMembershipOption{
NIC: tcpip.NICID(req.InterfaceIndex),
MulticastAddr: tcpip.Address(req.MulticastAddr[:]),
MulticastAddr: tcpip.AddrFrom16(req.MulticastAddr),
}))

case linux.IPV6_IPSEC_POLICY,
Expand Down Expand Up @@ -2399,8 +2402,8 @@ func setSockOptIP(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int,
NIC: tcpip.NICID(req.InterfaceIndex),
// TODO(igudger): Change AddMembership to use the standard
// any address representation.
InterfaceAddr: tcpip.Address(req.InterfaceAddr[:]),
MulticastAddr: tcpip.Address(req.MulticastAddr[:]),
InterfaceAddr: tcpip.AddrFrom4(req.InterfaceAddr),
MulticastAddr: tcpip.AddrFrom4(req.MulticastAddr),
}))

case linux.IP_DROP_MEMBERSHIP:
Expand All @@ -2413,8 +2416,8 @@ func setSockOptIP(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int,
NIC: tcpip.NICID(req.InterfaceIndex),
// TODO(igudger): Change DropMembership to use the standard
// any address representation.
InterfaceAddr: tcpip.Address(req.InterfaceAddr[:]),
MulticastAddr: tcpip.Address(req.MulticastAddr[:]),
InterfaceAddr: tcpip.AddrFrom4(req.InterfaceAddr),
MulticastAddr: tcpip.AddrFrom4(req.MulticastAddr),
}))

case linux.IP_MULTICAST_IF:
Expand Down
20 changes: 10 additions & 10 deletions pkg/sentry/socket/netstack/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr {
addrs = append(addrs, inet.InterfaceAddr{
Family: family,
PrefixLen: uint8(a.AddressWithPrefix.PrefixLen),
Addr: []byte(a.AddressWithPrefix.Address),
Addr: a.AddressWithPrefix.Address.AsSlice(),
// TODO(b/68878065): Other fields.
})
}
Expand All @@ -145,7 +145,7 @@ func convertAddr(addr inet.InterfaceAddr) (tcpip.ProtocolAddress, error) {
return protocolAddress, linuxerr.EINVAL
}
protocol = ipv4.ProtocolNumber
address = tcpip.Address(addr.Addr)
address = tcpip.AddrFrom4Slice(addr.Addr)
case linux.AF_INET6:
if len(addr.Addr) != header.IPv6AddressSize {
return protocolAddress, linuxerr.EINVAL
Expand All @@ -154,7 +154,7 @@ func convertAddr(addr inet.InterfaceAddr) (tcpip.ProtocolAddress, error) {
return protocolAddress, linuxerr.EINVAL
}
protocol = ipv6.ProtocolNumber
address = tcpip.Address(addr.Addr)
address = tcpip.AddrFrom16Slice(addr.Addr)
default:
return protocolAddress, linuxerr.ENOTSUP
}
Expand Down Expand Up @@ -185,7 +185,7 @@ func (s *Stack) AddInterfaceAddr(idx int32, addr inet.InterfaceAddr) error {
// Add route for local network if it doesn't exist already.
localRoute := tcpip.Route{
Destination: protocolAddress.AddressWithPrefix.Subnet(),
Gateway: "", // No gateway for local network.
Gateway: tcpip.Address{}, // No gateway for local network.
NIC: nicID,
}

Expand Down Expand Up @@ -217,7 +217,7 @@ func (s *Stack) RemoveInterfaceAddr(idx int32, addr inet.InterfaceAddr) error {
// Remove the corresponding local network route if it exists.
localRoute := tcpip.Route{
Destination: protocolAddress.AddressWithPrefix.Subnet(),
Gateway: "", // No gateway for local network.
Gateway: tcpip.Address{}, // No gateway for local network.
NIC: nicID,
}
s.Stack.RemoveRoutes(func(rt tcpip.Route) bool {
Expand Down Expand Up @@ -430,10 +430,10 @@ func (s *Stack) RouteTable() []inet.Route {

for _, rt := range s.Stack.GetRouteTable() {
var family uint8
switch len(rt.Destination.ID()) {
case header.IPv4AddressSize:
switch rt.Destination.ID().BitLen() {
case header.IPv4AddressSizeBits:
family = linux.AF_INET
case header.IPv6AddressSize:
case header.IPv6AddressSizeBits:
family = linux.AF_INET6
default:
log.Warningf("Unknown network protocol in route %+v", rt)
Expand All @@ -453,9 +453,9 @@ func (s *Stack) RouteTable() []inet.Route {
Scope: linux.RT_SCOPE_LINK,
Type: linux.RTN_UNICAST,

DstAddr: []byte(rt.Destination.ID()),
DstAddr: rt.Destination.ID().AsSlice(),
OutputInterface: int32(rt.NIC),
GatewayAddr: []byte(rt.Gateway),
GatewayAddr: rt.Gateway.AsSlice(),
})
}

Expand Down

0 comments on commit 64268c8

Please sign in to comment.