Skip to content

Commit 9e326f1

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 9e326f1

File tree

2 files changed

+93
-165
lines changed

2 files changed

+93
-165
lines changed

eloop.c

Lines changed: 81 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <sys/time.h>
2121
#include <unistd.h>
2222
#include <fcntl.h>
23+
#include <poll.h>
2324
#include "eloop.h"
2425
#include "include/messages.h"
2526

@@ -67,9 +68,11 @@ int os_get_time(struct os_time *t)
6768
} \
6869
} while (0)
6970

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

7174
struct eloop_sock {
72-
int sock;
75+
struct pollfd sock;
7376
void *eloop_data;
7477
void *user_data;
7578
eloop_sock_handler handler;
@@ -99,11 +102,9 @@ struct eloop_sock_table {
99102
struct eloop_data {
100103
void *user_data;
101104

102-
int max_sock;
105+
int max_sockfd;
103106

104-
struct eloop_sock_table readers;
105-
struct eloop_sock_table writers;
106-
struct eloop_sock_table exceptions;
107+
struct eloop_sock_table sock_table;
107108

108109
struct eloop_timeout *timeout;
109110

@@ -127,167 +128,122 @@ int eloop_init(void *user_data)
127128
}
128129

129130

130-
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
131-
int sock, eloop_sock_handler handler,
131+
int eloop_register_sock(struct pollfd sock, eloop_sock_handler handler,
132132
void *eloop_data, void *user_data)
133133
{
134134
struct eloop_sock *tmp;
135135

136-
if (table == NULL)
137-
return -EINVAL;
138-
139136
tmp = (struct eloop_sock *)
140-
realloc(table->table,
141-
(table->count + 1) * sizeof(struct eloop_sock));
137+
realloc(eloop.sock_table.table,
138+
(eloop.sock_table.count + 1) * sizeof(struct eloop_sock));
142139
if (tmp == NULL)
143140
return -ENOMEM;
144141

145-
tmp[table->count].sock = sock;
146-
tmp[table->count].eloop_data = eloop_data;
147-
tmp[table->count].user_data = user_data;
148-
tmp[table->count].handler = handler;
149-
table->count++;
150-
table->table = tmp;
151-
if (sock > eloop.max_sock)
152-
eloop.max_sock = sock;
153-
table->changed = 1;
142+
tmp[eloop.sock_table.count].sock = sock;
143+
tmp[eloop.sock_table.count].eloop_data = eloop_data;
144+
tmp[eloop.sock_table.count].user_data = user_data;
145+
tmp[eloop.sock_table.count].handler = handler;
146+
eloop.sock_table.count++;
147+
eloop.sock_table.table = tmp;
148+
if (sock.fd > eloop.max_sockfd)
149+
eloop.max_sockfd = sock.fd;
150+
eloop.sock_table.changed = 1;
154151

155152
return 0;
156153
}
157154

158155

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

164-
if (table == NULL || table->table == NULL || table->count == 0)
160+
if (eloop.sock_table.table == NULL || eloop.sock_table.count == 0)
165161
return;
166162

167-
for (i = 0; i < table->count; i++) {
168-
if (table->table[i].sock == sock)
163+
for (i = 0; i < eloop.sock_table.count; i++) {
164+
if (eloop.sock_table.table[i].sock.fd == sockfd)
169165
break;
170166
}
171-
if (i == table->count)
167+
if (i == eloop.sock_table.count)
172168
return;
173-
if (i != table->count - 1) {
174-
memmove(&table->table[i], &table->table[i + 1],
175-
(table->count - i - 1) *
169+
if (i != eloop.sock_table.count - 1) {
170+
memmove(&eloop.sock_table.table[i], &eloop.sock_table.table[i + 1],
171+
(eloop.sock_table.count - i - 1) *
176172
sizeof(struct eloop_sock));
177173
}
178-
table->count--;
179-
table->changed = 1;
174+
eloop.sock_table.count--;
175+
eloop.sock_table.changed = 1;
180176
}
181177

182178

183-
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
184-
fd_set *fds)
179+
static void eloop_sock_table_set_fds(struct pollfd *fds)
185180
{
186181
int i;
187-
188-
FD_ZERO(fds);
189-
190-
if (table->table == NULL)
182+
if (eloop.sock_table.table == NULL)
191183
return;
192184

193-
for (i = 0; i < table->count; i++)
194-
FD_SET(table->table[i].sock, fds);
185+
for (i = 0; i < eloop.sock_table.count; i++) {
186+
fds[eloop.sock_table.table[i].sock.fd] = eloop.sock_table.table[i].sock;
187+
}
195188
}
196189

197190

198-
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
199-
fd_set *fds)
191+
static void eloop_sock_table_dispatch(struct pollfd *fds)
200192
{
201193
int i;
202194

203-
if (table == NULL || table->table == NULL)
195+
if (eloop.sock_table.table == NULL)
204196
return;
205197

206-
table->changed = 0;
207-
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,
210-
table->table[i].eloop_data,
211-
table->table[i].user_data);
212-
if (table->changed)
198+
eloop.sock_table.changed = 0;
199+
for (i = 0; i < eloop.sock_table.count; i++) {
200+
if (fds[eloop.sock_table.table[i].sock.fd].revents & POLL_IN) {
201+
eloop.sock_table.table[i].handler(eloop.sock_table.table[i].sock.fd,
202+
eloop.sock_table.table[i].eloop_data,
203+
eloop.sock_table.table[i].user_data);
204+
if (eloop.sock_table.changed)
213205
break;
214206
}
215207
}
216208
}
217209

218210

219-
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
211+
static void eloop_sock_table_destroy()
220212
{
221-
int rc, tc, sock;
222-
223-
if (table) {
224-
tc = table->count;
213+
int rc, tc, sockfd;
214+
if (eloop.sock_table.table) {
215+
tc = eloop.sock_table.count;
225216
while (tc > 0) {
226-
sock = table->table[tc].sock;
227-
rc = fcntl(sock, F_GETFD);
217+
sockfd = eloop.sock_table.table[tc].sock.fd;
218+
rc = fcntl(sockfd, F_GETFD);
228219
if (rc != -1) {
229-
rc = close(sock);
220+
rc = close(sockfd);
230221
if (rc)
231222
LLDPAD_ERR("Failed to close fd - %s\n",
232223
strerror(errno));
233224
}
234225
tc--;
235226
}
236-
free(table->table);
227+
free(eloop.sock_table.table);
237228
}
238229
}
239230

240231

241-
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
232+
int eloop_register_read_sock(int sockfd, eloop_sock_handler handler,
242233
void *eloop_data, void *user_data)
243234
{
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)
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,
278-
eloop_data, user_data);
235+
struct pollfd sock = {0};
236+
sock.fd = sockfd;
237+
sock.events = POLLIN;
238+
return eloop_register_sock(sock, handler, eloop_data, user_data);
279239
}
280240

