-
Notifications
You must be signed in to change notification settings - Fork 158
Description
This is closely related to #103.
I was observing a similar issue: after writing about 240 rules I'd receive conn.Receive: netlink receive: recvmsg: no buffer space available
. The rules I'm writing are always created in pairs, two AddRule
calls are always followed by a Flush
. Using the NLDEBUG=level=1
to produce debug output from the netlink library I was able to observe that my application executed 490 calls to SendMessages
but only around 320 messages were received (this doesn't match with the 240 rules I see but I'll ignore that for now).
Looking at the receive logic it seems like it doesn't really care how many messages are read back:
Lines 234 to 241 in d27cc52
for _, msg := range cc.messages { | |
if msg.Header.Flags&netlink.Acknowledge == 0 { | |
continue // message did not request an acknowledgement | |
} | |
if _, err := conn.Receive(); err != nil { | |
return fmt.Errorf("conn.Receive: %w", err) | |
} | |
} |
We may, or may not, get multiple messages with that single receive call. What should be done at this stage is to ensure we read as many messages as we expect.
The amount of messages returned by each call to Receive
seems to depend on a number of variables but it looks like netlink is unable to return more than two (and often not even two) at a time. This causes messages to collect in the receive buffer as we call Receive
only once per message sent.
To confirm my theory I've implemented a fix in #236. With the fix applied I was able to write 10.000 rules continuously without any changes to my logic.