fix: ensure we receive all messages we expect

After sending a message only a single call to `conn.Receive` is made
which can cause messages to queue up in the receive buffer if not all
messages can be returned at once. This causes `ENOBUFS` as the kernel is
unable to write any further messages.

This commit introduces a check that ensures we call `conn.Receive` as
often as needed to get the right number of responses: one for
acknowledgment and one for the echo.

Resolves: #235
This commit is contained in:
Maximilian Moehl 2023-08-10 17:56:09 +02:00
parent d27cc52f15
commit 6773488cc0
1 changed files with 15 additions and 5 deletions

20
conn.go
View File

@ -230,13 +230,23 @@ func (cc *Conn) Flush() error {
return fmt.Errorf("SendMessages: %w", err)
}
// Fetch the requested acknowledgement for each message we sent.
// Fetch the requested acknowledgement and echo for each message we sent.
for _, msg := range cc.messages {
if msg.Header.Flags&netlink.Acknowledge == 0 {
continue // message did not request an acknowledgement
var expectedResponses int
if msg.Header.Flags&netlink.Acknowledge != 0 {
expectedResponses++
}
if _, err := conn.Receive(); err != nil {
return fmt.Errorf("conn.Receive: %w", err)
if msg.Header.Flags&netlink.Echo != 0 {
expectedResponses++
}
for i := 0; i < expectedResponses; {
responses, err := conn.Receive()
if err != nil {
return fmt.Errorf("conn.Receive: %w", err)
}
i += len(responses)
}
}