reduce allocations of OOB data
This commit is contained in:
parent
cd9725276c
commit
e61557048b
65
main.go
65
main.go
|
@ -31,27 +31,36 @@ func (vx *vx46) transform46(msgs4 []ipv4.Message, msgs6 []ipv6.Message) error {
|
||||||
// embed the "client" ipv4 into the src address for the packet to the upstream vxlan ipv6 endpoint
|
// embed the "client" ipv4 into the src address for the packet to the upstream vxlan ipv6 endpoint
|
||||||
// the destination is the upstream vxlan endpoint
|
// the destination is the upstream vxlan endpoint
|
||||||
for i := range msgs4 {
|
for i := range msgs4 {
|
||||||
cm4 := ipv4.ControlMessage{}
|
if len(msgs6[i].OOB) < OOB_SIZE {
|
||||||
if err := cm4.Parse(msgs4[i].OOB[:msgs4[i].NN]); err != nil {
|
msgs6[i].OOB = make([]byte, OOB_SIZE)
|
||||||
return err
|
msgs6[i].NN = OOB_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hdr syscall.Cmsghdr
|
||||||
|
hdr.SetLen(syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
|
||||||
|
hdr.Level = syscall.IPPROTO_IPV6
|
||||||
|
hdr.Type = syscall.IPV6_PKTINFO
|
||||||
|
|
||||||
|
oobdata := msgs6[i].OOB[:0]
|
||||||
|
|
||||||
|
// set cmsg header
|
||||||
|
oobdata = binary.NativeEndian.AppendUint64(oobdata, hdr.Len)
|
||||||
|
oobdata = binary.NativeEndian.AppendUint32(oobdata, uint32(hdr.Level))
|
||||||
|
oobdata = binary.NativeEndian.AppendUint32(oobdata, uint32(hdr.Type))
|
||||||
|
|
||||||
|
// set the address
|
||||||
|
// prefix + embeded v4 + port
|
||||||
|
oobdata = append(oobdata, vx.natprefix[:10]...)
|
||||||
inUDPAddr4 := msgs4[i].Addr.(*net.UDPAddr)
|
inUDPAddr4 := msgs4[i].Addr.(*net.UDPAddr)
|
||||||
egressSrcAddr := vx.natprefix.As16()
|
oobdata = append(oobdata, inUDPAddr4.IP.To4()[:4]...)
|
||||||
copy(egressSrcAddr[10:14], inUDPAddr4.IP.To4()[:4]) // panics if To4 returns nil
|
oobdata = binary.BigEndian.AppendUint16(oobdata, uint16(inUDPAddr4.Port))
|
||||||
binary.BigEndian.PutUint16(egressSrcAddr[14:16], uint16(inUDPAddr4.Port))
|
|
||||||
|
|
||||||
if vx.oobkey != egressSrcAddr {
|
// let the kernel decide which interface to use
|
||||||
vx.oobkey = egressSrcAddr
|
oobdata = binary.NativeEndian.AppendUint32(oobdata, 0) // iface
|
||||||
cm6 := ipv6.ControlMessage{Src: net.IP(egressSrcAddr[:])}
|
|
||||||
vx.oobcache = cm6.Marshal()
|
|
||||||
}
|
|
||||||
|
|
||||||
msgs6[i].Buffers[0] = msgs4[i].Buffers[0][:msgs4[i].N]
|
msgs6[i].Buffers[0] = msgs4[i].Buffers[0][:msgs4[i].N]
|
||||||
msgs6[i].OOB = vx.oobcache
|
|
||||||
msgs6[i].Addr = vx.upstream
|
msgs6[i].Addr = vx.upstream
|
||||||
msgs6[i].N = msgs4[i].N
|
msgs6[i].N = msgs4[i].N
|
||||||
msgs6[i].NN = len(msgs6[i].OOB)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -93,21 +102,30 @@ func (vx *vx46) transform64(msgs6 []ipv6.Message, msgs4 []ipv4.Message) error {
|
||||||
// embed the "client" ipv4 into the src address for the packet to the upstream vxlan ipv6 endpoint
|
// embed the "client" ipv4 into the src address for the packet to the upstream vxlan ipv6 endpoint
|
||||||
// the destination is the upstream vxlan endpoint
|
// the destination is the upstream vxlan endpoint
|
||||||
for i := range msgs6 {
|
for i := range msgs6 {
|
||||||
cm6 := ipv6.ControlMessage{}
|
var hdr syscall.Cmsghdr
|
||||||
if err := cm6.Parse(msgs6[i].OOB[:msgs6[i].NN]); err != nil {
|
hdr.Len = binary.NativeEndian.Uint64(msgs6[i].OOB[0:])
|
||||||
return err
|
hdr.Level = int32(binary.NativeEndian.Uint32(msgs6[i].OOB[8:]))
|
||||||
|
hdr.Type = int32(binary.NativeEndian.Uint32(msgs6[i].OOB[12:]))
|
||||||
|
|
||||||
|
if hdr.Len != uint64(syscall.CmsgLen(syscall.SizeofInet6Pktinfo)) {
|
||||||
|
log.Fatal("OOB: unexpected Len: ", hdr.Len, syscall.CmsgLen(syscall.SizeofInet6Pktinfo))
|
||||||
}
|
}
|
||||||
if cm6.Dst.To16() == nil {
|
if hdr.Level != syscall.IPPROTO_IPV6 {
|
||||||
return fmt.Errorf("Destination information not available")
|
log.Fatal("OOB: unexpected Level", hdr.Level)
|
||||||
}
|
}
|
||||||
|
if hdr.Type != syscall.IPV6_PKTINFO {
|
||||||
|
log.Fatal("OOB: unexpected Type", hdr.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
dstaddr6 := msgs6[i].OOB[16:32]
|
||||||
|
|
||||||
msgs4[i].Buffers[0] = msgs6[i].Buffers[0][:msgs6[i].N]
|
msgs4[i].Buffers[0] = msgs6[i].Buffers[0][:msgs6[i].N]
|
||||||
if msgs4[i].Addr == nil {
|
if msgs4[i].Addr == nil {
|
||||||
msgs4[i].Addr = &net.UDPAddr{}
|
msgs4[i].Addr = &net.UDPAddr{}
|
||||||
}
|
}
|
||||||
addr := msgs4[i].Addr.(*net.UDPAddr)
|
addr := msgs4[i].Addr.(*net.UDPAddr)
|
||||||
addr.IP = cm6.Dst[10:14]
|
addr.IP = dstaddr6[10:14]
|
||||||
addr.Port = int(binary.BigEndian.Uint16(cm6.Dst[14:16]))
|
addr.Port = int(binary.BigEndian.Uint16(dstaddr6[14:16]))
|
||||||
msgs4[i].N = msgs6[i].N
|
msgs4[i].N = msgs6[i].N
|
||||||
msgs4[i].OOB = nil
|
msgs4[i].OOB = nil
|
||||||
msgs4[i].NN = 0
|
msgs4[i].NN = 0
|
||||||
|
@ -190,15 +208,12 @@ func (vx *vx46) forward() error {
|
||||||
type vx46 struct {
|
type vx46 struct {
|
||||||
pc4 *ipv4.PacketConn
|
pc4 *ipv4.PacketConn
|
||||||
pc6 *ipv6.PacketConn
|
pc6 *ipv6.PacketConn
|
||||||
natprefix netip.Addr
|
natprefix [16]byte
|
||||||
upstreamAddr netip.Addr
|
upstreamAddr netip.Addr
|
||||||
upstream *net.UDPAddr
|
upstream *net.UDPAddr
|
||||||
port uint16
|
port uint16
|
||||||
mtu uint16
|
mtu uint16
|
||||||
buffers int
|
buffers int
|
||||||
|
|
||||||
oobkey [16]byte
|
|
||||||
oobcache []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func vx46forward(natprefix netip.Addr, upstreamAddr netip.Addr, port uint16, mtu uint16) error {
|
func vx46forward(natprefix netip.Addr, upstreamAddr netip.Addr, port uint16, mtu uint16) error {
|
||||||
|
@ -309,7 +324,7 @@ func main() {
|
||||||
log.Println(vx46forward(natprefix, upstreamAddr, port, mtu))
|
log.Println(vx46forward(natprefix, upstreamAddr, port, mtu))
|
||||||
} else {
|
} else {
|
||||||
vx := vx46{
|
vx := vx46{
|
||||||
natprefix: natprefix,
|
natprefix: natprefix.As16(),
|
||||||
upstream: &net.UDPAddr{
|
upstream: &net.UDPAddr{
|
||||||
IP: net.IP(upstreamAddr.AsSlice()),
|
IP: net.IP(upstreamAddr.AsSlice()),
|
||||||
Port: *portInt,
|
Port: *portInt,
|
||||||
|
|
Loading…
Reference in New Issue