Patchwork [U-Boot,06/28] net: Move ARP out of net.c

login
register
mail settings
Submitter Joe Hershberger
Date Jan. 20, 2012, 12:53 a.m.
Message ID <1327020811-1538-7-git-send-email-joe.hershberger@ni.com>
Download mbox | patch
Permalink /patch/136973/
State Superseded
Delegated to: Joe Hershberger
Headers show

Comments

Joe Hershberger - Jan. 20, 2012, 12:53 a.m.
Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Cc: Joe Hershberger <joe.hershberger@gmail.com>
Cc: Wolfgang Denk <wd@denx.de>
---
 include/net.h |    3 +-
 net/Makefile  |    1 +
 net/arp.c     |  213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/arp.h     |   30 ++++++++
 net/net.c     |  209 ++++----------------------------------------------------
 5 files changed, 259 insertions(+), 197 deletions(-)
 create mode 100644 net/arp.c
 create mode 100644 net/arp.h
Simon Glass - Jan. 24, 2012, 5:35 a.m.
On Thu, Jan 19, 2012 at 4:53 PM, Joe Hershberger <joe.hershberger@ni.com> wrote:
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

Acked-by: Simon Glass <sjg@chromium.org>

> Cc: Joe Hershberger <joe.hershberger@gmail.com>
> Cc: Wolfgang Denk <wd@denx.de>
> ---
>  include/net.h |    3 +-
>  net/Makefile  |    1 +
>  net/arp.c     |  213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  net/arp.h     |   30 ++++++++
>  net/net.c     |  209 ++++----------------------------------------------------
>  5 files changed, 259 insertions(+), 197 deletions(-)
>  create mode 100644 net/arp.c
>  create mode 100644 net/arp.h
>
> diff --git a/include/net.h b/include/net.h
> index 0396b69..2d00233 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -418,7 +418,8 @@ extern void NetSetIP(uchar *, IPaddr_t, int, int, int);
>  extern int     NetCksumOk(uchar *, int);       /* Return true if cksum OK */
>  extern uint    NetCksum(uchar *, int);         /* Calculate the checksum */
>
> -/* Set callbacks */
> +/* Callbacks */
> +extern rxhand_f *NetGetHandler(void);          /* Get RX packet handler */
>  extern void    NetSetHandler(rxhand_f *);      /* Set RX packet handler */
>  extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
>  extern void    NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
> diff --git a/net/Makefile b/net/Makefile
> index b350bfc..0916a56 100644
> --- a/net/Makefile
> +++ b/net/Makefile
> @@ -27,6 +27,7 @@ include $(TOPDIR)/config.mk
>
>  LIB    = $(obj)libnet.o
>
> +COBJS-$(CONFIG_CMD_NET)  += arp.o
>  COBJS-$(CONFIG_CMD_NET)  += bootp.o
>  COBJS-$(CONFIG_CMD_CDP)  += cdp.o
>  COBJS-$(CONFIG_CMD_DNS)  += dns.o
> diff --git a/net/arp.c b/net/arp.c
> new file mode 100644
> index 0000000..f75217c
> --- /dev/null
> +++ b/net/arp.c
> @@ -0,0 +1,213 @@
> +/*
> + *     Copied from Linux Monitor (LiMon) - Networking.
> + *
> + *     Copyright 1994 - 2000 Neil Russell.
> + *     (See License)
> + *     Copyright 2000 Roland Borde
> + *     Copyright 2000 Paolo Scaffardi
> + *     Copyright 2000-2002 Wolfgang Denk, wd@denx.de
> + */
> +
> +#include <common.h>
> +
> +#include "arp.h"
> +
> +#ifndef        CONFIG_ARP_TIMEOUT
> +/* Milliseconds before trying ARP again */
> +# define ARP_TIMEOUT           5000UL
> +#else
> +# define ARP_TIMEOUT           CONFIG_ARP_TIMEOUT
> +#endif
> +
> +
> +#ifndef        CONFIG_NET_RETRY_COUNT
> +# define ARP_TIMEOUT_COUNT     5       /* # of timeouts before giving up  */
> +#else
> +# define ARP_TIMEOUT_COUNT     CONFIG_NET_RETRY_COUNT
> +#endif
> +
> +IPaddr_t       NetArpWaitPacketIP;
> +IPaddr_t       NetArpWaitReplyIP;
> +/* MAC address of waiting packet's destination */
> +uchar         *NetArpWaitPacketMAC;
> +/* THE transmit packet */
> +uchar         *NetArpWaitTxPacket;
> +int            NetArpWaitTxPacketSize;
> +uchar          NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
> +ulong          NetArpWaitTimerStart;
> +int            NetArpWaitTry;
> +
> +void ArpInit(void)
> +{
> +       /* XXX problem with bss workaround */
> +       NetArpWaitPacketMAC = NULL;
> +       NetArpWaitPacketIP = 0;
> +       NetArpWaitReplyIP = 0;
> +       NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
> +       NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
> +       NetArpWaitTxPacketSize = 0;
> +}
> +
> +void ArpRequest(void)
> +{
> +       uchar *pkt;
> +       ARP_t *arp;
> +
> +       debug("ARP broadcast %d\n", NetArpWaitTry);
> +
> +       pkt = NetTxPacket;
> +
> +       pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
> +
> +       arp = (ARP_t *) pkt;
> +
> +       arp->ar_hrd = htons(ARP_ETHER);
> +       arp->ar_pro = htons(PROT_IP);
> +       arp->ar_hln = 6;
> +       arp->ar_pln = 4;
> +       arp->ar_op = htons(ARPOP_REQUEST);
> +
> +       /* source ET addr */
> +       memcpy(&arp->ar_data[0], NetOurEther, 6);
> +       /* source IP addr */
> +       NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
> +       /* dest ET addr = 0 */
> +       memset(&arp->ar_data[10], '\0', 6);
> +       if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
> +           (NetOurIP & NetOurSubnetMask)) {
> +               if (NetOurGatewayIP == 0) {
> +                       puts("## Warning: gatewayip needed but not set\n");
> +                       NetArpWaitReplyIP = NetArpWaitPacketIP;
> +               } else {
> +                       NetArpWaitReplyIP = NetOurGatewayIP;
> +               }
> +       } else {
> +               NetArpWaitReplyIP = NetArpWaitPacketIP;
> +       }
> +
> +       NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP);
> +       (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
> +}
> +
> +void ArpTimeoutCheck(void)
> +{
> +       ulong t;
> +
> +       if (!NetArpWaitPacketIP)
> +               return;
> +
> +       t = get_timer(0);
> +
> +       /* check for arp timeout */
> +       if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
> +               NetArpWaitTry++;
> +
> +               if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
> +                       puts("\nARP Retry count exceeded; starting again\n");
> +                       NetArpWaitTry = 0;
> +                       NetStartAgain();
> +               } else {
> +                       NetArpWaitTimerStart = t;
> +                       ArpRequest();
> +               }
> +       }
> +}
> +
> +void ArpReceive(Ethernet_t *et, IP_t *ip, int len)
> +{
> +       ARP_t *arp;
> +       IPaddr_t tmp;
> +       uchar *pkt;
> +
> +       /*
> +        * We have to deal with two types of ARP packets:
> +        * - REQUEST packets will be answered by sending  our
> +        *   IP address - if we know it.
> +        * - REPLY packates are expected only after we asked
> +        *   for the TFTP server's or the gateway's ethernet
> +        *   address; so if we receive such a packet, we set
> +        *   the server ethernet address
> +        */
> +       debug("Got ARP\n");
> +
> +       arp = (ARP_t *)ip;
> +       if (len < ARP_HDR_SIZE) {
> +               printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
> +               return;
> +       }
> +       if (ntohs(arp->ar_hrd) != ARP_ETHER)
> +               return;
> +       if (ntohs(arp->ar_pro) != PROT_IP)
> +               return;
> +       if (arp->ar_hln != 6)
> +               return;
> +       if (arp->ar_pln != 4)
> +               return;
> +
> +       if (NetOurIP == 0)
> +               return;
> +
> +       if (NetReadIP(&arp->ar_data[16]) != NetOurIP)
> +               return;
> +
> +       switch (ntohs(arp->ar_op)) {
> +       case ARPOP_REQUEST:
> +               /* reply with our IP address */
> +               debug("Got ARP REQUEST, return our IP\n");
> +               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,
> +                               (pkt - (uchar *)et) + ARP_HDR_SIZE);
> +               return;
> +
> +       case ARPOP_REPLY:               /* arp reply */
> +               /* are we waiting for a reply */
> +               if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
> +                       break;
> +
> +#ifdef CONFIG_KEEP_SERVERADDR
> +               if (NetServerIP == NetArpWaitPacketIP) {
> +                       char buf[20];
> +                       sprintf(buf, "%pM", arp->ar_data);
> +                       setenv("serveraddr", buf);
> +               }
> +#endif
> +
> +               tmp = NetReadIP(&arp->ar_data[6]);
> +
> +               /* matched waiting packet's address */
> +               if (tmp == NetArpWaitReplyIP) {
> +                       debug("Got ARP REPLY, set eth addr (%pM)\n",
> +                               arp->ar_data);
> +
> +                       /* save address for later use */
> +                       memcpy(NetArpWaitPacketMAC,
> +                              &arp->ar_data[0], 6);
> +
> +#ifdef CONFIG_NETCONSOLE
> +                       NetGetHandler()(0, 0, 0, 0, 0);
> +#endif
> +                       /* modify header, and transmit it */
> +                       memcpy(((Ethernet_t *)NetArpWaitTxPacket)->
> +                               et_dest, NetArpWaitPacketMAC, 6);
> +                       (void) eth_send(NetArpWaitTxPacket,
> +                                       NetArpWaitTxPacketSize);
> +
> +                       /* no arp request pending now */
> +                       NetArpWaitPacketIP = 0;
> +                       NetArpWaitTxPacketSize = 0;
> +                       NetArpWaitPacketMAC = NULL;
> +
> +               }
> +               return;
> +       default:
> +               debug("Unexpected ARP opcode 0x%x\n",
> +                     ntohs(arp->ar_op));
> +               return;
> +       }
> +}
> diff --git a/net/arp.h b/net/arp.h
> new file mode 100644
> index 0000000..09c763d
> --- /dev/null
> +++ b/net/arp.h
> @@ -0,0 +1,30 @@
> +/*
> + *     Copied from Linux Monitor (LiMon) - Networking.
> + *
> + *     Copyright 1994 - 2000 Neil Russell.
> + *     (See License)
> + *     Copyright 2000 Roland Borde
> + *     Copyright 2000 Paolo Scaffardi
> + *     Copyright 2000-2002 Wolfgang Denk, wd@denx.de
> + */
> +
> +#ifndef __ARP_H__
> +#define __ARP_H__
> +
> +#include <net.h>
> +
> +extern IPaddr_t        NetArpWaitPacketIP;
> +/* MAC address of waiting packet's destination */
> +extern uchar *NetArpWaitPacketMAC;
> +/* THE transmit packet */
> +extern uchar *NetArpWaitTxPacket;
> +extern int NetArpWaitTxPacketSize;
> +extern ulong NetArpWaitTimerStart;
> +extern int NetArpWaitTry;
> +
> +void ArpInit(void);
> +void ArpRequest(void);
> +void ArpTimeoutCheck(void);
> +void ArpReceive(Ethernet_t *et, IP_t *ip, int len);
> +
> +#endif /* __ARP_H__ */
> diff --git a/net/net.c b/net/net.c
> index 48d3ca8..2dae5a0 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -78,6 +78,7 @@
>  #include <watchdog.h>
>  #include <command.h>
>  #include <net.h>
> +#include "arp.h"
>  #include "bootp.h"
>  #include "tftp.h"
>  #ifdef CONFIG_CMD_RARP
> @@ -100,20 +101,6 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> -#ifndef        CONFIG_ARP_TIMEOUT
> -/* Milliseconds before trying ARP again */
> -# define ARP_TIMEOUT           5000UL
> -#else
> -# define ARP_TIMEOUT           CONFIG_ARP_TIMEOUT
> -#endif
> -
> -
> -#ifndef        CONFIG_NET_RETRY_COUNT
> -# define ARP_TIMEOUT_COUNT     5       /* # of timeouts before giving up  */
> -#else
> -# define ARP_TIMEOUT_COUNT     CONFIG_NET_RETRY_COUNT
> -#endif
> -
>  /** BOOTP EXTENTIONS **/
>
>  /* Our subnet mask (0=unknown) */
> @@ -220,82 +207,6 @@ static int NetTryCount;
>
>  /**********************************************************************/
>
> -IPaddr_t       NetArpWaitPacketIP;
> -IPaddr_t       NetArpWaitReplyIP;
> -/* MAC address of waiting packet's destination */
> -uchar         *NetArpWaitPacketMAC;
> -/* THE transmit packet */
> -uchar         *NetArpWaitTxPacket;
> -int            NetArpWaitTxPacketSize;
> -uchar          NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
> -ulong          NetArpWaitTimerStart;
> -int            NetArpWaitTry;
> -
> -void ArpRequest(void)
> -{
> -       uchar *pkt;
> -       ARP_t *arp;
> -
> -       debug("ARP broadcast %d\n", NetArpWaitTry);
> -
> -       pkt = NetTxPacket;
> -
> -       pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
> -
> -       arp = (ARP_t *) pkt;
> -
> -       arp->ar_hrd = htons(ARP_ETHER);
> -       arp->ar_pro = htons(PROT_IP);
> -       arp->ar_hln = 6;
> -       arp->ar_pln = 4;
> -       arp->ar_op = htons(ARPOP_REQUEST);
> -
> -       /* source ET addr */
> -       memcpy(&arp->ar_data[0], NetOurEther, 6);
> -       /* source IP addr */
> -       NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
> -       /* dest ET addr = 0 */
> -       memset(&arp->ar_data[10], '\0', 6);
> -       if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
> -           (NetOurIP & NetOurSubnetMask)) {
> -               if (NetOurGatewayIP == 0) {
> -                       puts("## Warning: gatewayip needed but not set\n");
> -                       NetArpWaitReplyIP = NetArpWaitPacketIP;
> -               } else {
> -                       NetArpWaitReplyIP = NetOurGatewayIP;
> -               }
> -       } else {
> -               NetArpWaitReplyIP = NetArpWaitPacketIP;
> -       }
> -
> -       NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP);
> -       (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
> -}
> -
> -void ArpTimeoutCheck(void)
> -{
> -       ulong t;
> -
> -       if (!NetArpWaitPacketIP)
> -               return;
> -
> -       t = get_timer(0);
> -
> -       /* check for arp timeout */
> -       if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
> -               NetArpWaitTry++;
> -
> -               if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
> -                       puts("\nARP Retry count exceeded; starting again\n");
> -                       NetArpWaitTry = 0;
> -                       NetStartAgain();
> -               } else {
> -                       NetArpWaitTimerStart = t;
> -                       ArpRequest();
> -               }
> -       }
> -}
> -
>  /*
>  * Check if autoload is enabled. If so, use either NFS or TFTP to download
>  * the boot file.
> @@ -363,15 +274,11 @@ int NetLoop(enum proto_t protocol)
>        NetRestarted = 0;
>        NetDevExists = 0;
>
> -       /* XXX problem with bss workaround */
> -       NetArpWaitPacketMAC = NULL;
> -       NetArpWaitTxPacket = NULL;
> -       NetArpWaitPacketIP = 0;
> -       NetArpWaitReplyIP = 0;
> -       NetArpWaitTxPacket = NULL;
>        NetTxPacket = NULL;
>        NetTryCount = 1;
>
> +       ArpInit();
> +
>        if (!NetTxPacket) {
>                int     i;
>                /*
> @@ -383,12 +290,6 @@ int NetLoop(enum proto_t protocol)
>                        NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
>        }
>
> -       if (!NetArpWaitTxPacket) {
> -               NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
> -               NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
> -               NetArpWaitTxPacketSize = 0;
> -       }
> -
>        eth_halt();
>        eth_set_current();
>        if (eth_init(bd) < 0) {
> @@ -661,6 +562,13 @@ void NetStartAgain(void)
>  *     Miscelaneous bits.
>  */
>
> +rxhand_f *
> +NetGetHandler(void)
> +{
> +       return packetHandler;
> +}
> +
> +
>  void
>  NetSetHandler(rxhand_f *f)
>  {
> @@ -1072,11 +980,12 @@ NetReceive(volatile uchar *inpkt, int len)
>  {
>        Ethernet_t *et;
>        IP_t    *ip;
> +#ifdef CONFIG_CMD_RARP
>        ARP_t   *arp;
> +#endif
>        IPaddr_t tmp;
>        IPaddr_t src_ip;
>        int     x;
> -       uchar *pkt;
>  #if defined(CONFIG_CMD_CDP)
>        int iscdp;
>  #endif
> @@ -1173,99 +1082,7 @@ NetReceive(volatile uchar *inpkt, int len)
>        switch (x) {
>
>        case PROT_ARP:
> -               /*
> -                * We have to deal with two types of ARP packets:
> -                * - REQUEST packets will be answered by sending  our
> -                *   IP address - if we know it.
> -                * - REPLY packates are expected only after we asked
> -                *   for the TFTP server's or the gateway's ethernet
> -                *   address; so if we receive such a packet, we set
> -                *   the server ethernet address
> -                */
> -               debug("Got ARP\n");
> -
> -               arp = (ARP_t *)ip;
> -               if (len < ARP_HDR_SIZE) {
> -                       printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
> -                       return;
> -               }
> -               if (ntohs(arp->ar_hrd) != ARP_ETHER)
> -                       return;
> -               if (ntohs(arp->ar_pro) != PROT_IP)
> -                       return;
> -               if (arp->ar_hln != 6)
> -                       return;
> -               if (arp->ar_pln != 4)
> -                       return;
> -
> -               if (NetOurIP == 0)
> -                       return;
> -
> -               if (NetReadIP(&arp->ar_data[16]) != NetOurIP)
> -                       return;
> -
> -               switch (ntohs(arp->ar_op)) {
> -               case ARPOP_REQUEST:
> -                       /* reply with our IP address */
> -                       debug("Got ARP REQUEST, return our IP\n");
> -                       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,
> -                                       (pkt - (uchar *)et) + ARP_HDR_SIZE);
> -                       return;
> -
> -               case ARPOP_REPLY:               /* arp reply */
> -                       /* are we waiting for a reply */
> -                       if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
> -                               break;
> -
> -#ifdef CONFIG_KEEP_SERVERADDR
> -                       if (NetServerIP == NetArpWaitPacketIP) {
> -                               char buf[20];
> -                               sprintf(buf, "%pM", arp->ar_data);
> -                               setenv("serveraddr", buf);
> -                       }
> -#endif
> -
> -                       debug("Got ARP REPLY, set server/gtwy eth addr (%pM)\n",
> -                               arp->ar_data);
> -
> -                       tmp = NetReadIP(&arp->ar_data[6]);
> -
> -                       /* matched waiting packet's address */
> -                       if (tmp == NetArpWaitReplyIP) {
> -                               debug("Got it\n");
> -
> -                               /* save address for later use */
> -                               memcpy(NetArpWaitPacketMAC,
> -                                      &arp->ar_data[0], 6);
> -
> -#ifdef CONFIG_NETCONSOLE
> -                               (*packetHandler)(0, 0, 0, 0, 0);
> -#endif
> -                               /* modify header, and transmit it */
> -                               memcpy(((Ethernet_t *)NetArpWaitTxPacket)->
> -                                       et_dest, NetArpWaitPacketMAC, 6);
> -                               (void) eth_send(NetArpWaitTxPacket,
> -                                               NetArpWaitTxPacketSize);
> -
> -                               /* no arp request pending now */
> -                               NetArpWaitPacketIP = 0;
> -                               NetArpWaitTxPacketSize = 0;
> -                               NetArpWaitPacketMAC = NULL;
> -
> -                       }
> -                       return;
> -               default:
> -                       debug("Unexpected ARP opcode 0x%x\n",
> -                             ntohs(arp->ar_op));
> -                       return;
> -               }
> +               ArpReceive(et, ip, len);
>                break;
>
>  #ifdef CONFIG_CMD_RARP
> --
> 1.6.0.2
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
Mike Frysinger - Feb. 3, 2012, 11:56 a.m.
Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike

Patch

diff --git a/include/net.h b/include/net.h
index 0396b69..2d00233 100644
--- a/include/net.h
+++ b/include/net.h
@@ -418,7 +418,8 @@  extern void NetSetIP(uchar *, IPaddr_t, int, int, int);
 extern int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
 extern uint	NetCksum(uchar *, int);		/* Calculate the checksum */
 
-/* Set callbacks */
+/* Callbacks */
+extern rxhand_f *NetGetHandler(void);		/* Get RX packet handler */
 extern void	NetSetHandler(rxhand_f *);	/* Set RX packet handler */
 extern void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
 extern void	NetSetTimeout(ulong, thand_f *);/* Set timeout handler */
diff --git a/net/Makefile b/net/Makefile
index b350bfc..0916a56 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -27,6 +27,7 @@  include $(TOPDIR)/config.mk
 
 LIB	= $(obj)libnet.o
 
+COBJS-$(CONFIG_CMD_NET)  += arp.o
 COBJS-$(CONFIG_CMD_NET)  += bootp.o
 COBJS-$(CONFIG_CMD_CDP)  += cdp.o
 COBJS-$(CONFIG_CMD_DNS)  += dns.o
diff --git a/net/arp.c b/net/arp.c
new file mode 100644
index 0000000..f75217c
--- /dev/null
+++ b/net/arp.c
@@ -0,0 +1,213 @@ 
+/*
+ *	Copied from Linux Monitor (LiMon) - Networking.
+ *
+ *	Copyright 1994 - 2000 Neil Russell.
+ *	(See License)
+ *	Copyright 2000 Roland Borde
+ *	Copyright 2000 Paolo Scaffardi
+ *	Copyright 2000-2002 Wolfgang Denk, wd@denx.de
+ */
+
+#include <common.h>
+
+#include "arp.h"
+
+#ifndef	CONFIG_ARP_TIMEOUT
+/* Milliseconds before trying ARP again */
+# define ARP_TIMEOUT		5000UL
+#else
+# define ARP_TIMEOUT		CONFIG_ARP_TIMEOUT
+#endif
+
+
+#ifndef	CONFIG_NET_RETRY_COUNT
+# define ARP_TIMEOUT_COUNT	5	/* # of timeouts before giving up  */
+#else
+# define ARP_TIMEOUT_COUNT	CONFIG_NET_RETRY_COUNT
+#endif
+
+IPaddr_t	NetArpWaitPacketIP;
+IPaddr_t	NetArpWaitReplyIP;
+/* MAC address of waiting packet's destination */
+uchar	       *NetArpWaitPacketMAC;
+/* THE transmit packet */
+uchar	       *NetArpWaitTxPacket;
+int		NetArpWaitTxPacketSize;
+uchar		NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
+ulong		NetArpWaitTimerStart;
+int		NetArpWaitTry;
+
+void ArpInit(void)
+{
+	/* XXX problem with bss workaround */
+	NetArpWaitPacketMAC = NULL;
+	NetArpWaitPacketIP = 0;
+	NetArpWaitReplyIP = 0;
+	NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
+	NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
+	NetArpWaitTxPacketSize = 0;
+}
+
+void ArpRequest(void)
+{
+	uchar *pkt;
+	ARP_t *arp;
+
+	debug("ARP broadcast %d\n", NetArpWaitTry);
+
+	pkt = NetTxPacket;
+
+	pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
+
+	arp = (ARP_t *) pkt;
+
+	arp->ar_hrd = htons(ARP_ETHER);
+	arp->ar_pro = htons(PROT_IP);
+	arp->ar_hln = 6;
+	arp->ar_pln = 4;
+	arp->ar_op = htons(ARPOP_REQUEST);
+
+	/* source ET addr */
+	memcpy(&arp->ar_data[0], NetOurEther, 6);
+	/* source IP addr */
+	NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
+	/* dest ET addr = 0 */
+	memset(&arp->ar_data[10], '\0', 6);
+	if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
+	    (NetOurIP & NetOurSubnetMask)) {
+		if (NetOurGatewayIP == 0) {
+			puts("## Warning: gatewayip needed but not set\n");
+			NetArpWaitReplyIP = NetArpWaitPacketIP;
+		} else {
+			NetArpWaitReplyIP = NetOurGatewayIP;
+		}
+	} else {
+		NetArpWaitReplyIP = NetArpWaitPacketIP;
+	}
+
+	NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP);
+	(void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
+}
+
+void ArpTimeoutCheck(void)
+{
+	ulong t;
+
+	if (!NetArpWaitPacketIP)
+		return;
+
+	t = get_timer(0);
+
+	/* check for arp timeout */
+	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
+		NetArpWaitTry++;
+
+		if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
+			puts("\nARP Retry count exceeded; starting again\n");
+			NetArpWaitTry = 0;
+			NetStartAgain();
+		} else {
+			NetArpWaitTimerStart = t;
+			ArpRequest();
+		}
+	}
+}
+
+void ArpReceive(Ethernet_t *et, IP_t *ip, int len)
+{
+	ARP_t *arp;
+	IPaddr_t tmp;
+	uchar *pkt;
+
+	/*
+	 * We have to deal with two types of ARP packets:
+	 * - REQUEST packets will be answered by sending  our
+	 *   IP address - if we know it.
+	 * - REPLY packates are expected only after we asked
+	 *   for the TFTP server's or the gateway's ethernet
+	 *   address; so if we receive such a packet, we set
+	 *   the server ethernet address
+	 */
+	debug("Got ARP\n");
+
+	arp = (ARP_t *)ip;
+	if (len < ARP_HDR_SIZE) {
+		printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
+		return;
+	}
+	if (ntohs(arp->ar_hrd) != ARP_ETHER)
+		return;
+	if (ntohs(arp->ar_pro) != PROT_IP)
+		return;
+	if (arp->ar_hln != 6)
+		return;
+	if (arp->ar_pln != 4)
+		return;
+
+	if (NetOurIP == 0)
+		return;
+
+	if (NetReadIP(&arp->ar_data[16]) != NetOurIP)
+		return;
+
+	switch (ntohs(arp->ar_op)) {
+	case ARPOP_REQUEST:
+		/* reply with our IP address */
+		debug("Got ARP REQUEST, return our IP\n");
+		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,
+				(pkt - (uchar *)et) + ARP_HDR_SIZE);
+		return;
+
+	case ARPOP_REPLY:		/* arp reply */
+		/* are we waiting for a reply */
+		if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
+			break;
+
+#ifdef CONFIG_KEEP_SERVERADDR
+		if (NetServerIP == NetArpWaitPacketIP) {
+			char buf[20];
+			sprintf(buf, "%pM", arp->ar_data);
+			setenv("serveraddr", buf);
+		}
+#endif
+
+		tmp = NetReadIP(&arp->ar_data[6]);
+
+		/* matched waiting packet's address */
+		if (tmp == NetArpWaitReplyIP) {
+			debug("Got ARP REPLY, set eth addr (%pM)\n",
+				arp->ar_data);
+
+			/* save address for later use */
+			memcpy(NetArpWaitPacketMAC,
+			       &arp->ar_data[0], 6);
+
+#ifdef CONFIG_NETCONSOLE
+			NetGetHandler()(0, 0, 0, 0, 0);
+#endif
+			/* modify header, and transmit it */
+			memcpy(((Ethernet_t *)NetArpWaitTxPacket)->
+				et_dest, NetArpWaitPacketMAC, 6);
+			(void) eth_send(NetArpWaitTxPacket,
+					NetArpWaitTxPacketSize);
+
+			/* no arp request pending now */
+			NetArpWaitPacketIP = 0;
+			NetArpWaitTxPacketSize = 0;
+			NetArpWaitPacketMAC = NULL;
+
+		}
+		return;
+	default:
+		debug("Unexpected ARP opcode 0x%x\n",
+		      ntohs(arp->ar_op));
+		return;
+	}
+}
diff --git a/net/arp.h b/net/arp.h
new file mode 100644
index 0000000..09c763d
--- /dev/null
+++ b/net/arp.h
@@ -0,0 +1,30 @@ 
+/*
+ *	Copied from Linux Monitor (LiMon) - Networking.
+ *
+ *	Copyright 1994 - 2000 Neil Russell.
+ *	(See License)
+ *	Copyright 2000 Roland Borde
+ *	Copyright 2000 Paolo Scaffardi
+ *	Copyright 2000-2002 Wolfgang Denk, wd@denx.de
+ */
+
+#ifndef __ARP_H__
+#define __ARP_H__
+
+#include <net.h>
+
+extern IPaddr_t	NetArpWaitPacketIP;
+/* MAC address of waiting packet's destination */
+extern uchar *NetArpWaitPacketMAC;
+/* THE transmit packet */
+extern uchar *NetArpWaitTxPacket;
+extern int NetArpWaitTxPacketSize;
+extern ulong NetArpWaitTimerStart;
+extern int NetArpWaitTry;
+
+void ArpInit(void);
+void ArpRequest(void);
+void ArpTimeoutCheck(void);
+void ArpReceive(Ethernet_t *et, IP_t *ip, int len);
+
+#endif /* __ARP_H__ */
diff --git a/net/net.c b/net/net.c
index 48d3ca8..2dae5a0 100644
--- a/net/net.c
+++ b/net/net.c
@@ -78,6 +78,7 @@ 
 #include <watchdog.h>
 #include <command.h>
 #include <net.h>
