diff options
author | wdenk <wdenk> | 2004-04-15 21:48:45 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2004-04-15 21:48:45 +0000 |
commit | a3d991bd0da8b9fb9dbf2c7481091c3d082b9b13 (patch) | |
tree | c474375dc1cc812e006921ab2ad122b21923e512 /net | |
parent | a6ab4bf978a3d5a52a47bbd259b7eb4c860ebd0c (diff) | |
download | u-boot-a3d991bd0da8b9fb9dbf2c7481091c3d082b9b13.zip u-boot-a3d991bd0da8b9fb9dbf2c7481091c3d082b9b13.tar.gz u-boot-a3d991bd0da8b9fb9dbf2c7481091c3d082b9b13.tar.bz2 |
Patches by Pantelis Antoniou, 30 Mar 2004:
add networking support for VLANs (802.1q), and CDP (Cisco Discovery Protocol)
Diffstat (limited to 'net')
-rw-r--r-- | net/bootp.c | 6 | ||||
-rw-r--r-- | net/eth.c | 50 | ||||
-rw-r--r-- | net/net.c | 592 | ||||
-rw-r--r-- | net/nfs.c | 2 | ||||
-rw-r--r-- | net/rarp.c | 5 | ||||
-rw-r--r-- | net/tftp.c | 2 |
6 files changed, 611 insertions, 46 deletions
diff --git a/net/bootp.c b/net/bootp.c index 21ce7b2..4bca50d 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -644,8 +644,7 @@ BootpRequest (void) pkt = NetTxPacket; memset ((void*)pkt, 0, PKTSIZE); - NetSetEther(pkt, NetBcastAddr, PROT_IP); - pkt += ETHER_HDR_SIZE; + pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP); /* * Next line results in incorrect packet size being transmitted, resulting @@ -791,8 +790,7 @@ static void DhcpSendRequestPkt(Bootp_t *bp_offer) pkt = NetTxPacket; memset ((void*)pkt, 0, PKTSIZE); - NetSetEther(pkt, NetBcastAddr, PROT_IP); - pkt += ETHER_HDR_SIZE; + pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP); iphdr = pkt; /* We'll need this later to set proper pkt size */ pkt += IP_HDR_SIZE; @@ -87,6 +87,14 @@ int eth_register(struct eth_device* dev) if (!eth_devices) { eth_current = eth_devices = dev; +#ifdef CONFIG_NET_MULTI + /* update current ethernet name */ + { + char *act = getenv("ethact"); + if (act == NULL || strcmp(act, eth_current->name) != 0) + setenv("ethact", eth_current->name); + } +#endif } else { for (d=eth_devices; d->next!=eth_devices; d=d->next); d->next = dev; @@ -221,6 +229,16 @@ int eth_initialize(bd_t *bis) dev = dev->next; } while(dev != eth_devices); +#ifdef CONFIG_NET_MULTI + /* update current ethernet name */ + if (eth_current) { + char *act = getenv("ethact"); + if (act == NULL || strcmp(act, eth_current->name) != 0) + setenv("ethact", eth_current->name); + } else + setenv("ethact", NULL); +#endif + putc ('\n'); } @@ -326,12 +344,44 @@ void eth_try_another(int first_restart) eth_current = eth_current->next; +#ifdef CONFIG_NET_MULTI + /* update current ethernet name */ + { + char *act = getenv("ethact"); + if (act == NULL || strcmp(act, eth_current->name) != 0) + setenv("ethact", eth_current->name); + } +#endif + if (first_failed == eth_current) { NetRestartWrap = 1; } } +#ifdef CONFIG_NET_MULTI +void eth_set_current(void) +{ + char *act; + struct eth_device* old_current; + + if (!eth_current) /* XXX no current */ + return; + + act = getenv("ethact"); + if (act != NULL) { + old_current = eth_current; + do { + if (strcmp(eth_current->name, act) == 0) + return; + eth_current = eth_current->next; + } while (old_current != eth_current); + } + + setenv("ethact", eth_current->name); +} +#endif + char *eth_get_name (void) { return (eth_current ? eth_current->name : "unknown"); @@ -121,6 +121,10 @@ uchar NetBcastAddr[6] = /* Ethernet bcast address */ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; uchar NetEtherNullAddr[6] = { 0, 0, 0, 0, 0, 0 }; +#if (CONFIG_COMMANDS & CFG_CMD_CDP) +uchar NetCDPAddr[6] = /* Ethernet bcast address */ + { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc }; +#endif int NetState; /* Network loop state */ #ifdef CONFIG_NET_MULTI int NetRestartWrap = 0; /* Tried all network devices */ @@ -128,6 +132,9 @@ static int NetRestarted = 0; /* Network loop restarted */ static int NetDevExists = 0; /* At least one device configured */ #endif +ushort NetOurVLAN = ntohs(-1); /* default is without VLAN */ +ushort NetOurNativeVLAN = htons(-1); /* dido */ + char BootFile[128]; /* Boot File name */ #if (CONFIG_COMMANDS & CFG_CMD_PING) @@ -136,6 +143,10 @@ IPaddr_t NetPingIP; /* the ip address to ping */ static void PingStart(void); #endif +#if (CONFIG_COMMANDS & CFG_CMD_CDP) +static void CDPStart(void); +#endif + volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */ @@ -170,8 +181,7 @@ void ArpRequest(void) #endif pkt = NetTxPacket; - NetSetEther(pkt, NetBcastAddr, PROT_ARP); - pkt += ETHER_HDR_SIZE; + pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP); arp = (ARP_t *)pkt; @@ -196,7 +206,7 @@ void ArpRequest(void) NetArpWaitReplyIP = NetArpWaitPacketIP; NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitReplyIP); - (void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE); + (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE); } void ArpTimeoutCheck(void) @@ -269,6 +279,7 @@ NetLoop(proto_t protocol) } eth_halt(); + eth_set_current(); if(eth_init(bd) < 0) return(-1); @@ -298,6 +309,8 @@ restart: NetCopyIP(&NetOurIP, &bd->bi_ip_addr); NetOurGatewayIP = getenv_IPaddr ("gatewayip"); NetOurSubnetMask= getenv_IPaddr ("netmask"); + NetOurVLAN = getenv_VLAN("vlan"); + NetOurNativeVLAN = getenv_VLAN("nvlan"); switch (protocol) { #if (CONFIG_COMMANDS & CFG_CMD_NFS) @@ -324,6 +337,11 @@ restart: */ NetOurIP = 0; NetServerIP = getenv_IPaddr ("serverip"); + NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */ + NetOurNativeVLAN = getenv_VLAN("nvlan"); + case CDP: + NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */ + NetOurNativeVLAN = getenv_VLAN("nvlan"); break; default: break; @@ -378,6 +396,11 @@ restart: NfsStart(); break; #endif +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + case CDP: + CDPStart(); + break; +#endif default: break; } @@ -469,6 +492,9 @@ restart: NetBootFileXferSize); sprintf(buf, "%lx", NetBootFileXferSize); setenv("filesize", buf); + + sprintf(buf, "%lX", (unsigned long)load_addr); + setenv("fileaddr", buf); } eth_halt(); return NetBootFileXferSize; @@ -496,12 +522,19 @@ startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) void NetStartAgain(void) { + DECLARE_GLOBAL_DATA_PTR; + char *s; + + if ((s = getenv("netretry")) != NULL && *s == 'n') { + eth_halt(); + NetState = NETLOOP_FAIL; + return; + } + #ifndef CONFIG_NET_MULTI NetSetTimeout(10 * CFG_HZ, startAgainTimeout); NetSetHandler(startAgainHandler); #else - DECLARE_GLOBAL_DATA_PTR; - eth_halt(); eth_try_another(!NetRestarted); eth_init(gd->bd); @@ -559,6 +592,8 @@ NetSendPacket(volatile uchar * pkt, int len) int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) { + uchar *pkt; + /* convert to new style broadcast */ if (dest == 0) dest = 0xFFFFFFFF; @@ -573,16 +608,17 @@ NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) #ifdef ET_DEBUG printf("sending ARP for %08lx\n", dest); #endif - NetArpWaitPacketIP = dest; NetArpWaitPacketMAC = ether; - NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP); - NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len); - memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, - (uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len); + + pkt = NetArpWaitTxPacket; + pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP); + + NetSetIP (pkt, dest, dport, sport, len); + memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len); /* size of the waiting packet */ - NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len; + NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len; /* and do the ARP request */ NetArpWaitTry = 1; @@ -596,9 +632,10 @@ NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); #endif - NetSetEther (NetTxPacket, ether, PROT_IP); - NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len); - (void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len); + pkt = (uchar *)NetTxPacket; + pkt += NetSetEther (pkt, ether, PROT_IP); + NetSetIP (pkt, dest, dport, sport, len); + (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len); return 0; /* transmited */ } @@ -611,6 +648,7 @@ int PingSend(void) static uchar mac[6]; volatile IP_t *ip; volatile ushort *s; + uchar *pkt; /* XXX always send arp request */ @@ -623,9 +661,10 @@ int PingSend(void) NetArpWaitPacketIP = NetPingIP; NetArpWaitPacketMAC = mac; - NetSetEther(NetArpWaitTxPacket, mac, PROT_IP); + pkt = NetArpWaitTxPacket; + pkt += NetSetEther(pkt, mac, PROT_IP); - ip = (volatile IP_t *)(NetArpWaitTxPacket + ETHER_HDR_SIZE); + ip = (volatile IP_t *)pkt; /* * Construct an IP and ICMP header. (need to set no fragment bit - XXX) @@ -650,7 +689,7 @@ int PingSend(void) s[1] = ~NetCksum((uchar *)s, 8/2); /* size of the waiting packet */ - NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE_NO_UDP + 8; + NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8; /* and do the ARP request */ NetArpWaitTry = 1; @@ -681,6 +720,9 @@ PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) static void PingStart(void) { +#if defined(CONFIG_NET_MULTI) + printf ("Using %s device\n", eth_get_name()); +#endif NetSetTimeout (10 * CFG_HZ, PingTimeout); NetSetHandler (PingHandler); @@ -689,37 +731,454 @@ static void PingStart(void) #endif +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + +#define CDP_DEVICE_ID_TLV 0x0001 +#define CDP_ADDRESS_TLV 0x0002 +#define CDP_PORT_ID_TLV 0x0003 +#define CDP_CAPABILITIES_TLV 0x0004 +#define CDP_VERSION_TLV 0x0005 +#define CDP_PLATFORM_TLV 0x0006 +#define CDP_NATIVE_VLAN_TLV 0x000a +#define CDP_APPLIANCE_VLAN_TLV 0x000e +#define CDP_TRIGGER_TLV 0x000f +#define CDP_POWER_CONSUMPTION_TLV 0x0010 +#define CDP_SYSNAME_TLV 0x0014 +#define CDP_SYSOBJECT_TLV 0x0015 +#define CDP_MANAGEMENT_ADDRESS_TLV 0x0016 + +#define CDP_TIMEOUT (CFG_HZ/4) /* one packet every 250ms */ + +static int CDPSeq; +static int CDPOK; + +ushort CDPNativeVLAN; +ushort CDPApplianceVLAN; + +static const uchar CDP_SNAP_hdr[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00 }; + +static ushort CDP_compute_csum(const uchar *buff, ushort len) +{ + ushort csum; + int odd; + ulong result = 0; + ushort leftover; + + if (len > 0) { + odd = 1 & (ulong)buff; + if (odd) { + result = *buff << 8; + len--; + buff++; + } + while (len > 1) { + result += *((const ushort *)buff)++; + if (result & 0x80000000) + result = (result & 0xFFFF) + (result >> 16); + len -= 2; + } + if (len) { + leftover = (signed short)(*(const signed char *)buff); + /* * XXX CISCO SUCKS big time! (and blows too) */ + result = (result & 0xffff0000) | ((result + leftover) & 0x0000ffff); + } + while (result >> 16) + result = (result & 0xFFFF) + (result >> 16); + + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + } + + /* add up 16-bit and 17-bit words for 17+c bits */ + result = (result & 0xffff) + (result >> 16); + /* add up 16-bit and 2-bit for 16+c bit */ + result = (result & 0xffff) + (result >> 16); + /* add up carry.. */ + result = (result & 0xffff) + (result >> 16); + + /* negate */ + csum = ~(ushort)result; + + /* run time endian detection */ + if (csum != htons(csum)) /* little endian */ + csum = htons(csum); + + return csum; +} + +int CDPSendTrigger(void) +{ + volatile uchar *pkt; + volatile ushort *s; + volatile ushort *cp; + Ethernet_t *et; + char buf[32]; + int len; + ushort chksum; + + pkt = NetTxPacket; + et = (Ethernet_t *)pkt; + + /* NOTE: trigger sent not on any VLAN */ + + /* form ethernet header */ + memcpy(et->et_dest, NetCDPAddr, 6); + memcpy(et->et_src, NetOurEther, 6); + + pkt += ETHER_HDR_SIZE; + + /* SNAP header */ + memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)); + pkt += sizeof(CDP_SNAP_hdr); + + /* CDP header */ + *pkt++ = 0x02; /* CDP version 2 */ + *pkt++ = 180; /* TTL */ + s = (volatile ushort *)pkt; + cp = s; + *s++ = htons(0); /* checksum (0 for later calculation) */ + + /* CDP fields */ +#ifdef CONFIG_CDP_DEVICE_ID + *s++ = htons(CDP_DEVICE_ID_TLV); + *s++ = htons(CONFIG_CDP_DEVICE_ID); + memset(buf, 0, sizeof(buf)); + sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%02X%02X%02X%02X%02X%02X", + NetOurEther[0] & 0xff, NetOurEther[1] & 0xff, + NetOurEther[2] & 0xff, NetOurEther[3] & 0xff, + NetOurEther[4] & 0xff, NetOurEther[5] & 0xff); + memcpy((uchar *)s, buf, 16); + s += 16 / 2; +#endif + +#ifdef CONFIG_CDP_PORT_ID + *s++ = htons(CDP_PORT_ID_TLV); + memset(buf, 0, sizeof(buf)); + sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index()); + len = strlen(buf); + if (len & 1) /* make it even */ + len++; + *s++ = htons(len + 4); + memcpy((uchar *)s, buf, len); + s += len / 2; +#endif + +#ifdef CONFIG_CDP_CAPABILITIES + *s++ = htons(CDP_CAPABILITIES_TLV); + *s++ = htons(8); + *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES); + s += 2; +#endif + +#ifdef CONFIG_CDP_VERSION + *s++ = htons(CDP_VERSION_TLV); + memset(buf, 0, sizeof(buf)); + strcpy(buf, CONFIG_CDP_VERSION); + len = strlen(buf); + if (len & 1) /* make it even */ + len++; + *s++ = htons(len + 4); + memcpy((uchar *)s, buf, len); + s += len / 2; +#endif + +#ifdef CONFIG_CDP_PLATFORM + *s++ = htons(CDP_PLATFORM_TLV); + memset(buf, 0, sizeof(buf)); + strcpy(buf, CONFIG_CDP_PLATFORM); + len = strlen(buf); + if (len & 1) /* make it even */ + len++; + *s++ = htons(len + 4); + memcpy((uchar *)s, buf, len); + s += len / 2; +#endif + +#ifdef CONFIG_CDP_TRIGGER + *s++ = htons(CDP_TRIGGER_TLV); + *s++ = htons(8); + *(ulong *)s = htonl(CONFIG_CDP_TRIGGER); + s += 2; +#endif + +#ifdef CONFIG_CDP_POWER_CONSUMPTION + *s++ = htons(CDP_POWER_CONSUMPTION_TLV); + *s++ = htons(6); + *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION); +#endif + + /* length of ethernet packet */ + len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE); + et->et_protlen = htons(len); + + len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr); + chksum = CDP_compute_csum((uchar *)NetTxPacket + len, (uchar *)s - (NetTxPacket + len)); + if (chksum == 0) + chksum = 0xFFFF; + *cp = htons(chksum); + + (void) eth_send(NetTxPacket, (uchar *)s - NetTxPacket); + return 0; +} + +static void +CDPTimeout (void) +{ + CDPSeq++; + + if (CDPSeq < 3) { + NetSetTimeout (CDP_TIMEOUT, CDPTimeout); + CDPSendTrigger(); + return; + } + + /* if not OK try again */ + if (!CDPOK) + NetStartAgain(); + else + NetState = NETLOOP_SUCCESS; +} + +static void +CDPDummyHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + /* nothing */ +} + +static void +CDPHandler(const uchar * pkt, unsigned len) +{ + const uchar *t; + const ushort *ss; + ushort type, tlen; + uchar applid; + ushort vlan, nvlan; + + /* minimum size? */ + if (len < sizeof(CDP_SNAP_hdr) + 4) + goto pkt_short; + + /* check for valid CDP SNAP header */ + if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0) + return; + + pkt += sizeof(CDP_SNAP_hdr); + len -= sizeof(CDP_SNAP_hdr); + + /* Version of CDP protocol must be >= 2 and TTL != 0 */ + if (pkt[0] < 0x02 || pkt[1] == 0) + return; + + /* if version is greater than 0x02 maybe we'll have a problem; output a warning */ + if (pkt[0] != 0x02) + printf("** WARNING: CDP packet received with a protocol version %d > 2\n", + pkt[0] & 0xff); + + if (CDP_compute_csum(pkt, len) != 0) + return; + + pkt += 4; + len -= 4; + + vlan = htons(-1); + nvlan = htons(-1); + while (len > 0) { + if (len < 4) + goto pkt_short; + + ss = (const ushort *)pkt; + type = ntohs(ss[0]); + tlen = ntohs(ss[1]); + if (tlen > len) { + goto pkt_short; + } + + pkt += tlen; + len -= tlen; + + ss += 2; /* point ss to the data of the TLV */ + tlen -= 4; + + switch (type) { + case CDP_DEVICE_ID_TLV: + break; + case CDP_ADDRESS_TLV: + break; + case CDP_PORT_ID_TLV: + break; + case CDP_CAPABILITIES_TLV: + break; + case CDP_VERSION_TLV: + break; + case CDP_PLATFORM_TLV: + break; + case CDP_NATIVE_VLAN_TLV: + nvlan = *ss; + break; + case CDP_APPLIANCE_VLAN_TLV: + t = (const uchar *)ss; + while (tlen > 0) { + if (tlen < 3) + goto pkt_short; + + applid = t[0]; + ss = (const ushort *)(t + 1); + +#ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE + if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE) + vlan = *ss; +#else + vlan = ntohs(*ss); /* XXX will this work; dunno */ +#endif + t += 3; tlen -= 3; + } + break; + case CDP_TRIGGER_TLV: + break; + case CDP_POWER_CONSUMPTION_TLV: + break; + case CDP_SYSNAME_TLV: + break; + case CDP_SYSOBJECT_TLV: + break; + case CDP_MANAGEMENT_ADDRESS_TLV: + break; + } + } + + CDPApplianceVLAN = vlan; + CDPNativeVLAN = nvlan; + + CDPOK = 1; + return; + + pkt_short: + printf("** CDP packet is too short\n"); + return; +} + +static void CDPStart(void) +{ +#if defined(CONFIG_NET_MULTI) + printf ("Using %s device\n", eth_get_name()); +#endif + CDPSeq = 0; + CDPOK = 0; + + CDPNativeVLAN = htons(-1); + CDPApplianceVLAN = htons(-1); + + NetSetTimeout (CDP_TIMEOUT, CDPTimeout); + NetSetHandler (CDPDummyHandler); + + CDPSendTrigger(); +} + +#endif + + void -NetReceive(volatile uchar * pkt, int len) +NetReceive(volatile uchar * inpkt, int len) { Ethernet_t *et; IP_t *ip; ARP_t *arp; IPaddr_t tmp; int x; + uchar *pkt; +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + int iscdp; +#endif + ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid; + +#ifdef ET_DEBUG + printf("packet received\n"); +#endif - NetRxPkt = pkt; + NetRxPkt = inpkt; NetRxPktLen = len; - et = (Ethernet_t *)pkt; + et = (Ethernet_t *)inpkt; + + /* too small packet? */ + if (len < ETHER_HDR_SIZE) + return; + +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + /* keep track if packet is CDP */ + iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0; +#endif + + myvlanid = ntohs(NetOurVLAN); + if (myvlanid == (ushort)-1) + myvlanid = VLAN_NONE; + mynvlanid = ntohs(NetOurNativeVLAN); + if (mynvlanid == (ushort)-1) + mynvlanid = VLAN_NONE; x = ntohs(et->et_protlen); +#ifdef ET_DEBUG + printf("packet received\n"); +#endif + if (x < 1514) { /* * Got a 802 packet. Check the other protocol field. */ x = ntohs(et->et_prot); - ip = (IP_t *)(pkt + E802_HDR_SIZE); + + ip = (IP_t *)(inpkt + E802_HDR_SIZE); len -= E802_HDR_SIZE; - } else { - ip = (IP_t *)(pkt + ETHER_HDR_SIZE); + + } else if (x != PROT_VLAN) { /* normal packet */ + ip = (IP_t *)(inpkt + ETHER_HDR_SIZE); len -= ETHER_HDR_SIZE; + + } else { /* VLAN packet */ + VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et; + +#ifdef ET_DEBUG + printf("VLAN packet received\n"); +#endif + /* too small packet? */ + if (len < VLAN_ETHER_HDR_SIZE) + return; + + /* if no VLAN active */ + if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + && iscdp == 0 +#endif + ) + return; + + cti = ntohs(vet->vet_tag); + vlanid = cti & VLAN_IDMASK; + x = ntohs(vet->vet_type); + + ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE); + len -= VLAN_ETHER_HDR_SIZE; } #ifdef ET_DEBUG printf("Receive from protocol 0x%x\n", x); #endif +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + if (iscdp) { + CDPHandler((uchar *)ip, len); + return; + } +#endif + + if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) { + if (vlanid == VLAN_NONE) + vlanid = (mynvlanid & VLAN_IDMASK); + /* not matched? */ + if (vlanid != (myvlanid & VLAN_IDMASK)) + return; + } + switch (x) { case PROT_ARP: @@ -766,13 +1225,14 @@ NetReceive(volatile uchar * pkt, int len) #ifdef ET_DEBUG puts ("Got ARP REQUEST, return our IP\n"); #endif - NetSetEther((uchar *)et, et->et_src, PROT_ARP); + pkt = (uchar *)et; + pkt += NetSetEther(pkt, et->et_src, PROT_ARP); arp->ar_op = htons(ARPOP_REPLY); memcpy (&arp->ar_data[10], &arp->ar_data[0], 6); NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]); memcpy (&arp->ar_data[ 0], NetOurEther, 6); NetCopyIP(&arp->ar_data[ 6], &NetOurIP); - (void) eth_send((uchar *)et, ((uchar *)arp-pkt) + ARP_HDR_SIZE); + (void) eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE); return; case ARPOP_REPLY: /* arp reply */ @@ -963,6 +1423,7 @@ static int net_check_prereq (proto_t protocol) case DHCP: case RARP: case BOOTP: + case CDP: if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) { #ifdef CONFIG_NET_MULTI extern int eth_get_dev_index (void); @@ -1016,17 +1477,42 @@ NetCksum(uchar * ptr, int len) return (xsum & 0xffff); } +int +NetEthHdrSize(void) +{ + ushort myvlanid; -void + myvlanid = ntohs(NetOurVLAN); + if (myvlanid == (ushort)-1) + myvlanid = VLAN_NONE; + + return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE; +} + +int NetSetEther(volatile uchar * xet, uchar * addr, uint prot) { Ethernet_t *et = (Ethernet_t *)xet; + ushort myvlanid; + + myvlanid = ntohs(NetOurVLAN); + if (myvlanid == (ushort)-1) + myvlanid = VLAN_NONE; memcpy (et->et_dest, addr, 6); memcpy (et->et_src, NetOurEther, 6); + if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) { et->et_protlen = htons(prot); -} + return ETHER_HDR_SIZE; + } else { + VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet; + vet->vet_vlan_type = htons(PROT_VLAN); + vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK)); + vet->vet_type = htons(prot); + return VLAN_ETHER_HDR_SIZE; + } +} void NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len) @@ -1079,13 +1565,12 @@ void copy_filename (uchar *dst, uchar *src, int size) void ip_to_string (IPaddr_t x, char *s) { - x = ntohl(x); - sprintf (s,"%d.%d.%d.%d", - (int)((x >> 24) & 0xff), - (int)((x >> 16) & 0xff), - (int)((x >> 8) & 0xff), - (int)((x >> 0) & 0xff) - ); + x = ntohl (x); + sprintf (s, "%d.%d.%d.%d", + (int) ((x >> 24) & 0xff), + (int) ((x >> 16) & 0xff), + (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff) + ); } IPaddr_t string_to_ip(char *s) @@ -1109,16 +1594,49 @@ IPaddr_t string_to_ip(char *s) return (htonl(addr)); } +void VLAN_to_string(ushort x, char *s) +{ + x = ntohs(x); + + if (x == (ushort)-1) + x = VLAN_NONE; + + if (x == VLAN_NONE) + strcpy(s, "none"); + else + sprintf(s, "%d", x & VLAN_IDMASK); +} + +ushort string_to_VLAN(char *s) +{ + ushort id; + + if (s == NULL) + return VLAN_NONE; + + if (*s < '0' || *s > '9') + id = VLAN_NONE; + else + id = (ushort)simple_strtoul(s, NULL, 10); + + return id; +} + void print_IPaddr (IPaddr_t x) { - char tmp[16]; + char tmp[16]; - ip_to_string(x, tmp); + ip_to_string (x, tmp); - puts(tmp); + puts (tmp); } IPaddr_t getenv_IPaddr (char *var) { return (string_to_ip(getenv(var))); } + +ushort getenv_VLAN(char *var) +{ + return (string_to_VLAN(getenv(var))); +} @@ -192,7 +192,7 @@ rpc_req (int rpc_prog, int rpc_proc, uint32_t *data, int datalen) pktlen = (char *)p + datalen*sizeof(uint32_t) - (char *)&pkt; - memcpy ((char *)NetTxPacket+ETHER_HDR_SIZE+IP_HDR_SIZE, (char *)&pkt, pktlen); + memcpy ((char *)NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE, (char *)&pkt, pktlen); if (rpc_prog == PROG_PORTMAP) sport = SUNRPC_PORT; @@ -96,8 +96,7 @@ RarpRequest (void) printf("RARP broadcast %d\n", ++RarpTry); pkt = NetTxPacket; - NetSetEther(pkt, NetBcastAddr, PROT_RARP); - pkt += ETHER_HDR_SIZE; + pkt += NetSetEther(pkt, NetBcastAddr, PROT_RARP); rarp = (ARP_t *)pkt; @@ -114,7 +113,7 @@ RarpRequest (void) rarp->ar_data[16 + i] = 0xff; } - NetSendPacket(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE); + NetSendPacket(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE); NetSetTimeout(TIMEOUT * CFG_HZ, RarpTimeout); NetSetHandler(RarpHandler); @@ -111,7 +111,7 @@ TftpSend (void) * We will always be sending some sort of packet, so * cobble together the packet headers now. */ - pkt = NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE; + pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE; switch (TftpState) { |