Index: include/lwip/opt.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/lwip/opt.h,v
retrieving revision 1.124
diff -u -r1.124 opt.h
--- include/lwip/opt.h	11 Feb 2009 20:43:41 -0000	1.124
+++ include/lwip/opt.h	12 Feb 2009 18:32:22 -0000
@@ -357,6 +357,13 @@
 #define ETHARP_TRUST_IP_MAC             1
 #endif
 
+/**
+ * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header
+ */
+#ifndef ETHARP_SUPPORT_VLAN
+#define ETHARP_SUPPORT_VLAN             0
+#endif
+
 /*
    --------------------------------
    ---------- IP options ----------
Index: include/netif/etharp.h
===================================================================
RCS file: /sources/lwip/lwip/src/include/netif/etharp.h,v
retrieving revision 1.40
diff -u -r1.40 etharp.h
--- include/netif/etharp.h	9 Oct 2007 19:59:59 -0000	1.40
+++ include/netif/etharp.h	12 Feb 2009 18:43:58 -0000
@@ -85,13 +85,33 @@
 #  include "arch/epstruct.h"
 #endif
 
+#define SIZEOF_ETH_HDR 14
+
+#if ETHARP_SUPPORT_VLAN
+
+#ifdef PACK_STRUCT_USE_INCLUDES
+#  include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+struct eth_vlan_hdr {
+  PACK_STRUCT_FIELD(u16_t tpid);
+  PACK_STRUCT_FIELD(u16_t prio_vid);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+#  include "arch/epstruct.h"
+#endif
+
+#define SIZEOF_VLAN_HDR 4
+
+#endif /* ETHARP_SUPPORT_VLAN */
+
 #ifdef PACK_STRUCT_USE_INCLUDES
 #  include "arch/bpstruct.h"
 #endif
 PACK_STRUCT_BEGIN
 /** the ARP message */
 struct etharp_hdr {
-  PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
   PACK_STRUCT_FIELD(u16_t hwtype);
   PACK_STRUCT_FIELD(u16_t proto);
   PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
@@ -106,24 +126,15 @@
 #  include "arch/epstruct.h"
 #endif
 
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-struct ethip_hdr {
-  PACK_STRUCT_FIELD(struct eth_hdr eth);
-  PACK_STRUCT_FIELD(struct ip_hdr ip);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-#  include "arch/epstruct.h"
-#endif
+#define SIZEOF_ETHARP_HDR 18
+#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
 
 /** 5 seconds period */
 #define ARP_TMR_INTERVAL 5000
 
 #define ETHTYPE_ARP       0x0806
 #define ETHTYPE_IP        0x0800
+#define ETHTYPE_VLAN      0x8100
 #define ETHTYPE_PPPOEDISC 0x8863  /* PPP Over Ethernet Discovery Stage */
 #define ETHTYPE_PPPOE     0x8864  /* PPP Over Ethernet Session Stage */
 
Index: netif/etharp.c
===================================================================
RCS file: /sources/lwip/lwip/src/netif/etharp.c,v
retrieving revision 1.149
diff -u -r1.149 etharp.c
--- netif/etharp.c	3 Oct 2008 14:47:33 -0000	1.149
+++ netif/etharp.c	12 Feb 2009 18:48:37 -0000
@@ -580,13 +580,21 @@
 void
 etharp_ip_input(struct netif *netif, struct pbuf *p)
 {
-  struct ethip_hdr *hdr;
+  struct eth_hdr *ethhdr;
+  struct ip_hdr *iphdr;
   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
   /* Only insert an entry if the source IP address of the
      incoming IP packet comes from a host on the local network. */
-  hdr = p->payload;
+  ethhdr = p->payload;
+  iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
+#if ETHARP_SUPPORT_VLAN
+  if (ethhdr->type == ETHTYPE_VLAN) {
+    iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
+  }
+#endif /* ETHARP_SUPPORT_VLAN */
+
   /* source is not on the local network? */
-  if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
+  if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
     /* do nothing */
     return;
   }
@@ -595,7 +603,7 @@
   /* update ARP table */
   /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
    * back soon (for example, if the destination IP address is ours. */
-  update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), 0);
+  update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0);
 }
 
 
@@ -618,6 +626,7 @@
 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
 {
   struct etharp_hdr *hdr;
+  struct eth_hdr *ethhdr;
   /* these are aligned properly, whereas the ARP header fields might not be */
   struct ip_addr sipaddr, dipaddr;
   u8_t i;
@@ -630,24 +639,30 @@
   
   /* drop short ARP packets: we have to check for p->len instead of p->tot_len here
      since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
-  if (p->len < sizeof(struct etharp_hdr)) {
-    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));
+  if (p->len < SIZEOF_ETHARP_PACKET) {
+    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)SIZEOF_ETHARP_PACKET));
     ETHARP_STATS_INC(etharp.lenerr);
     ETHARP_STATS_INC(etharp.drop);
     pbuf_free(p);
     return;
   }
 
-  hdr = p->payload;
+  ethhdr = p->payload;
+  hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
+#if ETHARP_SUPPORT_VLAN
+  if (ethhdr->type == ETHTYPE_VLAN) {
+    hdr = (struct etharp_hdr *)(u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
+  }
+#endif /* ETHARP_SUPPORT_VLAN */
 
   /* RFC 826 "Packet Reception": */
   if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
       (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||
       (hdr->proto != htons(ETHTYPE_IP)) ||
-      (hdr->ethhdr.type != htons(ETHTYPE_ARP)))  {
+      (ethhdr->type != htons(ETHTYPE_ARP)))  {
     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1,
       ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
-      hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), hdr->ethhdr.type));
+      hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
     ETHARP_STATS_INC(etharp.proterr);
     ETHARP_STATS_INC(etharp.drop);
     pbuf_free(p);
@@ -720,12 +735,12 @@
         i--;
         hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
 #if LWIP_AUTOIP
-        hdr->ethhdr.dest.addr[i] = ethdst_hwaddr[i];
+        ethhdr->dest.addr[i] = ethdst_hwaddr[i];
 #else  /* LWIP_AUTOIP */
-        hdr->ethhdr.dest.addr[i] = hdr->shwaddr.addr[i];
+        ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
 #endif /* LWIP_AUTOIP */
         hdr->shwaddr.addr[i] = ethaddr->addr[i];
-        hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
+        ethhdr->src.addr[i] = ethaddr->addr[i];
       }
 
       /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
@@ -787,7 +802,7 @@
   struct eth_addr *dest, mcastaddr;
 
   /* make room for Ethernet header - should not fail */
-  if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
+  if (pbuf_header(q, SIZEOF_ETH_HDR) != 0) {
     /* bail out */
     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
     LINK_STATS_INC(link.lenerr);
@@ -1035,13 +1050,14 @@
   struct pbuf *p;
   err_t result = ERR_OK;
   u8_t k; /* ARP entry index */
+  struct eth_hdr *ethhdr;
   struct etharp_hdr *hdr;
 #if LWIP_AUTOIP
   const u8_t * ethdst_hwaddr;
 #endif /* LWIP_AUTOIP */
 
   /* allocate a pbuf for the outgoing ARP request packet */
-  p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
+  p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_PACKET, PBUF_RAM);
   /* could allocate a pbuf for an ARP request? */
   if (p == NULL) {
     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, ("etharp_raw: could not allocate pbuf for ARP request.\n"));
@@ -1049,9 +1065,10 @@
     return ERR_MEM;
   }
   LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
-              (p->len >= sizeof(struct etharp_hdr)));
+              (p->len >= SIZEOF_ETHARP_PACKET));
 
-  hdr = p->payload;
+  ethhdr = p->payload;
+  hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
   hdr->opcode = htons(opcode);
 
@@ -1071,11 +1088,11 @@
     hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
     /* Write the Ethernet MAC-Addresses */
 #if LWIP_AUTOIP
-    hdr->ethhdr.dest.addr[k] = ethdst_hwaddr[k];
+    ethhdr->dest.addr[k] = ethdst_hwaddr[k];
 #else  /* LWIP_AUTOIP */
-    hdr->ethhdr.dest.addr[k] = ethdst_addr->addr[k];
+    ethhdr->dest.addr[k] = ethdst_addr->addr[k];
 #endif /* LWIP_AUTOIP */
-    hdr->ethhdr.src.addr[k]  = ethsrc_addr->addr[k];
+    ethhdr->src.addr[k]  = ethsrc_addr->addr[k];
   }
   hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr;
   hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr;
@@ -1085,7 +1102,7 @@
   /* set hwlen and protolen together */
   hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr));
 
-  hdr->ethhdr.type = htons(ETHTYPE_ARP);
+  ethhdr->type = htons(ETHTYPE_ARP);
   /* send ARP query */
   result = netif->linkoutput(netif, p);
   ETHARP_STATS_INC(etharp.xmit);
@@ -1146,7 +1163,7 @@
       etharp_ip_input(netif, p);
 #endif /* ETHARP_TRUST_IP_MAC */
       /* skip Ethernet header */
-      if(pbuf_header(p, -(s16_t)sizeof(struct eth_hdr))) {
+      if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
         LWIP_ASSERT("Can't move over header in packet", 0);
         pbuf_free(p);
         p = NULL;

