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
This commit is contained in:
parent
cd698095c7
commit
90ef31873c
|
@ -108,6 +108,8 @@ void AF__PACKET__PT_PROVIDER::set_parameter(const char *parameter_name, const ch
|
|||
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::user_stop()
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
|
||||
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 */
|
||||
|
|
Loading…
Reference in New Issue