Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 583 → Rev 584

/shark/trunk/drivers/newnet/arp.c
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.");
}