Skip to content

Commit 1de73a9

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 1de73a9

File tree

2 files changed

+93
-165
lines changed

2 files changed

+93
-165
lines changed

eloop.c

Lines changed: 80 additions & 138 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,9 @@ struct eloop_sock_table {
99101
struct eloop_data {
100102
void *user_data;
101103

102-
int max_sock;
104+
int max_sockfd;
103105

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

108108
struct eloop_timeout *timeout;
109109

@@ -127,167 +127,122 @@ int eloop_init(void *user_data)
127127
}
128128

129129

130-
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
131-
int sock, eloop_sock_handler handler,
130+
int eloop_register_sock(struct pollfd sock, eloop_sock_handler handler,
132131
void *eloop_data, void *user_data)
133132
{
134133
struct eloop_sock *tmp;
135134

136-
if (table == NULL)
137-
return -EINVAL;
138-
139135
tmp = (struct eloop_sock *)
140-
realloc(table->table,
141-
(table->count + 1) * sizeof(struct eloop_sock));
136+
realloc(eloop.sock_table.table,
137+
(eloop.sock_table.count + 1) * sizeof(struct eloop_sock));
142138
if (tmp == NULL)
143139
return -ENOMEM;
144140

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;
141+
tmp[eloop.sock_table.count].sock = sock;
142+
tmp[eloop.sock_table.count].eloop_data = eloop_data;
143+
tmp[eloop.sock_table.count].user_data = user_data;
144+
tmp[eloop.sock_table.count].handler = handler;
145+
eloop.sock_table.count++;
146+
eloop.sock_table.table = tmp;
147+
if (sock.fd > eloop.max_sockfd)
148+
eloop.max_sockfd = sock.fd;
149+
eloop.sock_table.changed = 1;
154150

155151
return 0;
156152
}
157153

158154

159-
static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
160-
int sock)
155+
void eloop_unregister_sock(int sockfd)
161156
{
162157
int i;
163158

164-
if (table == NULL || table->table == NULL || table->count == 0)
159+
if (eloop.sock_table.table == NULL || eloop.sock_table.count == 0)
165160
return;
166161

167-
for (i = 0; i < table->count; i++) {
168-
if (table->table[i].sock == sock)
162+
for (i = 0; i < eloop.sock_table.count; i++) {
163+
if (eloop.sock_table.table[i].sock.fd == sockfd)
169164
break;
170165
}
171-
if (i == table->count)
166+
if (i == eloop.sock_table.count)
172167
return;
173-
if (i != table->count - 1) {
174-
memmove(&table->table[i], &table->table[i + 1],
175-
(table->count - i - 1) *
168+
if (i != eloop.sock_table.count - 1) {
169+
memmove(&eloop.sock_table.table[i], &eloop.sock_table.table[i + 1],
170+
(eloop.sock_table.count - i - 1) *
176171
sizeof(struct eloop_sock));
177172
}
178-
table->count--;
179-
table->changed = 1;
173+
eloop.sock_table.count--;
174+
eloop.sock_table.changed = 1;
180175
}
181176

182177

183-
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
184-
fd_set *fds)
178+
static void eloop_sock_table_set_fds(struct pollfd *fds)
185179
{
186180
int i;
187-
188-
FD_ZERO(fds);
189-
190-
if (table->table == NULL)
181+
if (eloop.sock_table.table == NULL)
191182
return;
192183

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

197189

198-
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
199-
fd_set *fds)
190+
static void eloop_sock_table_dispatch(struct pollfd *fds)
200191
{
201192
int i;
202193

203-
if (table == NULL || table->table == NULL)
194+
if (eloop.sock_table.table == NULL)
204195
return;
205196

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)
197+
eloop.sock_table.changed = 0;
198+
for (i = 0; i < eloop.sock_table.count; i++) {
199+
if (fds[eloop.sock_table.table[i].sock.fd].revents & POLL_IN) {
200+
eloop.sock_table.table[i].handler(eloop.sock_table.table[i].sock.fd,
201+
eloop.sock_table.table[i].eloop_data,
202+
eloop.sock_table.table[i].user_data);
203+
if (eloop.sock_table.changed)
213204
break;
214205
}
215206
}
216207
}
217208

218209

219-
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
210+
static void eloop_sock_table_destroy()
220211
{
221-
int rc, tc, sock;
222-
223-
if (table) {
224-
tc = table->count;
212+
int rc, tc, sockfd;
213+
if (eloop.sock_table.table) {
214+
tc = eloop.sock_table.count;
225215
while (tc > 0) {
226-
sock = table->table[tc].sock;
227-
rc = fcntl(sock, F_GETFD);
216+
sockfd = eloop.sock_table.table[tc].sock.fd;
217+
rc = fcntl(sockfd, F_GETFD);
228218
if (rc != -1) {
229-
rc = close(sock);
219+
rc = close(sockfd);
230220
if (rc)
231221
LLDPAD_ERR("Failed to close fd - %s\n",
232222
strerror(errno));
233223
}
234224
tc--;
235225
}
236-
free(table->table);
226+
free(eloop.sock_table.table);
237227
}
238228
}
239229

240230

241-
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
231+
int eloop_register_read_sock(int sockfd, eloop_sock_handler handler,
242232
void *eloop_data, void *user_data)
243233
{
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);
234+
struct pollfd sock = {0};
235+
sock.fd = sockfd;
236+
sock.events = POLLIN;
237+
return eloop_register_sock(sock, handler, eloop_data, user_data);
279238
}
280239

281240

282-
void eloop_unregister_sock(int sock, eloop_event_type type)
241+
void eloop_unregister_read_sock(int sockfd)
283242
{
284-
struct eloop_sock_table *table;
285-
286-
table = eloop_get_sock_table(type);
287-
eloop_sock_table_remove_sock(table, sock);
243+
eloop_unregister_sock(sockfd);
288244
}
289245

290-
291246
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
292247
eloop_timeout_handler handler,
293248
void *eloop_data, void *user_data)
@@ -468,37 +423,31 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
468423

