Skip to content

Commit 636966c

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 636966c

File tree

4 files changed

+68
-139
lines changed

4 files changed

+68
-139
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: 55 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ int os_get_time(struct os_time *t)
6767
} \
6868
} while (0)
6969

70+
#define os_time_to_ms(a) \
71+
((a)->sec * 1000 + (a)->usec / 1000)
7072

7173
struct eloop_sock {
72-
int sock;
74+
struct pollfd sock;
7375
void *eloop_data;
7476
void *user_data;
7577
eloop_sock_handler handler;
@@ -99,11 +101,7 @@ struct eloop_sock_table {
99101
struct eloop_data {
100102
void *user_data;
101103

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

108106
struct eloop_timeout *timeout;
109107

@@ -128,7 +126,7 @@ int eloop_init(void *user_data)
128126

129127

130128
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
131-
int sock, eloop_sock_handler handler,
129+
struct pollfd sock, eloop_sock_handler handler,
132130
void *eloop_data, void *user_data)
133131
{
134132
struct eloop_sock *tmp;
@@ -148,24 +146,22 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
148146
tmp[table->count].handler = handler;
149147
table->count++;
150148
table->table = tmp;
151-
if (sock > eloop.max_sock)
152-
eloop.max_sock = sock;
153149
table->changed = 1;
154150

155151
return 0;
156152
}
157153

158154

159155
static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
160-
int sock)
156+
int sockfd)
161157
{
162158
int i;
163159

164160
if (table == NULL || table->table == NULL || table->count == 0)
165161
return;
166162

167163
for (i = 0; i < table->count; i++) {
168-
if (table->table[i].sock == sock)
164+
if (table->table[i].sock.fd == sockfd)
169165
break;
170166
}
171167
if (i == table->count)
@@ -181,22 +177,20 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
181177

182178

183179
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
184-
fd_set *fds)
180+
struct pollfd *fds)
185181
{
186182
int i;
187-
188-
FD_ZERO(fds);
189-
190183
if (table->table == NULL)
191184
return;
192185

193-
for (i = 0; i < table->count; i++)
194-
FD_SET(table->table[i].sock, fds);
186+
for (i = 0; i < table->count; i++) {
187+
fds[i] = table->table[i].sock;
188+
}
195189
}
196190

197191

198192
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
199-
fd_set *fds)
193+
struct pollfd *fds, int events)
200194
{
201195
int i;
202196

@@ -205,8 +199,8 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
205199

206200
table->changed = 0;
207201
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,
202+
if (fds[i].revents & events) {
203+
table->table[i].handler(table->table[i].sock.fd,
210204
table->table[i].eloop_data,
211205
table->table[i].user_data);
212206
if (table->changed)
@@ -218,15 +212,14 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
218212

219213
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
220214
{
221-
int rc, tc, sock;
222-
223-
if (table) {
215+
int rc, tc, sockfd;
216+
if (table->table) {
224217
tc = table->count;
225218
while (tc > 0) {
226-
sock = table->table[tc].sock;
227-
rc = fcntl(sock, F_GETFD);
219+
sockfd = table->table[tc].sock.fd;
220+
rc = fcntl(sockfd, F_GETFD);
228221
if (rc != -1) {
229-
rc = close(sock);
222+
rc = close(sockfd);
230223
if (rc)
231224
LLDPAD_ERR("Failed to close fd - %s\n",
232225
strerror(errno));
@@ -238,56 +231,29 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
238231
}
239232

240233

241-
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
242-
void *eloop_data, void *user_data)
243-
{
244-
return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
245-
eloop_data, user_data);
246-
}
247-
248-
249-
void eloop_unregister_read_sock(int sock)
250-
{
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)
234+
int eloop_register_read_sock(int sockfd, eloop_sock_handler handler,
235+
void *eloop_data, void *user_data)
256236
{
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;
237+
struct pollfd sock = {0};
238+
sock.fd = sockfd;
239+
sock.events = POLLIN;
240+
return eloop_register_sock(sock, handler, eloop_data, user_data);
267241
}
268242

269-
270-
int eloop_register_sock(int sock, eloop_event_type type,
271-
eloop_sock_handler handler,
272-
void *eloop_data, void *user_data)
243+
int eloop_register_sock(struct pollfd sock,
244+
eloop_sock_handler handler,
245+
void *eloop_data, void *user_data)
273246
{
274-
struct eloop_sock_table *table;
275-
276-
table = eloop_get_sock_table(type);
277-
return eloop_sock_table_add_sock(table, sock, handler,
247+
return eloop_sock_table_add_sock(&eloop.sock_table, sock, handler,
278248
eloop_data, user_data);
279249
}
280250

281251

282-
void eloop_unregister_sock(int sock, eloop_event_type type)
252+
void eloop_unregister_sock(int sockfd)
283253
{
284-
struct eloop_sock_table *table;
285-
286-
table = eloop_get_sock_table(type);
287-
eloop_sock_table_remove_sock(table, sock);
254+
eloop_sock_table_remove_sock(&eloop.sock_table, sockfd);
288255
}
289256

290-
291257
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
292258
eloop_timeout_handler handler,
293259
void *eloop_data, void *user_data)
@@ -468,39 +434,32 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
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

@@ -564,16 +516,16 @@ int eloop_terminated(void)
564516
}
565517

566518

567-
void eloop_wait_for_read_sock(int sock)
519+
void eloop_wait_for_read_sock(int sockfd)
568520
{
569-
fd_set rfds;
521+
struct pollfd fds;
570522

571-
if (sock < 0)
523+
if (sockfd < 0)
572524
return;
573525

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

579531

0 commit comments

Comments
 (0)