Skip to content

Commit b8e4ca4

Browse files
authored
udp: fix again pbuf management (#7132)
* udp: fix again pbuf management * Process rx buffer size, cache it, because _rx_buf->tot_len is *not* the total size
1 parent b64e8da commit b8e4ca4

File tree

1 file changed

+72
-27
lines changed

1 file changed

+72
-27
lines changed

libraries/ESP8266WiFi/src/include/UdpContext.h

+72-27
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class UdpContext
4747
, _rx_buf(0)
4848
, _first_buf_taken(false)
4949
, _rx_buf_offset(0)
50+
, _rx_buf_size(0)
5051
, _refcnt(0)
5152
, _tx_buf_head(0)
5253
, _tx_buf_cur(0)
@@ -74,6 +75,7 @@ class UdpContext
7475
pbuf_free(_rx_buf);
7576
_rx_buf = 0;
7677
_rx_buf_offset = 0;
78+
_rx_buf_size = 0;
7779
}
7880
}
7981

@@ -202,12 +204,36 @@ class UdpContext
202204
_on_rx = handler;
203205
}
204206

207+
#ifdef DEBUG_ESP_CORE
208+
// this helper is ready to be used when debugging UDP
209+
void printChain (const pbuf* pb, const char* msg, size_t n) const
210+
{
211+
// printf the pb pbuf chain, bufferred and all at once
212+
char buf[128];
213+
int l = snprintf(buf, sizeof(buf), "UDP: %s %u: ", msg, n);
214+
while (pb)
215+
{
216+
l += snprintf(&buf[l], sizeof(buf) -l, "%p(H=%d,%d<=%d)-",
217+
pb, pb->flags == PBUF_HELPER_FLAG, pb->len, pb->tot_len);
218+
pb = pb->next;
219+
}
220+
l += snprintf(&buf[l], sizeof(buf) - l, "(end)");
221+
DEBUGV("%s\n", buf);
222+
}
223+
#else
224+
void printChain (const pbuf* pb, const char* msg) const
225+
{
226+
(void)pb;
227+
(void)msg;
228+
}
229+
#endif
230+
205231
size_t getSize() const
206232
{
207233
if (!_rx_buf)
208234
return 0;
209235

210-
return _rx_buf->tot_len - _rx_buf_offset;
236+
return _rx_buf_size - _rx_buf_offset;
211237
}
212238

213239
size_t tell() const
@@ -222,7 +248,7 @@ class UdpContext
222248
}
223249

224250
bool isValidOffset(const size_t pos) const {
225-
return (pos <= _rx_buf->tot_len);
251+
return (pos <= _rx_buf_size);
226252
}
227253

228254
netif* getInputNetif() const
@@ -262,47 +288,54 @@ class UdpContext
262288
return true;
263289
}
264290

291+
// We have interleaved informations on addresses within received pbuf chain:
292+
// (before ipv6 code we had: (data-pbuf) -> (data-pbuf) -> (data-pbuf) -> ... in the receiving order)
293+
// Now: (address-info-pbuf -> chained-data-pbuf [-> chained-data-pbuf...]) ->
294+
// (chained-address-info-pbuf -> chained-data-pbuf [-> chained...]) -> ...
295+
// _rx_buf is currently adressing a data pbuf,
296+
// in this function it is going to be discarded.
297+
265298
auto deleteme = _rx_buf;
266299

267-
while(_rx_buf->len != _rx_buf->tot_len)
300+
// forward in the chain until next address-info pbuf or end of chain
301+
while(_rx_buf && _rx_buf->flags != PBUF_HELPER_FLAG)
268302
_rx_buf = _rx_buf->next;
269303

270-
_rx_buf = _rx_buf->next;
271-
272304
if (_rx_buf)
273305
{
274-
if (_rx_buf->flags == PBUF_HELPER_FLAG)
275-
{
276-
// we have interleaved informations on addresses within reception pbuf chain:
277-
// before: (data-pbuf) -> (data-pbuf) -> (data-pbuf) -> ... in the receiving order
278-
// now: (address-info-pbuf -> data-pbuf) -> (address-info-pbuf -> data-pbuf) -> ...
306+
assert(_rx_buf->flags == PBUF_HELPER_FLAG);
279307

280-
// so the first rx_buf contains an address helper,
281-
// copy it to "current address"
282-
auto helper = (AddrHelper*)PBUF_ALIGNER(_rx_buf->payload);
283-
_currentAddr = *helper;
308+
// copy address helper to "current address"
309+
auto helper = (AddrHelper*)PBUF_ALIGNER(_rx_buf->payload);
310+
_currentAddr = *helper;
284311

285-
// destroy the helper in the about-to-be-released pbuf
286-
helper->~AddrHelper();
312+
// destroy the helper in the about-to-be-released pbuf
313+
helper->~AddrHelper();
287314

288-
// forward in rx_buf list, next one is effective data
289-
// current (not ref'ed) one will be pbuf_free'd with deleteme
290-
_rx_buf = _rx_buf->next;
291-
}
315+
// forward in rx_buf list, next one is effective data
316+
// current (not ref'ed) one will be pbuf_free'd
317+
// with the 'deleteme' pointer above
318+
_rx_buf = _rx_buf->next;
292319

293320
// this rx_buf is not nullptr by construction,
321+
assert(_rx_buf);
294322
// ref'ing it to prevent release from the below pbuf_free(deleteme)
323+
// (ref counter prevents release and will be decreased by pbuf_free)
295324
pbuf_ref(_rx_buf);
296325
}
326+
327+
// release in chain previous data, and if any:
328+
// current helper, but not start of current data
297329
pbuf_free(deleteme);
298330

