Skip to content

Commit 9489659

Browse files
wengzhepkarashchenko
authored andcommitted
netutils/ping: Optimize stack usage of icmp_ping
Can reduce 88~144 Bytes on ARMv7-A depending on optimization level. Signed-off-by: Zhe Weng <[email protected]>
1 parent 16bca8b commit 9489659

File tree

1 file changed

+85
-71
lines changed

1 file changed

+85
-71
lines changed

netutils/ping/icmp_ping.c

Lines changed: 85 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,28 @@
5252

5353
#define ICMP_IOBUFFER_SIZE(x) (sizeof(struct icmp_hdr_s) + (x))
5454

55+
/****************************************************************************
56+
* Private Types
57+
****************************************************************************/
58+
59+
/* Data needed for ping, reduce stack usage. */
60+
61+
struct ping_priv_s
62+
{
63+
struct sockaddr_in destaddr;
64+
struct sockaddr_in fromaddr;
65+
struct icmp_hdr_s outhdr;
66+
struct pollfd recvfd;
67+
socklen_t addrlen;
68+
clock_t kickoff;
69+
clock_t start;
70+
ssize_t nsent;
71+
ssize_t nrecvd;
72+
long elapsed;
73+
bool retry;
74+
int sockfd;
75+
};
76+
5577
/****************************************************************************
5678
* Private Data
5779
****************************************************************************/
@@ -107,14 +129,14 @@ static int ping_gethostip(FAR const char *hostname, FAR struct in_addr *dest)
107129
#ifdef CONFIG_LIBC_NETDB
108130
/* Netdb DNS client support is enabled */
109131

110-
FAR struct addrinfo hint;
111132
FAR struct addrinfo *info;
112133
FAR struct sockaddr_in *addr;
134+
static const struct addrinfo s_hint =
135+
{
136+
.ai_family = AF_INET
137+
};
113138

114-
memset(&hint, 0, sizeof(hint));
115-
hint.ai_family = AF_INET;
116-
117-
if (getaddrinfo(hostname, NULL, &hint, &info) != OK)
139+
if (getaddrinfo(hostname, NULL, &s_hint, &info) != OK)
118140
{
119141
return ERROR;
120142
}
@@ -166,21 +188,10 @@ static void icmp_callback(FAR struct ping_result_s *result,
166188
void icmp_ping(FAR const struct ping_info_s *info)
167189
{
168190
struct ping_result_s result;
169-
struct sockaddr_in destaddr;
170-
struct sockaddr_in fromaddr;
171-
struct icmp_hdr_s outhdr;
191+
FAR struct ping_priv_s *priv;
172192
FAR struct icmp_hdr_s *inhdr;
173-
struct pollfd recvfd;
174193
FAR uint8_t *iobuffer;
175194
FAR uint8_t *ptr;
176-
long elapsed;
177-
clock_t kickoff;
178-
clock_t start;
179-
socklen_t addrlen;
180-
ssize_t nsent;
181-
ssize_t nrecvd;
182-
bool retry;
183-
int sockfd;
184195
int ret;
185196
int ch;
186197
int i;
@@ -200,34 +211,36 @@ void icmp_ping(FAR const struct ping_info_s *info)
200211
return;
201212
}
202213

203-
/* Allocate memory to hold ping buffer */
214+
/* Allocate memory to hold private data and ping buffer */
204215

205-
iobuffer = (FAR uint8_t *)malloc(result.outsize);
206-
if (iobuffer == NULL)
216+
priv = malloc(sizeof(*priv) + result.outsize);
217+
if (priv == NULL)
207218
{
208219
icmp_callback(&result, ICMP_E_MEMORY, 0);
209220
return;
210221
}
211222

212-
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
213-
if (sockfd < 0)
223+
iobuffer = (FAR uint8_t *)(priv + 1);
224+
225+
priv->sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
226+
if (priv->sockfd < 0)
214227
{
215228
icmp_callback(&result, ICMP_E_SOCKET, errno);
216-
free(iobuffer);
229+
free(priv);
217230
return;
218231
}
219232

220-
kickoff = clock();
233+
priv->kickoff = clock();
221234

222-
memset(&destaddr, 0, sizeof(struct sockaddr_in));
223-
destaddr.sin_family = AF_INET;
224-
destaddr.sin_port = 0;
225-
destaddr.sin_addr.s_addr = result.dest.s_addr;
235+
memset(&priv->destaddr, 0, sizeof(struct sockaddr_in));
236+
priv->destaddr.sin_family = AF_INET;
237+
priv->destaddr.sin_port = 0;
238+
priv->destaddr.sin_addr.s_addr = result.dest.s_addr;
226239

227-
memset(&outhdr, 0, sizeof(struct icmp_hdr_s));
228-
outhdr.type = ICMP_ECHO_REQUEST;
229-
outhdr.id = htons(result.id);
230-
outhdr.seqno = htons(result.seqno);
240+
memset(&priv->outhdr, 0, sizeof(struct icmp_hdr_s));
241+
priv->outhdr.type = ICMP_ECHO_REQUEST;
242+
priv->outhdr.id = htons(result.id);
243+
priv->outhdr.seqno = htons(result.seqno);
231244

232245
icmp_callback(&result, ICMP_I_BEGIN, 0);
233246

@@ -240,7 +253,7 @@ void icmp_ping(FAR const struct ping_info_s *info)
240253

241254
/* Copy the ICMP header into the I/O buffer */
242255

243-
memcpy(iobuffer, &outhdr, sizeof(struct icmp_hdr_s));
256+
memcpy(iobuffer, &priv->outhdr, sizeof(struct icmp_hdr_s));
244257

245258
/* Add some easily verifiable payload data */
246259

@@ -256,33 +269,33 @@ void icmp_ping(FAR const struct ping_info_s *info)
256269
}
257270
}
258271