281241

282-
void eloop_unregister_sock(int sock, eloop_event_type type)
242+
void eloop_unregister_read_sock(int sockfd)
283243
{
284-
struct eloop_sock_table *table;
285-
286-
table = eloop_get_sock_table(type);
287-
eloop_sock_table_remove_sock(table, sock);
244+
eloop_unregister_sock(sockfd);
288245
}
289246

290-
291247
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
292248
eloop_timeout_handler handler,
293249
void *eloop_data, void *user_data)
@@ -468,37 +424,31 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
468424

469425
void eloop_run(void)
470426
{
471-
fd_set *rfds, *wfds, *efds;
472-
int res;
473-
struct timeval _tv;
427+
int res, timeout;
474428
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-
}
429+
struct pollfd *fds = NULL;
483430

484431
while (!eloop.terminate &&
485-
(eloop.timeout || eloop.readers.count > 0 ||
486-
eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
432+
(eloop.timeout || eloop.sock_table.count > 0)) {
487433
if (eloop.timeout) {
488434
os_get_time(&now);
489435
if (os_time_before(&now, &eloop.timeout->time))
490436
os_time_sub(&eloop.timeout->time, &now, &tv);
491437
else
492438
tv.sec = tv.usec = 0;
493-
_tv.tv_sec = tv.sec;
494-
_tv.tv_usec = tv.usec;
439+
timeout = os_time_to_ms(&tv);
495440
}
496441

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);
442+
fds = (struct pollfd *)
443+
realloc(fds, (eloop.max_sockfd + 1) * sizeof(struct eloop_sock));
444+
if (fds == NULL) {
445+
perror("realloc");
446+
goto out;
447+
}
448+
memset(fds, 0, (eloop.max_sockfd + 1) * sizeof(struct eloop_sock));
449+
450+
eloop_sock_table_set_fds(fds);
451+
res = poll(fds, eloop.max_sockfd + 1, eloop.timeout ? timeout : -1);
502452
if (res < 0 && errno != EINTR && errno != 0) {
503453
perror("select");
504454
goto out;
@@ -522,16 +472,11 @@ void eloop_run(void)
522472

523473
if (res <= 0)
524474
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);
475+
eloop_sock_table_dispatch(fds);
529476
}
530-
531477
out:
532-
free(rfds);
533-
free(wfds);
534-
free(efds);
478+
if (fds)
479+
free(fds);
535480
}
536481

537482

@@ -551,9 +496,7 @@ void eloop_destroy(void)
551496
timeout = timeout->next;
552497
free(prev);
553498
}
554-
eloop_sock_table_destroy(&eloop.readers);
555-
eloop_sock_table_destroy(&eloop.writers);
556-
eloop_sock_table_destroy(&eloop.exceptions);
499+
eloop_sock_table_destroy();
557500
free(eloop.signals);
558501
}
559502

@@ -564,16 +507,16 @@ int eloop_terminated(void)
564507
}
565508

566509

567-
void eloop_wait_for_read_sock(int sock)
510+
void eloop_wait_for_read_sock(int sockfd)
568511
{
569-
fd_set rfds;
512+
struct pollfd fds;
570513

571-
if (sock < 0)
514+
if (sockfd < 0)
572515
return;
573516

574-
FD_ZERO(&rfds);
575-
FD_SET(sock, &rfds);
576-
select(sock + 1, &rfds, NULL, NULL, NULL);
517+
fds.fd = sockfd;
518+
fds.events = POLLIN;
519+
poll(&fds, 1, -1);
577520
}
578521

579522

0 commit comments

Comments
 (0)