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/net.c | |
| parent | a6ab4bf978a3d5a52a47bbd259b7eb4c860ebd0c (diff) | |
| download | olio-uboot-2014.01-a3d991bd0da8b9fb9dbf2c7481091c3d082b9b13.tar.xz olio-uboot-2014.01-a3d991bd0da8b9fb9dbf2c7481091c3d082b9b13.zip | |
Patches by Pantelis Antoniou, 30 Mar 2004:
add networking support for VLANs (802.1q), and CDP (Cisco Discovery Protocol)
Diffstat (limited to 'net/net.c')
| -rw-r--r-- | net/net.c | 592 | 
1 files changed, 555 insertions, 37 deletions
| @@ -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; -	NetRxPkt = pkt; +#ifdef ET_DEBUG +	printf("packet received\n"); +#endif + +	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; + +	myvlanid = ntohs(NetOurVLAN); +	if (myvlanid == (ushort)-1) +		myvlanid = VLAN_NONE; -void +	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))); +} |