259-
start = clock();
260-
nsent = sendto(sockfd, iobuffer, result.outsize, 0,
261-
(FAR struct sockaddr *)&destaddr,
262-
sizeof(struct sockaddr_in));
263-
if (nsent < 0)
272+
priv->start = clock();
273+
priv->nsent = sendto(priv->sockfd, iobuffer, result.outsize, 0,
274+
(FAR struct sockaddr *)&priv->destaddr,
275+
sizeof(struct sockaddr_in));
276+
if (priv->nsent < 0)
264277
{
265278
icmp_callback(&result, ICMP_E_SENDTO, errno);
266279
goto done;
267280
}
268-
else if (nsent != result.outsize)
281+
else if (priv->nsent != result.outsize)
269282
{
270-
icmp_callback(&result, ICMP_E_SENDSMALL, nsent);
283+
icmp_callback(&result, ICMP_E_SENDSMALL, priv->nsent);
271284
goto done;
272285
}
273286

274287
result.nrequests++;
275288

276-
elapsed = 0;
289+
priv->elapsed = 0;
277290
do
278291
{
279-
retry = false;
280-
281-
recvfd.fd = sockfd;
282-
recvfd.events = POLLIN;
283-
recvfd.revents = 0;
292+
priv->retry = false;
293+
priv->recvfd.fd = priv->sockfd;
294+
priv->recvfd.events = POLLIN;
295+
priv->recvfd.revents = 0;
284296

285-
ret = poll(&recvfd, 1, info->timeout - elapsed / USEC_PER_MSEC);
297+
ret = poll(&priv->recvfd, 1,
298+
info->timeout - priv->elapsed / USEC_PER_MSEC);
286299
if (ret < 0)
287300
{
288301
icmp_callback(&result, ICMP_E_POLL, errno);
@@ -296,57 +309,58 @@ void icmp_ping(FAR const struct ping_info_s *info)
296309

297310
/* Get the ICMP response (ignoring the sender) */
298311

299-
addrlen = sizeof(struct sockaddr_in);
300-
nrecvd = recvfrom(sockfd, iobuffer, result.outsize, 0,
301-
(FAR struct sockaddr *)&fromaddr, &addrlen);
302-
if (nrecvd < 0)
312+
priv->addrlen = sizeof(struct sockaddr_in);
313+
priv->nrecvd = recvfrom(priv->sockfd, iobuffer,
314+
result.outsize, 0,
315+
(FAR struct sockaddr *)&priv->fromaddr,
316+
&priv->addrlen);
317+
if (priv->nrecvd < 0)
303318
{
304319
icmp_callback(&result, ICMP_E_RECVFROM, errno);
305320
goto done;
306321
}
307-
else if (nrecvd < sizeof(struct icmp_hdr_s))
322+
else if (priv->nrecvd < sizeof(struct icmp_hdr_s))
308323
{
309-
icmp_callback(&result, ICMP_E_RECVSMALL, nrecvd);
324+
icmp_callback(&result, ICMP_E_RECVSMALL, priv->nrecvd);
310325
goto done;
311326
}
312327

313-
elapsed = TICK2USEC(clock() - start);
314-
inhdr = (FAR struct icmp_hdr_s *)iobuffer;
328+
priv->elapsed = TICK2USEC(clock() - priv->start);
329+
inhdr = (FAR struct icmp_hdr_s *)iobuffer;
315330

316331
if (inhdr->type == ICMP_ECHO_REPLY)
317332
{
318333
#ifndef CONFIG_SIM_NETUSRSOCK
319334
if (ntohs(inhdr->id) != result.id)
320335
{
321336
icmp_callback(&result, ICMP_W_IDDIFF, ntohs(inhdr->id));
322-
retry = true;
337+
priv->retry = true;
323338
}
324339
else
325340
#endif
326341
if (ntohs(inhdr->seqno) > result.seqno)
327342
{
328343
icmp_callback(&result, ICMP_W_SEQNOBIG,
329344
ntohs(inhdr->seqno));
330-
retry = true;
345+
priv->retry = true;
331346
}
332347
else if (ntohs(inhdr->seqno) < result.seqno)
333348
{
334349
icmp_callback(&result, ICMP_W_SEQNOSMALL,
335350
ntohs(inhdr->seqno));
336-
retry = true;
351+
priv->retry = true;
337352
}
338353
else
339354
{
340355
bool verified = true;
341-
long pktdelay = elapsed;
342356

343-
icmp_callback(&result, ICMP_I_ROUNDTRIP, pktdelay);
357+
icmp_callback(&result, ICMP_I_ROUNDTRIP, priv->elapsed);
344358

345359
/* Verify the payload data */
346360

347-
if (nrecvd != result.outsize)
361+
if (priv->nrecvd != result.outsize)
348362
{
349-
icmp_callback(&result, ICMP_W_RECVBIG, nrecvd);
363+
icmp_callback(&result, ICMP_W_RECVBIG, priv->nrecvd);
350364
verified = false;
351365
}
352366
else
@@ -383,20 +397,20 @@ void icmp_ping(FAR const struct ping_info_s *info)
383397
icmp_callback(&result, ICMP_W_TYPE, inhdr->type);
384398
}
385399
}
386-
while (retry && info->delay > elapsed / USEC_PER_MSEC &&
387-
info->timeout > elapsed / USEC_PER_MSEC);
400+
while (priv->retry && info->delay > priv->elapsed / USEC_PER_MSEC &&
401+
info->timeout > priv->elapsed / USEC_PER_MSEC);
388402

389403
/* Wait if necessary to preserved the requested ping rate */
390404

391-
elapsed = TICK2MSEC(clock() - start);
392-
if (elapsed < info->delay)
405+
priv->elapsed = TICK2MSEC(clock() - priv->start);
406+
if (priv->elapsed < info->delay)
393407
{
394408
struct timespec rqt;
395409
unsigned int remaining;
396410
unsigned int sec;
397411
unsigned int frac; /* In deciseconds */
398412

399-
remaining = info->delay - elapsed;
413+
remaining = info->delay - priv->elapsed;
400414
sec = remaining / MSEC_PER_SEC;
401415
frac = remaining - MSEC_PER_SEC * sec;
402416

@@ -406,11 +420,11 @@ void icmp_ping(FAR const struct ping_info_s *info)
406420
nanosleep(&rqt, NULL);
407421
}
408422

409-
outhdr.seqno = htons(++result.seqno);
423+
priv->outhdr.seqno = htons(++result.seqno);
410424
}
411425

412426
done:
413-
icmp_callback(&result, ICMP_I_FINISH, TICK2USEC(clock() - kickoff));
414-
close(sockfd);
415-
free(iobuffer);
427+
icmp_callback(&result, ICMP_I_FINISH, TICK2USEC(clock() - priv->kickoff));
428+
close(priv->sockfd);
429+
free(priv);
416430
}

0 commit comments

Comments
 (0)