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; return GRUB_ERR_NONE;
} }
static grub_ssize_t static struct grub_net_buff *
get_card_packet (const struct grub_net_card *dev, get_card_packet (const struct grub_net_card *dev)
struct grub_net_buff *nb)
{ {
grub_efi_simple_network_t *net = dev->efi_net; grub_efi_simple_network_t *net = dev->efi_net;
grub_err_t err; grub_err_t err;
grub_efi_status_t st; 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); nb = grub_netbuff_alloc (bufsize);
if (err) if (!nb)
return -1; return NULL;
err = grub_netbuff_put (nb, 1500); /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
if (err) by 4. So that IP header is aligned on 4 bytes. */
return -1; grub_netbuff_reserve (nb, 2);
if (!nb)
{
grub_netbuff_free (nb);
return NULL;
}
st = efi_call_7 (net->receive, net, NULL, &bufsize, st = efi_call_7 (net->receive, net, NULL, &bufsize,
nb->data, NULL, NULL, NULL); nb->data, NULL, NULL, NULL);
if (st == GRUB_EFI_BUFFER_TOO_SMALL) if (st == GRUB_EFI_BUFFER_TOO_SMALL)
{ {
err = grub_netbuff_put (nb, bufsize - 1500); grub_netbuff_free (nb);
if (err)
return -1; 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, st = efi_call_7 (net->receive, net, NULL, &bufsize,
nb->data, NULL, NULL, NULL); nb->data, NULL, NULL, NULL);
} }
if (st != GRUB_EFI_SUCCESS) if (st != GRUB_EFI_SUCCESS)
{ {
grub_netbuff_clear (nb); grub_netbuff_free (nb);
return -1; return NULL;
} }
err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize); err = grub_netbuff_put (nb, bufsize);
if (err) if (err)
return -1; {
grub_netbuff_free (nb);
return NULL;
}
return bufsize; return nb;
} }
static struct grub_net_card_driver efidriver = 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; return GRUB_ERR_NONE;
} }
static grub_ssize_t static struct grub_net_buff *
get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)), get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)))
struct grub_net_buff *pack)
{ {
ssize_t actual; ssize_t actual;
struct grub_net_buff *nb;
grub_netbuff_clear (pack); nb = grub_netbuff_alloc (1536);
actual = read (fd, pack->data, 1500); 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) 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 = static struct grub_net_card_driver emudriver =

View file

@ -164,14 +164,13 @@ grub_pxe_scan (void)
return bangpxe; return bangpxe;
} }
static grub_ssize_t static struct grub_net_buff *
grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)))
struct grub_net_buff *buf)
{ {
struct grub_pxe_undi_isr *isr; struct grub_pxe_undi_isr *isr;
static int in_progress = 0; static int in_progress = 0;
char *ptr, *end; char *ptr, *end;
int len; struct grub_net_buff *buf;
isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; 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) if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS)
{ {
in_progress = 0; in_progress = 0;
return -1; return NULL;
} }
grub_memset (isr, 0, sizeof (*isr)); grub_memset (isr, 0, sizeof (*isr));
isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; 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) if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE)
{ {
in_progress = 0; in_progress = 0;
return -1; return NULL;
} }
grub_memset (isr, 0, sizeof (*isr)); grub_memset (isr, 0, sizeof (*isr));
isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); 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; ptr = buf->data;
end = ptr + isr->frame_len; 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); grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
ptr += isr->buffer_len; ptr += isr->buffer_len;
while (ptr < end) 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) if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE)
{ {
in_progress = 1; in_progress = 1;
return -1; grub_netbuff_free (buf);
return NULL;
} }
grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); 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; in_progress = 1;
return len; return buf;
} }
static grub_err_t 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; return GRUB_ERR_NONE;
} }
static grub_ssize_t static struct grub_net_buff *
get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) get_card_packet (const struct grub_net_card *dev)
{ {
grub_ssize_t actual; grub_ssize_t actual;
int rc; int rc;
struct grub_ofnetcard_data *data = dev->data; struct grub_ofnetcard_data *data = dev->data;
grub_uint64_t start_time; 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 (); start_time = grub_get_time_ms ();
do 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)); while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
if (actual) if (actual)
{ {
grub_netbuff_put (nb, 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 = 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; struct grub_net_network_level_interface *inf = NULL;
grub_net_network_level_address_t source; 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) if ((iph->verhdrlen >> 4) != 4)
{ {
grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 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 /* Maybe should be better have a fixed number of packets for each card
and just mark them as used and not used. */ and just mark them as used and not used. */
struct grub_net_buff *nb; struct grub_net_buff *nb;
grub_ssize_t actual;
nb = grub_netbuff_alloc (1500); nb = card->driver->recv (card);
if (!nb) 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 (); card->last_poll = grub_get_time_ms ();
break; break;
} }

View file

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