ofnet: implement the receive buffer
get_card_packet() from ofnet.c allocates a netbuff based on the device's MTU: nb = grub_netbuff_alloc (dev->mtu + 64 + 2); In the case when the MTU is large, and the received packet is relatively small, this leads to allocation of significantly more memory, than it's required. An example could be transmission of TFTP packets with 0x400 blksize via a network card with 0x10000 MTU. This patch implements a per-card receive buffer in a way similar to efinet.c, and makes get_card_packet() allocate a netbuff of the received data size. Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
parent
7b4c54c4ad
commit
130234bc78
1 changed files with 75 additions and 15 deletions
|
@ -85,26 +85,32 @@ get_card_packet (struct grub_net_card *dev)
|
||||||
grub_uint64_t start_time;
|
grub_uint64_t start_time;
|
||||||
struct grub_net_buff *nb;
|
struct grub_net_buff *nb;
|
||||||
|
|
||||||
nb = grub_netbuff_alloc (dev->mtu + 64 + 2);
|
start_time = grub_get_time_ms ();
|
||||||
|
do
|
||||||
|
rc = grub_ieee1275_read (data->handle, dev->rcvbuf, dev->rcvbufsize, &actual);
|
||||||
|
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
|
||||||
|
|
||||||
|
if (actual <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nb = grub_netbuff_alloc (actual + 2);
|
||||||
if (!nb)
|
if (!nb)
|
||||||
return NULL;
|
return NULL;
|
||||||
/* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
|
/* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
|
||||||
by 4. So that IP header is aligned on 4 bytes. */
|
by 4. So that IP header is aligned on 4 bytes. */
|
||||||
grub_netbuff_reserve (nb, 2);
|
grub_netbuff_reserve (nb, 2);
|
||||||
|
|
||||||
start_time = grub_get_time_ms ();
|
grub_memcpy (nb->data, dev->rcvbuf, actual);
|
||||||
do
|
|
||||||
rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual);
|
if (grub_netbuff_put (nb, actual))
|
||||||
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
|
|
||||||
if (actual > 0)
|
|
||||||
{
|
{
|
||||||
grub_netbuff_put (nb, actual);
|
|
||||||
return nb;
|
|
||||||
}
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nb;
|
||||||
|
}
|
||||||
|
|
||||||
static struct grub_net_card_driver ofdriver =
|
static struct grub_net_card_driver ofdriver =
|
||||||
{
|
{
|
||||||
.name = "ofnet",
|
.name = "ofnet",
|
||||||
|
@ -327,6 +333,40 @@ grub_ieee1275_alloc_mem (grub_size_t len)
|
||||||
return (void *)args.result;
|
return (void *)args.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free memory allocated by alloc-mem */
|
||||||
|
static grub_err_t
|
||||||
|
grub_ieee1275_free_mem (void *addr, grub_size_t len)
|
||||||
|
{
|
||||||
|
struct free_args
|
||||||
|
{
|
||||||
|
struct grub_ieee1275_common_hdr common;
|
||||||
|
grub_ieee1275_cell_t method;
|
||||||
|
grub_ieee1275_cell_t len;
|
||||||
|
grub_ieee1275_cell_t addr;
|
||||||
|
grub_ieee1275_cell_t catch;
|
||||||
|
}
|
||||||
|
args;
|
||||||
|
|
||||||
|
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("interpret is not supported"));
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_IEEE1275_COMMON (&args.common, "interpret", 3, 1);
|
||||||
|
args.addr = (grub_ieee1275_cell_t)addr;
|
||||||
|
args.len = len;
|
||||||
|
args.method = (grub_ieee1275_cell_t) "free-mem";
|
||||||
|
|
||||||
|
if (IEEE1275_CALL_ENTRY_FN(&args) == -1 || args.catch)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_INVALID_COMMAND, N_("free-mem failed"));
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
ofnet_alloc_netbuf (grub_size_t len)
|
ofnet_alloc_netbuf (grub_size_t len)
|
||||||
{
|
{
|
||||||
|
@ -336,6 +376,15 @@ ofnet_alloc_netbuf (grub_size_t len)
|
||||||
return grub_zalloc (len);
|
return grub_zalloc (len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ofnet_free_netbuf (void *addr, grub_size_t len)
|
||||||
|
{
|
||||||
|
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
|
||||||
|
grub_ieee1275_free_mem (addr, len);
|
||||||
|
else
|
||||||
|
grub_free (addr);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
search_net_devices (struct grub_ieee1275_devalias *alias)
|
search_net_devices (struct grub_ieee1275_devalias *alias)
|
||||||
{
|
{
|
||||||
|
@ -451,15 +500,19 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
|
||||||
card->default_address = lla;
|
card->default_address = lla;
|
||||||
|
|
||||||
card->txbufsize = ALIGN_UP (card->mtu, 64) + 256;
|
card->txbufsize = ALIGN_UP (card->mtu, 64) + 256;
|
||||||
|
card->rcvbufsize = ALIGN_UP (card->mtu, 64) + 256;
|
||||||
|
|
||||||
card->txbuf = ofnet_alloc_netbuf (card->txbufsize);
|
card->txbuf = ofnet_alloc_netbuf (card->txbufsize);
|
||||||
if (!card->txbuf)
|
if (!card->txbuf)
|
||||||
|
goto fail_netbuf;
|
||||||
|
|
||||||
|
card->rcvbuf = ofnet_alloc_netbuf (card->rcvbufsize);
|
||||||
|
if (!card->rcvbuf)
|
||||||
{
|
{
|
||||||
grub_free (ofdata->path);
|
grub_error_push ();
|
||||||
grub_free (ofdata);
|
ofnet_free_netbuf (card->txbuf, card->txbufsize);
|
||||||
grub_free (card);
|
grub_error_pop ();
|
||||||
grub_print_error ();
|
goto fail_netbuf;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
card->driver = NULL;
|
card->driver = NULL;
|
||||||
card->data = ofdata;
|
card->data = ofdata;
|
||||||
|
@ -472,6 +525,13 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
|
||||||
card->driver = &ofdriver;
|
card->driver = &ofdriver;
|
||||||
grub_net_card_register (card);
|
grub_net_card_register (card);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail_netbuf:
|
||||||
|
grub_free (ofdata->path);
|
||||||
|
grub_free (ofdata);
|
||||||
|
grub_free (card);
|
||||||
|
grub_print_error ();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue