move packet allocation to recv code to allow bigger buffers

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-07-08 20:38:12 +02:00
parent 6a1af81a97
commit e2955971a3
7 changed files with 105 additions and 55 deletions

View file

@ -42,43 +42,65 @@ send_card_buffer (const struct grub_net_card *dev,
return GRUB_ERR_NONE;
}
static grub_ssize_t
get_card_packet (const struct grub_net_card *dev,
struct grub_net_buff *nb)
static struct grub_net_buff *
get_card_packet (const struct grub_net_card *dev)
{
grub_efi_simple_network_t *net = dev->efi_net;
grub_err_t err;
grub_efi_status_t st;
grub_efi_uintn_t bufsize = 1500;
grub_efi_uintn_t bufsize = 1536;
struct grub_net_buff *nb;
err = grub_netbuff_clear (nb);
if (err)
return -1;
nb = grub_netbuff_alloc (bufsize);
if (!nb)
return NULL;
err = grub_netbuff_put (nb, 1500);
if (err)
return -1;
/* 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. */
grub_netbuff_reserve (nb, 2);
if (!nb)
{
grub_netbuff_free (nb);
return NULL;
}
st = efi_call_7 (net->receive, net, NULL, &bufsize,
nb->data, NULL, NULL, NULL);
if (st == GRUB_EFI_BUFFER_TOO_SMALL)
{
err = grub_netbuff_put (nb, bufsize - 1500);
if (err)
return -1;
grub_netbuff_free (nb);
bufsize = ALIGN_UP (bufsize, 32);
nb = grub_netbuff_alloc (bufsize);
if (!nb)
return NULL;
/* 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. */
grub_netbuff_reserve (nb, 2);
if (!nb)
{
grub_netbuff_free (nb);
return NULL;
}
st = efi_call_7 (net->receive, net, NULL, &bufsize,
nb->data, NULL, NULL, NULL);
}
if (st != GRUB_EFI_SUCCESS)
{
grub_netbuff_clear (nb);
return -1;
grub_netbuff_free (nb);
return NULL;
}
err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize);
err = grub_netbuff_put (nb, bufsize);
if (err)
return -1;
{
grub_netbuff_free (nb);
return NULL;
}
return bufsize;
return nb;
}
static struct grub_net_card_driver efidriver =

View file

@ -43,19 +43,34 @@ send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)),
return GRUB_ERR_NONE;
}
static grub_ssize_t
get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)),
struct grub_net_buff *pack)
static struct grub_net_buff *
get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)))
{
ssize_t actual;
struct grub_net_buff *nb;
grub_netbuff_clear (pack);
actual = read (fd, pack->data, 1500);
nb = grub_netbuff_alloc (1536);
if (!nb)
return NULL;
/* 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. */
grub_netbuff_reserve (nb, 2);
if (!nb)
{
grub_netbuff_free (nb);
return NULL;
}
actual = read (fd, nb->data, 1536);
if (actual < 0)
return -1;
grub_netbuff_put (pack, actual);
{
grub_netbuff_free (nb);
return NULL;
}
grub_netbuff_put (nb, actual);
return actual;
return nb;
}
static struct grub_net_card_driver emudriver =

View file

@ -164,14 +164,13 @@ grub_pxe_scan (void)
return bangpxe;
}
static grub_ssize_t
grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
struct grub_net_buff *buf)
static struct grub_net_buff *
grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)))
{
struct grub_pxe_undi_isr *isr;
static int in_progress = 0;
char *ptr, *end;
int len;
struct grub_net_buff *buf;
isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
@ -183,7 +182,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS)
{
in_progress = 0;
return -1;
return NULL;
}
grub_memset (isr, 0, sizeof (*isr));
isr->func_flag = GRUB_PXE_ISR_IN_PROCESS;
@ -201,17 +200,27 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE)
{
in_progress = 0;
return -1;
return NULL;
}
grub_memset (isr, 0, sizeof (*isr));
isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
}
grub_netbuff_put (buf, isr->frame_len);
buf = grub_netbuff_alloc (isr->frame_len);
if (!buf)
return NULL;
/* 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. */
grub_netbuff_reserve (buf, 2);
if (!buf)
{
grub_netbuff_free (buf);
return NULL;
}
ptr = buf->data;
end = ptr + isr->frame_len;
len = isr->frame_len;
grub_netbuff_put (buf, isr->frame_len);
grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
ptr += isr->buffer_len;
while (ptr < end)
@ -222,7 +231,8 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE)
{
in_progress = 1;
return -1;
grub_netbuff_free (buf);
return NULL;
}
grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
@ -230,7 +240,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
}
in_progress = 1;
return len;
return buf;
}
static grub_err_t

View file

@ -73,25 +73,35 @@ send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack)
return GRUB_ERR_NONE;
}
static grub_ssize_t
get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb)
static struct grub_net_buff *
get_card_packet (const struct grub_net_card *dev)
{
grub_ssize_t actual;
int rc;
struct grub_ofnetcard_data *data = dev->data;
grub_uint64_t start_time;
struct grub_net_buff *nb;
grub_netbuff_clear (nb);
nb = grub_netbuff_alloc (dev->mtu + 64);
/* 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. */
grub_netbuff_reserve (nb, 2);
if (!nb)
{
grub_netbuff_free (nb);
return NULL;
}
start_time = grub_get_time_ms ();
do
rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu, &actual);
rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual);
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
if (actual)
{
grub_netbuff_put (nb, actual);
return actual;
return nb;
}
return -1;
grub_netbuff_free (nb);
return NULL;
}
static struct grub_net_card_driver ofdriver =

View file

@ -123,6 +123,9 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb,
struct grub_net_network_level_interface *inf = NULL;
grub_net_network_level_address_t source;
if (((grub_addr_t) nb->data) & 3)
grub_fatal ("unaligned %p\n", nb->data);
if ((iph->verhdrlen >> 4) != 4)
{
grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4));

View file

@ -764,19 +764,10 @@ receive_packets (struct grub_net_card *card)
/* Maybe should be better have a fixed number of packets for each card
and just mark them as used and not used. */
struct grub_net_buff *nb;
grub_ssize_t actual;
nb = grub_netbuff_alloc (1500);
nb = card->driver->recv (card);
if (!nb)
{
grub_print_error ();
card->last_poll = grub_get_time_ms ();
return;
}
actual = card->driver->recv (card, nb);
if (actual < 0)
{
grub_netbuff_free (nb);
card->last_poll = grub_get_time_ms ();
break;
}

View file

@ -64,8 +64,7 @@ struct grub_net_card_driver
void (*close) (const struct grub_net_card *dev);
grub_err_t (*send) (const struct grub_net_card *dev,
struct grub_net_buff *buf);
grub_ssize_t (*recv) (const struct grub_net_card *dev,
struct grub_net_buff *buf);
struct grub_net_buff * (*recv) (const struct grub_net_card *dev);
};
typedef struct grub_net_packet