grub-devel
[Top][All Lists]
Advanced

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

[PATCH] [next] net: VLAN cleanup


From: Andrei Borzenkov
Subject: [PATCH] [next] net: VLAN cleanup
Date: Mon, 7 Mar 2016 23:40:19 +0300

- strip priority bits in received packets. We do not control them and need
  to compare VLAN number only, which takes just 12 bits.

- store VLAN number and priority bits separately in interface structure.

- fix VLAN comparison when searching for matching interface. We need to
  continiue, not break out of loop, if VLAN number does not match.

- add missing VLAN check in BOOTP/DHCP processing.

- introduce 802.1Q header structure to avoid shuffling parts of packet around.
  This streamlines code and makes it more clear.

- remove misleading dprintf - non-matching VLAN is not really an error. It is
  quite possible to have multiple interfaces on the same physical card with
  different VLAN numbers.

- pass VLAN number by value, there is no need to use reference.

- print VLAN ID in net_ls_addr

---
 grub-core/net/arp.c                    | 10 ++---
 grub-core/net/drivers/ieee1275/ofnet.c |  4 +-
 grub-core/net/ethernet.c               | 79 +++++++++++++++++-----------------
 grub-core/net/ip.c                     | 21 ++++-----
 grub-core/net/net.c                    |  5 ++-
 include/grub/net.h                     |  3 +-
 include/grub/net/arp.h                 |  2 +-
 include/grub/net/ethernet.h            |  1 +
 include/grub/net/ip.h                  |  2 +-
 9 files changed, 62 insertions(+), 65 deletions(-)

diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
index 54306e3..2c57032 100644
--- a/grub-core/net/arp.c
+++ b/grub-core/net/arp.c
@@ -112,7 +112,7 @@ grub_net_arp_send_request (struct 
grub_net_network_level_interface *inf,
 
 grub_err_t
 grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card,
-                      grub_uint16_t *vlantag)
+                      grub_uint16_t vlantag)
 {
   struct arppkt *arp_packet = (struct arppkt *) nb->data;
   grub_net_network_level_address_t sender_addr, target_addr;
@@ -139,12 +139,8 @@ grub_net_arp_receive (struct grub_net_buff *nb, struct 
grub_net_card *card,
   FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
   {
     /* Verify vlantag id */
-    if (inf->card == card && inf->vlantag != *vlantag)
-      {
-        grub_dprintf ("net", "invalid vlantag! %x != %x\n",
-                      inf->vlantag, *vlantag);
-        break;
-      }
+    if (inf->vlantag != vlantag)
+      continue;
 
     /* Am I the protocol address target? */
     if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
diff --git a/grub-core/net/drivers/ieee1275/ofnet.c 
b/grub-core/net/drivers/ieee1275/ofnet.c
index 9d83c9f..0283a51 100644
--- a/grub-core/net/drivers/ieee1275/ofnet.c
+++ b/grub-core/net/drivers/ieee1275/ofnet.c
@@ -212,10 +212,10 @@ grub_ieee1275_parse_bootargs (const char *devpath, char 
*bootpath,
                                   hw_addr.mac, sizeof(hw_addr.mac), 0);
       inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr,
                                  flags);
-      inter->vlantag = vlantag;
+      inter->vlantag = vlantag & 0xfff;
+      inter->prio = vlantag & 0xf000;
       grub_net_add_ipv4_local (inter,
                           __builtin_ctz (~grub_le_to_cpu32 
(subnet_mask.ipv4)));
-
     }
 
   if (gateway_addr.ipv4 != 0)
diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c
index 4d7ceed..3541d8c 100644
--- a/grub-core/net/ethernet.c
+++ b/grub-core/net/ethernet.c
@@ -36,6 +36,12 @@ struct etherhdr
   grub_uint16_t type;
 } GRUB_PACKED;
 
