reformatted sources, added start of bootp protocol implementation

This commit is contained in:
Markus Fröschle
2013-12-24 08:23:01 +00:00
parent c938b07cc6
commit 62db6515c9
8 changed files with 1383 additions and 1169 deletions

View File

@@ -100,6 +100,7 @@ CSRCS= \
ip.c \ ip.c \
udp.c \ udp.c \
arp.c \ arp.c \
bootp.c \
\ \
basflash.c \ basflash.c \
basflash_start.c basflash_start.c

View File

@@ -1,99 +1,99 @@
/* /*
* File: arp.h * File: arp.h
* Purpose: ARP definitions. * Purpose: ARP definitions.
* *
* Notes: * Notes:
*/ */
#ifndef _ARP_H #ifndef _ARP_H
#define _ARP_H #define _ARP_H
/********************************************************************/ /********************************************************************/
/* /*
* This data definition is defined for Ethernet only! * This data definition is defined for Ethernet only!
*/ */
typedef struct typedef struct
{ {
uint16_t ar_hrd; uint16_t ar_hrd;
uint16_t ar_pro; uint16_t ar_pro;
uint8_t ar_hln; uint8_t ar_hln;
uint8_t ar_pln; uint8_t ar_pln;
uint16_t opcode; uint16_t opcode;
uint8_t ar_sha[6]; /* ethernet hw address */ uint8_t ar_sha[6]; /* ethernet hw address */
uint8_t ar_spa[4]; /* ip address */ uint8_t ar_spa[4]; /* ip address */
uint8_t ar_tha[6]; /* ethernet hw address */ uint8_t ar_tha[6]; /* ethernet hw address */
uint8_t ar_tpa[4]; /* ip address */ uint8_t ar_tpa[4]; /* ip address */
} arp_frame_hdr; } arp_frame_hdr;
#define ARP_HDR_LEN sizeof(arp_frame_hdr) #define ARP_HDR_LEN sizeof(arp_frame_hdr)
/* /*
* ARP table entry definition. Note that this table only designed * ARP table entry definition. Note that this table only designed
* with Ethernet and IP in mind. * with Ethernet and IP in mind.
*/ */
#define MAX_HWA_SIZE (6) /* 6 is enough for Ethernet address */ #define MAX_HWA_SIZE (6) /* 6 is enough for Ethernet address */
#define MAX_PA_SIZE (4) /* 4 is enough for Protocol address */ #define MAX_PA_SIZE (4) /* 4 is enough for Protocol address */
typedef struct typedef struct
{ {
uint16_t protocol; uint16_t protocol;
uint8_t hwa_size; uint8_t hwa_size;
uint8_t hwa[MAX_HWA_SIZE]; uint8_t hwa[MAX_HWA_SIZE];
uint8_t pa_size; uint8_t pa_size;
uint8_t pa[MAX_PA_SIZE]; uint8_t pa[MAX_PA_SIZE];
int longevity; int longevity;
} ARPENTRY; } ARPENTRY;
#define MAX_ARP_ENTRY (10) #define MAX_ARP_ENTRY (10)
typedef struct typedef struct
{ {
unsigned int tab_size; unsigned int tab_size;
ARPENTRY table[MAX_ARP_ENTRY]; ARPENTRY table[MAX_ARP_ENTRY];
} ARP_INFO; } ARP_INFO;
#define ARP_ENTRY_EMPTY (0) #define ARP_ENTRY_EMPTY (0)
#define ARP_ENTRY_PERM (1) #define ARP_ENTRY_PERM (1)
#define ARP_ENTRY_TEMP (2) #define ARP_ENTRY_TEMP (2)
#define ETHERNET (1) #define ETHERNET (1)
#define ARP_REQUEST (1) #define ARP_REQUEST (1)
#define ARP_REPLY (2) #define ARP_REPLY (2)
#define ARP_TIMEOUT (1) /* Timeout in seconds */ #define ARP_TIMEOUT (1) /* Timeout in seconds */
/* Protocol Header information */ /* Protocol Header information */
#define ARP_HDR_OFFSET ETH_HDR_LEN #define ARP_HDR_OFFSET ETH_HDR_LEN
/********************************************************************/ /********************************************************************/
uint8_t * uint8_t *
arp_get_mypa (void); arp_get_mypa (void);
uint8_t * uint8_t *
arp_get_myha (void); arp_get_myha (void);
uint8_t * uint8_t *
arp_get_broadcast (void); arp_get_broadcast (void);
void void
arp_merge (ARP_INFO *, uint16_t, int, uint8_t *, int, uint8_t *, int); arp_merge (ARP_INFO *, uint16_t, int, uint8_t *, int, uint8_t *, int);
void void
arp_remove (ARP_INFO *, uint16_t, uint8_t *, uint8_t *); arp_remove (ARP_INFO *, uint16_t, uint8_t *, uint8_t *);
void void
arp_request (NIF *, uint8_t *); arp_request (NIF *, uint8_t *);
void void
arp_handler (NIF *, NBUF *); arp_handler (NIF *, NBUF *);
uint8_t * uint8_t *
arp_resolve (NIF *, uint16_t, uint8_t *); arp_resolve (NIF *, uint16_t, uint8_t *);
void void
arp_init (ARP_INFO *); arp_init (ARP_INFO *);
/********************************************************************/ /********************************************************************/
#endif /* _ARP_H */ #endif /* _ARP_H */

58
include/bootp.h Normal file
View File

@@ -0,0 +1,58 @@
/*
* File: bootp.h
* Purpose: BOOTP definitions.
*
* Notes:
*/
#ifndef _BOOTP_H_
#define _BOOTP_H_
/********************************************************************/
/*
* This data definition is defined for Ethernet only!
*/
typedef struct
{
uint8_t type; /* bootp operation type */
uint8_t htype; /* hardware type */
uint8_t hlen; /* hardware address length */
uint8_t hops; /* hops */
uint32_t xid; /* transaction identifier */
uint16_t secs; /* seconds since trying to boot */
uint16_t flags; /* only broadcast flag in use */
uint32_t cl_addr; /* client ip address. Set to all 0 on request */
uint32_t yi_addr; /* this field contains the new IP */
uint32_t gi_addr; /* gateway address */
uint8_t ch_addr[16]; /* client hw address */
uint8_t sname[64]; /* server name */
uint8_t file[128]; /* name of bootfile */
uint8_t vend[64]; /* vendor specific (see below) */
} bootp_frame_hdr;
#define BOOTP_HDR_LEN sizeof(bootp_frame_hdr)
/* possible values for type field */
#define BOOTP_TYPE_BOOTREQUEST 1
#define BOOTP_TYPE_BOOTREPLY 2
/* values for hardware type - we only use ethernet */
#define BOOTP_HTYPE_ETHERNET 1
/* values for hlen - again only ethernet defined */
#define BOOTP_HLEN_ETHERNET 6
/* values for flags - only broadcast flag in use */
#define BOOTP_FLAGS_BROADCAST 1
#define BOOTP_TIMEOUT (1) /* Timeout in seconds */
/* Protocol Header information */
#define BOOTP_HDR_OFFSET ETH_HDR_LEN
extern void bootp_request(NIF *, uint8_t *);
extern void bootp_handler(NIF *, NBUF *);
//extern void bootp_init(BOOTP_INFO *);
#endif /* _BOOTP_H_ */

924
net/arp.c
View File

