新闻中心

EEPW首页>嵌入式系统>设计应用> 51单片机ARP协议实现原理

51单片机ARP协议实现原理

作者: 时间:2012-10-12 来源:网络 收藏


----------
|网卡中断|
----------
|
V
---------- |>
|发信号量| | 收完/收溢出错
|SemPost |---->-------------- RxSemPost
---------- |>
| | 发完/发被中断错
---------->-------------- TxSemPost
图5 网卡中断处理程序


进入
| ------
V | | 发
---------- | 低优先级
------> | 等待 |---
| |TxQPend |--------------------- -----
| ---------- | | |
| | TxQFIFO非空 | | |
| V | ------| |------
| ---------- | 数据源 | | 各任务发送来的数据
| | 发送包 | | | |
| ---------- | -----
| | | TxQFIFO
| V |
| --------------------- |
| | 释放内存 | |
| |(包已存入网卡RAM里)| |
| --------------------- |
| | ----- |
| V | | |
| ----------- | |
| | 等待 |-- | (等效发送包被抛弃)
| |TxSemPend|----------- |
| ----------- | |
| | 发完/超时 | |
| V | |
| Y ---------------- ----------- |
----| 发送成功吗? | |重发第n次| |
|(无错且不超时)| | nN | |
---------------- ----------- |
| N /^ |
V N | |
------------------>------ |
|已发了N次吗?|---------->--------
--------------- Y

图6 发送流程图


进入
| -----
V | | 收
----------- | 高优先级
------------------>| 等待 |--
| --------->|RxSemPend|---------------
| | ----------- /| /|
| | | 收到包 或 | |
| | V 收错 或 | |
| | | 超时 | |
| | ----------- | ----------
| | |存并清ISR| | |复位网卡|
----------- | ----------- | ----------
|RxSemPost| | | | /^ /^
----------- | V | | |
| | -------------------- | | |
| | |超时且无新包且无错| Y| | |
| | | (防死锁) |->- | |
| | -------------------- | |
/| |(不执行 | N | |
| |RxSemPost) V | |
| | ------------ Y | |
| | | 收溢出错 |--->--------- |
| | | ISR之OVW | |
| Y | N ------------ |
------------------ | N |
|网卡中还有包吗?| V |
| CURR!=BNRY+1 | ------------------------ Y |
------------------ |读出包头,查有无逻辑错|--->-------
| ------------------------
/| | N
| V
| ------------------------
---------- |按包长度申请合适的大中|
|释放内存| |小号内存,并存入整个包|
---------- |,再调整BNRY |
/^ /^ ------------------------
| | |
| | V
| | N ----------------------------
| ------|是否是发给自己IP地址的包?|
| ----------------------------
| | Y
| V
| ------------
| | 包分发 |
| ------------
| |
| V
| ----------------------------
| | | | |
| V -------------------------- IP_in过滤
| | V V V
| ARP ICMP(Ping) UDP TCP
| | | | |
| ----------------------------
| | 串行处理
| | (32bitMCU可设计成并发模式)
|----------------------

图7 接收流程图

我仔细检查了几遍,似乎比较完备了,各种情况下均可以正常工作。在超负荷流量下,只会抛包,不会死机。当然,由于本人接触资料有限和个人局限性,肯定有错误和疏漏之处,希望大家提出意见和建议。

伪代码清单:
ARP_init() //ARP缓存初始化
{
for(i=0;iARPTabSize;i++)
ARPTable[i].status=0;
}

ARP_request(目的IP地址) //ARP请求
{
//判断IP地址是否属于同一子网的任务交给上层软件处理
//(由它决定请求网卡IP地址还是默认网关IP地址),
//这有利于减少代码量。

//申请小号内存
pARP=OSMemGet();

//填以太网帧
以太网协议=0x0806;//
目的MAC地址=0xffff;//广播地址
源MAC地址=自己的MAC地址;

//填ARP表
硬件类型=0x0001;
协议类型=0x0800;
硬件地址长度=0x06;
协议长度=0x04;
操作=0x0001;//请求
发送方首部=自己的MAC地址;
发送方IP地址=源IP地址;
目标首部=0x0000;
目标IP地址=目的IP地址;

//填充PAD
没有内容处填充0;

//发送ARP包至TxQFIFO缓存
OSQSend(QID,*pARP);
}

ARP_answer(*pARP) //ARP应答
{
学习/更新ARP缓存表;

//修改收到的ARP包,形成ARP应答
//填以太网帧
目的MAC地址=对方(网卡/网关)发来的源MAC地址;
源MAC地址=自己的MAC地址;

//填ARP表
目标首部=发送方首部;发送方首部=自己的MAC地址;
交换发送方IP地址和目标IP地址;
操作=0x0002;//ARP应答

//发送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 //初始化网卡
//创建资源
TxSem和RxSem信号量
TxQFIFO队列
大中小内存设立
//创建任务






参考文献:
1。《用TCP/IP进行网际互连》(第3版)第一、二、三卷 DOUGLAS E.COMER著 电子工业出版社


上一页 1 2 下一页

评论


相关推荐

技术专区

关闭