Improve darwin forwarding
This commit is contained in:
parent
dcfbe83ca6
commit
b0188bc3f1
4 changed files with 116 additions and 56 deletions
|
|
@ -90,6 +90,8 @@ type recvMMsgDispatcher struct {
|
|||
// fd is the file descriptor used to send and receive packets.
|
||||
fd int
|
||||
|
||||
poller *rawfile.Poller
|
||||
|
||||
// e is the endpoint this dispatcher is attached to.
|
||||
e *endpoint
|
||||
|
||||
|
|
@ -123,9 +125,15 @@ func newRecvMMsgDispatcher(fd int, e *endpoint, opts *Options) (linkDispatcher,
|
|||
} else {
|
||||
batchSize = 1
|
||||
}
|
||||
poller, err := rawfile.NewPoller(stopFD.ReadFD, fd)
|
||||
if err != nil {
|
||||
stopFD.Close()
|
||||
return nil, err
|
||||
}
|
||||
d := &recvMMsgDispatcher{
|
||||
StopFD: stopFD,
|
||||
fd: fd,
|
||||
poller: poller,
|
||||
e: e,
|
||||
bufs: make([]*iovecBuffer, batchSize),
|
||||
msgHdrs: make([]rawfile.MsgHdrX, batchSize),
|
||||
|
|
@ -144,6 +152,7 @@ func (d *recvMMsgDispatcher) release() {
|
|||
for _, iov := range d.bufs {
|
||||
iov.release()
|
||||
}
|
||||
_ = d.poller.Close()
|
||||
d.mgr.close()
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +170,7 @@ func (d *recvMMsgDispatcher) dispatch() (bool, tcpip.Error) {
|
|||
d.msgHdrs[k].Msg.SetIovlen(iovLen)
|
||||
}
|
||||
|
||||
nMsgs, errno := rawfile.BlockingRecvMMsgUntilStopped(d.ReadFD, d.fd, d.msgHdrs)
|
||||
nMsgs, errno := rawfile.BlockingRecvMMsgUntilStopped(d.poller, d.fd, d.msgHdrs)
|
||||
if errno != 0 {
|
||||
return false, TranslateErrno(errno)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func NonBlockingWriteIovec(fd int, iovec []unix.Iovec) unix.Errno {
|
|||
return e
|
||||
}
|
||||
|
||||
func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix.Errno) {
|
||||
func BlockingReadvUntilStopped(poller *Poller, fd int, iovecs []unix.Iovec) (int, unix.Errno) {
|
||||
for {
|
||||
//nolint:staticcheck
|
||||
n, _, e := unix.RawSyscall(unix.SYS_READV, uintptr(fd), uintptr(unsafe.Pointer(&iovecs[0])), uintptr(len(iovecs)))
|
||||
|
|
@ -79,7 +79,7 @@ func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix.
|
|||
if e != 0 && e != unix.EWOULDBLOCK {
|
||||
return 0, e
|
||||
}
|
||||
stopped, e := BlockingPollUntilStopped(efd, fd, unix.POLLIN)
|
||||
stopped, e := poller.Wait()
|
||||
if stopped {
|
||||
return -1, e
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix.
|
|||
}
|
||||
}
|
||||
|
||||
func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MsgHdrX) (int, unix.Errno) {
|
||||
func BlockingRecvMMsgUntilStopped(poller *Poller, fd int, msgHdrs []MsgHdrX) (int, unix.Errno) {
|
||||
for {
|
||||
//nolint:staticcheck
|
||||
n, _, e := unix.RawSyscall6(unix.SYS_RECVMSG_X, uintptr(fd), uintptr(unsafe.Pointer(&msgHdrs[0])), uintptr(len(msgHdrs)), unix.MSG_DONTWAIT, 0, 0)
|
||||
|
|
@ -101,7 +101,7 @@ func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MsgHdrX) (int, unix
|
|||
return 0, e
|
||||
}
|
||||
|
||||
stopped, e := BlockingPollUntilStopped(efd, fd, unix.POLLIN)
|
||||
stopped, e := poller.Wait()
|
||||
if stopped {
|
||||
return -1, e
|
||||
}
|
||||
|
|
@ -111,71 +111,58 @@ func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MsgHdrX) (int, unix
|
|||
}
|
||||
}
|
||||
|
||||
func BlockingPollUntilStopped(efd int, fd int, events int16) (bool, unix.Errno) {
|
||||
// Create kqueue
|
||||
type Poller struct {
|
||||
kq int
|
||||
efd int
|
||||
fd int
|
||||
}
|
||||
|
||||
func NewPoller(efd int, fd int) (*Poller, error) {
|
||||
kq, err := unix.Kqueue()
|
||||
if err != nil {
|
||||
return false, unix.Errno(err.(unix.Errno))
|
||||
return nil, err
|
||||
}
|
||||
defer unix.Close(kq)
|
||||
|
||||
// Prepare kevents for registration
|
||||
var kevents []unix.Kevent_t
|
||||
|
||||
// Always monitor efd for read events
|
||||
kevents = append(kevents, unix.Kevent_t{
|
||||
Ident: uint64(efd),
|
||||
Filter: unix.EVFILT_READ,
|
||||
Flags: unix.EV_ADD | unix.EV_ENABLE,
|
||||
})
|
||||
|
||||
// Monitor fd based on requested events
|
||||
// Convert poll events to kqueue filters
|
||||
if events&unix.POLLIN != 0 {
|
||||
kevents = append(kevents, unix.Kevent_t{
|
||||
kevents := []unix.Kevent_t{
|
||||
{
|
||||
Ident: uint64(efd),
|
||||
Filter: unix.EVFILT_READ,
|
||||
Flags: unix.EV_ADD | unix.EV_ENABLE,
|
||||
},
|
||||
{
|
||||
Ident: uint64(fd),
|
||||
Filter: unix.EVFILT_READ,
|
||||
Flags: unix.EV_ADD | unix.EV_ENABLE,
|
||||
})
|
||||
},
|
||||
}
|
||||
if events&unix.POLLOUT != 0 {
|
||||
kevents = append(kevents, unix.Kevent_t{
|
||||
Ident: uint64(fd),
|
||||
Filter: unix.EVFILT_WRITE,
|
||||
Flags: unix.EV_ADD | unix.EV_ENABLE,
|
||||
})
|
||||
}
|
||||
|
||||
// Register events
|
||||
_, err = unix.Kevent(kq, kevents, nil, nil)
|
||||
if err != nil {
|
||||
return false, unix.Errno(err.(unix.Errno))
|
||||
unix.Close(kq)
|
||||
return nil, err
|
||||
}
|
||||
return &Poller{kq: kq, efd: efd, fd: fd}, nil
|
||||
}
|
||||
|
||||
// Wait for events (blocking)
|
||||
revents := make([]unix.Kevent_t, len(kevents))
|
||||
n, err := unix.Kevent(kq, nil, revents, nil)
|
||||
func (p *Poller) Wait() (bool, unix.Errno) {
|
||||
var revents [2]unix.Kevent_t
|
||||
n, err := unix.Kevent(p.kq, nil, revents[:], nil)
|
||||
if err != nil {
|
||||
return false, unix.Errno(err.(unix.Errno))
|
||||
return false, err.(unix.Errno)
|
||||
}
|
||||
|
||||
// Check results
|
||||
var efdHasData bool
|
||||
var errno unix.Errno
|
||||
|
||||
for i := range n {
|
||||
ev := &revents[i]
|
||||
|
||||
if int(ev.Ident) == efd && ev.Filter == unix.EVFILT_READ {
|
||||
if int(ev.Ident) == p.efd && ev.Filter == unix.EVFILT_READ {
|
||||
efdHasData = true
|
||||
}
|
||||
|
||||
if int(ev.Ident) == fd {
|
||||
// Check for errors or EOF
|
||||
if int(ev.Ident) == p.fd {
|
||||
if ev.Flags&unix.EV_EOF != 0 {
|
||||
errno = unix.ECONNRESET
|
||||
} else if ev.Flags&unix.EV_ERROR != 0 {
|
||||
// Extract error from Data field
|
||||
if ev.Data != 0 {
|
||||
errno = unix.Errno(ev.Data)
|
||||
} else {
|
||||
|
|
@ -187,3 +174,7 @@ func BlockingPollUntilStopped(efd int, fd int, events int16) (bool, unix.Errno)
|
|||
|
||||
return efdHasData, errno
|
||||
}
|
||||
|
||||
func (p *Poller) Close() error {
|
||||
return unix.Close(p.kq)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue