grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] efinet: add efinet_multicast_filter command


From: Vladimir 'phcoder' Serbinenko
Subject: Re: [PATCH] efinet: add efinet_multicast_filter command
Date: Thu, 5 Nov 2015 21:28:09 +0100

I don't have EFI spec under my hand now. Can we get away with making it a default or at least for the case when no interface overrides mac address. Extra config to workaround firmware bugs is usually harmful

Le 5 nov. 2015 9:17 PM, "Josef Bacik" <address@hidden> a écrit :
We have some hardware that doesn't honor
EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST properly so we aren't getting
RA's that are multicasted properly (our switches respond to solicitations with a
multicast rather than a unicast).  I don't want to add this filtering by
default, so add a new command to allow a user to specify a multicast receive
filter.  We use it like this

efinet_multicast_filter efinet0 33:33:0:0:0:1

to get ipv6 multicasts which allows us to receive the router advertisements.
Thanks,

Signed-off-by: Josef Bacik <address@hidden>
---
 grub-core/kern/efi/efi.c           | 12 ++++-----
 grub-core/net/drivers/efi/efinet.c | 51 ++++++++++++++++++++++++++++++++++++++
 grub-core/net/net.c                | 43 ++++++++++++++++++++++++++++++++
 include/grub/efi/api.h             |  5 +++-
 include/grub/net.h                 |  3 +++
 5 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 2e77834..efc3d33 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -652,12 +652,12 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
                grub_efi_mac_address_device_path_t *mac
                  = (grub_efi_mac_address_device_path_t *) dp;
                grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)",
-                            (unsigned) mac->mac_address[0],
-                            (unsigned) mac->mac_address[1],
-                            (unsigned) mac->mac_address[2],
-                            (unsigned) mac->mac_address[3],
-                            (unsigned) mac->mac_address[4],
-                            (unsigned) mac->mac_address[5],
+                            (unsigned) mac->mac_address.addr[0],
+                            (unsigned) mac->mac_address.addr[1],
+                            (unsigned) mac->mac_address.addr[2],
+                            (unsigned) mac->mac_address.addr[3],
+                            (unsigned) mac->mac_address.addr[4],
+                            (unsigned) mac->mac_address.addr[5],
                             (unsigned) mac->if_type);
              }
              break;
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index c8f80a1..8c2c4f8 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -23,6 +23,7 @@
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
 #include <grub/i18n.h>
+#include <grub/command.h>

 GRUB_MOD_LICENSE ("GPLv3+");

@@ -451,9 +452,58 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
   }
 }

+static grub_err_t
+grub_cmd_multicast_filter (struct grub_command *cmd __attribute__ ((unused)),
+                          int argc, char **args)
+{
+  struct grub_net_card *card;
+  grub_efi_simple_network_t *net;
+  grub_net_link_level_address_t hwaddr;
+  grub_efi_mac_address_t filter_mac[1];
+  grub_efi_status_t st;
+
+  if (argc != 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
+
+  FOR_NET_CARDS (card)
+    if (grub_strcmp (card->name, args[0]) == 0)
+      break;
+
+  if (card == NULL)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
+  if (card->driver != &efidriver)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not an efi card"));
+
+  if (grub_net_str_to_hwaddr (args[1], &hwaddr) == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("couldn't parse hw address"));
+  grub_memset (filter_mac, 0, sizeof(filter_mac));
+  grub_memcpy (filter_mac, hwaddr.mac, 6);
+
+  net = card->efi_net;
+  if (!(net->mode->receive_filter_mask &
+       GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST))
+    return grub_error (GRUB_ERR_IO,
+                      N_("device doesn't support multicast filtering"));
+
+  st = efi_call_6 (net->receive_filters, net,
+                  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, 0, 0, 1,
+                  filter_mac);
+  if (st != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_IO,
+                      N_("could not set multicast filter address"));
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_multicast_filter;
+
 GRUB_MOD_INIT(efinet)
 {
   grub_efinet_findcards ();
+  cmd_multicast_filter = grub_register_command ("efinet_multicast_filter",
+                                               grub_cmd_multicast_filter,
+                                               N_("CARD HWADDRESS"),
+                                               N_("Add a multicast filter"));
   grub_efi_net_config = grub_efi_net_config_real;
 }

@@ -464,5 +514,6 @@ GRUB_MOD_FINI(efinet)
   FOR_NET_CARDS_SAFE (card, next)
     if (card->driver == &efidriver)
       grub_net_card_unregister (card);
+  grub_unregister_command(cmd_multicast_filter);
 }

diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 65bea28..3a69f63 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -480,6 +480,49 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
   return 1;
 }

+int
+grub_net_str_to_hwaddr (const char *val, grub_net_link_level_address_t *hwaddr)
+{
+  grub_uint8_t newmac[6];
+  const char *ptr = val;
+  int word;
+
+  if (ptr[0] == ':' && ptr[1] != ':')
+    return 0;
+  if (ptr[0] == ':')
+    ptr++;
+
+  for (word = 0; word < 6; word++)
+    {
+      unsigned long t;
+      if (*ptr == ':')
+       {
+         word--;
+         ptr++;
+         continue;
+       }
+      t = grub_strtoul (ptr, (char **) &ptr, 16);
+      if (grub_errno)
+       {
+         grub_errno = GRUB_ERR_NONE;
+         break;
+       }
+      if (t & ~0xff)
+       return 0;
+      newmac[word] = t;
+      if (*ptr != ':')
+       break;
+      ptr++;
+    }
+  if (*ptr != 0)
+         return grub_error (GRUB_ERR_NET_BAD_ADDRESS,
+                            N_("unrecognized link level address '%s'"),
+                            val);
+  hwaddr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+  grub_memcpy (hwaddr->mac, newmac, 6);
+  return 1;
+}
+
 static int
 match_net (const grub_net_network_level_netaddress_t *net,
           const grub_net_network_level_address_t *addr)
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 9a73976..48940be 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -523,7 +523,10 @@ typedef void *grub_efi_handle_t;
 typedef void *grub_efi_event_t;
 typedef grub_efi_uint64_t grub_efi_lba_t;
 typedef grub_efi_uintn_t grub_efi_tpl_t;
-typedef grub_uint8_t grub_efi_mac_address_t[32];
+typedef struct {
+       grub_uint8_t addr[32];
+} grub_efi_mac_address_t;
+
 typedef grub_uint8_t grub_efi_ipv4_address_t[4];
 typedef grub_uint16_t grub_efi_ipv6_address_t[8];
 typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4)));
diff --git a/include/grub/net.h b/include/grub/net.h
index a1ff519..12cc1db 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -522,6 +522,9 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target,
                      char *buf);
 void
 grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str);
+int
+grub_net_str_to_hwaddr (const char *val,
+                       grub_net_link_level_address_t *hwaddr);

 grub_err_t
 grub_env_set_net_property (const char *intername, const char *suffix,
--
1.8.1


_______________________________________________
Grub-devel mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/grub-devel

reply via email to

[Prev in Thread] Current Thread [Next in Thread]