|
ETHERIF.C
//===========================================================================
// 嵌入式 TCP/IP 协议栈 MSC51 专用版
// ETHERIF.C = 以太网数据链路层
// 作 者:南开大学-李章林
// 注 释:李清林
// 日 期:2008 年3 月
// 声 明:英文注释由作者李章林添加,中文注释由■李清林添加。
// 转载时请保留上述信息。
// 成都理工学院/应用数字系/应用数字专业
//===========================================================================
#include "..\TCPIP\TCPIPmem.h"
#include "..\TCPIP\IP.h"
#include "..\Netif\etherif.h"
#include "..\Netif\ARP.h"
#include "..\TCPIP\Netif.h"
//===========================================================================
/* call output to put a packet from IP layer to device. After
Ip layer selected a device, it use output to send this packet.
MemHead contain a packet and Netif tell dirver which netif it
is. NOTE:MemHead->pStart point to pIPHead
return:
TRUE: send successfuly.*/
// 作 者:南开大学-李章林
// 注 释:李清林
// 日 期:2008 年3 月
// 声 明:英文注释由作者李章林添加,中文注释由■李清林添加。
// 转载时请保留上述信息。
// 成都理工学院/应用数字系/应用数字专业
//---------------------------------------------------------------------------
// 程序名称:EtherOutput=以太网数据链路层发送子程序
// 入口参数:
// *MemHead=缓冲控制块指针
// *NetIf=网络接口设备队列指针
// DestIP=目的IP 地址
// 出口参数:
// BOOL=TRUE (发送成功) FALSE (发送失败)
//===========================================================================
BOOL EtherOutput(struct SMemHead DT_XDATA *MemHead,
struct SNetIf DT_XDATA* NetIf,IP_ADDR DestIP) REENTRANT_SIG
{
/* next host to receive the packet in rout */
DWORD NextIP;
// 以太网数据链路层首部结构体指针
struct SEtherHead DT_XDATA * pEtherHead; ETHERIF.C
// 缓存控制块指针
struct SMemHead DT_XDATA *p;
// 缓存控制块中得到以太网数据链路层指针位置
// 入口时 MemHead 的.pStart 域指向 IP 数据报文位置
pEtherHead = (struct SEtherHead DT_XDATA *)
(MemHead->pStart - sizeof(struct SEtherHead));
/* if DestIP in this subnet ... */
// ????????????????????????????
if ((NetIf->NetMask & NetIf->IPAddr) == (NetIf->NetMask & DestIP))
NextIP = DestIP;
else
NextIP = NetIf->GateWay;
/* find Ether addr of NextIP */
// 查找 NextIP 对应的网卡物理地址
if (ARPFind(pEtherHead->DestAddr,NextIP) == FALSE)
{
/* send a arp query */
//---------------------------------------------------------------------
// 如果 ARP 高速缓存表中未找到 NextIP,则调用 ARPQuery 发送程序发送一条
// ARP 广播。其中在 ARPQuery 程序中已经填写好以太网数据链路层报文和 ARP
// 报文。 ARPQuery 如果申请内存成功,则返回缓存控制块指针,否则返回 NULL。
//---------------------------------------------------------------------
if ((p = ARPQuery(NetIf,NextIP)) != NULL)
{ // 如果发送 ARP 广播时申请内存成功
// 调用网络接口设备队列的发送指针函数,发送 ARP 数据包
((struct SEtherDevice DT_XDATA *)
(NetIf->Info))->send(p->pStart,sizeof(struct SARPPacket) +
sizeof(struct SEtherHead));
MemFree(p); // 释放缓存控制块
}
}
else
{
//---------------------------------------------------------------------
// 如果 ARP 高速缓存表中找到 NextIP,则 pEtherHead->DestAddr 中存储
// NextIP 对应的以太网物理地址。
//---------------------------------------------------------------------
/* fill ehter header, DestAddr already filled in ARPFind */
// 填写以太网数据链路层首部.ScrAddr 域=以太网源物理地址
// 网络接口设备队列指针中获取以太网源物理地址
MemCopy(pEtherHead->ScrAddr,
((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN);
// 填写以太网数据链路层首部.type 域=数据帧类型
// 以太网帧类型=IP 数据包 ETHERIF.C
pEtherHead->type = htons(ETHER_TYPE_IP);
// 注:以太网目的物理地址已经在调用 ARPFind 程序时填写到
// pEtherHead->DestAddr 中。
/* send the packet. packet lenth is less than MemHead size */
// 调用网络接口设备队列的发送指针函数,发送 IP 数据包
return ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->send(
pEtherHead,(WORD)(MemHead->pEnd - (BYTE DT_XDATA *)pEtherHead));
}
return FALSE;
/* free MemHead when it is acked in tcp model */
}
//===========================================================================
/* this function is called periodically.Get a packet from specific
device. If there is a packet, call NetIf->Input to do more */
// 作 者:南开大学-李章林
// 注 释:李清林
// 日 期:2008 年3 月
// 声 明:英文注释由作者李章林添加,中文注释由■李清林添加。
// 转载时请保留上述信息。
// 成都理工学院/应用数字系/应用数字专业
//---------------------------------------------------------------------------
// 程序名称:EtherInput=以太网数据链路层接收子程序
// 入口参数:
// *NetIf=网络接口设备队列指针
// 出口参数:
// 无
//=============================================================================
void EtherInput(struct SNetIf DT_XDATA * NetIf) REENTRANT_SIG
{
struct SMemHead DT_XDATA *MemHead; // 缓存控制块指针
struct SEtherHead DT_XDATA *pEtherHead; // 以太网数据链路层指针
struct SMemHead DT_XDATA *p; // 临时缓存控制块指针
/* if there is a packet to deal with */
// 如果以太网网络接口设备接收到数据包
while ((MemHead = ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->recv())
!= NULL)
{
/* Note, pStart point to EtherHead */
// 以太网数据链路层指针 EetherHead 指向数据包数据链路层位置
pEtherHead = (struct SEtherHead DT_XDATA *)(MemHead->pStart);
/* which packet type */
switch(ntohs(pEtherHead->type)) // 分析数据包帧类型 ETHERIF.C
{
case ETHER_TYPE_IP: // IP 数据包
/* before pass to IP layer, let MemHead->pStart point
to IP header */
MemHead->pStart += sizeof(struct SEtherHead);
/* pass to IP layer for more dealing */
// 将缓存控制块指针的 pStart 域指针指向IP 首部
IPInput(MemHead); // 调用 IP 数据包接收子程序,
break;
case ETHER_TYPE_ARP: // ARP 数据包
//--------------------------------------------------------------------------
// ARPInput 程序中如果接收到 ARP 请求报文,填写以太网数据链路层首部信息,然后
// 填写 ARP 应答报文,并返回 MemHead;如果接收到 ARP 应答报文,填写 ARP 高速缓存表,
// 然后返回 NULL。据此通过返回值可确定是接收到 ARP 请求报文还是 ARP 应答报文。
//--------------------------------------------------------------------------
if ((p = ARPInput(MemHead,NetIf)) != NULL)
{
/* a arp reply need to be send */
// 接收到 ARP 请求报文后,发送 ARP 应答报文
// 调用网络接口设备发送函数指针发送 ARP 应答报文
((struct SEtherDevice DT_XDATA *)(NetIf->Info))->send(
p->pStart,sizeof(struct SARPPacket)
+ sizeof(struct SEtherHead));
MemFree(p);
}
/* 'MemHead' is freed in ARPInput() */
break;
//---------------------------------------------------------------------------
// 以太网数据链路层支持三种数据包。而一般嵌入式 TCP/IP 协议栈只支持IP 数据包和
// ARP 数据包,不支持 RARP 数据包(RARP 数据包针对无盘网络工作)。
//---------------------------------------------------------------------------
default:
/* unknown packet type free */
MemFree(MemHead);
}
}
}
//=============================================================================
/* ethernet device init */
// 作 者:南开大学-李章林
// 注 释:李清林
// 日 期:2008 年3 月
// 声 明:英文注释由作者李章林添加,中文注释由■李清林添加。
// 转载时请保留上述信息。 ETHERIF.C
// 成都理工学院/应用数字系/应用数字专业
//---------------------------------------------------------------------------
// 程序名称:EtherDevInit=以太网数据链路层网络接口设备队列初始化子程序
// 入口参数:
// *pDevice=以太网数据链路层设备指针
// EtherAddr[]=网卡物理地址
// 以太网数据链路层发送指针函数
// BOOL (DT_CODE * send)(void DT_XDATA *buf, WORD size)
// 以太网数据链路层接收指针函数
// struct SMemHead DT_XDATA *(DT_CODE * recv)()
// 出口参数:
// 无
//=============================================================================
void EtherDevInit(struct SEtherDevice DT_XDATA * pDevice,
BYTE EtherAddr[],
BOOL (DT_CODE * send)(void DT_XDATA *buf, WORD size) REENTRANT_SIG,
struct SMemHead DT_XDATA *(DT_CODE * recv)() REENTRANT_SIG) REENTRANT_MUL
{
// 网卡物理地址拷贝到以太网数据链路层设备驱动结构体指针.Addr 域
MemCopy(pDevice->Addr,EtherAddr,ETHER_ADDR_LEN);
// 填写以太网数据链路层设备驱动结构体指针.recv 域
pDevice->recv = recv;
// 填写以太网数据链路层设备驱动结构体指针.send 域
pDevice->send = send;
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|