469424
void eloop_run(void)
470425
{
471-
fd_set *rfds, *wfds, *efds;
472-
int res;
473-
struct timeval _tv;
426+
int res, timeout;
474427
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-
}
428+
struct pollfd *fds = NULL;
483429

484430
while (!eloop.terminate &&
485-
(eloop.timeout || eloop.readers.count > 0 ||
486-
eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
431+
(eloop.timeout || eloop.sock_table.count > 0)) {
487432
if (eloop.timeout) {
488433
os_get_time(&now);
489434
if (os_time_before(&now, &eloop.timeout->time))
490435
os_time_sub(&eloop.timeout->time, &now, &tv);
491436
else
492437
tv.sec = tv.usec = 0;
493-
_tv.tv_sec = tv.sec;
494-
_tv.tv_usec = tv.usec;
438+
timeout = os_time_to_ms(&tv);
495439
}
496440

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

523472
if (res <= 0)
524473
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);
474+
eloop_sock_table_dispatch(fds);
529475
}
530-
531476
out:
532-
free(rfds);
533-
free(wfds);
534-
free(efds);
477+
if (fds)
478+
free(fds);
535479
}
536480

537481

@@ -551,9 +495,7 @@ void eloop_destroy(void)
551495
timeout = timeout->next;
552496
free(prev);
553497
}
554-
eloop_sock_table_destroy(&eloop.readers);
555-
eloop_sock_table_destroy(&eloop.writers);
556-
eloop_sock_table_destroy(&eloop.exceptions);
498+
eloop_sock_table_destroy();
557499
free(eloop.signals);
558500
}
559501

@@ -564,16 +506,16 @@ int eloop_terminated(void)
564506
}
565507

566508

567-
void eloop_wait_for_read_sock(int sock)
509+
void eloop_wait_for_read_sock(int sockfd)
568510
{
569-
fd_set rfds;
511+
struct pollfd fds;
570512

571-
if (sock < 0)
513+
if (sockfd < 0)
572514
return;
573515

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

579521

0 commit comments

Comments
 (0)