reformatted sources, added start of bootp protocol implementation
This commit is contained in:
1
Makefile
1
Makefile
@@ -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
|
||||||
|
|||||||
198
include/arp.h
198
include/arp.h
@@ -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
58
include/bootp.h
Normal 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
924
net/arp.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
205
net/bootp.c
205
net/bootp.c
@@ -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
128
net/fec.c
@@ -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);
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
|
|
||||||
|
|||||||
452
net/fecbd.c
452
net/fecbd.c
@@ -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
586
net/ip.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user