Skip to content

Commit b58c4ad

Browse files
committed
lldpad eloop select change to poll
In an environment with 576 virtual NICs, when the function eloop_sock_table_dispatch calls FD_ISSET, the value of file descriptor table->table[i].sock exceeds 1024 (the kernel fds structure has only 1024 bits). As a result, the glibc determines that a buffer overflow occurs and aborts the process. To solve this problem, we change select to poll because poll has no restriction on the fd size. Poll allows file descriptors to listen to different events, such as POLLIN and POLLOUT. Therefore, no need to create different queues for different events, we delete writers and exceptions and rename readers to sock_table.
1 parent 3689d5a commit b58c4ad

File tree

4 files changed

+57
-114
lines changed

4 files changed

+57
-114
lines changed

ctrl_iface.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ void ctrl_iface_deinit(struct clif_data *clifd)
505505
struct ctrl_dst *dst, *prev;
506506

507507
if (clifd->ctrl_sock > -1) {
508-
eloop_unregister_read_sock(clifd->ctrl_sock);
508+
eloop_unregister_sock(clifd->ctrl_sock);
509509
close(clifd->ctrl_sock);
510510
clifd->ctrl_sock = -1;
511511
}

eloop.c

Lines changed: 48 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,8 @@ int os_get_time(struct os_time *t)
6767
} \
6868
} while (0)
6969

