]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
move packet allocation to recv code to allow bigger buffers
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 8 Jul 2011 18:38:12 +0000 (20:38 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 8 Jul 2011 18:38:12 +0000 (20:38 +0200)
grub-core/net/drivers/efi/efinet.c
grub-core/net/drivers/emu/emunet.c
grub-core/net/drivers/i386/pc/pxe.c
grub-core/net/drivers/ieee1275/ofnet.c
grub-core/net/ip.c
grub-core/net/net.c
include/grub/net.h

index 0fc7799660145ec25df125af214b0139e8ac8fac..906a688dc06572bdb40cfcf62aa6e10ccbe47237 100644 (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 =
index 96f773340abd7f2f2fd295c9c2305a7fc90bcbe9..ff333d3701940dab1c676717d1c2fcf457fcd010 100644 (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 = 
index 588673177bda85f20d5dd6034503996eb5fc23ee..6c5f2fdc432c6ff97e32d9a58d5bf77f9d8519e5 100644 (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 
index 035a9622034688801dafa6c1a773a8353e3e64fc..9c0c84c6520d54bd2ebcff5084ad69e310f1a5f9 100644 (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 =
index ee3ccd4d640b6da4b605bf7191eec34c3bc87d9a..eaecc9ea695ccd89b9cfed196ea7debe8753fb4a 100644 (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));
index 7bed078e31bbb36a074f3c64001ca2fc79232eb2..ab0fbd3c5ad08e1c7a4f8282892412254caaf550 100644 (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);
-      if (!nb)
-       {
-         grub_print_error ();
-         card->last_poll = grub_get_time_ms ();
-         return;
-       }
 
-      actual = card->driver->recv (card, nb);
-      if (actual < 0)
+      nb = card->driver->recv (card);
+      if (!nb)
        {
-         grub_netbuff_free (nb);
          card->last_poll = grub_get_time_ms ();
          break;
        }
index f3c0489e20a66905e0ee33f75d5909835de926fd..83f260d63e19809a0049fd2af2c2d5564baf641e 100644 (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