+struct vlanhdr
+{
+  grub_uint16_t vtag;
+  grub_uint16_t type;
+} GRUB_PACKED;
+
 struct llchdr
 {
   grub_uint8_t dsap;
@@ -56,18 +62,25 @@ send_ethernet_packet (struct 
grub_net_network_level_interface *inf,
                      grub_net_ethertype_t ethertype)
 {
   struct etherhdr *eth;
+  struct vlanhdr *vlan;
   grub_err_t err;
-  grub_uint8_t etherhdr_size;
-  grub_uint16_t vlantag_id = VLANTAG_IDENTIFIER;
 
-  etherhdr_size = sizeof (*eth);
-  COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE);
+  COMPILE_TIME_ASSERT (sizeof (*eth) + sizeof (*vlan) < 
GRUB_NET_MAX_LINK_HEADER_SIZE);
 
-  /* Increase ethernet header in case of vlantag */
-  if (inf->vlantag != 0)
-    etherhdr_size += 4;
+  /* Add 802.1Q header in case of vlantag or priority */
+  if (inf->vlantag || inf->prio)
+    {
+      err = grub_netbuff_push (nb, sizeof (*vlan));
+      if (err)
+       return err;
 
-  err = grub_netbuff_push (nb, etherhdr_size);
+      vlan = (struct vlanhdr *) nb->data;
+      vlan->vtag = grub_cpu_to_be16 (inf->vlantag | inf->prio);
+      vlan->type = grub_cpu_to_be16 (ethertype);
+      ethertype = GRUB_NET_ETHERTYPE_802_1Q;
+    }
+
+  err = grub_netbuff_push (nb, sizeof (*eth));
   if (err)
     return err;
   eth = (struct etherhdr *) nb->data;
@@ -84,19 +97,6 @@ send_ethernet_packet (struct 
grub_net_network_level_interface *inf,
        return err;
       inf->card->opened = 1;
     }
-
-  /* Check and add a vlan-tag if needed. */
-  if (inf->vlantag != 0)
-    {
-      /* Move eth type to the right */
-      grub_memcpy ((char *) nb->data + etherhdr_size - 2,
-                   (char *) nb->data + etherhdr_size - 6, 2);
-
-      /* Add the tag in the middle */
-      grub_memcpy ((char *) nb->data + etherhdr_size - 6, &vlantag_id, 2);
-      grub_memcpy ((char *) nb->data + etherhdr_size - 4, (char *) 
&(inf->vlantag), 2);
-    }
-
   return inf->card->driver->send (inf->card, nb);
 }
 
@@ -105,33 +105,31 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
                               struct grub_net_card *card)
 {
   struct etherhdr *eth;
+  struct vlanhdr *vlan;
   struct llchdr *llch;
   struct snaphdr *snaph;
   grub_net_ethertype_t type;
   grub_net_link_level_address_t hwaddress;
   grub_net_link_level_address_t src_hwaddress;
   grub_err_t err;
-  grub_uint8_t etherhdr_size = sizeof (*eth);
   grub_uint16_t vlantag = 0;
 
-
-  /* Check if a vlan-tag is present. If so, the ethernet header is 4 bytes */
-  /* longer than the original one. The vlantag id is extracted and the header 
*/
-  /* is reseted to the original size. */
-  if (grub_get_unaligned16 (nb->data + etherhdr_size - 2) == 
VLANTAG_IDENTIFIER)
-    {
-      vlantag = grub_get_unaligned16 (nb->data + etherhdr_size);
-      etherhdr_size += 4;
-      /* Move eth type to the original position */
-      grub_memcpy((char *) nb->data + etherhdr_size - 6,
-                  (char *) nb->data + etherhdr_size - 2, 2);
-    }
-
   eth = (struct etherhdr *) nb->data;
-  type = grub_be_to_cpu16 (eth->type);
-  err = grub_netbuff_pull (nb, etherhdr_size);
+  err = grub_netbuff_pull (nb, sizeof (*eth));
   if (err)
     return err;
+  type = grub_be_to_cpu16 (eth->type);
+
+  /* Check if a vlan-tag is present. */
+  if (type == GRUB_NET_ETHERTYPE_802_1Q)
+    {
+      vlan = (struct vlanhdr *) nb->data;
+      err = grub_netbuff_pull (nb, sizeof (*vlan));
+      if (err)
+       return err;
+      vlantag = grub_be_to_cpu16 (vlan->vtag) & 0xfff;
+      type = grub_be_to_cpu16 (vlan->type);
+    }
 
   if (type <= 1500)
     {
@@ -157,14 +155,17 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
     {
       /* ARP packet. */
     case GRUB_NET_ETHERTYPE_ARP:
-      grub_net_arp_receive (nb, card, &vlantag);
+      grub_net_arp_receive (nb, card, vlantag);
       grub_netbuff_free (nb);
       return GRUB_ERR_NONE;
       /* IP packet.  */
     case GRUB_NET_ETHERTYPE_IP:
     case GRUB_NET_ETHERTYPE_IP6:
       return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress,
-                                       &vlantag);
+                                       vlantag);
+    case GRUB_NET_ETHERTYPE_802_1Q:
+      /* pacify compiler */
+      break;
     }
   grub_netbuff_free (nb);
   return GRUB_ERR_NONE;
diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
index ffdc760..afa35ef 100644
--- a/grub-core/net/ip.c
+++ b/grub-core/net/ip.c
@@ -228,7 +228,7 @@ handle_dgram (struct grub_net_buff *nb,
              grub_net_ip_protocol_t proto,
              const grub_net_network_level_address_t *source,
              const grub_net_network_level_address_t *dest,
-              grub_uint16_t *vlantag,
+              grub_uint16_t vlantag,
              grub_uint8_t ttl)
 {
   struct grub_net_network_level_interface *inf = NULL;
@@ -274,6 +274,7 @@ handle_dgram (struct grub_net_buff *nb,
        
        FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
          if (inf->card == card
+             && inf->vlantag == vlantag
              && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
              && inf->hwaddress.type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET
              && grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr,
@@ -290,19 +291,15 @@ handle_dgram (struct grub_net_buff *nb,
 
   FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
   {
+    /* Verify vlantag id */
+    if (inf->vlantag != vlantag)
+      continue;
+
     if (inf->card == card
        && grub_net_addr_cmp (&inf->address, dest) == 0
        && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
       break;
 
-    /* Verify vlantag id */
-    if (inf->card == card && inf->vlantag != *vlantag)
-      {
-        grub_dprintf ("net", "invalid vlantag! %x != %x\n",
-                      inf->vlantag, *vlantag);
-        break;
-      }
-
     /* Solicited node multicast.  */
     if (inf->card == card
        && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
@@ -392,7 +389,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
                           struct grub_net_card *card,
                           const grub_net_link_level_address_t *hwaddress,
                           const grub_net_link_level_address_t *src_hwaddress,
-                           grub_uint16_t *vlantag)
+                           grub_uint16_t vlantag)
 {
   struct iphdr *iph = (struct iphdr *) nb->data;
   grub_err_t err;
@@ -662,7 +659,7 @@ grub_net_recv_ip6_packets (struct grub_net_buff *nb,
                           struct grub_net_card *card,
                           const grub_net_link_level_address_t *hwaddress,
                           const grub_net_link_level_address_t *src_hwaddress,
-                           grub_uint16_t *vlantag)
+                           grub_uint16_t vlantag)
 {
   struct ip6hdr *iph = (struct ip6hdr *) nb->data;
   grub_err_t err;
@@ -721,7 +718,7 @@ grub_net_recv_ip_packets (struct grub_net_buff *nb,
                          struct grub_net_card *card,
                          const grub_net_link_level_address_t *hwaddress,
                          const grub_net_link_level_address_t *src_hwaddress,
-                          grub_uint16_t *vlantag)
+                          grub_uint16_t vlantag)
 {
   struct iphdr *iph = (struct iphdr *) nb->data;
 
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 9424595..40125e1 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1247,7 +1247,10 @@ grub_cmd_listaddrs (struct grub_command *cmd 
__attribute__ ((unused)),
     char bufn[GRUB_NET_MAX_STR_ADDR_LEN];
     grub_net_hwaddr_to_str (&inf->hwaddress, bufh);
     grub_net_addr_to_str (&inf->address, bufn);
-    grub_printf ("%s %s %s\n", inf->name, bufh, bufn);
+    grub_printf ("%s %s %s", inf->name, bufh, bufn);
+    if (inf->vlantag)
+      grub_printf (" VID=%u", inf->vlantag);
+    grub_printf ("\n");
   }
   return GRUB_ERR_NONE;
 }
diff --git a/include/grub/net.h b/include/grub/net.h
index 1096b24..20fb832 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -292,6 +292,7 @@ struct grub_net_network_level_interface
   struct grub_net_bootp_packet *dhcp_ack;
   grub_size_t dhcp_acklen;
   grub_uint16_t vlantag;
+  grub_uint16_t prio;
   void *data;
 };
 
@@ -562,6 +563,4 @@ extern char *grub_net_default_server;
 #define GRUB_NET_INTERVAL 400
 #define GRUB_NET_INTERVAL_ADDITION 20
 
-#define VLANTAG_IDENTIFIER 0x8100
-
 #endif /* ! GRUB_NET_HEADER */
diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h
index 8d9d081..c82f3a2 100644
--- a/include/grub/net/arp.h
+++ b/include/grub/net/arp.h
@@ -23,7 +23,7 @@
 
 extern grub_err_t grub_net_arp_receive (struct grub_net_buff *nb,
                                         struct grub_net_card *card,
-                                        grub_uint16_t *vlantag);
+                                        grub_uint16_t vlantag);
 
 grub_err_t
 grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h
index 23a935e..78c5ebc 100644
--- a/include/grub/net/ethernet.h
+++ b/include/grub/net/ethernet.h
@@ -27,6 +27,7 @@ typedef enum
     GRUB_NET_ETHERTYPE_IP = 0x0800,
     GRUB_NET_ETHERTYPE_ARP = 0x0806,
     GRUB_NET_ETHERTYPE_IP6 = 0x86DD,
+    GRUB_NET_ETHERTYPE_802_1Q = 0x8100,
   } grub_net_ethertype_t;
 
 grub_err_t 
diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h
index ab9d68f..de934bd 100644
--- a/include/grub/net/ip.h
+++ b/include/grub/net/ip.h
@@ -49,7 +49,7 @@ grub_net_recv_ip_packets (struct grub_net_buff *nb,
                          struct grub_net_card *card,
                          const grub_net_link_level_address_t *hwaddress,
                          const grub_net_link_level_address_t *src_hwaddress,
-                          grub_uint16_t *vlantag);
+                          grub_uint16_t vlantag);
 
 grub_err_t
 grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
-- 
tg: (b4fc7bc..) n/vlan-cleanup (depends on: next)



reply via email to

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