+#include "arp.h"
 #include "bootp.h"
 #include "tftp.h"
 #ifdef CONFIG_CMD_RARP
@@ -100,20 +101,6 @@ 
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#ifndef	CONFIG_ARP_TIMEOUT
-/* Milliseconds before trying ARP again */
-# define ARP_TIMEOUT		5000UL
-#else
-# define ARP_TIMEOUT		CONFIG_ARP_TIMEOUT
-#endif
-
-
-#ifndef	CONFIG_NET_RETRY_COUNT
-# define ARP_TIMEOUT_COUNT	5	/* # of timeouts before giving up  */
-#else
-# define ARP_TIMEOUT_COUNT	CONFIG_NET_RETRY_COUNT
-#endif
-
 /** BOOTP EXTENTIONS **/
 
 /* Our subnet mask (0=unknown) */
@@ -220,82 +207,6 @@  static int NetTryCount;
 
 /**********************************************************************/
 
-IPaddr_t	NetArpWaitPacketIP;
-IPaddr_t	NetArpWaitReplyIP;
-/* MAC address of waiting packet's destination */
-uchar	       *NetArpWaitPacketMAC;
-/* THE transmit packet */
-uchar	       *NetArpWaitTxPacket;
-int		NetArpWaitTxPacketSize;
-uchar		NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
-ulong		NetArpWaitTimerStart;
-int		NetArpWaitTry;
-
-void ArpRequest(void)
-{
-	uchar *pkt;
-	ARP_t *arp;
-
-	debug("ARP broadcast %d\n", NetArpWaitTry);
-
-	pkt = NetTxPacket;
-
-	pkt += NetSetEther(pkt, NetBcastAddr, PROT_ARP);
-
-	arp = (ARP_t *) pkt;
-
-	arp->ar_hrd = htons(ARP_ETHER);
-	arp->ar_pro = htons(PROT_IP);
-	arp->ar_hln = 6;
-	arp->ar_pln = 4;
-	arp->ar_op = htons(ARPOP_REQUEST);
-
-	/* source ET addr */
-	memcpy(&arp->ar_data[0], NetOurEther, 6);
-	/* source IP addr */
-	NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
-	/* dest ET addr = 0 */
-	memset(&arp->ar_data[10], '\0', 6);
-	if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
-	    (NetOurIP & NetOurSubnetMask)) {
-		if (NetOurGatewayIP == 0) {
-			puts("## Warning: gatewayip needed but not set\n");
-			NetArpWaitReplyIP = NetArpWaitPacketIP;
-		} else {
-			NetArpWaitReplyIP = NetOurGatewayIP;
-		}
-	} else {
-		NetArpWaitReplyIP = NetArpWaitPacketIP;
-	}
-
-	NetWriteIP((uchar *) &arp->ar_data[16], NetArpWaitReplyIP);
-	(void) eth_send(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
-}
-
-void ArpTimeoutCheck(void)
-{
-	ulong t;
-
-	if (!NetArpWaitPacketIP)
-		return;
-
-	t = get_timer(0);
-
-	/* check for arp timeout */
-	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT) {
-		NetArpWaitTry++;
-
-		if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
-			puts("\nARP Retry count exceeded; starting again\n");
-			NetArpWaitTry = 0;
-			NetStartAgain();
-		} else {
-			NetArpWaitTimerStart = t;
-			ArpRequest();
-		}
-	}
-}
-
 /*
  * Check if autoload is enabled. If so, use either NFS or TFTP to download
  * the boot file.
@@ -363,15 +274,11 @@  int NetLoop(enum proto_t protocol)
 	NetRestarted = 0;
 	NetDevExists = 0;
 
-	/* XXX problem with bss workaround */
-	NetArpWaitPacketMAC = NULL;
-	NetArpWaitTxPacket = NULL;
-	NetArpWaitPacketIP = 0;
-	NetArpWaitReplyIP = 0;
-	NetArpWaitTxPacket = NULL;
 	NetTxPacket = NULL;
 	NetTryCount = 1;
 