299331
_rx_buf_offset = 0;
332+
_rx_buf_size = _processSize(_rx_buf);
300333
return _rx_buf != nullptr;
301334
}
302335

303336
int read()
304337
{
305-
if (!_rx_buf || _rx_buf_offset >= _rx_buf->tot_len)
338+
if (!_rx_buf || _rx_buf_offset >= _rx_buf_size)
306339
return -1;
307340

308341
char c = pbuf_get_at(_rx_buf, _rx_buf_offset);
@@ -315,9 +348,9 @@ class UdpContext
315348
if (!_rx_buf)
316349
return 0;
317350

318-
size_t max_size = _rx_buf->tot_len - _rx_buf_offset;
351+
size_t max_size = _rx_buf_size - _rx_buf_offset;
319352
size = (size < max_size) ? size : max_size;
320-
DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf->tot_len, _rx_buf_offset);
353+
DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf_size, _rx_buf_offset);
321354

322355
void* buf = pbuf_get_contiguous(_rx_buf, dst, size, size, _rx_buf_offset);
323356
if(!buf)
@@ -333,7 +366,7 @@ class UdpContext
333366

334367
int peek() const
335368
{
336-
if (!_rx_buf || _rx_buf_offset == _rx_buf->tot_len)
369+
if (!_rx_buf || _rx_buf_offset == _rx_buf_size)
337370
return -1;
338371

339372
return pbuf_get_at(_rx_buf, _rx_buf_offset);
@@ -345,7 +378,7 @@ class UdpContext
345378
if (!_rx_buf)
346379
return;
347380

348-
_consume(_rx_buf->tot_len - _rx_buf_offset);
381+
_consume(_rx_buf_size - _rx_buf_offset);
349382
}
350383

351384
size_t append(const char* data, size_t size)
@@ -429,6 +462,14 @@ class UdpContext
429462

430463
private:
431464

465+
size_t _processSize (const pbuf* pb)
466+
{
467+
size_t ret = 0;
468+
for (; pb && pb->flags != PBUF_HELPER_FLAG; pb = pb->next)
469+
ret += pb->len;
470+
return ret;
471+
}
472+
432473
void _reserve(size_t size)
433474
{
434475
const size_t pbuf_unit_size = 128;
@@ -466,8 +507,8 @@ class UdpContext
466507
void _consume(size_t size)
467508
{
468509
_rx_buf_offset += size;
469-
if (_rx_buf_offset > _rx_buf->tot_len) {
470-
_rx_buf_offset = _rx_buf->tot_len;
510+
if (_rx_buf_offset > _rx_buf_size) {
511+
_rx_buf_offset = _rx_buf_size;
471512
}
472513
}
473514

@@ -476,6 +517,7 @@ class UdpContext
476517
{
477518
(void) upcb;
478519
// check receive pbuf chain depth
520+
// optimization path: cache the pbuf chain length
479521
{
480522
pbuf* p;
481523
int count = 0;
@@ -488,6 +530,7 @@ class UdpContext
488530
return;
489531
}
490532
}
533+
491534
#if LWIP_VERSION_MAJOR == 1
492535
#define TEMPDSTADDR (&current_iphdr_dest)
493536
#define TEMPINPUTNETIF (current_netif)
@@ -541,6 +584,7 @@ class UdpContext
541584
_first_buf_taken = false;
542585
_rx_buf = pb;
543586
_rx_buf_offset = 0;
587+
_rx_buf_size = pb->tot_len;
544588
}
545589

546590
if (_on_rx) {
@@ -648,6 +692,7 @@ class UdpContext
648692
pbuf* _rx_buf;
649693
bool _first_buf_taken;
650694
size_t _rx_buf_offset;
695+
size_t _rx_buf_size;
651696
int _refcnt;
652697
pbuf* _tx_buf_head;
653698
pbuf* _tx_buf_cur;

0 commit comments

Comments
 (0)