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