+	ArpInit();
+
 	if (!NetTxPacket) {
 		int	i;
 		/*
@@ -383,12 +290,6 @@  int NetLoop(enum proto_t protocol)
 			NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
 	}
 
-	if (!NetArpWaitTxPacket) {
-		NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
-		NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
-		NetArpWaitTxPacketSize = 0;
-	}
-
 	eth_halt();
 	eth_set_current();
 	if (eth_init(bd) < 0) {
@@ -661,6 +562,13 @@  void NetStartAgain(void)
  *	Miscelaneous bits.
  */
 
+rxhand_f *
+NetGetHandler(void)
+{
+	return packetHandler;
+}
+
+
 void
 NetSetHandler(rxhand_f *f)
 {
@@ -1072,11 +980,12 @@  NetReceive(volatile uchar *inpkt, int len)
 {
 	Ethernet_t *et;
 	IP_t	*ip;
+#ifdef CONFIG_CMD_RARP
 	ARP_t	*arp;
+#endif
 	IPaddr_t tmp;
 	IPaddr_t src_ip;
 	int	x;
-	uchar *pkt;
 #if defined(CONFIG_CMD_CDP)
 	int iscdp;
 #endif
@@ -1173,99 +1082,7 @@  NetReceive(volatile uchar *inpkt, int len)
 	switch (x) {
 
 	case PROT_ARP:
-		/*
-		 * We have to deal with two types of ARP packets:
-		 * - REQUEST packets will be answered by sending  our
-		 *   IP address - if we know it.
-		 * - REPLY packates are expected only after we asked
-		 *   for the TFTP server's or the gateway's ethernet
-		 *   address; so if we receive such a packet, we set
-		 *   the server ethernet address
-		 */
-		debug("Got ARP\n");
-
-		arp = (ARP_t *)ip;
-		if (len < ARP_HDR_SIZE) {
-			printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
-			return;
-		}
-		if (ntohs(arp->ar_hrd) != ARP_ETHER)
-			return;
-		if (ntohs(arp->ar_pro) != PROT_IP)
-			return;
-		if (arp->ar_hln != 6)
-			return;
-		if (arp->ar_pln != 4)
-			return;
-
-		if (NetOurIP == 0)
-			return;
-
-		if (NetReadIP(&arp->ar_data[16]) != NetOurIP)
-			return;
-
-		switch (ntohs(arp->ar_op)) {
-		case ARPOP_REQUEST:
-			/* reply with our IP address */
-			debug("Got ARP REQUEST, return our IP\n");
-			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,
-					(pkt - (uchar *)et) + ARP_HDR_SIZE);
-			return;
-
-		case ARPOP_REPLY:		/* arp reply */
-			/* are we waiting for a reply */
-			if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
-				break;
-
-#ifdef CONFIG_KEEP_SERVERADDR
-			if (NetServerIP == NetArpWaitPacketIP) {
-				char buf[20];
-				sprintf(buf, "%pM", arp->ar_data);
-				setenv("serveraddr", buf);
-			}
-#endif
-
-			debug("Got ARP REPLY, set server/gtwy eth addr (%pM)\n",
-				arp->ar_data);
-
-			tmp = NetReadIP(&arp->ar_data[6]);
-
-			/* matched waiting packet's address */
-			if (tmp == NetArpWaitReplyIP) {
-				debug("Got it\n");
-
-				/* save address for later use */
-				memcpy(NetArpWaitPacketMAC,
-				       &arp->ar_data[0], 6);
-
-#ifdef CONFIG_NETCONSOLE
-				(*packetHandler)(0, 0, 0, 0, 0);
-#endif
-				/* modify header, and transmit it */
-				memcpy(((Ethernet_t *)NetArpWaitTxPacket)->
-					et_dest, NetArpWaitPacketMAC, 6);
-				(void) eth_send(NetArpWaitTxPacket,
-						NetArpWaitTxPacketSize);
-
-				/* no arp request pending now */
-				NetArpWaitPacketIP = 0;
-				NetArpWaitTxPacketSize = 0;
-				NetArpWaitPacketMAC = NULL;
-
-			}
-			return;
-		default:
-			debug("Unexpected ARP opcode 0x%x\n",
-			      ntohs(arp->ar_op));
-			return;
-		}
+		ArpReceive(et, ip, len);
 		break;
 
 #ifdef CONFIG_CMD_RARP