laforge has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/titan.TestPorts.AF_PACKET/+/22539 )


Change subject: add module parameter "sleep_on_enobufs" to work around -ENOBUFS
......................................................................

add module parameter "sleep_on_enobufs" to work around -ENOBUFS

AF_PACKET sockets have these incredibly useful semantics in where
for both non-blocking and blocking I/O, they will tell you the
socket is rwite-able, but then still return -1 and sett errno=ENOBUFS
if the current socket buffer / transmit queue is full.

All we can do is usleep and retry.  The new module parameter, if set
to non-zero, determines the number of microseconds we shall sleep before
any retry.  If set to zero, the existing behavior is preserved:
TTCN_error().

Related: SYS#5343
Change-Id: I1608403d94a10ae52c7e1de0f1b02687b048c01e
---
M src/AF_PACKET_PT.cc
M src/AF_PACKET_PT.hh
2 files changed, 17 insertions(+), 5 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/titan.TestPorts.AF_PACKET 
refs/changes/39/22539/1

diff --git a/src/AF_PACKET_PT.cc b/src/AF_PACKET_PT.cc
index aa2def6..935f47c 100644
--- a/src/AF_PACKET_PT.cc
+++ b/src/AF_PACKET_PT.cc
@@ -108,6 +108,8 @@
                        mNetdev_name = NULL;
                }
                mNetdev_name = strdup(parameter_value);
+       } else if (!strcmp(parameter_name, "sleep_on_enobufs")) {
+               mSleepUsOnEnobufs = atoi(parameter_value);
        } else
                TTCN_error("Unsupported test port parameter `%s'.", 
parameter_name);
 }
@@ -204,13 +206,22 @@

 void AF__PACKET__PT_PROVIDER::outgoing_send(const AF__PACKET__Unitdata& 
send_par)
 {
-       int rc;
-
        assert(mSocket >= 0);

-       rc = write(mSocket, send_par.data(), send_par.data().lengthof());
-       if (rc < send_par.data().lengthof())
-               TTCN_error("Short write on AF_PACKET socket: %s", 
strerror(errno));
+       while (true) {
+               int rc = write(mSocket, send_par.data(), 
send_par.data().lengthof());
+               if (rc == send_par.data().lengthof())
+                       break;
+               if (mSleepUsOnEnobufs && rc == -1 && errno == -ENOBUFS) {
+                       /* This is fscking insane.  Even select() would tell us 
the FD
+                        * is write-able, but then we still get -ENOBUFS.  The 
only way
+                        * to do this os to sleep. */
+                       usleep(mSleepUsOnEnobufs);
+               } else if (rc < send_par.data().lengthof()) {
+                       TTCN_error("Short write on AF_PACKET socket: %s", 
strerror(errno));
+                       break;
+               }
+       }
 }


diff --git a/src/AF_PACKET_PT.hh b/src/AF_PACKET_PT.hh
index 7f8f6b5..ab3e8c6 100644
--- a/src/AF_PACKET_PT.hh
+++ b/src/AF_PACKET_PT.hh
@@ -50,6 +50,7 @@

 private:
        char *mNetdev_name;             /* name of the network interface */
+       bool mSleepUsOnEnobufs;         /* how many us to sleep on ENOBUFS */
        int mIfindex;                   /* interface index of the network 
device */
        int mSocket;                    /* socket/file descriptor of the 
AF_PACKET socket */
        uint8_t mRxBuf[2048];           /* read buffer */

--
To view, visit https://gerrit.osmocom.org/c/titan.TestPorts.AF_PACKET/+/22539
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: titan.TestPorts.AF_PACKET
Gerrit-Branch: master
Gerrit-Change-Id: I1608403d94a10ae52c7e1de0f1b02687b048c01e
Gerrit-Change-Number: 22539
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <lafo...@osmocom.org>
Gerrit-MessageType: newchange

Reply via email to