@@ -1,462 +1,462 @@
/* /*
* File: arp.c * File: arp.c
* Purpose: Address Resolution Protocol routines. * Purpose: Address Resolution Protocol routines.
* *
* Notes: * Notes:
*/ */
#include "net.h" #include "net.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#define TIMER_NETWORK 0 #define TIMER_NETWORK 0
static uint8_t *arp_find_pair(ARP_INFO *arptab, uint16_t protocol, uint8_t *hwa, uint8_t *pa) static uint8_t *arp_find_pair(ARP_INFO *arptab, uint16_t protocol, uint8_t *hwa, uint8_t *pa)
{ {
/* /*
* This function searches through the ARP table for the * This function searches through the ARP table for the
* specified <protocol,hwa> or <protocol,pa> address pair. * specified <protocol,hwa> or <protocol,pa> address pair.
* If it is found, then a a pointer to the non-specified * If it is found, then a a pointer to the non-specified
* address is returned. Otherwise NULL is returned. * address is returned. Otherwise NULL is returned.
* If you pass in <protocol,pa> then you get <hwa> out. * If you pass in <protocol,pa> then you get <hwa> out.
* If you pass in <protocol,hwa> then you get <pa> out. * If you pass in <protocol,hwa> then you get <pa> out.
*/ */
int slot, i, match = false; int slot, i, match = false;
uint8_t *rvalue; uint8_t *rvalue;
if (((hwa == 0) && (pa == 0)) || (arptab == 0)) if (((hwa == 0) && (pa == 0)) || (arptab == 0))
return NULL; return NULL;
rvalue = NULL; rvalue = NULL;
/* /*
* Check each protocol address for a match * Check each protocol address for a match
*/ */
for (slot = 0; slot < arptab->tab_size; slot++) for (slot = 0; slot < arptab->tab_size; slot++)
{ {
if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) && if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) &&
(arptab->table[slot].protocol == protocol)) (arptab->table[slot].protocol == protocol))
{ {
match = true; match = true;
if (hwa != 0) if (hwa != 0)
{ {
/* /*
* Check the Hardware Address field * Check the Hardware Address field
*/ */
rvalue = &arptab->table[slot].pa[0]; rvalue = &arptab->table[slot].pa[0];
for (i = 0; i < arptab->table[slot].hwa_size; i++) for (i = 0; i < arptab->table[slot].hwa_size; i++)
{ {
if (arptab->table[slot].hwa[i] != hwa[i]) if (arptab->table[slot].hwa[i] != hwa[i])
{ {
match = false; match = false;
break; break;
} }
} }
} }
else else
{ {
/* /*
* Check the Protocol Address field * Check the Protocol Address field
*/ */
rvalue = &arptab->table[slot].hwa[0]; rvalue = &arptab->table[slot].hwa[0];
for (i = 0; i < arptab->table[slot].pa_size; i++) for (i = 0; i < arptab->table[slot].pa_size; i++)
{ {
if (arptab->table[slot].pa[i] != pa[i]) if (arptab->table[slot].pa[i] != pa[i])
{ {
match = false; match = false;
break; break;
} }
} }
} }
if (match) if (match)
{ {
break; break;
} }
} }
} }
if (match) if (match)
return rvalue; return rvalue;
else else
return NULL; return NULL;
} }
void arp_merge(ARP_INFO *arptab, uint16_t protocol, int hwa_size, uint8_t *hwa, void arp_merge(ARP_INFO *arptab, uint16_t protocol, int hwa_size, uint8_t *hwa,
int pa_size, uint8_t *pa, int longevity) int pa_size, uint8_t *pa, int longevity)
{ {
/* /*
* This function merges an entry into the ARP table. If * This function merges an entry into the ARP table. If
* either piece is NULL, the function exits, otherwise * either piece is NULL, the function exits, otherwise
* the entry is merged or added, provided there is space. * the entry is merged or added, provided there is space.
*/ */
int i, slot; int i, slot;
uint8_t *ta; uint8_t *ta;
if ((hwa == NULL) || (pa == NULL) || (arptab == NULL) || if ((hwa == NULL) || (pa == NULL) || (arptab == NULL) ||
((longevity != ARP_ENTRY_TEMP) && ((longevity != ARP_ENTRY_TEMP) &&
(longevity != ARP_ENTRY_PERM))) (longevity != ARP_ENTRY_PERM)))
{ {
return; return;
} }
/* First search ARP table for existing entry */ /* First search ARP table for existing entry */
if ((ta = arp_find_pair(arptab,protocol,NULL,pa)) != 0) if ((ta = arp_find_pair(arptab,protocol,NULL,pa)) != 0)
{ {
/* Update hardware address */ /* Update hardware address */
for (i = 0; i < hwa_size; i++) for (i = 0; i < hwa_size; i++)
ta[i] = hwa[i]; ta[i] = hwa[i];
return; return;
} }
/* Next try to find an empty slot */ /* Next try to find an empty slot */
slot = -1; slot = -1;
for (i = 0; i < MAX_ARP_ENTRY; i++) for (i = 0; i < MAX_ARP_ENTRY; i++)
{ {
if (arptab->table[i].longevity == ARP_ENTRY_EMPTY) if (arptab->table[i].longevity == ARP_ENTRY_EMPTY)
{ {
slot = i; slot = i;
break; break;
} }
} }
/* if no empty slot was found, pick a temp slot */ /* if no empty slot was found, pick a temp slot */
if (slot == -1) if (slot == -1)
{ {
for (i = 0; i < MAX_ARP_ENTRY; i++) for (i = 0; i < MAX_ARP_ENTRY; i++)
{ {
if (arptab->table[i].longevity == ARP_ENTRY_TEMP) if (arptab->table[i].longevity == ARP_ENTRY_TEMP)
{ {
slot = i; slot = i;
break; break;
} }
} }
} }
/* if after all this, still no slot found, add in last slot */ /* if after all this, still no slot found, add in last slot */
if (slot == -1) if (slot == -1)
slot = (MAX_ARP_ENTRY -1); slot = (MAX_ARP_ENTRY - 1);
/* add the entry into the slot */ /* add the entry into the slot */
arptab->table[slot].protocol = protocol; arptab->table[slot].protocol = protocol;
arptab->table[slot].hwa_size = (uint8_t) hwa_size; arptab->table[slot].hwa_size = (uint8_t) hwa_size;
for (i = 0; i < hwa_size; i++) for (i = 0; i < hwa_size; i++)
arptab->table[slot].hwa[i] = hwa[i]; arptab->table[slot].hwa[i] = hwa[i];
arptab->table[slot].pa_size = (uint8_t) pa_size; arptab->table[slot].pa_size = (uint8_t) pa_size;
for (i = 0; i < pa_size; i++) for (i = 0; i < pa_size; i++)
arptab->table[slot].pa[i] = pa[i]; arptab->table[slot].pa[i] = pa[i];
arptab->table[slot].longevity = longevity; arptab->table[slot].longevity = longevity;
} }
void arp_remove(ARP_INFO *arptab, uint16_t protocol, uint8_t *hwa, uint8_t *pa) void arp_remove(ARP_INFO *arptab, uint16_t protocol, uint8_t *hwa, uint8_t *pa)
{ {
/* /*
* This function removes an entry from the ARP table. The * This function removes an entry from the ARP table. The
* ARP table is searched according to the non-NULL address * ARP table is searched according to the non-NULL address
* that is provided. * that is provided.
*/ */
int slot, i, match; int slot, i, match;
if (((hwa == 0) && (pa == 0)) || (arptab == 0)) if (((hwa == 0) && (pa == 0)) || (arptab == 0))
return; return;
/* check each hardware adress for a match */ /* check each hardware adress for a match */
for (slot = 0; slot < arptab->tab_size; slot++) for (slot = 0; slot < arptab->tab_size; slot++)
{ {
if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) && if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) &&
(arptab->table[slot].protocol == protocol)) (arptab->table[slot].protocol == protocol))
{ {
match = true; match = true;
if (hwa != 0) if (hwa != 0)
{ {
/* Check Hardware Address field */ /* Check Hardware Address field */
for (i = 0; i < arptab->table[slot].hwa_size; i++) for (i = 0; i < arptab->table[slot].hwa_size; i++)
{ {
if (arptab->table[slot].hwa[i] != hwa[i]) if (arptab->table[slot].hwa[i] != hwa[i])
{ {
match = false; match = false;
break; break;
} }
} }
} }
else else
{ {
/* Check Protocol Address field */ /* Check Protocol Address field */
for (i = 0; i < arptab->table[slot].pa_size; i++) for (i = 0; i < arptab->table[slot].pa_size; i++)
{ {
if (arptab->table[slot].pa[i] != pa[i]) if (arptab->table[slot].pa[i] != pa[i])
{ {
match = false; match = false;
break; break;
} }
} }
} }
if (match) if (match)
{ {
for (i = 0; i < arptab->table[slot].hwa_size; i++) for (i = 0; i < arptab->table[slot].hwa_size; i++)
arptab->table[slot].hwa[i] = 0; arptab->table[slot].hwa[i] = 0;
for (i = 0; i < arptab->table[slot].pa_size; i++) for (i = 0; i < arptab->table[slot].pa_size; i++)
arptab->table[slot].pa[i] = 0; arptab->table[slot].pa[i] = 0;
arptab->table[slot].longevity = ARP_ENTRY_EMPTY; arptab->table[slot].longevity = ARP_ENTRY_EMPTY;
break; break;
} }
} }
} }
} }
void arp_request(NIF *nif, uint8_t *pa) void arp_request(NIF *nif, uint8_t *pa)
{ {
/* /*
* This function broadcasts an ARP request for the protocol * This function broadcasts an ARP request for the protocol
* address "pa" * address "pa"
*/ */
uint8_t *addr; uint8_t *addr;
NBUF *pNbuf; NBUF *pNbuf;
arp_frame_hdr *arpframe; arp_frame_hdr *arpframe;
int i, result; int i, result;
pNbuf = nbuf_alloc(); pNbuf = nbuf_alloc();
if (pNbuf == NULL) if (pNbuf == NULL)
{ {
#if defined(DEBUG_PRINT) #if defined(DEBUG_PRINT)
printf("ARP: arp_request couldn't allocate Tx buffer\n"); printf("ARP: arp_request couldn't allocate Tx buffer\n");
#endif #endif
return; return;
} }
arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET]; arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET];
/* Build the ARP request packet */ /* Build the ARP request packet */
arpframe->ar_hrd = ETHERNET; arpframe->ar_hrd = ETHERNET;
arpframe->ar_pro = ETH_FRM_IP; arpframe->ar_pro = ETH_FRM_IP;
arpframe->ar_hln = 6; arpframe->ar_hln = 6;
arpframe->ar_pln = 4; arpframe->ar_pln = 4;
arpframe->opcode = ARP_REQUEST; arpframe->opcode = ARP_REQUEST;
addr = &nif->hwa[0]; addr = &nif->hwa[0];
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
arpframe->ar_sha[i] = addr[i]; arpframe->ar_sha[i] = addr[i];
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP)); addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
arpframe->ar_spa[i] = addr[i]; arpframe->ar_spa[i] = addr[i];
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
arpframe->ar_tha[i] = 0x00; arpframe->ar_tha[i] = 0x00;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
arpframe->ar_tpa[i] = pa[i]; arpframe->ar_tpa[i] = pa[i];
pNbuf->length = ARP_HDR_LEN; pNbuf->length = ARP_HDR_LEN;
/* Send the ARP request */ /* Send the ARP request */
result = nif->send(nif, nif->broadcast, nif->hwa, ETH_FRM_ARP, pNbuf); result = nif->send(nif, nif->broadcast, nif->hwa, ETH_FRM_ARP, pNbuf);
if (result == 0) if (result == 0)
nbuf_free(pNbuf); nbuf_free(pNbuf);
} }
static int arp_resolve_pa(NIF *nif, uint16_t protocol, uint8_t *pa, uint8_t **ha) static int arp_resolve_pa(NIF *nif, uint16_t protocol, uint8_t *pa, uint8_t **ha)
{ {
/* /*
* This function accepts a pointer to a protocol address and * This function accepts a pointer to a protocol address and
* searches the ARP table for a hardware address match. If no * searches the ARP table for a hardware address match. If no
* no match found, false is returned. * no match found, false is returned.
*/ */
ARP_INFO *arptab; ARP_INFO *arptab;
if ((pa == NULL) || (nif == NULL) || (protocol == 0)) if ((pa == NULL) || (nif == NULL) || (protocol == 0))
return 0; return 0;
arptab = nif_get_protocol_info (nif,ETH_FRM_ARP); arptab = nif_get_protocol_info (nif,ETH_FRM_ARP);
*ha = arp_find_pair(arptab,protocol,0,pa); *ha = arp_find_pair(arptab,protocol,0,pa);
if (*ha == NULL) if (*ha == NULL)
return 0; return 0;
else else
return 1; return 1;
} }
uint8_t *arp_resolve(NIF *nif, uint16_t protocol, uint8_t *pa) uint8_t *arp_resolve(NIF *nif, uint16_t protocol, uint8_t *pa)
{ {
int i; int i;
uint8_t *hwa; uint8_t *hwa;
/* /*
* Check to see if the necessary MAC-to-IP translation information * Check to see if the necessary MAC-to-IP translation information
* is in table already * is in table already
*/ */
if (arp_resolve_pa (nif, protocol, pa, &hwa)) if (arp_resolve_pa (nif, protocol, pa, &hwa))
return hwa; return hwa;
/* /*
* Ok, it's not, so we need to try to obtain it by broadcasting * Ok, it's not, so we need to try to obtain it by broadcasting
* an ARP request. Hopefully the desired host is listening and * an ARP request. Hopefully the desired host is listening and
* will respond with it's MAC address * will respond with it's MAC address
*/ */
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
arp_request (nif, pa); arp_request (nif, pa);
timer_set_secs(TIMER_NETWORK, ARP_TIMEOUT); timer_set_secs(TIMER_NETWORK, ARP_TIMEOUT);
while (timer_get_reference(TIMER_NETWORK)) while (timer_get_reference(TIMER_NETWORK))
{ {
if (arp_resolve_pa (nif, protocol, pa, &hwa)) if (arp_resolve_pa (nif, protocol, pa, &hwa))
return hwa; return hwa;
} }
} }
return NULL; return NULL;
} }
void arp_init(ARP_INFO *arptab) void arp_init(ARP_INFO *arptab)
{ {
int slot, i; int slot, i;
arptab->tab_size = MAX_ARP_ENTRY; arptab->tab_size = MAX_ARP_ENTRY;
for (slot = 0; slot < arptab->tab_size; slot++) for (slot = 0; slot < arptab->tab_size; slot++)
{ {
for (i = 0; i < MAX_HWA_SIZE; i++) for (i = 0; i < MAX_HWA_SIZE; i++)
arptab->table[slot].hwa[i] = 0; arptab->table[slot].hwa[i] = 0;
for (i = 0; i < MAX_PA_SIZE; i++) for (i = 0; i < MAX_PA_SIZE; i++)
arptab->table[slot].pa[i] = 0; arptab->table[slot].pa[i] = 0;
arptab->table[slot].longevity = ARP_ENTRY_EMPTY; arptab->table[slot].longevity = ARP_ENTRY_EMPTY;
arptab->table[slot].hwa_size = 0; arptab->table[slot].hwa_size = 0;
arptab->table[slot].pa_size = 0; arptab->table[slot].pa_size = 0;
} }
} }
void arp_handler(NIF *nif, NBUF *pNbuf) void arp_handler(NIF *nif, NBUF *pNbuf)
{ {
/* /*
* ARP protocol handler * ARP protocol handler
*/ */
uint8_t *addr; uint8_t *addr;
ARP_INFO *arptab; ARP_INFO *arptab;
int longevity; int longevity;
arp_frame_hdr *rx_arpframe, *tx_arpframe; arp_frame_hdr *rx_arpframe, *tx_arpframe;
arptab = nif_get_protocol_info(nif, ETH_FRM_ARP); arptab = nif_get_protocol_info(nif, ETH_FRM_ARP);
rx_arpframe = (arp_frame_hdr *) &pNbuf->data[pNbuf->offset]; rx_arpframe = (arp_frame_hdr *) &pNbuf->data[pNbuf->offset];
/* /*
* Check for an appropriate ARP packet * Check for an appropriate ARP packet
*/ */
if ((pNbuf->length < ARP_HDR_LEN) || if ((pNbuf->length < ARP_HDR_LEN) ||
(rx_arpframe->ar_hrd != ETHERNET) || (rx_arpframe->ar_hrd != ETHERNET) ||
(rx_arpframe->ar_hln != 6) || (rx_arpframe->ar_hln != 6) ||
(rx_arpframe->ar_pro != ETH_FRM_IP) || (rx_arpframe->ar_pro != ETH_FRM_IP) ||
(rx_arpframe->ar_pln != 4)) (rx_arpframe->ar_pln != 4))
{ {
nbuf_free(pNbuf); nbuf_free(pNbuf);
return; return;
} }
/* /*
* Check to see if it was addressed to me - if it was, keep this * Check to see if it was addressed to me - if it was, keep this
* ARP entry in the table permanently; if not, mark it so that it * ARP entry in the table permanently; if not, mark it so that it
* can be displaced later if necessary * can be displaced later if necessary
*/ */
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP)); addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
if ((rx_arpframe->ar_tpa[0] == addr[0]) && if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
(rx_arpframe->ar_tpa[1] == addr[1]) && (rx_arpframe->ar_tpa[1] == addr[1]) &&
(rx_arpframe->ar_tpa[2] == addr[2]) && (rx_arpframe->ar_tpa[2] == addr[2]) &&
(rx_arpframe->ar_tpa[3] == addr[3]) ) (rx_arpframe->ar_tpa[3] == addr[3]) )
{ {
longevity = ARP_ENTRY_PERM; longevity = ARP_ENTRY_PERM;
} }
else else
longevity = ARP_ENTRY_TEMP; longevity = ARP_ENTRY_TEMP;
/* /*
* Add ARP info into the table * Add ARP info into the table
*/ */
arp_merge(arptab, arp_merge(arptab,
rx_arpframe->ar_pro, rx_arpframe->ar_pro,
rx_arpframe->ar_hln, rx_arpframe->ar_hln,
&rx_arpframe->ar_sha[0], &rx_arpframe->ar_sha[0],
rx_arpframe->ar_pln, rx_arpframe->ar_pln,
&rx_arpframe->ar_spa[0], &rx_arpframe->ar_spa[0],
longevity longevity
); );
switch (rx_arpframe->opcode) switch (rx_arpframe->opcode)
{ {
case ARP_REQUEST: case ARP_REQUEST:
/* /*
* Check to see if request is directed to me * Check to see if request is directed to me
*/ */
if ((rx_arpframe->ar_tpa[0] == addr[0]) && if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
(rx_arpframe->ar_tpa[1] == addr[1]) && (rx_arpframe->ar_tpa[1] == addr[1]) &&
(rx_arpframe->ar_tpa[2] == addr[2]) && (rx_arpframe->ar_tpa[2] == addr[2]) &&
(rx_arpframe->ar_tpa[3] == addr[3]) ) (rx_arpframe->ar_tpa[3] == addr[3]) )
{ {
/* /*
* Reuse the current network buffer to assemble an ARP reply * Reuse the current network buffer to assemble an ARP reply
*/ */
tx_arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET]; tx_arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET];
/* /*
* Build new ARP frame from the received data * Build new ARP frame from the received data
*/ */
tx_arpframe->ar_hrd = ETHERNET; tx_arpframe->ar_hrd = ETHERNET;
tx_arpframe->ar_pro = ETH_FRM_IP; tx_arpframe->ar_pro = ETH_FRM_IP;
tx_arpframe->ar_hln = 6; tx_arpframe->ar_hln = 6;
tx_arpframe->ar_pln = 4; tx_arpframe->ar_pln = 4;
tx_arpframe->opcode = ARP_REPLY; tx_arpframe->opcode = ARP_REPLY;
tx_arpframe->ar_tha[0] = rx_arpframe->ar_sha[0]; tx_arpframe->ar_tha[0] = rx_arpframe->ar_sha[0];
tx_arpframe->ar_tha[1] = rx_arpframe->ar_sha[1]; tx_arpframe->ar_tha[1] = rx_arpframe->ar_sha[1];
tx_arpframe->ar_tha[2] = rx_arpframe->ar_sha[2]; tx_arpframe->ar_tha[2] = rx_arpframe->ar_sha[2];
tx_arpframe->ar_tha[3] = rx_arpframe->ar_sha[3]; tx_arpframe->ar_tha[3] = rx_arpframe->ar_sha[3];
tx_arpframe->ar_tha[4] = rx_arpframe->ar_sha[4]; tx_arpframe->ar_tha[4] = rx_arpframe->ar_sha[4];
tx_arpframe->ar_tha[5] = rx_arpframe->ar_sha[5]; tx_arpframe->ar_tha[5] = rx_arpframe->ar_sha[5];
tx_arpframe->ar_tpa[0] = rx_arpframe->ar_spa[0]; tx_arpframe->ar_tpa[0] = rx_arpframe->ar_spa[0];
tx_arpframe->ar_tpa[1] = rx_arpframe->ar_spa[1]; tx_arpframe->ar_tpa[1] = rx_arpframe->ar_spa[1];
tx_arpframe->ar_tpa[2] = rx_arpframe->ar_spa[2]; tx_arpframe->ar_tpa[2] = rx_arpframe->ar_spa[2];
tx_arpframe->ar_tpa[3] = rx_arpframe->ar_spa[3]; tx_arpframe->ar_tpa[3] = rx_arpframe->ar_spa[3];
/* /*
* Now copy in the new information * Now copy in the new information
*/ */
addr = &nif->hwa[0]; addr = &nif->hwa[0];
tx_arpframe->ar_sha[0] = addr[0]; tx_arpframe->ar_sha[0] = addr[0];
tx_arpframe->ar_sha[1] = addr[1]; tx_arpframe->ar_sha[1] = addr[1];
tx_arpframe->ar_sha[2] = addr[2]; tx_arpframe->ar_sha[2] = addr[2];
tx_arpframe->ar_sha[3] = addr[3]; tx_arpframe->ar_sha[3] = addr[3];
tx_arpframe->ar_sha[4] = addr[4]; tx_arpframe->ar_sha[4] = addr[4];
tx_arpframe->ar_sha[5] = addr[5]; tx_arpframe->ar_sha[5] = addr[5];
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP)); addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
tx_arpframe->ar_spa[0] = addr[0]; tx_arpframe->ar_spa[0] = addr[0];
tx_arpframe->ar_spa[1] = addr[1]; tx_arpframe->ar_spa[1] = addr[1];
tx_arpframe->ar_spa[2] = addr[2]; tx_arpframe->ar_spa[2] = addr[2];
tx_arpframe->ar_spa[3] = addr[3]; tx_arpframe->ar_spa[3] = addr[3];
/* /*
* Save the length of my packet in the buffer structure * Save the length of my packet in the buffer structure
*/ */
pNbuf->length = ARP_HDR_LEN; pNbuf->length = ARP_HDR_LEN;
nif->send(nif, nif->send(nif,
&tx_arpframe->ar_tha[0], &tx_arpframe->ar_tha[0],
&tx_arpframe->ar_sha[0], &tx_arpframe->ar_sha[0],
ETH_FRM_ARP, ETH_FRM_ARP,
pNbuf); pNbuf);
} }
else else
nbuf_free(pNbuf); nbuf_free(pNbuf);
break; break;
case ARP_REPLY: case ARP_REPLY:
/* /*
* The ARP Reply case is already taken care of * The ARP Reply case is already taken care of
*/ */
default: default:
nbuf_free(pNbuf); nbuf_free(pNbuf);
break; break;
} }
return; return;
} }

View File

@@ -1,33 +1,190 @@
#include "bas_types.h"
#include <stdint.h>
#include <stdbool.h>
static bool bootp_initialized = false;
/* /*
* bootp client state * File: arp.c
* Purpose: Address Resolution Protocol routines.
*
* Notes:
*/ */
struct bootp_client #include "net.h"
{ #include "bootp.h"
uint8_t state; #include <stdbool.h>
uint8_t mode; #include <stddef.h>
uint8_t socket_handle;
uint16_t timer_handle;
uint16_t boot_secs;
};
static struct bootp_client client; #define TIMER_NETWORK 0
int bootpc_init(int mode) void bootp_request(NIF *nif, uint8_t *pa)
{ {
if (bootp_initialized)
{
return true;
}
/* /*
* get socket handle * This function broadcasts a BOOTP request for the protocol
* address "pa"
*/ */
client.socket_handle = udp_getsocket uint8_t *addr;
NBUF *pNbuf;
bootp_frame_hdr *bootpframe;
int i, result;
pNbuf = nbuf_alloc();
if (pNbuf == NULL)
{
#if defined(DEBUG_PRINT)
xprintf("%s: arp_request couldn't allocate Tx buffer\r\n", __FUNCTION__);
#endif
return;
}
bootpframe = (bootp_frame_hdr *) &pNbuf->data[BOOTP_HDR_OFFSET];
/* Build the BOOTP request packet */
bootpframe->type = BOOTP_TYPE_BOOTREQUEST;
bootpframe->htype = BOOTP_HTYPE_ETHERNET;
bootpframe->hlen = BOOTP_HLEN_ETHERNET;
bootpframe->hops = 0;
bootpframe->xid = 0x1234;
bootpframe->secs = 1;
bootpframe->flags = BOOTP_FLAGS_BROADCAST;
bootpframe->cl_addr = 0x0;
bootpframe->yi_addr = 0x0;
bootpframe->gi_addr = 0x0;
addr = &nif->hwa[0];
for (i = 0; i < 6; i++)
bootpframe->ch_addr[i] = addr[i];
pNbuf->length = BOOTP_HDR_LEN;
/* Send the BOOTP request */
result = nif->send(nif, nif->broadcast, nif->hwa, ETH_FRM_IP, pNbuf);
if (result == 0)
nbuf_free(pNbuf);
}
void bootp_handler(NIF *nif, NBUF *pNbuf)
{
/*
* ARP protocol handler
*/
uint8_t *addr;
bootp_frame_hdr *rx_bootpframe, *tx_bootpframe;
rx_bootpframe = (bootp_frame_hdr *) &pNbuf->data[pNbuf->offset];
#ifdef _NOT_USED_
/*
* Check for an appropriate ARP packet
*/
if ((pNbuf->length < ARP_HDR_LEN) ||
(rx_arpframe->ar_hrd != ETHERNET) ||
(rx_arpframe->ar_hln != 6) ||
(rx_arpframe->ar_pro != ETH_FRM_IP) ||
(rx_arpframe->ar_pln != 4))
{
nbuf_free(pNbuf);
return;
}
/*
* Check to see if it was addressed to me - if it was, keep this
* ARP entry in the table permanently; if not, mark it so that it
* can be displaced later if necessary
*/
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
(rx_arpframe->ar_tpa[1] == addr[1]) &&
(rx_arpframe->ar_tpa[2] == addr[2]) &&
(rx_arpframe->ar_tpa[3] == addr[3]) )
{
longevity = ARP_ENTRY_PERM;
}
else
longevity = ARP_ENTRY_TEMP;
/*
* Add ARP info into the table
*/
arp_merge(arptab,
rx_arpframe->ar_pro,
rx_arpframe->ar_hln,
&rx_arpframe->ar_sha[0],
rx_arpframe->ar_pln,
&rx_arpframe->ar_spa[0],
longevity
);
switch (rx_arpframe->opcode)
{
case ARP_REQUEST:
/*
* Check to see if request is directed to me
*/
if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
(rx_arpframe->ar_tpa[1] == addr[1]) &&
(rx_arpframe->ar_tpa[2] == addr[2]) &&
(rx_arpframe->ar_tpa[3] == addr[3]) )
{
/*
* Reuse the current network buffer to assemble an ARP reply
*/
tx_arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET];
/*
* Build new ARP frame from the received data
*/
tx_arpframe->ar_hrd = ETHERNET;
tx_arpframe->ar_pro = ETH_FRM_IP;
tx_arpframe->ar_hln = 6;
tx_arpframe->ar_pln = 4;
tx_arpframe->opcode = ARP_REPLY;
tx_arpframe->ar_tha[0] = rx_arpframe->ar_sha[0];
tx_arpframe->ar_tha[1] = rx_arpframe->ar_sha[1];
tx_arpframe->ar_tha[2] = rx_arpframe->ar_sha[2];
tx_arpframe->ar_tha[3] = rx_arpframe->ar_sha[3];
tx_arpframe->ar_tha[4] = rx_arpframe->ar_sha[4];
tx_arpframe->ar_tha[5] = rx_arpframe->ar_sha[5];
tx_arpframe->ar_tpa[0] = rx_arpframe->ar_spa[0];
tx_arpframe->ar_tpa[1] = rx_arpframe->ar_spa[1];
tx_arpframe->ar_tpa[2] = rx_arpframe->ar_spa[2];
tx_arpframe->ar_tpa[3] = rx_arpframe->ar_spa[3];
/*
* Now copy in the new information
*/
addr = &nif->hwa[0];
tx_arpframe->ar_sha[0] = addr[0];
tx_arpframe->ar_sha[1] = addr[1];
tx_arpframe->ar_sha[2] = addr[2];
tx_arpframe->ar_sha[3] = addr[3];
tx_arpframe->ar_sha[4] = addr[4];
tx_arpframe->ar_sha[5] = addr[5];
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
tx_arpframe->ar_spa[0] = addr[0];
tx_arpframe->ar_spa[1] = addr[1];
tx_arpframe->ar_spa[2] = addr[2];
tx_arpframe->ar_spa[3] = addr[3];
/*
* Save the length of my packet in the buffer structure
*/
pNbuf->length = ARP_HDR_LEN;
nif->send(nif,
&tx_arpframe->ar_tha[0],
&tx_arpframe->ar_sha[0],
ETH_FRM_ARP,
pNbuf);
}
else
nbuf_free(pNbuf);
break;
case ARP_REPLY:
/*
* The ARP Reply case is already taken care of
*/
default:
nbuf_free(pNbuf);
break;
}
#endif /* _NOT_USED_ */
return;
}

