📄 arp协议实现原理.txt
字号:
| ------------
| | 包分发 |
| ------------
| |
| V
| ----------------------------
| | | | |
| V -------------------------- IP_in过滤
| | V V V
| ARP ICMP(Ping) UDP TCP
| | | | |
| ----------------------------
| | 串行处理
| | (32bitMCU可设计成并发模式)
|---------<-------------
图7 接收流程图
我仔细检查了几遍,似乎比较完备了,各种情况下均可以正常工作。在超负荷流量下,只会抛包,不会死机。当然,由于本人接触资料有限和个人局限性,肯定有错误和疏漏之处,希望大家提出意见和建议。
伪代码清单:
ARP_init() //ARP缓存初始化
{
for(i=0;i<ARPTabSize;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;//请求
发送方首部=自己的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;i<ARPTabSize;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;i<ARPTabSize;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;i<ARPTabSize;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;i<ARPTabSize;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;i<ARPTabSize;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著 电子工业出版社
2。www.laogu.com
3。www.sics.se/~adam/lwip/ 的uip6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -