mirror of
https://github.com/slackhq/nebula.git
synced 2025-11-22 16:34:25 +01:00
what about with bad GRO on UDP
This commit is contained in:
23
packet/outpacket.go
Normal file
23
packet/outpacket.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package packet
|
||||
|
||||
type OutPacket struct {
|
||||
Segments [][]byte
|
||||
//todo virtio header?
|
||||
SegSize int
|
||||
SegCounter int
|
||||
Valid bool
|
||||
wasSegmented bool
|
||||
|
||||
Scratch []byte
|
||||
}
|
||||
|
||||
func NewOut() *OutPacket {
|
||||
out := new(OutPacket)
|
||||
const numSegments = 64
|
||||
out.Segments = make([][]byte, numSegments)
|
||||
for i := 0; i < numSegments; i++ { //todo this is dumb
|
||||
out.Segments[i] = make([]byte, Size)
|
||||
}
|
||||
out.Scratch = make([]byte, Size)
|
||||
return out
|
||||
}
|
||||
117
packet/packet.go
Normal file
117
packet/packet.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"iter"
|
||||
"net/netip"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const Size = 0xffff
|
||||
|
||||
type Packet struct {
|
||||
Payload []byte
|
||||
Control []byte
|
||||
Name []byte
|
||||
SegSize int
|
||||
|
||||
//todo should this hold out as well?
|
||||
OutLen int
|
||||
|
||||
wasSegmented bool
|
||||
isV4 bool
|
||||
//Addr netip.AddrPort
|
||||
}
|
||||
|
||||
func New(isV4 bool) *Packet {
|
||||
return &Packet{
|
||||
Payload: make([]byte, Size),
|
||||
Control: make([]byte, unix.CmsgSpace(2)),
|
||||
Name: make([]byte, unix.SizeofSockaddrInet6),
|
||||
isV4: isV4,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Packet) AddrPort() netip.AddrPort {
|
||||
var ip netip.Addr
|
||||
// Its ok to skip the ok check here, the slicing is the only error that can occur and it will panic
|
||||
if p.isV4 {
|
||||
ip, _ = netip.AddrFromSlice(p.Name[4:8])
|
||||
} else {
|
||||
ip, _ = netip.AddrFromSlice(p.Name[8:24])
|
||||
}
|
||||
return netip.AddrPortFrom(ip.Unmap(), binary.BigEndian.Uint16(p.Name[2:4]))
|
||||
}
|
||||
|
||||
func (p *Packet) updateCtrl(ctrlLen int) {
|
||||
p.SegSize = len(p.Payload)
|
||||
p.wasSegmented = false
|
||||
if ctrlLen == 0 {
|
||||
return
|
||||
}
|
||||
if len(p.Control) == 0 {
|
||||
return
|
||||
}
|
||||
cmsgs, err := unix.ParseSocketControlMessage(p.Control)
|
||||
if err != nil {
|
||||
return // oh well
|
||||
}
|
||||
|
||||
for _, c := range cmsgs {
|
||||
if c.Header.Level == unix.SOL_UDP && c.Header.Type == unix.UDP_GRO && len(c.Data) >= 2 {
|
||||
p.wasSegmented = true
|
||||
p.SegSize = int(binary.LittleEndian.Uint16(c.Data[:2]))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update sets a Packet into "just received, not processed" state
|
||||
func (p *Packet) Update(ctrlLen int) {
|
||||
p.OutLen = -1
|
||||
p.updateCtrl(ctrlLen)
|
||||
}
|
||||
|
||||
func (p *Packet) Segments() iter.Seq[[]byte] {
|
||||
return func(yield func([]byte) bool) {
|
||||
//cursor := 0
|
||||
for offset := 0; offset < len(p.Payload); offset += p.SegSize {
|
||||
end := offset + p.SegSize
|
||||
if end > len(p.Payload) {
|
||||
end = len(p.Payload)
|
||||
}
|
||||
if !yield(p.Payload[offset:end]) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//if p.SegSize > 0 && p.SegSize < len(p.Payload) {
|
||||
//
|
||||
//} else {
|
||||
// f.readOutsidePackets(p.Addr, nil, result2[:0], p.Payload, h, fwPacket2, lhh, nb2, i, conntrackCache.Get(f.l))
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//type Pool struct {
|
||||
// pool sync.Pool
|
||||
//}
|
||||
//
|
||||
//var bigPool = &Pool{
|
||||
// pool: sync.Pool{New: func() any { return New() }},
|
||||
//}
|
||||
//
|
||||
//func GetPool() *Pool {
|
||||
// return bigPool
|
||||
//}
|
||||
//
|
||||
//func (p *Pool) Get() *Packet {
|
||||
// return p.pool.Get().(*Packet)
|
||||
//}
|
||||
//
|
||||
//func (p *Pool) Put(x *Packet) {
|
||||
// x.Payload = x.Payload[:Size]
|
||||
// p.pool.Put(x)
|
||||
//}
|
||||
Reference in New Issue
Block a user