128
net/fec.c
View File

@@ -28,8 +28,6 @@
#endif #endif
/********************************************************************/
FEC_EVENT_LOG fec_log[2]; FEC_EVENT_LOG fec_log[2];
/********************************************************************/ /********************************************************************/
@@ -184,7 +182,7 @@ void fec_mii_init(uint8_t ch, uint32_t sys_clk)
* MII Speed Setting = System_Clock / (2.5MHz * 2) * MII Speed Setting = System_Clock / (2.5MHz * 2)
* (plus 1 to make sure we round up) * (plus 1 to make sure we round up)
*/ */
MCF_FEC_MSCR(ch) = MCF_FEC_MSCR_MII_SPEED((sys_clk/5)+1); MCF_FEC_MSCR(ch) = MCF_FEC_MSCR_MII_SPEED((sys_clk / 5) + 1);
} }
/********************************************************************/ /********************************************************************/
@@ -217,7 +215,7 @@ void fec_mib_dump(uint8_t ch)
*/ */
void fec_log_init(uint8_t ch) void fec_log_init(uint8_t ch)
{ {
memset(&fec_log[ch],0,sizeof(FEC_EVENT_LOG)); memset(&fec_log[ch], 0, sizeof(FEC_EVENT_LOG));
} }
/********************************************************************/ /********************************************************************/
@@ -229,30 +227,30 @@ void fec_log_init(uint8_t ch)
void fec_log_dump(uint8_t ch) void fec_log_dump(uint8_t ch)
{ {
xprintf("\n FEC%d Log\n---------------\n",ch); xprintf("\n FEC%d Log\n---------------\n",ch);
xprintf("Total: %4d\n",fec_log[ch].total); xprintf("Total: %4d\n", fec_log[ch].total);
xprintf("hberr: %4d\n",fec_log[ch].hberr); xprintf("hberr: %4d\n", fec_log[ch].hberr);
xprintf("babr: %4d\n",fec_log[ch].babr); xprintf("babr: %4d\n", fec_log[ch].babr);
xprintf("babt: %4d\n",fec_log[ch].babt); xprintf("babt: %4d\n", fec_log[ch].babt);
xprintf("gra: %4d\n",fec_log[ch].gra); xprintf("gra: %4d\n", fec_log[ch].gra);
xprintf("txf: %4d\n",fec_log[ch].txf); xprintf("txf: %4d\n", fec_log[ch].txf);
xprintf("mii: %4d\n",fec_log[ch].mii); xprintf("mii: %4d\n", fec_log[ch].mii);
xprintf("lc: %4d\n",fec_log[ch].lc); xprintf("lc: %4d\n", fec_log[ch].lc);
xprintf("rl: %4d\n",fec_log[ch].rl); xprintf("rl: %4d\n", fec_log[ch].rl);
xprintf("xfun: %4d\n",fec_log[ch].xfun); xprintf("xfun: %4d\n", fec_log[ch].xfun);
xprintf("xferr: %4d\n",fec_log[ch].xferr); xprintf("xferr: %4d\n", fec_log[ch].xferr);
xprintf("rferr: %4d\n",fec_log[ch].rferr); xprintf("rferr: %4d\n", fec_log[ch].rferr);
xprintf("dtxf: %4d\n",fec_log[ch].dtxf); xprintf("dtxf: %4d\n", fec_log[ch].dtxf);
xprintf("drxf: %4d\n",fec_log[ch].drxf); xprintf("drxf: %4d\n", fec_log[ch].drxf);
xprintf("\nRFSW:\n"); xprintf("\nRFSW:\n");
xprintf("inv: %4d\n",fec_log[ch].rfsw_inv); xprintf("inv: %4d\n", fec_log[ch].rfsw_inv);
xprintf("m: %4d\n",fec_log[ch].rfsw_m); xprintf("m: %4d\n", fec_log[ch].rfsw_m);
xprintf("bc: %4d\n",fec_log[ch].rfsw_bc); xprintf("bc: %4d\n", fec_log[ch].rfsw_bc);
xprintf("mc: %4d\n",fec_log[ch].rfsw_mc); xprintf("mc: %4d\n", fec_log[ch].rfsw_mc);
xprintf("lg: %4d\n",fec_log[ch].rfsw_lg); xprintf("lg: %4d\n", fec_log[ch].rfsw_lg);
xprintf("no: %4d\n",fec_log[ch].rfsw_no); xprintf("no: %4d\n", fec_log[ch].rfsw_no);
xprintf("cr: %4d\n",fec_log[ch].rfsw_cr); xprintf("cr: %4d\n", fec_log[ch].rfsw_cr);
xprintf("ov: %4d\n",fec_log[ch].rfsw_ov); xprintf("ov: %4d\n", fec_log[ch].rfsw_ov);
xprintf("tr: %4d\n",fec_log[ch].rfsw_tr); xprintf("tr: %4d\n", fec_log[ch].rfsw_tr);
xprintf("---------------\n\n"); xprintf("---------------\n\n");
} }
@@ -266,28 +264,28 @@ void fec_log_dump(uint8_t ch)
void fec_debug_dump(uint8_t ch) void fec_debug_dump(uint8_t ch)
{ {
xprintf("\n------------- FEC%d -------------\n",ch); xprintf("\n------------- FEC%d -------------\n",ch);
xprintf("EIR %08x \n",MCF_FEC_EIR(ch)); xprintf("EIR %08x \n", MCF_FEC_EIR(ch));
xprintf("EIMR %08x \n",MCF_FEC_EIMR(ch)); xprintf("EIMR %08x \n", MCF_FEC_EIMR(ch));
xprintf("ECR %08x \n",MCF_FEC_ECR(ch)); xprintf("ECR %08x \n", MCF_FEC_ECR(ch));
xprintf("RCR %08x \n",MCF_FEC_RCR(ch)); xprintf("RCR %08x \n", MCF_FEC_RCR(ch));
xprintf("R_HASH %08x \n",MCF_FEC_RHR_HASH(ch)); xprintf("R_HASH %08x \n", MCF_FEC_RHR_HASH(ch));
xprintf("TCR %08x \n",MCF_FEC_TCR(ch)); xprintf("TCR %08x \n", MCF_FEC_TCR(ch));
xprintf("FECTFWR %08x \n",MCF_FEC_FECTFWR(ch)); xprintf("FECTFWR %08x \n", MCF_FEC_FECTFWR(ch));
xprintf("FECRFSR %08x \n",MCF_FEC_FECRFSR(ch)); xprintf("FECRFSR %08x \n", MCF_FEC_FECRFSR(ch));
xprintf("FECRFCR %08x \n",MCF_FEC_FECRFCR(ch)); xprintf("FECRFCR %08x \n", MCF_FEC_FECRFCR(ch));
xprintf("FECRLRFP %08x \n",MCF_FEC_FECRLRFP(ch)); xprintf("FECRLRFP %08x \n", MCF_FEC_FECRLRFP(ch));
xprintf("FECRLWFP %08x \n",MCF_FEC_FECRLWFP(ch)); xprintf("FECRLWFP %08x \n", MCF_FEC_FECRLWFP(ch));
xprintf("FECRFAR %08x \n",MCF_FEC_FECRFAR(ch)); xprintf("FECRFAR %08x \n", MCF_FEC_FECRFAR(ch));
xprintf("FECRFRP %08x \n",MCF_FEC_FECRFRP(ch)); xprintf("FECRFRP %08x \n", MCF_FEC_FECRFRP(ch));
xprintf("FECRFWP %08x \n",MCF_FEC_FECRFWP(ch)); xprintf("FECRFWP %08x \n", MCF_FEC_FECRFWP(ch));
xprintf("FECTFSR %08x \n",MCF_FEC_FECTFSR(ch)); xprintf("FECTFSR %08x \n", MCF_FEC_FECTFSR(ch));
xprintf("FECTFCR %08x \n",MCF_FEC_FECTFCR(ch)); xprintf("FECTFCR %08x \n", MCF_FEC_FECTFCR(ch));
xprintf("FECTLRFP %08x \n",MCF_FEC_FECTLRFP(ch)); xprintf("FECTLRFP %08x \n", MCF_FEC_FECTLRFP(ch));
xprintf("FECTLWFP %08x \n",MCF_FEC_FECTLWFP(ch)); xprintf("FECTLWFP %08x \n", MCF_FEC_FECTLWFP(ch));
xprintf("FECTFAR %08x \n",MCF_FEC_FECTFAR(ch)); xprintf("FECTFAR %08x \n", MCF_FEC_FECTFAR(ch));
xprintf("FECTFRP %08x \n",MCF_FEC_FECTFRP(ch)); xprintf("FECTFRP %08x \n", MCF_FEC_FECTFRP(ch));
xprintf("FECTFWP %08x \n",MCF_FEC_FECTFWP(ch)); xprintf("FECTFWP %08x \n", MCF_FEC_FECTFWP(ch));
xprintf("FRST %08x \n",MCF_FEC_FECFRST(ch)); xprintf("FRST %08x \n", MCF_FEC_FECFRST(ch));
xprintf("--------------------------------\n\n"); xprintf("--------------------------------\n\n");
} }
@@ -305,11 +303,11 @@ void fec_duplex (uint8_t ch, uint8_t duplex)
{ {
case FEC_MII_HALF_DUPLEX: case FEC_MII_HALF_DUPLEX:
MCF_FEC_RCR(ch) |= MCF_FEC_RCR_DRT; MCF_FEC_RCR(ch) |= MCF_FEC_RCR_DRT;
MCF_FEC_TCR(ch) &= (uint32_t)~MCF_FEC_TCR_FDEN; MCF_FEC_TCR(ch) &= (uint32_t) ~MCF_FEC_TCR_FDEN;
break; break;
case FEC_MII_FULL_DUPLEX: case FEC_MII_FULL_DUPLEX:
default: default:
MCF_FEC_RCR(ch) &= (uint32_t)~MCF_FEC_RCR_DRT; MCF_FEC_RCR(ch) &= (uint32_t) ~MCF_FEC_RCR_DRT;
MCF_FEC_TCR(ch) |= MCF_FEC_TCR_FDEN; MCF_FEC_TCR(ch) |= MCF_FEC_TCR_FDEN;
break; break;
} }
@@ -332,12 +330,12 @@ uint8_t fec_hash_address(const uint8_t *addr)
int i, j; int i, j;
crc = 0xFFFFFFFF; crc = 0xFFFFFFFF;
for(i=0; i<6; ++i) for (i = 0; i < 6; ++i)
{ {
byte = addr[i]; byte = addr[i];
for(j=0; j<8; ++j) for (j = 0; j < 8; ++j)
{ {
if((byte & 0x01)^(crc & 0x01)) if ((byte & 0x01)^(crc & 0x01))
{ {
crc >>= 1; crc >>= 1;
crc = crc ^ 0xEDB88320; crc = crc ^ 0xEDB88320;
@@ -366,8 +364,8 @@ void fec_set_address (uint8_t ch, const uint8_t *pa)
/* /*
* Set the Physical Address * Set the Physical Address
*/ */
MCF_FEC_PALR(ch) = (uint32_t)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]); MCF_FEC_PALR(ch) = (uint32_t)((pa[0] << 24) | (pa[1] << 16) | (pa[2] << 8) | pa[3]);
MCF_FEC_PAHR(ch) = (uint32_t)((pa[4]<<24) | (pa[5]<<16)); MCF_FEC_PAHR(ch) = (uint32_t)((pa[4] << 24) | (pa[5] << 16));
/* /*
* Calculate and set the hash for given Physical Address * Calculate and set the hash for given Physical Address
@@ -555,9 +553,6 @@ void fec_rx_start(uint8_t ch, int8_t *rxbd)
channel = dma_set_channel(DMA_FEC_RX(ch), channel = dma_set_channel(DMA_FEC_RX(ch),
(ch == 0) ? fec0_rx_frame : fec1_rx_frame); (ch == 0) ? fec0_rx_frame : fec1_rx_frame);
/*
* Start the Rx DMA task
*/
/* /*
* Start the Rx DMA task * Start the Rx DMA task
*/ */
@@ -729,6 +724,7 @@ void fec_rx_frame(uint8_t ch, NIF *nif)
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
xprintf("nbuf_alloc() failed\n"); xprintf("nbuf_alloc() failed\n");
#endif #endif
/* /*
* Can't allocate a new network buffer, so we * Can't allocate a new network buffer, so we
* have to trash the received data and reuse the buffer * have to trash the received data and reuse the buffer
@@ -811,12 +807,14 @@ void fec_rx_frame(uint8_t ch, NIF *nif)
void fec0_rx_frame(void) void fec0_rx_frame(void)
{ {
extern NIF nif1; extern NIF nif1;
fec_rx_frame(0, &nif1); fec_rx_frame(0, &nif1);
} }
void fec1_rx_frame(void) void fec1_rx_frame(void)
{ {
extern NIF nif1; extern NIF nif1;
fec_rx_frame(1, &nif1); fec_rx_frame(1, &nif1);
} }
@@ -1078,6 +1076,7 @@ int fec1_send(NIF *nif, uint8_t *dst, uint8_t *src, uint16_t type, NBUF *nbuf)
{ {
return fec_send(1, nif, dst, src, type, nbuf); return fec_send(1, nif, dst, src, type, nbuf);
} }
/********************************************************************/ /********************************************************************/
/* /*
* Enable interrupts on the selected FEC * Enable interrupts on the selected FEC
@@ -1163,7 +1162,7 @@ static void fec_irq_handler(uint8_t ch)
#ifdef DEBUG #ifdef DEBUG
if (event != eir) if (event != eir)
xprintf("Pending but not enabled: 0x%08X\n",(event ^ eir)); xprintf("Pending but not enabled: 0x%08X\n", (event ^ eir));
#endif #endif
/* /*
@@ -1177,7 +1176,7 @@ static void fec_irq_handler(uint8_t ch)
fec_log[ch].rferr++; fec_log[ch].rferr++;
#ifdef DEBUG #ifdef DEBUG
xprintf("RFERR\n"); xprintf("RFERR\n");
xprintf("FECRFSR%d = 0x%08x\n",ch,MCF_FEC_FECRFSR(ch)); xprintf("FECRFSR%d = 0x%08x\n", ch, MCF_FEC_FECRFSR(ch));
fec_eth_stop(ch); fec_eth_stop(ch);
#endif #endif
} }
@@ -1319,8 +1318,8 @@ void fec_eth_setup(uint8_t ch, uint8_t trcvr, uint8_t speed, uint8_t duplex, con
/* /*
* Enable the multi-channel DMA tasks * Enable the multi-channel DMA tasks
*/ */
fec_rx_start(ch, (int8_t*) fecbd_get_start(ch,Rx)); fec_rx_start(ch, (int8_t*) fecbd_get_start(ch, Rx));
fec_tx_start(ch, (int8_t*) fecbd_get_start(ch,Tx)); fec_tx_start(ch, (int8_t*) fecbd_get_start(ch, Tx));
/* /*
* Enable the FEC channel * Enable the FEC channel
@@ -1337,7 +1336,7 @@ void fec_eth_setup(uint8_t ch, uint8_t trcvr, uint8_t speed, uint8_t duplex, con
*/ */
void fec_eth_reset(uint8_t ch) void fec_eth_reset(uint8_t ch)
{ {
// To do // To do
} }
/********************************************************************/ /********************************************************************/
@@ -1387,5 +1386,4 @@ void fec_eth_stop(uint8_t ch)
*/ */
set_ipl(level); set_ipl(level);
} }
/********************************************************************/

View File

@@ -1,226 +1,226 @@
/* /*
* File: fecbd.c * File: fecbd.c
* Purpose: Provide a simple buffer management driver * Purpose: Provide a simple buffer management driver
* *
* Notes: * Notes:
*/ */
#include "MCD_dma.h" #include "MCD_dma.h"
#include "fecbd.h" #include "fecbd.h"
#include "nbuf.h" #include "nbuf.h"
#include "eth.h" #include "eth.h"
#include "bas_printf.h" #include "bas_printf.h"
#include <stddef.h> #include <stddef.h>
/* /*
* This implements a simple static buffer descriptor * This implements a simple static buffer descriptor
* ring for each channel and each direction * ring for each channel and each direction
* *
* FEC Buffer Descriptors need to be aligned to a 4-byte boundary. * FEC Buffer Descriptors need to be aligned to a 4-byte boundary.
* In order to accomplish this, data is over-allocated and manually * In order to accomplish this, data is over-allocated and manually
* aligned at runtime * aligned at runtime
* *
* Enough space is allocated for each of the two FEC channels to have * Enough space is allocated for each of the two FEC channels to have
* NRXBD Rx BDs and NTXBD Tx BDs * NRXBD Rx BDs and NTXBD Tx BDs
* *
*/ */
FECBD unaligned_bds[(2 * NRXBD) + (2 * NTXBD) + 1]; FECBD unaligned_bds[(2 * NRXBD) + (2 * NTXBD) + 1];
/* /*
* These pointers are used to reference into the chunck of data set * These pointers are used to reference into the chunck of data set
* aside for buffer descriptors * aside for buffer descriptors
*/ */
FECBD *RxBD; FECBD *RxBD;
FECBD *TxBD; FECBD *TxBD;
/* /*
* Macros to easier access to the BD ring * Macros to easier access to the BD ring
*/ */
#define RxBD(ch,i) RxBD[(ch * NRXBD) + i] #define RxBD(ch,i) RxBD[(ch * NRXBD) + i]
#define TxBD(ch,i) TxBD[(ch * NTXBD) + i] #define TxBD(ch,i) TxBD[(ch * NTXBD) + i]
/* /*
* Buffer descriptor indexes * Buffer descriptor indexes
*/ */
static int iTxbd_new; static int iTxbd_new;
static int iTxbd_old; static int iTxbd_old;
static int iRxbd; static int iRxbd;
/* /*
* Initialize the FEC Buffer Descriptor ring * Initialize the FEC Buffer Descriptor ring
* Buffer Descriptor format is defined by the MCDAPI * Buffer Descriptor format is defined by the MCDAPI
* *
* Parameters: * Parameters:
* ch FEC channel * ch FEC channel
*/ */
void fecbd_init(uint8_t ch) void fecbd_init(uint8_t ch)
{ {
NBUF *nbuf; NBUF *nbuf;
int i; int i;
/* /*
* Align Buffer Descriptors to 4-byte boundary * Align Buffer Descriptors to 4-byte boundary
*/ */
RxBD = (FECBD *)(((int)unaligned_bds + 3) & 0xFFFFFFFC); RxBD = (FECBD *)(((int) unaligned_bds + 3) & 0xFFFFFFFC);
TxBD = (FECBD *)((int)RxBD + (sizeof(FECBD) * 2 * NRXBD)); TxBD = (FECBD *)((int) RxBD + (sizeof(FECBD) * 2 * NRXBD));
/* /*
* Initialize the Rx Buffer Descriptor ring * Initialize the Rx Buffer Descriptor ring
*/ */
for (i = 0; i < NRXBD; ++i) for (i = 0; i < NRXBD; ++i)
{ {
/* Grab a network buffer from the free list */ /* Grab a network buffer from the free list */
nbuf = nbuf_alloc(); nbuf = nbuf_alloc();
if (nbuf == NULL) if (nbuf == NULL)
{ {
xprintf("%s: could not allocate network buffer\r\n", __FUNCTION__); xprintf("%s: could not allocate network buffer\r\n", __FUNCTION__);
return; return;
} }
/* Initialize the BD */ /* Initialize the BD */
RxBD(ch,i).status = RX_BD_E | RX_BD_INTERRUPT; RxBD(ch,i).status = RX_BD_E | RX_BD_INTERRUPT;
RxBD(ch,i).length = RX_BUF_SZ; RxBD(ch,i).length = RX_BUF_SZ;
RxBD(ch,i).data = nbuf->data; RxBD(ch,i).data = nbuf->data;
/* Add the network buffer to the Rx queue */ /* Add the network buffer to the Rx queue */
nbuf_add(NBUF_RX_RING, nbuf); nbuf_add(NBUF_RX_RING, nbuf);
} }
/* /*
* Set the WRAP bit on the last one * Set the WRAP bit on the last one
*/ */
RxBD(ch,i-1).status |= RX_BD_W; RxBD(ch,i-1).status |= RX_BD_W;
/* /*
* Initialize the Tx Buffer Descriptor ring * Initialize the Tx Buffer Descriptor ring
*/ */
for (i = 0; i < NTXBD; ++i) for (i = 0; i < NTXBD; ++i)
{ {
TxBD(ch,i).status = TX_BD_INTERRUPT; TxBD(ch, i).status = TX_BD_INTERRUPT;
TxBD(ch,i).length = 0; TxBD(ch, i).length = 0;
TxBD(ch,i).data = NULL; TxBD(ch, i).data = NULL;
} }
/* /*
* Set the WRAP bit on the last one * Set the WRAP bit on the last one
*/ */
TxBD(ch,i-1).status |= TX_BD_W; TxBD(ch,i-1).status |= TX_BD_W;
/* /*
* Initialize the buffer descriptor indexes * Initialize the buffer descriptor indexes
*/ */
iTxbd_new = iTxbd_old = iRxbd = 0; iTxbd_new = iTxbd_old = iRxbd = 0;
} }
void fecbd_dump(uint8_t ch) void fecbd_dump(uint8_t ch)
{ {
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
int i; int i;
printf("\n------------ FEC%d BDs -----------\n",ch); printf("\n------------ FEC%d BDs -----------\n",ch);
printf("RxBD Ring\n"); printf("RxBD Ring\n");
for (i=0; i<NRXBD; i++) for (i = 0; i < NRXBD; i++)
{ {
printf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n", printf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
i, &RxBD(ch,i), i, &RxBD(ch, i),
RxBD(ch,i).status, RxBD(ch, i).status,
RxBD(ch,i).length, RxBD(ch, i).length,
RxBD(ch,i).data); RxBD(ch, i).data);
} }
printf("TxBD Ring\n"); printf("TxBD Ring\n");
for (i=0; i<NTXBD; i++) for (i = 0; i < NTXBD; i++)
{ {
printf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n", printf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
i, &TxBD(ch,i), i, &TxBD(ch, i),
TxBD(ch,i).status, TxBD(ch, i).status,
TxBD(ch,i).length, TxBD(ch, i).length,
TxBD(ch,i).data); TxBD(ch, i).data);
} }
printf("--------------------------------\n\n"); printf("--------------------------------\n\n");
#endif #endif
} }
/* /*
* Return the address of the first buffer descriptor in the ring. * Return the address of the first buffer descriptor in the ring.
* *
* Parameters: * Parameters:
* ch FEC channel * ch FEC channel
* direction Rx or Tx Macro * direction Rx or Tx Macro
* *
* Return Value: * Return Value:
* The start address of the selected Buffer Descriptor ring * The start address of the selected Buffer Descriptor ring
*/ */
uint32_t fecbd_get_start(uint8_t ch, uint8_t direction) uint32_t fecbd_get_start(uint8_t ch, uint8_t direction)
{ {
switch (direction) switch (direction)
{ {
case Rx: case Rx:
return (uint32_t)((int)RxBD + (ch * sizeof(FECBD) * NRXBD)); return (uint32_t)((int)RxBD + (ch * sizeof(FECBD) * NRXBD));
case Tx: case Tx:
default: default:
return (uint32_t)((int)TxBD + (ch * sizeof(FECBD) * NTXBD)); return (uint32_t)((int)TxBD + (ch * sizeof(FECBD) * NTXBD));
} }
} }
FECBD *fecbd_rx_alloc(uint8_t ch) FECBD *fecbd_rx_alloc(uint8_t ch)
{ {
int i = iRxbd; int i = iRxbd;
/* Check to see if the ring of BDs is full */ /* Check to see if the ring of BDs is full */
if (RxBD(ch,i).status & RX_BD_E) if (RxBD(ch, i).status & RX_BD_E)
return NULL; return NULL;
/* Increment the circular index */ /* Increment the circular index */
iRxbd = (uint8_t)((iRxbd + 1) % NRXBD); iRxbd = (uint8_t)((iRxbd + 1) % NRXBD);
return &RxBD(ch,i); return &RxBD(ch, i);
} }
/* /*
* This function keeps track of the next available Tx BD in the ring * This function keeps track of the next available Tx BD in the ring
* *
* Parameters: * Parameters:
* ch FEC channel * ch FEC channel
* *
* Return Value: * Return Value:
* Pointer to next available buffer descriptor. * Pointer to next available buffer descriptor.
* NULL if the BD ring is full * NULL if the BD ring is full
*/ */
FECBD *fecbd_tx_alloc(uint8_t ch) FECBD *fecbd_tx_alloc(uint8_t ch)
{ {
int i = iTxbd_new; int i = iTxbd_new;
/* Check to see if the ring of BDs is full */ /* Check to see if the ring of BDs is full */
if (TxBD(ch,i).status & TX_BD_R) if (TxBD(ch, i).status & TX_BD_R)
return NULL; return NULL;
/* Increment the circular index */ /* Increment the circular index */
iTxbd_new = (uint8_t)((iTxbd_new + 1) % NTXBD); iTxbd_new = (uint8_t)((iTxbd_new + 1) % NTXBD);
return &TxBD(ch,i); return &TxBD(ch, i);
} }
/* /*
* This function keeps track of the Tx BDs that have already been * This function keeps track of the Tx BDs that have already been
* processed by the FEC * processed by the FEC
* *
* Parameters: * Parameters:
* ch FEC channel * ch FEC channel
* *
* Return Value: * Return Value:
* Pointer to the oldest buffer descriptor that has already been sent * Pointer to the oldest buffer descriptor that has already been sent
* by the FEC, NULL if the BD ring is empty * by the FEC, NULL if the BD ring is empty
*/ */
FECBD *fecbd_tx_free(uint8_t ch) FECBD *fecbd_tx_free(uint8_t ch)
{ {
int i = iTxbd_old; int i = iTxbd_old;
/* Check to see if the ring of BDs is empty */ /* Check to see if the ring of BDs is empty */
if ((TxBD(ch,i).data == NULL) || (TxBD(ch,i).status & TX_BD_R)) if ((TxBD(ch, i).data == NULL) || (TxBD(ch, i).status & TX_BD_R))
return NULL; return NULL;
/* Increment the circular index */ /* Increment the circular index */
iTxbd_old = (uint8_t)((iTxbd_old + 1) % NTXBD); iTxbd_old = (uint8_t)((iTxbd_old + 1) % NTXBD);
return &TxBD(ch,i); return &TxBD(ch, i);
} }

