diff --git a/conn/bind_std.go b/conn/bind_std.go index 2ecbd11..c437da3 100644 --- a/conn/bind_std.go +++ b/conn/bind_std.go @@ -408,6 +408,13 @@ func (e ErrUDPGSODisabled) Unwrap() error { } func (s *StdNetBind) Send(bufs [][]byte, endpoint Endpoint, offset int) error { + for len(bufs) > IdealBatchSize { + err := s.Send(bufs[:IdealBatchSize], endpoint, offset) + if err != nil { + return err + } + bufs = bufs[IdealBatchSize:] + } s.mu.Lock() blackhole := s.blackhole4 conn := s.ipv4 diff --git a/device/send.go b/device/send.go index bf4b85c..add170b 100644 --- a/device/send.go +++ b/device/send.go @@ -374,7 +374,7 @@ type InputPacketRef struct { func (device *Device) InputPackets(packets []*InputPacketRef) []*InputPacketRef { var unmatched []*InputPacketRef - elemsByPeer := make(map[*Peer]*QueueOutboundElementsContainer, len(packets)) + elemsByPeer := make(map[*Peer][]*QueueOutboundElementsContainer, len(packets)) for _, packetRef := range packets { peer := device.allowedips.Lookup(packetRef.Destination) if peer == nil { @@ -401,23 +401,28 @@ func (device *Device) InputPackets(packets []*InputPacketRef) []*InputPacketRef n += copy(packet[n:], packetSlice) } elem.packet = packet[:n] - elemsForPeer, ok := elemsByPeer[peer] - if !ok { - elemsForPeer = device.GetOutboundElementsContainer() - elemsByPeer[peer] = elemsForPeer + containers := elemsByPeer[peer] + if len(containers) == 0 || len(containers[len(containers)-1].elems) >= conn.IdealBatchSize { + containers = append(containers, device.GetOutboundElementsContainer()) + elemsByPeer[peer] = containers } + elemsForPeer := containers[len(containers)-1] elemsForPeer.elems = append(elemsForPeer.elems, elem) } - for peer, elemsForPeer := range elemsByPeer { + for peer, containers := range elemsByPeer { if peer.isRunning.Load() { - peer.StagePackets(elemsForPeer) + for _, elemsForPeer := range containers { + peer.StagePackets(elemsForPeer) + } peer.SendStagedPackets() } else { - for _, elem := range elemsForPeer.elems { - device.PutOutboundBuffer(elem.buffer) - device.PutOutboundElement(elem) + for _, elemsForPeer := range containers { + for _, elem := range elemsForPeer.elems { + device.PutOutboundBuffer(elem.buffer) + device.PutOutboundElement(elem) + } + device.PutOutboundElementsContainer(elemsForPeer) } - device.PutOutboundElementsContainer(elemsForPeer) } } return unmatched