n-dhcp4/connection: dynamically allocate the receive buffer
Each connection object includes a 64KiB scratch buffer used for
receiving packets. When many instances of the client are created,
those buffers use a significant amount of memory. For example, 500
clients take ~30MiB of memory constantly reserved only for those
buffers.
Since the buffer is used only in the function and is never passed
outside, a stack allocation would suffice; however, it's not wise to
do such large allocations on the stack; dynamically allocate it.
https://github.com/nettools/n-dhcp4/issues/26
https://github.com/nettools/n-dhcp4/pull/27
64513e31c0
This commit is contained in:

committed by
Thomas Haller

parent
197e73ac7c
commit
a5a5654f18
@@ -1147,16 +1147,21 @@ int n_dhcp4_c_connection_dispatch_timer(NDhcp4CConnection *connection,
|
|||||||
int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
|
int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
|
||||||
NDhcp4Incoming **messagep) {
|
NDhcp4Incoming **messagep) {
|
||||||
_c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = NULL;
|
_c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = NULL;
|
||||||
|
_c_cleanup_(c_freep) uint8_t *buffer = NULL;
|
||||||
char serv_addr[INET_ADDRSTRLEN];
|
char serv_addr[INET_ADDRSTRLEN];
|
||||||
char client_addr[INET_ADDRSTRLEN];
|
char client_addr[INET_ADDRSTRLEN];
|
||||||
uint8_t type = 0;
|
uint8_t type = 0;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
buffer = malloc(UINT16_MAX);
|
||||||
|
if (!buffer)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
switch (connection->state) {
|
switch (connection->state) {
|
||||||
case N_DHCP4_C_CONNECTION_STATE_PACKET:
|
case N_DHCP4_C_CONNECTION_STATE_PACKET:
|
||||||
r = n_dhcp4_c_socket_packet_recv(connection->fd_packet,
|
r = n_dhcp4_c_socket_packet_recv(connection->fd_packet,
|
||||||
connection->scratch_buffer,
|
buffer,
|
||||||
sizeof(connection->scratch_buffer),
|
UINT16_MAX,
|
||||||
&message);
|
&message);
|
||||||
if (!r)
|
if (!r)
|
||||||
break;
|
break;
|
||||||
@@ -1165,8 +1170,8 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
|
|||||||
return N_DHCP4_E_AGAIN;
|
return N_DHCP4_E_AGAIN;
|
||||||
case N_DHCP4_C_CONNECTION_STATE_DRAINING:
|
case N_DHCP4_C_CONNECTION_STATE_DRAINING:
|
||||||
r = n_dhcp4_c_socket_packet_recv(connection->fd_packet,
|
r = n_dhcp4_c_socket_packet_recv(connection->fd_packet,
|
||||||
connection->scratch_buffer,
|
buffer,
|
||||||
sizeof(connection->scratch_buffer),
|
UINT16_MAX,
|
||||||
&message);
|
&message);
|
||||||
if (!r)
|
if (!r)
|
||||||
break;
|
break;
|
||||||
@@ -1188,8 +1193,8 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
|
|||||||
/* fall-through */
|
/* fall-through */
|
||||||
case N_DHCP4_C_CONNECTION_STATE_UDP:
|
case N_DHCP4_C_CONNECTION_STATE_UDP:
|
||||||
r = n_dhcp4_c_socket_udp_recv(connection->fd_udp,
|
r = n_dhcp4_c_socket_udp_recv(connection->fd_udp,
|
||||||
connection->scratch_buffer,
|
buffer,
|
||||||
sizeof(connection->scratch_buffer),
|
UINT16_MAX,
|
||||||
&message);
|
&message);
|
||||||
if (!r)
|
if (!r)
|
||||||
break;
|
break;
|
||||||
|
@@ -334,15 +334,6 @@ struct NDhcp4CConnection {
|
|||||||
uint32_t client_ip; /* client IP address, or 0 */
|
uint32_t client_ip; /* client IP address, or 0 */
|
||||||
uint32_t server_ip; /* server IP address, or 0 */
|
uint32_t server_ip; /* server IP address, or 0 */
|
||||||
uint16_t mtu; /* client mtu, or 0 */
|
uint16_t mtu; /* client mtu, or 0 */
|
||||||
|
|
||||||
/*
|
|
||||||
* When we get DHCP packets from the kernel, we need a buffer to read
|
|
||||||
* the data into. Since UDP packets can be up to 2^16 bytes in size, we
|
|
||||||
* avoid placing it on the stack and instead read into this scratch
|
|
||||||
* buffer. It is purely meant as stack replacement, no data is returned
|
|
||||||
* through this buffer.
|
|
||||||
*/
|
|
||||||
uint8_t scratch_buffer[UINT16_MAX];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define N_DHCP4_C_CONNECTION_NULL(_x) { \
|
#define N_DHCP4_C_CONNECTION_NULL(_x) { \
|
||||||
|
Reference in New Issue
Block a user