51單片機(jī)ARP協(xié)議實(shí)現(xiàn)原理
----------
|網(wǎng)卡中斷|
----------
|
V
---------- |>
|發(fā)信號(hào)量| | 收完/收溢出錯(cuò)
|SemPost |---->-------------- RxSemPost
---------- |>
| | 發(fā)完/發(fā)被中斷錯(cuò)
---------->-------------- TxSemPost
圖5 網(wǎng)卡中斷處理程序
進(jìn)入
| ------
V | | 發(fā)
---------- | 低優(yōu)先級(jí)
------> | 等待 |---
| |TxQPend |--------------------- -----
| ---------- | | |
| | TxQFIFO非空 | | |
| V | ------| |------
| ---------- | 數(shù)據(jù)源 | | 各任務(wù)發(fā)送來(lái)的數(shù)據(jù)
| | 發(fā)送包 | | | |
| ---------- | -----
| | | TxQFIFO
| V |
| --------------------- |
| | 釋放內(nèi)存 | |
| |(包已存入網(wǎng)卡RAM里)| |
| --------------------- |
| | ----- |
| V | | |
| ----------- | |
| | 等待 |-- | (等效發(fā)送包被拋棄)
| |TxSemPend|----------- |
| ----------- | |
| | 發(fā)完/超時(shí) | |
| V | |
| Y ---------------- ----------- |
----| 發(fā)送成功嗎? | |重發(fā)第n次| |
|(無(wú)錯(cuò)且不超時(shí))| | nN | |
---------------- ----------- |
| N /^ |
V N | |
------------------>------ |
|已發(fā)了N次嗎?|---------->--------
--------------- Y
圖6 發(fā)送流程圖
進(jìn)入
| -----
V | | 收
----------- | 高優(yōu)先級(jí)
------------------>| 等待 |--
| --------->|RxSemPend|---------------
| | ----------- /| /|
| | | 收到包 或 | |
| | V 收錯(cuò) 或 | |
| | | 超時(shí) | |
| | ----------- | ----------
| | |存并清ISR| | |復(fù)位網(wǎng)卡|
----------- | ----------- | ----------
|RxSemPost| | | | /^ /^
----------- | V | | |
| | -------------------- | | |
| | |超時(shí)且無(wú)新包且無(wú)錯(cuò)| Y| | |
| | | (防死鎖) |->- | |
| | -------------------- | |
/| |(不執(zhí)行 | N | |
| |RxSemPost) V | |
| | ------------ Y | |
| | | 收溢出錯(cuò) |--->--------- |
| | | ISR之OVW | |
| Y | N ------------ |
------------------ | N |
|網(wǎng)卡中還有包嗎?| V |
| CURR!=BNRY+1 | ------------------------ Y |
------------------ |讀出包頭,查有無(wú)邏輯錯(cuò)|--->-------
| ------------------------
/| | N
| V
| ------------------------
---------- |按包長(zhǎng)度申請(qǐng)合適的大中|
|釋放內(nèi)存| |小號(hào)內(nèi)存,并存入整個(gè)包|
---------- |,再調(diào)整BNRY |
/^ /^ ------------------------
| | |
| | V
| | N ----------------------------
| ------|是否是發(fā)給自己IP地址的包?|
| ----------------------------
| | Y
| V
| ------------
| | 包分發(fā) |
| ------------
| |
| V
| ----------------------------
| | | | |
| V -------------------------- IP_in過(guò)濾
| | V V V
| ARP ICMP(Ping) UDP TCP
| | | | |
| ----------------------------
| | 串行處理
| | (32bitMCU可設(shè)計(jì)成并發(fā)模式)
|----------------------
圖7 接收流程圖
我仔細(xì)檢查了幾遍,似乎比較完備了,各種情況下均可以正常工作。在超負(fù)荷流量下,只會(huì)拋包,不會(huì)死機(jī)。當(dāng)然,由于本人接觸資料有限和個(gè)人局限性,肯定有錯(cuò)誤和疏漏之處,希望大家提出意見(jiàn)和建議。
偽代碼清單:
ARP_init() //ARP緩存初始化
{
for(i=0;iARPTabSize;i++)
ARPTable[i].status=0;
}
ARP_request(目的IP地址) //ARP請(qǐng)求
{
//判斷IP地址是否屬于同一子網(wǎng)的任務(wù)交給上層軟件處理
//(由它決定請(qǐng)求網(wǎng)卡IP地址還是默認(rèn)網(wǎng)關(guān)IP地址),
//這有利于減少代碼量。
//申請(qǐng)小號(hào)內(nèi)存
pARP=OSMemGet();
//填以太網(wǎng)幀
以太網(wǎng)協(xié)議=0x0806;//ARP協(xié)議
目的MAC地址=0xffff;//廣播地址
源MAC地址=自己的MAC地址;
//填A(yù)RP表
硬件類型=0x0001;
協(xié)議類型=0x0800;
硬件地址長(zhǎng)度=0x06;
協(xié)議長(zhǎng)度=0x04;
操作=0x0001;//請(qǐng)求
發(fā)送方首部=自己的MAC地址;
發(fā)送方IP地址=源IP地址;
目標(biāo)首部=0x0000;
目標(biāo)IP地址=目的IP地址;
//填充PAD
沒(méi)有內(nèi)容處填充0;
//發(fā)送ARP包至TxQFIFO緩存
OSQSend(QID,*pARP);
}
ARP_answer(*pARP) //ARP應(yīng)答
{
學(xué)習(xí)/更新ARP緩存表;
//修改收到的ARP包,形成ARP應(yīng)答
//填以太網(wǎng)幀
目的MAC地址=對(duì)方(網(wǎng)卡/網(wǎng)關(guān))發(fā)來(lái)的源MAC地址;
源MAC地址=自己的MAC地址;
//填A(yù)RP表
目標(biāo)首部=發(fā)送方首部;發(fā)送方首部=自己的MAC地址;
交換發(fā)送方IP地址和目標(biāo)IP地址;
操作=0x0002;//ARP應(yīng)答
//發(fā)送ARP包至TxQFIFO緩存
OSQSend(QID,*pARP);
}
ARP_process(*pARP) //ARP應(yīng)答處理
{
//更新
for(i=0;iARPTabSize;i++){
if(ARPTab[i].status==1){
if(ARPTab[i].IPAdr==收到的ARP應(yīng)答包源IP地址){
ARPTab[i].ttl=最大壽命;
ARPTab[i].IPAdr=收到的包的源IP地址;
ARPTab[i].MACAdr=收到的包的源MAC地址;
return;
}
}
}
//學(xué)習(xí)
for(i=0;iARPTabSize;i++){
if(ARPTab[i].status==0){
ARPTab[i].status=1;
ARPTab[i].ttl=最大壽命;
ARPTab[i].IPAdr=收到的包的源IP地址;
ARPTab[i].MACAdr=收到的包的源MAC地址;
return;
}
}
//表滿處理,有損性能的快速算法
ARPTab[index].status=1; //注:index為全局變量,保存ARP緩存表項(xiàng)索引。每次處理加1取模。
ARPTab[index].ttl=最大壽命;
index++;
if(index>=ARPTabSize) index=0;
}
IP_in(*pIP) //IP包過(guò)濾(ARP地址學(xué)習(xí)) 注:這里處理的是IP包,偽代碼與上面程序相似,但源代碼差別很大。
{
//更新
for(i=0;iARPTabSize;i++){
if(ARPTab[i].status==1){
if(ARPTab[i].IPAdr==收到的IP包源IP地址){
ARPTab[i].ttl=最大壽命;
ARPTab[i].IPAdr=收到的包的源IP地址;
ARPTab[i].MACAdr=收到的包的源MAC地址;
return;
}
}
}
//學(xué)習(xí)
for(i=0;iARPTabSize;i++){
if(ARPTab[i].status==0){
ARPTab[i].status=1;
ARPTab[i].ttl=最大壽命;
ARPTab[i].IPAdr=收到的包的源IP地址;
ARPTab[i].MACAdr=收到的包的源MAC地址;
return;
}
}
//表滿處理,有損性能的快速算法
ARPTab[index].status=1; //注:index為全局變量,保存ARP緩存表項(xiàng)索引。每次處理加1取模。
ARPTab[index].ttl=最大壽命;
index++;
if(index>=ARPTabSize) index=0;
}
timer() //軟定時(shí)器任務(wù),用于ARP老化
{
for(;;){
taskDelay(1秒);
for(i=0;iARPTabSize;i++){
if(ARPTab[i].status==1){
if(ARPTab[i].ttl==0)
ARPTab[i].status=0;
else
ARPTab[i].ttl--;
}
}
}
主程序框架:
initNIC //初始化網(wǎng)卡
//創(chuàng)建資源
TxSem和RxSem信號(hào)量
TxQFIFO隊(duì)列
大中小內(nèi)存設(shè)立
//創(chuàng)建任務(wù)
收
發(fā)
。
。
。
參考文獻(xiàn):
1?!队肨CP/IP進(jìn)行網(wǎng)際互連》(第3版)第一、二、三卷 DOUGLAS E.COMER著 電子工業(yè)出版社
評(píng)論