586
net/ip.c
View File

@@ -1,293 +1,293 @@
/* /*
* File: ip.c * File: ip.c
* Purpose: Internet Protcol device driver * Purpose: Internet Protcol device driver
* *
* Notes: * Notes:
* *
* Modifications: * Modifications:
*/ */
#include "net.h" #include "net.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
void ip_init(IP_INFO *info, IP_ADDR_P myip, IP_ADDR_P gateway, IP_ADDR_P netmask) void ip_init(IP_INFO *info, IP_ADDR_P myip, IP_ADDR_P gateway, IP_ADDR_P netmask)
{ {
int index; int index;
for (index = 0; index < sizeof(IP_ADDR); index++) for (index = 0; index < sizeof(IP_ADDR); index++)
{ {
info->myip[index] = myip[index]; info->myip[index] = myip[index];
info->gateway[index] = gateway[index]; info->gateway[index] = gateway[index];
info->netmask[index] = netmask[index]; info->netmask[index] = netmask[index];
info->broadcast[index] = 0xFF; info->broadcast[index] = 0xFF;
} }
info->rx = 0; info->rx = 0;
info->rx_unsup = 0; info->rx_unsup = 0;
info->tx = 0; info->tx = 0;
info->err = 0; info->err = 0;
} }
uint8_t *ip_get_myip(IP_INFO *info) uint8_t *ip_get_myip(IP_INFO *info)
{ {
if (info != 0) if (info != 0)
{ {
return (uint8_t *) &info->myip[0]; return (uint8_t *) &info->myip[0];
} }
return 0; return 0;
} }
int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2) int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2)
{ {
int i; int i;
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
if (addr1[i] != addr2[i]) if (addr1[i] != addr2[i])
return 0; return 0;
} }
return 1; return 1;
} }
uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip) uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip)
{ {
/* /*
* This function determines whether or not an outgoing IP * This function determines whether or not an outgoing IP
* packet needs to be transmitted on the local net or sent * packet needs to be transmitted on the local net or sent
* to the router for transmission. * to the router for transmission.
*/ */
IP_INFO *info; IP_INFO *info;
IP_ADDR mask,result; IP_ADDR mask, result;
int i; int i;
info = nif_get_protocol_info(nif,ETH_FRM_IP); info = nif_get_protocol_info(nif, ETH_FRM_IP);
/* create mask for local IP */ /* create mask for local IP */
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
mask[i] = info->myip[i] & info->netmask[i]; mask[i] = info->myip[i] & info->netmask[i];
} }
/* apply mask to the destination IP */ /* apply mask to the destination IP */
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
result[i] = mask[i] & destip[i]; result[i] = mask[i] & destip[i];
} }
/* See if destination IP is local or not */ /* See if destination IP is local or not */
if (ip_addr_compare(mask,result)) if (ip_addr_compare(mask, result))
{ {
/* The destination IP is on the local net */ /* The destination IP is on the local net */
return arp_resolve(nif,ETH_FRM_IP,destip); return arp_resolve(nif, ETH_FRM_IP, destip);
} }
else else
{ {
/* The destination IP is not on the local net */ /* The destination IP is not on the local net */
return arp_resolve(nif,ETH_FRM_IP,info->gateway); return arp_resolve(nif, ETH_FRM_IP, info->gateway);
} }
} }
int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf) int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf)
{ {
/* /*
* This function assembles an IP datagram and passes it * This function assembles an IP datagram and passes it
* onto the hardware to be sent over the network. * onto the hardware to be sent over the network.
*/ */
uint8_t *route; uint8_t *route;
ip_frame_hdr *ipframe; ip_frame_hdr *ipframe;
/* /*
* Construct the IP header * Construct the IP header
*/ */
ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET]; ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET];
/* IP version 4, Internet Header Length of 5 32-bit words */ /* IP version 4, Internet Header Length of 5 32-bit words */
ipframe->version_ihl = 0x45; ipframe->version_ihl = 0x45;
/* Type of Service == 0, normal and routine */ /* Type of Service == 0, normal and routine */
ipframe->service_type = 0x00; ipframe->service_type = 0x00;
/* Total length of data */ /* Total length of data */
ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE); ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE);
/* User defined identification */ /* User defined identification */
ipframe->identification = 0x0000; ipframe->identification = 0x0000;
/* Fragment Flags and Offset -- Don't fragment, last frag */ /* Fragment Flags and Offset -- Don't fragment, last frag */
ipframe->flags_frag_offset = 0x0000; ipframe->flags_frag_offset = 0x0000;
/* Time To Live */ /* Time To Live */
ipframe->ttl = 0xFF; ipframe->ttl = 0xFF;
/* Protocol */ /* Protocol */
ipframe->protocol = protocol; ipframe->protocol = protocol;
/* Checksum, computed later, zeroed for computation */ /* Checksum, computed later, zeroed for computation */
ipframe->checksum = 0x0000; ipframe->checksum = 0x0000;
/* source IP address */ /* source IP address */
ipframe->source_addr[0] = src[0]; ipframe->source_addr[0] = src[0];
ipframe->source_addr[1] = src[1]; ipframe->source_addr[1] = src[1];
ipframe->source_addr[2] = src[2]; ipframe->source_addr[2] = src[2];
ipframe->source_addr[3] = src[3]; ipframe->source_addr[3] = src[3];
/* dest IP address */ /* dest IP address */
ipframe->dest_addr[0] = dest[0]; ipframe->dest_addr[0] = dest[0];
ipframe->dest_addr[1] = dest[1]; ipframe->dest_addr[1] = dest[1];
ipframe->dest_addr[2] = dest[2]; ipframe->dest_addr[2] = dest[2];
ipframe->dest_addr[3] = dest[3]; ipframe->dest_addr[3] = dest[3];
/* Compute checksum */ /* Compute checksum */
ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE); ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE);
/* Increment the packet length by the size of the IP header */ /* Increment the packet length by the size of the IP header */
pNbuf->length += IP_HDR_SIZE; pNbuf->length += IP_HDR_SIZE;
/* /*
* Determine the hardware address of the recipient * Determine the hardware address of the recipient
*/ */
route = ip_resolve_route(nif, dest); route = ip_resolve_route(nif, dest);
if (route == NULL) if (route == NULL)
{ {
xprintf("Unable to locate %d.%d.%d.%d\n", xprintf("Unable to locate %d.%d.%d.%d\n",
dest[0],dest[1],dest[2],dest[3]); dest[0], dest[1], dest[2], dest[3]);
return 0; return 0;
} }
return nif->send(nif, return nif->send(nif,
route, route,
&nif->hwa[0], &nif->hwa[0],
ETH_FRM_IP, ETH_FRM_IP,
pNbuf pNbuf
); );
} }
#if defined(DEBUG_PRINT) #if defined(DEBUG_PRINT)
void void
dump_ip_frame (ip_frame_hdr *ipframe) dump_ip_frame (ip_frame_hdr *ipframe)
{ {
printf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4)); printf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4));
printf("IHL: %02X\n", ipframe->version_ihl & 0x000f); printf("IHL: %02X\n", ipframe->version_ihl & 0x000f);
printf("Service: %02X\n", ipframe->service_type); printf("Service: %02X\n", ipframe->service_type);
printf("Length: %04X\n", ipframe->total_length); printf("Length: %04X\n", ipframe->total_length);
printf("Ident: %04X\n", ipframe->identification); printf("Ident: %04X\n", ipframe->identification);
printf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14)); printf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14));
printf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF); printf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF);
printf("TTL: %02X\n", ipframe->ttl); printf("TTL: %02X\n", ipframe->ttl);
printf("Protocol: %02X\n", ipframe->protocol); printf("Protocol: %02X\n", ipframe->protocol);
printf("Chksum: %04X\n", ipframe->checksum); printf("Chksum: %04X\n", ipframe->checksum);
printf("Source : %d.%d.%d.%d\n", printf("Source : %d.%d.%d.%d\n",
ipframe->source_addr[0], ipframe->source_addr[0],
ipframe->source_addr[1], ipframe->source_addr[1],
ipframe->source_addr[2], ipframe->source_addr[2],
ipframe->source_addr[3]); ipframe->source_addr[3]);
printf("Dest : %d.%d.%d.%d\n", printf("Dest : %d.%d.%d.%d\n",
ipframe->dest_addr[0], ipframe->dest_addr[0],
ipframe->dest_addr[1], ipframe->dest_addr[1],
ipframe->dest_addr[2], ipframe->dest_addr[2],
ipframe->dest_addr[3]); ipframe->dest_addr[3]);
printf("Options: %08X\n", ipframe->options); printf("Options: %08X\n", ipframe->options);
} }
#endif #endif
uint16_t ip_chksum(uint16_t *data, int num) uint16_t ip_chksum(uint16_t *data, int num)
{ {
int chksum, ichksum; int chksum, ichksum;
uint16_t temp; uint16_t temp;
chksum = 0; chksum = 0;
num = num >> 1; /* from bytes to words */ num = num >> 1; /* from bytes to words */
for (; num; num--, data++) for (; num; num--, data++)
{ {
temp = *data; temp = *data;
ichksum = chksum + temp; ichksum = chksum + temp;
ichksum = ichksum & 0x0000FFFF; ichksum = ichksum & 0x0000FFFF;
if ((ichksum < temp) || (ichksum < chksum)) if ((ichksum < temp) || (ichksum < chksum))
{ {
ichksum += 1; ichksum += 1;
ichksum = ichksum & 0x0000FFFF; ichksum = ichksum & 0x0000FFFF;
} }
chksum = ichksum; chksum = ichksum;
} }
return (uint16_t) ~chksum; return (uint16_t) ~chksum;
} }
static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe) static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe)
{ {
int index, chksum; int index, chksum;
IP_INFO *info; IP_INFO *info;
/* /*
* Check the IP Version * Check the IP Version
*/ */
if (IP_VERSION(ipframe) != 4) if (IP_VERSION(ipframe) != 4)
return 0; return 0;
/* /*
* Check Internet Header Length * Check Internet Header Length
*/ */
if (IP_IHL(ipframe) < 5) if (IP_IHL(ipframe) < 5)
return 0; return 0;
/* /*
* Check the destination IP address * Check the destination IP address
*/ */
info = nif_get_protocol_info(nif,ETH_FRM_IP); info = nif_get_protocol_info(nif,ETH_FRM_IP);
for (index = 0; index < sizeof(IP_ADDR); index++) for (index = 0; index < sizeof(IP_ADDR); index++)
if (info->myip[index] != ipframe->dest_addr[index]) if (info->myip[index] != ipframe->dest_addr[index])
return 0; return 0;
/* /*
* Check the checksum * Check the checksum
*/ */
chksum = (int)((uint16_t) IP_CHKSUM(ipframe)); chksum = (int)((uint16_t) IP_CHKSUM(ipframe));
IP_CHKSUM(ipframe) = 0; IP_CHKSUM(ipframe) = 0;
if (ip_chksum((uint16_t *) ipframe,IP_IHL(ipframe)*4) != chksum) if (ip_chksum((uint16_t *) ipframe, IP_IHL(ipframe) * 4) != chksum)
return 0; return 0;
IP_CHKSUM(ipframe) = (uint16_t) chksum; IP_CHKSUM(ipframe) = (uint16_t) chksum;
return 1; return 1;
} }
void ip_handler(NIF *nif, NBUF *pNbuf) void ip_handler(NIF *nif, NBUF *pNbuf)
{ {
/* /*
* IP packet handler * IP packet handler
*/ */
ip_frame_hdr *ipframe; ip_frame_hdr *ipframe;
ipframe = (ip_frame_hdr *)&pNbuf->data[pNbuf->offset]; ipframe = (ip_frame_hdr *)&pNbuf->data[pNbuf->offset];
/* /*
* Verify valid IP header and destination IP * Verify valid IP header and destination IP
*/ */
if (!validate_ip_hdr(nif,ipframe)) if (!validate_ip_hdr(nif, ipframe))
{ {
nbuf_free(pNbuf); nbuf_free(pNbuf);
return; return;
} }
pNbuf->offset += (IP_IHL(ipframe) * 4); pNbuf->offset += (IP_IHL(ipframe) * 4);
pNbuf->length = (uint16_t)(IP_LENGTH(ipframe) - (IP_IHL(ipframe) * 4)); pNbuf->length = (uint16_t)(IP_LENGTH(ipframe) - (IP_IHL(ipframe) * 4));
/* /*
* Call the appriopriate handler * Call the appriopriate handler
*/ */
switch (IP_PROTOCOL(ipframe)) switch (IP_PROTOCOL(ipframe))
{ {
case IP_PROTO_ICMP: case IP_PROTO_ICMP:
// FIXME: icmp_handler(nif,pNbuf); // FIXME: icmp_handler(nif,pNbuf);
break; break;
case IP_PROTO_UDP: case IP_PROTO_UDP:
udp_handler(nif,pNbuf); udp_handler(nif,pNbuf);
break; break;
default: default:
nbuf_free(pNbuf); nbuf_free(pNbuf);
break; break;
} }
return; return;
} }