20,11 → 20,11 |
|
/** |
------------ |
CVS : $Id: arp.c,v 1.1 2004-04-23 14:30:32 mauro Exp $ |
CVS : $Id: arp.c,v 1.2 2004-04-23 18:13:51 mauro Exp $ |
|
File: $File$ |
Revision: $Revision: 1.1 $ |
Last update: $Date: 2004-04-23 14:30:32 $ |
Revision: $Revision: 1.2 $ |
Last update: $Date: 2004-04-23 18:13:51 $ |
------------ |
**/ |
|
71,6 → 71,9 |
#include "arp.h" |
#include <signal.h> |
|
//#define __ARP_DBG__ |
#define ARP_INFO "[ARP] " |
|
#define FALSE 0 |
#define TRUE 1 |
#define PENDING 2 |
87,20 → 90,20 |
locally |
*/ |
typedef struct { |
int len; |
void *next; |
int len; |
void *next; |
} PKT_NXT; |
|
typedef struct arp_pkt{ |
WORD htype; |
WORD ptype; |
BYTE hlen; |
BYTE plen; |
WORD operation; |
struct eth_addr sha; |
IP_ADDR sip; |
struct eth_addr tha; |
IP_ADDR tip; |
WORD htype; |
WORD ptype; |
BYTE hlen; |
BYTE plen; |
WORD operation; |
struct eth_addr sha; |
IP_ADDR sip; |
struct eth_addr tha; |
IP_ADDR tip; |
} ARP_PKT; |
|
struct netbuff arp_txbuff; |
126,20 → 129,20 |
*/ |
void arp_exc(int err) |
{ |
int i, j, minused; |
int i, j, minused; |
|
minused = ARP_MAX_USED; j = -1; |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if ((arpTable[i].valid != PENDING) && (arpTable[i].used <= minused)) { |
j = i; |
minused = arpTable[i].used; |
minused = ARP_MAX_USED; j = -1; |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if ((arpTable[i].valid != PENDING) && (arpTable[i].used <= minused)) { |
j = i; |
minused = arpTable[i].used; |
} |
} |
} |
if (j == -1) { |
cprintf("ARP table overflow!!!\n"); |
sys_abort(AARPFULL); |
} |
arpTable[j].valid = FALSE; |
if (j == -1) { |
cprintf("ARP table overflow.\n"); |
sys_abort(AARPFULL); |
} |
arpTable[j].valid = FALSE; |
} |
|
/* |
148,100 → 151,91 |
*/ |
void arp_sendRequest(int i) |
{ |
ARP_PKT *pkt; |
BYTE *arpBuff; |
ARP_PKT *pkt; |
BYTE *arpBuff; |
|
if ((arpBuff= netbuff_get(&arp_txbuff, NON_BLOCK)) != NULL) { |
eth_setHeader(arpBuff,broadcast,ETH_ARP_TYPE); |
pkt = (ARP_PKT *)eth_getFDB(arpBuff); |
pkt->htype = htons(ARP_ETH_TYPE); |
pkt->ptype = htons(ARP_IP_TYPE); |
pkt->hlen = sizeof(struct eth_addr); |
pkt->plen = sizeof(IP_ADDR); |
pkt->operation = htons(ARP_REQUEST); |
setEthAddr(pkt->sha,myEthAddr); |
setEthAddr(pkt->tha,nulladdr); |
setIpAddr(pkt->sip,myIpAddr); |
setIpAddr(pkt->tip,arpTable[i].ip); |
eth_sendPkt(arpBuff,sizeof(ARP_PKT)); |
netbuff_release(&arp_txbuff, (void *)arpBuff); |
} |
if ((arpBuff= netbuff_get(&arp_txbuff, NON_BLOCK)) != NULL) { |
eth_setHeader(arpBuff,broadcast,ETH_ARP_TYPE); |
pkt = (ARP_PKT *)eth_getFDB(arpBuff); |
pkt->htype = htons(ARP_ETH_TYPE); |
pkt->ptype = htons(ARP_IP_TYPE); |
pkt->hlen = sizeof(struct eth_addr); |
pkt->plen = sizeof(IP_ADDR); |
pkt->operation = htons(ARP_REQUEST); |
setEthAddr(pkt->sha,myEthAddr); |
setEthAddr(pkt->tha,nulladdr); |
setIpAddr(pkt->sip,myIpAddr); |
setIpAddr(pkt->tip,arpTable[i].ip); |
eth_sendPkt(arpBuff,sizeof(ARP_PKT)); |
netbuff_release(&arp_txbuff, (void *)arpBuff); |
} |
} |
|
/* Retry task (periodic) */ |
TASK arp_retry(void) |
{ |
int i; |
PKT_NXT *p, *p1; |
#ifdef __ARP_DBG__ |
char msg[100]; |
#endif |
int i; |
PKT_NXT *p, *p1; |
|
while (1) { |
/* mutual exclusion on the ARP table */ |
sem_xwait(&arpMutex, 1, BLOCK); |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if (arpTable[i].valid == PENDING) { |
arpTable[i].time--; |
if (arpTable[i].time <= 0) { |
arpTable[i].ntrans++; |
if (arpTable[i].ntrans > ARP_MAX_RETRANS) { |
/* N. Max Retry? If yes, discard all the packets */ |
p = (PKT_NXT *)arpTable[i].pkt; |
while (p != NULL) { |
p1 = p->next; |
netbuff_release(&udp_txbuff, (void *)p); |
while (1) { |
/* mutual exclusion on the ARP table */ |
sem_xwait(&arpMutex, 1, BLOCK); |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if (arpTable[i].valid == PENDING) { |
arpTable[i].time--; |
if (arpTable[i].time <= 0) { |
arpTable[i].ntrans++; |
if (arpTable[i].ntrans > ARP_MAX_RETRANS) { |
/* N. Max Retry? If yes, discard all the packets */ |
p = (PKT_NXT *)arpTable[i].pkt; |
while (p != NULL) { |
p1 = p->next; |
netbuff_release(&udp_txbuff, (void *)p); |
#ifdef __ARP_DBG__ |
sprintf(msg,"Pacchetto : %lp scartato\n",p); |
win_puts(&w1,msg); |
printk(KERN_DEBUG ARP_INFO "Pacchetto : %lp scartato.\n",p); |
#endif |
p = p1; |
p = p1; |
} |
arpTable[i].valid = FALSE; |
} else { |
arp_sendRequest(i); |
arpTable[i].time = ARP_TIMEOUT; |
} |
} |
} |
arpTable[i].valid = FALSE; |
} |
else { |
arp_sendRequest(i); |
arpTable[i].time = ARP_TIMEOUT; |
} |
} |
} |
sem_post(&arpMutex); |
task_endcycle(); |
} |
sem_post(&arpMutex); |
task_endcycle(); |
} |
} |
|
/* Search for a free entry in the ARP table (if there isn't any, return -1 */ |
int arp_req(IP_ADDR dest) |
{ |
int j, done; |
int j, done; |
|
done = 0; j = 0; |
while ((j < ARP_MAX_ENTRIES) && !done) { |
if (arpTable[j].valid == FALSE) { |
done = 1; |
arpTable[j].valid = PENDING; |
} else j++; |
} |
done = 0; j = 0; |
while ((j < ARP_MAX_ENTRIES) && !done) { |
if (arpTable[j].valid == FALSE) { |
done = 1; |
arpTable[j].valid = PENDING; |
} else |
j++; |
} |
|
if (!done) return -1; |
/* Fill the entry */ |
setIpAddr(arpTable[j].ip, dest); |
if (!done) |
return -1; |
|
/* Fill the entry */ |
setIpAddr(arpTable[j].ip, dest); |
#ifdef __ARP_DBG__ |
sprintf(msg,"Indirizzo : %d.%d.%d.%d\n",dest.ad[0], |
dest.ad[1], |
dest.ad[2], |
dest.ad[3]); |
win_puts(&w1,msg); |
sprintf(msg,"Indirizzo : %d.%d.%d.%d\n",arpTable[j].ip.ad[0], |
arpTable[j].ip.ad[1], |
arpTable[j].ip.ad[2], |
arpTable[j].ip.ad[3]); |
win_puts(&w1,msg); |
printk(KERN_DEBUG ARP_INFO "Indirizzo : %d.%d.%d.%d\n",dest.ad[0], dest.ad[1], dest.ad[2], dest.ad[3]); |
printk(KERN_DEBUG ARP_INFO "Indirizzo : %d.%d.%d.%d\n",arpTable[j].ip.ad[0], arpTable[j].ip.ad[1], arpTable[j].ip.ad[2], arpTable[j].ip.ad[3]); |
#endif |
arpTable[j].time = ARP_TIMEOUT; |
arpTable[j].ntrans = 0; |
return j; |
arpTable[j].time = ARP_TIMEOUT; |
arpTable[j].ntrans = 0; |
|
return j; |
} |
|
/* |
250,227 → 244,213 |
*/ |
void arp_send(void *pkt, IP_ADDR dest, int len) |
{ |
int i,j; |
PKT_NXT *p,*p1 = NULL; |
int caso; |
#ifdef __ARP_DBG__ |
char msg[50]; |
#endif |
int i,j; |
PKT_NXT *p,*p1 = NULL; |
int caso; |
|
sem_xwait(&arpMutex, 1, BLOCK); |
caso = 0; |
j = -1; |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if (ip_compAddr(dest,arpTable[i].ip)) { |
/* found: CASE 1 */ |
if (arpTable[i].valid == TRUE) { |
caso = 1; |
j = i; |
} |
else if (arpTable[i].valid == PENDING) { |
/* Entry found, but the ethernet address is still unknown: CASE 2 */ |
caso = 2; |
j = i; |
} |
sem_xwait(&arpMutex, 1, BLOCK); |
caso = 0; |
j = -1; |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if (ip_compAddr(dest,arpTable[i].ip)) { |
/* found: CASE 1 */ |
if (arpTable[i].valid == TRUE) { |
caso = 1; |
j = i; |
} |
else if (arpTable[i].valid == PENDING) { |
/* Entry found, but the ethernet address is still unknown: CASE 2 */ |
caso = 2; |
j = i; |
} |
} |
} |
} |
|
if (caso == 1) { |
/* Send the IP packet */ |
eth_setHeader(pkt,arpTable[j].eth,ETH_IP_TYPE); |
eth_sendPkt(pkt,len); |
netbuff_release(&udp_txbuff, (void *)pkt); |
arpTable[j].used++; |
if (arpTable[j].used > ARP_MAX_USED) arpTable[j].used = ARP_MAX_USED; |
} |
else if (caso == 2) { |
/* Enqueue the packet until the ethernet address arrives */ |
p = arpTable[j].pkt; |
while (p != NULL) { |
p1 = p; |
p = p1->next; |
} |
p1->next = pkt; |
((PKT_NXT *)pkt)->next = NULL; |
((PKT_NXT *)pkt)->len = len; |
if (caso == 1) { |
/* Send the IP packet */ |
eth_setHeader(pkt,arpTable[j].eth,ETH_IP_TYPE); |
eth_sendPkt(pkt,len); |
netbuff_release(&udp_txbuff, (void *)pkt); |
arpTable[j].used++; |
if (arpTable[j].used > ARP_MAX_USED) arpTable[j].used = ARP_MAX_USED; |
} else if (caso == 2) { |
/* Enqueue the packet until the ethernet address arrives */ |
p = arpTable[j].pkt; |
while (p != NULL) { |
p1 = p; |
p = p1->next; |
} |
p1->next = pkt; |
((PKT_NXT *)pkt)->next = NULL; |
((PKT_NXT *)pkt)->len = len; |
#ifdef __ARP_DBG__ |
sprintf(msg,"Pacchetto : %lp accodato\n",pkt); |
win_puts(&w1,msg); |
printk(KERN_DEBUG ARP_INFO "Pacchetto : %lp accodato.\n", pkt); |
#endif |
} |
else { |
/* Search for a free entry in the ARP table...*/ |
j = -1; |
while (j == -1) { |
j = arp_req(dest); |
if (j == -1) { |
cprintf("FULL!!!\n"); |
kern_raise(XARP_TABLE_FULL,NIL); |
} |
} |
/*...fill it...*/ |
arpTable[j].pkt = pkt; |
((PKT_NXT *)arpTable[j].pkt)->next = NULL; |
((PKT_NXT *)pkt)->len = len; |
} else { |
/* Search for a free entry in the ARP table...*/ |
j = -1; |
while (j == -1) { |
j = arp_req(dest); |
if (j == -1) { |
cprintf("ARP Table Full.\n"); |
kern_raise(XARP_TABLE_FULL,NIL); |
} |
} |
/*...fill it...*/ |
arpTable[j].pkt = pkt; |
((PKT_NXT *)arpTable[j].pkt)->next = NULL; |
((PKT_NXT *)pkt)->len = len; |
#ifdef __ARP_DBG__ |
sprintf(msg,"Pacchetto : %lp accodato\n",pkt); |
win_puts(&w1,msg); |
printk(KERN_DEBUG ARP_INFO "Pacchetto : %lp accodato\n", pkt); |
#endif |
/*...and send the request!!! */ |
arp_sendRequest(j); |
} |
sem_post(&arpMutex); |
/*...and send the request!!! */ |
arp_sendRequest(j); |
} |
sem_post(&arpMutex); |
} |
|
/* ARP packet received CallBack*/ |
void arp_server_recv(void *pk) |
{ |
ARP_PKT *pkt,*rpkt; |
PKT_NXT *p1,*q1; |
int len; |
int i,j = 0; |
#ifdef __ARP_DBG__ |
char msg[100]; |
#endif |
BYTE found; |
ARP_PKT *pkt,*rpkt; |
PKT_NXT *p1,*q1; |
int len; |
int i,j = 0; |
BYTE found; |
|
pkt = (ARP_PKT *)eth_getFDB(pk); |
|
#if 0 |
{int ii; |
cprintf("Arp PKT...\n"); |
cprintf ("source..."); |
for (ii=0; ii<4; ii++) cprintf("%d ", pkt->sip.ad[ii]); |
cprintf ("\ndest..."); |
for (ii=0; ii<4; ii++) cprintf("%d ", pkt->tip.ad[ii]); |
{ |
int ii; |
|
cprintf("Arp PKT...\n"); |
cprintf ("source..."); |
for (ii=0; ii<4; ii++) cprintf("%d ", pkt->sip.ad[ii]); |
cprintf ("\ndest..."); |
for (ii=0; ii<4; ii++) cprintf("%d ", pkt->tip.ad[ii]); |
} |
#endif |
|
/* Check if the packet is directed to this host...*/ |
if (ip_compAddr(pkt->tip,myIpAddr)) { |
sem_xwait(&arpMutex, 1, BLOCK); |
/* 1 : Search an entry with his IP address */ |
found = FALSE; |
for (i = 0; (i < ARP_MAX_ENTRIES) && !found; i++) { |
if ((arpTable[i].valid != FALSE) && |
ip_compAddr(arpTable[i].ip,pkt->sip)) { |
setEthAddr(arpTable[i].eth,pkt->sha); |
found = TRUE; |
sem_xwait(&arpMutex, 1, BLOCK); |
/* 1 : Search an entry with his IP address */ |
found = FALSE; |
for (i = 0; (i < ARP_MAX_ENTRIES) && !found; i++) { |
if ((arpTable[i].valid != FALSE) && ip_compAddr(arpTable[i].ip,pkt->sip)) { |
setEthAddr(arpTable[i].eth,pkt->sha); |
found = TRUE; |
} |
} |
} |
/* |
If there isn't any, fill a new entry (if the table is |
not full) |
*/ |
if (!found) { |
for (i = 0; (i < ARP_MAX_ENTRIES) && !found; i++) |
if (arpTable[i].valid == FALSE) { |
j = i; |
found = TRUE; |
} |
if (found) { |
setIpAddr(arpTable[j].ip,pkt->sip); |
setEthAddr(arpTable[j].eth,pkt->sha); |
arpTable[j].valid = TRUE; |
/* If there isn't any, fill a new entry (if the table is not full) */ |
if (!found) { |
for (i = 0; (i < ARP_MAX_ENTRIES) && !found; i++) |
if (arpTable[i].valid == FALSE) { |
j = i; |
found = TRUE; |
} |
if (found) { |
setIpAddr(arpTable[j].ip,pkt->sip); |
setEthAddr(arpTable[j].eth,pkt->sha); |
arpTable[j].valid = TRUE; |
} |
} |
} |
/* If it is a request, send the reply */ |
if (ntohs(pkt->operation) == ARP_REQUEST) { |
rpkt = (ARP_PKT *)eth_getFDB(reply); |
rpkt->htype = htons(ARP_ETH_TYPE); |
rpkt->ptype = htons(ARP_IP_TYPE); |
rpkt->hlen = sizeof(struct eth_addr); |
rpkt->plen = sizeof(IP_ADDR); |
rpkt->operation = htons(ARP_REPLY); |
setEthAddr(rpkt->sha,myEthAddr); |
setIpAddr(rpkt->sip,myIpAddr); |
setEthAddr(rpkt->tha,pkt->sha); |
setIpAddr(rpkt->tip,pkt->sip); |
eth_setHeader(reply, pkt->sha, ETH_ARP_TYPE); |
eth_sendPkt(reply,sizeof(ARP_PKT)); |
} |
/* If it is a reply, search for his pending request */ |
else { |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if ((arpTable[i].valid == PENDING) && |
ip_compAddr(arpTable[i].ip,pkt->sip)) { |
/* |
the eth field in the ARP table was |
filled previously |
*/ |
arpTable[i].valid = TRUE; |
/* Send pending packets */ |
p1 = (PKT_NXT *)arpTable[i].pkt; |
while (p1 != NULL) { |
q1 = p1; |
p1 = q1->next; |
len = q1->len; |
eth_setHeader((struct ETH_HEADER *)q1,arpTable[i].eth,ETH_IP_TYPE); |
eth_sendPkt(q1,len); |
netbuff_release(&udp_txbuff, (void *)q1); |
|
/* If it is a request, send the reply */ |
if (ntohs(pkt->operation) == ARP_REQUEST) { |
rpkt = (ARP_PKT *)eth_getFDB(reply); |
rpkt->htype = htons(ARP_ETH_TYPE); |
rpkt->ptype = htons(ARP_IP_TYPE); |
rpkt->hlen = sizeof(struct eth_addr); |
rpkt->plen = sizeof(IP_ADDR); |
rpkt->operation = htons(ARP_REPLY); |
setEthAddr(rpkt->sha,myEthAddr); |
setIpAddr(rpkt->sip,myIpAddr); |
setEthAddr(rpkt->tha,pkt->sha); |
setIpAddr(rpkt->tip,pkt->sip); |
eth_setHeader(reply, pkt->sha, ETH_ARP_TYPE); |
eth_sendPkt(reply,sizeof(ARP_PKT)); |
} |
|
/* If it is a reply, search for his pending request */ |
else { |
for (i = 0; i < ARP_MAX_ENTRIES; i++) { |
if ((arpTable[i].valid == PENDING) && ip_compAddr(arpTable[i].ip,pkt->sip)) { |
/* the eth field in the ARP table was filled previously */ |
arpTable[i].valid = TRUE; |
/* Send pending packets */ |
p1 = (PKT_NXT *)arpTable[i].pkt; |
while (p1 != NULL) { |
q1 = p1; |
p1 = q1->next; |
len = q1->len; |
eth_setHeader((struct ETH_HEADER *)q1,arpTable[i].eth,ETH_IP_TYPE); |
eth_sendPkt(q1,len); |
netbuff_release(&udp_txbuff, (void *)q1); |
#ifdef __ARP_DBG__ |
sprintf(msg,"Pacchetto : %lp inviato\n",q1); |
win_puts(&w1,msg); |
printk(KERN_DEBUG ARP_INFO "Pacchetto : %lp inviato\n", q1); |
#endif |
} |
} |
} |
} |
} |
} |
} |
sem_post(&arpMutex); |
sem_post(&arpMutex); |
} |
} |
|
void arp_init(char *localAddr) |
{ |
int i; |
PID s; |
SOFT_TASK_MODEL m; |
int i; |
PID s; |
SOFT_TASK_MODEL m; |
|
struct sigaction action; |
struct sigaction action; |
|
if (!arpIsInstalled) { |
for (i = 0; i < ARP_MAX_ENTRIES; i++) arpTable[i].valid = FALSE; |
if (!arpIsInstalled) { |
for (i = 0; i < ARP_MAX_ENTRIES; i++) arpTable[i].valid = FALSE; |
|
/* ARP table mutex semaphore */ |
sem_init(&arpMutex, 0, 1); |
/* ARP table mutex semaphore */ |
sem_init(&arpMutex, 0, 1); |
|
netbuff_init(&arp_txbuff, 1, ARP_LEN); |
netbuff_init(&arp_txbuff, 1, ARP_LEN); |
|
ip_str2addr(localAddr,&myIpAddr); |
ip_str2addr(localAddr,&myIpAddr); |
|
eth_getAddress(&myEthAddr); |
eth_getAddress(&myEthAddr); |
|
/* Retry task */ |
soft_task_default_model(m); |
soft_task_def_wcet(m,1000); |
soft_task_def_period(m,1000000); |
soft_task_def_met(m,1000); |
soft_task_def_periodic(m); |
soft_task_def_system(m); |
soft_task_def_nokill(m); |
s = task_create("ArpRetry",arp_retry,&m,NULL); |
if (s == NIL) { |
kern_printf("Cannot create ArpRetry\n"); |
sys_end(); |
l1_exit(-1); |
} |
/* Retry task */ |
soft_task_default_model(m); |
soft_task_def_wcet(m,1000); |
soft_task_def_period(m,1000000); |
soft_task_def_met(m,1000); |
soft_task_def_periodic(m); |
soft_task_def_system(m); |
soft_task_def_nokill(m); |
s = task_create("ArpRetry",arp_retry,&m,NULL); |
if (s == NIL) { |
kern_printf("Cannot create ArpRetry\n"); |
sys_end(); |
l1_exit(-1); |
} |
|
eth_setProtocol(ETH_ARP_TYPE,arp_server_recv); |
eth_str2Addr("FF:FF:FF:FF:FF:FF",&broadcast); |
eth_str2Addr("00:00:00:00:00:00",&nulladdr); |
eth_setProtocol(ETH_ARP_TYPE,arp_server_recv); |
eth_str2Addr("FF:FF:FF:FF:FF:FF",&broadcast); |
eth_str2Addr("00:00:00:00:00:00",&nulladdr); |
|
// for (i = ARP_ERROR_BASE; i <= XARP_TABLE_FULL; i++) |
// exc_set(i, arp_exc); |
action.sa_flags = 0; |
action.sa_handler = arp_exc; |
sigfillset(&action.sa_mask); /* we block all the other signals... */ |
// for (i = ARP_ERROR_BASE; i <= XARP_TABLE_FULL; i++) |
// exc_set(i, arp_exc); |
action.sa_flags = 0; |
action.sa_handler = arp_exc; |
sigfillset(&action.sa_mask); /* we block all the other signals... */ |
|
if (sigaction(SIGARPFULL, &action, NULL) == -1) { |
perror("Error initializing ARP signal..."); |
sys_abort(AARPFULL); |
} |
if (sigaction(SIGARPFULL, &action, NULL) == -1) { |
perror("Error initializing ARP signal..."); |
sys_abort(AARPFULL); |
} |
|
task_activate(s); |
arpIsInstalled = TRUE; |
} else cprintf("Arp: already installed!!!!"); |
task_activate(s); |
arpIsInstalled = TRUE; |
} else |
cprintf("Arp: already installed."); |
} |