70-
7170
struct eloop_sock {
72-
int sock;
71+
struct pollfd pfd;
7372
void *eloop_data;
7473
void *user_data;
7574
eloop_sock_handler handler;
@@ -99,11 +98,7 @@ struct eloop_sock_table {
9998
struct eloop_data {
10099
void *user_data;
101100

102-
int max_sock;
103-
104-
struct eloop_sock_table readers;
105-
struct eloop_sock_table writers;
106-
struct eloop_sock_table exceptions;
101+
struct eloop_sock_table sock_table;
107102

108103
struct eloop_timeout *timeout;
109104

@@ -128,7 +123,7 @@ int eloop_init(void *user_data)
128123

129124

130125
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
131-
int sock, eloop_sock_handler handler,
126+
struct pollfd pfd, eloop_sock_handler handler,
132127
void *eloop_data, void *user_data)
133128
{
134129
struct eloop_sock *tmp;
@@ -142,14 +137,12 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
142137
if (tmp == NULL)
143138
return -ENOMEM;
144139

145-
tmp[table->count].sock = sock;
140+
tmp[table->count].pfd = pfd;
146141
tmp[table->count].eloop_data = eloop_data;
147142
tmp[table->count].user_data = user_data;
148143
tmp[table->count].handler = handler;
149144
table->count++;
150145
table->table = tmp;
151-
if (sock > eloop.max_sock)
152-
eloop.max_sock = sock;
153146
table->changed = 1;
154147

155148
return 0;
@@ -165,7 +158,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
165158
return;
166159

167160
for (i = 0; i < table->count; i++) {
168-
if (table->table[i].sock == sock)
161+
if (table->table[i].pfd.fd == sock)
169162
break;
170163
}
171164
if (i == table->count)
@@ -181,22 +174,19 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
181174

182175

183176
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
184-
fd_set *fds)
177+
struct pollfd *fds)
185178
{
186179
int i;
187-
188-
FD_ZERO(fds);
189-
190180
if (table->table == NULL)
191181
return;
192182

193183
for (i = 0; i < table->count; i++)
194-
FD_SET(table->table[i].sock, fds);
184+
fds[i] = table->table[i].pfd;
195185
}
196186

197187

198188
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
199-
fd_set *fds)
189+
struct pollfd *fds, int events)
200190
{
201191
int i;
202192

@@ -205,8 +195,8 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
205195

206196
table->changed = 0;
207197
for (i = 0; i < table->count; i++) {
208-
if (FD_ISSET(table->table[i].sock, fds)) {
209-
table->table[i].handler(table->table[i].sock,
198+
if (fds[i].revents & events) {
199+
table->table[i].handler(table->table[i].pfd.fd,
210200
table->table[i].eloop_data,
211201
table->table[i].user_data);
212202
if (table->changed)
@@ -219,11 +209,10 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
219209
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
220210
{
221211
int rc, tc, sock;
222-
223-
if (table) {
212+
if (table->table) {
224213
tc = table->count;
225214
while (tc > 0) {
226-
sock = table->table[tc].sock;
215+
sock = table->table[tc].pfd.fd;
227216
rc = fcntl(sock, F_GETFD);
228217
if (rc != -1) {
229218
rc = close(sock);
@@ -241,53 +230,26 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
241230
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
242231
void *eloop_data, void *user_data)
243232
{
244-
return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
245-
eloop_data, user_data);
233+
struct pollfd pfd = {0};
234+
pfd.fd = sock;
235+
pfd.events = POLLIN;
236+
return eloop_register_sock(pfd, handler, eloop_data, user_data);
246237
}
247238

248-
249-
void eloop_unregister_read_sock(int sock)
239+
int eloop_register_sock(struct pollfd pfd,
240+
eloop_sock_handler handler,
241+
void *eloop_data, void *user_data)
250242
{
251-
eloop_unregister_sock(sock, EVENT_TYPE_READ);
252-
}
253-
254-
255-
static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
256-
{
257-
switch (type) {
258-
case EVENT_TYPE_READ:
259-
return &eloop.readers;
260-
case EVENT_TYPE_WRITE:
261-
return &eloop.writers;
262-
case EVENT_TYPE_EXCEPTION:
263-
return &eloop.exceptions;
264-
}
265-
266-
return NULL;
267-
}
268-
269-
270-
int eloop_register_sock(int sock, eloop_event_type type,
271-
eloop_sock_handler handler,
272-
void *eloop_data, void *user_data)
273-
{
274-
struct eloop_sock_table *table;
275-
276-
table = eloop_get_sock_table(type);
277-
return eloop_sock_table_add_sock(table, sock, handler,
243+
return eloop_sock_table_add_sock(&eloop.sock_table, pfd, handler,
278244
eloop_data, user_data);
279245
}
280246

281247

282-
void eloop_unregister_sock(int sock, eloop_event_type type)
248+
void eloop_unregister_sock(int sock)
283249
{
284-
struct eloop_sock_table *table;
285-
286-
table = eloop_get_sock_table(type);
287-
eloop_sock_table_remove_sock(table, sock);
250+
eloop_sock_table_remove_sock(&eloop.sock_table, sock);
288251
}
289252

290-
291253
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
292254
eloop_timeout_handler handler,
293255
void *eloop_data, void *user_data)
@@ -465,42 +427,39 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
465427
return eloop_register_signal(SIGHUP, handler, user_data);
466428
}
467429

430+
static inline int os_time_to_ms(struct os_time *tv)
431+
{
432+
return ((tv)->sec * 1000 + (tv)->usec / 1000);
433+
}
468434

469435
void eloop_run(void)
470436
{
471-
fd_set *rfds, *wfds, *efds;
472-
int res;
473-
struct timeval _tv;
437+
int res, timeout = 0;
474438
struct os_time tv, now;
475-
476-
rfds = malloc(sizeof(*rfds));
477-
wfds = malloc(sizeof(*wfds));
478-
efds = malloc(sizeof(*efds));
479-
if (rfds == NULL || wfds == NULL || efds == NULL) {
480-
printf("eloop_run - malloc failed\n");
481-
goto out;
482-
}
439+
struct pollfd *fds = NULL;
483440

484441
while (!eloop.terminate &&
485-
(eloop.timeout || eloop.readers.count > 0 ||
486-
eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
442+
(eloop.timeout || eloop.sock_table.count > 0)) {
487443
if (eloop.timeout) {
488444
os_get_time(&now);
489445
if (os_time_before(&now, &eloop.timeout->time))
490446
os_time_sub(&eloop.timeout->time, &now, &tv);
491447
else
492448
tv.sec = tv.usec = 0;
493-
_tv.tv_sec = tv.sec;
494-
_tv.tv_usec = tv.usec;
449+
timeout = os_time_to_ms(&tv);
495450
}
496451

497-
eloop_sock_table_set_fds(&eloop.readers, rfds);
498-
eloop_sock_table_set_fds(&eloop.writers, wfds);
499-
eloop_sock_table_set_fds(&eloop.exceptions, efds);
500-
res = select(eloop.max_sock + 1, rfds, wfds, efds,
501-
eloop.timeout ? &_tv : NULL);
452+
fds = (struct pollfd *)
453+
realloc(fds, eloop.sock_table.count * sizeof(struct eloop_sock));
454+
if (fds == NULL) {
455+
perror("eloop_run realloc");
456+
goto out;
457+
}
458+
459+
eloop_sock_table_set_fds(&eloop.sock_table, fds);
460+
res = poll(fds, eloop.sock_table.count, eloop.timeout ? timeout : -1);
502461
if (res < 0 && errno != EINTR && errno != 0) {
503-
perror("select");
462+
perror("poll");
504463
goto out;
505464
}
506465
eloop_process_pending_signals();
@@ -522,16 +481,11 @@ void eloop_run(void)
522481

523482
if (res <= 0)
524483
continue;
525-
526-
eloop_sock_table_dispatch(&eloop.readers, rfds);
527-
eloop_sock_table_dispatch(&eloop.writers, wfds);
528-
eloop_sock_table_dispatch(&eloop.exceptions, efds);
484+
eloop_sock_table_dispatch(&eloop.sock_table, fds, POLLIN);
529485
}
530-
531486
out:
532-
free(rfds);
533-
free(wfds);
534-
free(efds);
487+
if (fds)
488+
free(fds);
535489
}
536490

537491

@@ -551,9 +505,7 @@ void eloop_destroy(void)
551505
timeout = timeout->next;
552506
free(prev);
553507
}
554-
eloop_sock_table_destroy(&eloop.readers);
555-
eloop_sock_table_destroy(&eloop.writers);
556-
eloop_sock_table_destroy(&eloop.exceptions);
508+
eloop_sock_table_destroy(&eloop.sock_table);
557509
free(eloop.signals);
558510
}
559511

@@ -566,14 +518,14 @@ int eloop_terminated(void)
566518

567519
void eloop_wait_for_read_sock(int sock)
568520
{
569-
fd_set rfds;
521+
struct pollfd pfd;
570522

571523
if (sock < 0)
572524
return;
573525

574-
FD_ZERO(&rfds);
575-
FD_SET(sock, &rfds);
576-
select(sock + 1, &rfds, NULL, NULL, NULL);
526+
pfd.fd = sock;
527+
pfd.events = POLLIN;
528+
poll(&pfd, 1, -1);
577529
}
578530

579531

include/eloop.h

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
#ifndef ELOOP_H
2424
#define ELOOP_H
2525

26+
#include <poll.h>
27+
2628
/**
2729
* ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts
2830
*/
2931
#define ELOOP_ALL_CTX (void *) -1
30-
32+
3133
/**
3234
* eloop_event_type - eloop socket event type for eloop_register_sock()
3335
* @EVENT_TYPE_READ: Socket has data available for reading
@@ -100,21 +102,11 @@ int eloop_init(void *user_data);
100102
* for the same event.
101103
*/
102104
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
103-
void *eloop_data, void *user_data);
104-
105-
/**
106-
* eloop_unregister_read_sock - Unregister handler for read events
107-
* @sock: File descriptor number for the socket
108-
*
109-
* Unregister a read socket notifier that was previously registered with
110-
* eloop_register_read_sock().
111-
*/
112-
void eloop_unregister_read_sock(int sock);
105+
void *eloop_data, void *user_data);
113106

114107
/**
115108
* eloop_register_sock - Register handler for socket events
116-
* @sock: File descriptor number for the socket
117-
* @type: Type of event to wait for
109+
* @pfd: Pollfd for the socket
118110
* @handler: Callback function to be called when the event is triggered
119111
* @eloop_data: Callback context data (eloop_ctx)
120112
* @user_data: Callback context data (sock_ctx)
@@ -126,19 +118,18 @@ void eloop_unregister_read_sock(int sock);
126118
* having processed it in order to avoid eloop from calling the handler again
127119
* for the same event.
128120
*/
129-
int eloop_register_sock(int sock, eloop_event_type type,
121+
int eloop_register_sock(struct pollfd pfd,
130122
eloop_sock_handler handler,
131123
void *eloop_data, void *user_data);
132124

133125
/**
134126
* eloop_unregister_sock - Unregister handler for socket events
135127
* @sock: File descriptor number for the socket
136-
* @type: Type of event for which sock was registered
137128
*
138129
* Unregister a socket event notifier that was previously registered with
139130
* eloop_register_sock().
140131
*/
141-
void eloop_unregister_sock(int sock, eloop_event_type type);
132+
void eloop_unregister_sock(int sock);
142133

143134
/**
144135
* eloop_register_event - Register handler for generic events

lldp/l2_packet_linux.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ void l2_packet_deinit(struct l2_packet_data *l2)
278278
return;
279279

280280
if (l2->fd >= 0) {
281-
eloop_unregister_read_sock(l2->fd);
281+
eloop_unregister_sock(l2->fd);
282282
close(l2->fd);
283283
}
284284

0 commit comments

Comments
 (0)