- 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) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel