1. 接口数据结构
/* netif.h – NIGET */
#define NI_MAXHWA 14 /* 任何硬件最大尺寸 max size of any hardware*/
/* (物理)网络地址 */
struct hwa { /* *硬件地址 */
int ha_len; /* 地址长度 */
unsigned char ha_addr[NI_MAXHWA]; /* 地址 */
};#define NI_INQSZ 30 /* 接口输入队列大小 */
#define NETNLEN 30 /* 网络名称长度 */#define NI_LOCAL 0 /* 本地接口序号index of local interface */
#define NI_PRIMARY 1 /* 主要接口序号index of primary interface */#define NI_MADD 0 /* 添加多播add multicast (ni_mcast) */
#define NI_MDEL 1 /* 删除多播 multicast (ni_mcast) *//* 接口状态 */
#define NIS_UP 0x1
#define NIS_DOWN 0x2
#define NIS_TESTING 0x3/* 网络接口结构 (one per interface) */
struct netif { /* 网络接口信息 */
char ni_name[NETNLEN]; /* 接口的域名 */
char ni_state; /* 接口的状态 取上边的三个值 */
IPaddr ni_ip; /* 接口的IP地址*/
IPaddr ni_net; /* 接口的网络IP地址 */
IPaddr ni_subnet; /* 子网的IP地址 */
IPaddr ni_mask; /* 接口的子网掩码 */
IPaddr ni_brc; /* IP广播地址 */
IPaddr ni_nbrc; /* IP的网络广播地址 */
unsigned int ni_mtu; /* 最大传输单元(字节) */
unsigned int ni_hwtype; /* 硬件类型 (for ARP) */
struct hwa ni_hwa; /* 接口的硬件地址*/
struct hwa ni_hwb; /* 硬件广播地址 */
/* 多播添加/删除函数 */
int (*ni_mcast)(int op,int dev,Eaddr hwa,IPaddr ipa);
Bool ni_ivalid; /* 接口的IP地址是否有效 */
Bool ni_nvalid; /* 接口的域名是否有效 */
Bool ni_svalid; /* 子网的IP地址是否有效 */
int ni_dev; /* 设备描述符 */
int ni_ipinq; /* IP输入队列 */
int ni_outq; /* (设备)的输出队列 */
/* 接口信息管理库- MIB */
char *ni_descr; /* 硬件的文字描述 */
int ni_mtype; /* MIB类型 */
long ni_speed; /* 速率 bit/s */
char ni_admstate; /* 管理状态 (NIS_*)*/
long ni_lastchange; /* 最后一个状态变化 (1/100 sec)*/
long ni_ioctets; /* # 收到的字节 */
long ni_iucast; /* # 收到的单播字节 */
long ni_inucast; /* # 收到的非单播字节 */
long ni_idiscard; /* # 丢弃 – 输出队列满*/
long ni_ierrors; /* # 输入包错误 */
long ni_iunkproto; /* # in packets for unk. protos */
long ni_ooctets; /* # 发送的字节 */
long ni_oucast; /* # 发送的单播字节 */
long ni_onucast; /* # 发送的非单播字节 */
long ni_odiscard; /* # 输出的数据包被丢弃 */
long ni_oerrors; /* # 发送的包错误 */
long ni_oqlen; /* 输出队列长度 */
long ni_maxreasm; /* 可以重新组装的最大数据包的长度 */
};#define NIGET(ifn) ((struct ep *)deq(nif[ifn].ni_ipinq))
#define NIF Neth+Noth+1 /* # of interfaces, +1 for local*/
extern struct netif nif[];
int netwrite(struct netif *, struct ep *, unsigned);
2. 以太网的基本定义
/* ether.h */
/* 以太网的定义和常量 */
#define EP_MAXMULTI 10 /* 多播地址表的大小 */
#define EP_MINLEN 60 /* 最小数据包长度 */
#define EP_DLEN 1500 /* 数据字段长度 */
#define EP_HLEN 24 /* 头长度 */
#define EP_CRC 4 /* 效检位长度 ether CRC (trailer) */
#define EP_MAXLEN EP_HLEN+EP_DLEN
#define EP_ALEN 6 /* 物理地址的字节数 */
typedef unsigned char Eaddr[EP_ALEN]; /* 物理地址 */
#define EP_RETRY 3 /* number of times to retry xmit errors */
#define EP_BRC "377377377377377377"/* 以太网广播地址 */
#define EP_RTO 300 /* time out in seconds for reads */#define EP_NUMRCV 16 /* number LANCE recv buffers (power 2) */
#define EP_NUMRCVL2 4 /* log2 of the number of buffers */#define EPT_LOOP 0x0060 /* type: Loopback 回环 */
#define EPT_ECHO 0x0200 /* type: Echo 应答 */
#define EPT_PUP 0x0400 /* type: Xerox PUP */
#define EPT_IP 0x0800 /* type: Internet Protocol */
#define EPT_ARP 0x0806 /* type: ARP */
#define EPT_RARP 0x8035 /* type: Reverse ARP */struct eh { /* 以太网报头 */
Eaddr eh_dst; /* 目标主机地址 */
Eaddr eh_src; /* 源主机地址 */
unsigned short eh_type;/* 以太网数据包类型(见下文) */
};struct ep { /* 结构完整的以太网数据包*/
u_long ep_nexthop; /* niput() uses this */
short ep_ifn; /* 原接口序号originating interface number*/
short ep_len; /* 数据包的长度 */
short ep_order; /* 字节顺序 (for debugging) */
struct eh ep_eh; /* 以太网报头 */
char ep_data[EP_DLEN]; /* 数据 */
};/* 数据包字节顺序的常量(设置方法主机顺序) */
#define EPO_NET 1 /* 网络层 network layer */
#define EPO_IP 2 /* level 1 protocols… */
#define EPO_ARP 2
#define EPO_RARP 2
#define EPO_ICMP 4 /* level 2 protocols */
#define EPO_IGMP 4
#define EPO_TCP 4
#define EPO_UDP 4
#define EPO_OSPF 4
#define EPO_DNS 5 /* 应用协议 application protocols*//* these allow us to pretend it's all one big happy structure */
#define ep_dst ep_eh.eh_dst
#define ep_src ep_eh.eh_src
#define ep_type ep_eh.eh_type#if Noth > 0
/* this is for Othernet simulation */struct otblk {
Bool ot_valid; /* these entries are valid? */
Eaddr ot_paddr; /* the Othernet physical address */
Eaddr ot_baddr; /* the Othernet broadcast address */
int ot_rpid; /* id of process reading from othernet */
int ot_rsem; /* mutex for reading from the othernet */
int ot_pdev; /* Physical device devtab index */
int ot_intf; /* the associate interface */
char *ot_descr; /* text description of the device */
};
#endif /* Noth */#define ETOUTQSZ 30
/* 以太网控制模块的描述 */
struct etblk {
int etxpending; /* 号的数据包等待输出number of packets pending output*/
int etrpending; /* 正在等待已接收1 => a receive is pending already*/
int etwtry; /* 重试num. of times to retry xmit errors */
char *etwbuf; /* 当前发送缓冲区的指针 */
short etnextbuf; /* 检查缓冲区循环for checking buffers round robin */
#if Noth > 0
struct otblk *etoth[Noth]; /* eaddr to oaddr translations */
#endif /* Noth */
};/* 以太网功能的代码 */
#define EPC_PROMON 1 /* 打开混杂模式 */
#define EPC_PROMOFF 2 /* 关闭混杂模式 */
#define EPC_MADD 3 /* 添加多播地址 */
#define EPC_MDEL 4 /* 删除多播地址 */struct utdev {
unsigned int ud_iomem;
unsigned int ud_iosize;
struct devsw *ud_pdev;
Eaddr ud_paddr;
Eaddr ud_bcast;
char *ud_descr;
int ud_outq;
int ud_ifnum;
int ud_nextbuf;
int ud_xpending;
int ud_xmaddr; /* 发送基地缓冲区transmit base buf # */
int ud_wretry;
int ud_rmin; /* 接收环形缓冲区基地址receive ring buffer base addr*/
int ud_rmax; /* 环形缓冲区最大接收地址receive ring buffer max addr */
};struct etdev {
unsigned int ed_iomem;
unsigned int ed_iosize;
struct devsw *ed_pdev;
Eaddr ed_paddr;
Eaddr ed_bcast;
char *ed_descr;
int ed_outq;
int ed_ifnum;
int ed_wretry;
struct scb *ed_scb;
struct cbl *ed_cbl;
struct rfd *ed_rfd; /* first in RFD ring */
struct rfd *ed_rfdend; /* last in RFDring */
struct rbd *ed_rbd; /* first in RBD ring */
struct rbd *ed_rbdend; /* last in RBD ring */
struct tbd *ed_tbd; /* transmit buffer descriptor */
unsigned char *ed_xmbuf; /* transmit buffer base */
unsigned char ed_irq; /* SIRQ reg value */
int ed_mcc; /* # valid mca's */
Eaddr ed_mca[EP_MAXMULTI]; /* multicast addr. table */
/* XXX */
int ed_xpending;
};extern struct utdev ue[];
extern struct etdev ee[];
3. 传入分组的多路分解
/* ni_in.c – ni_in */
#include <conf.h>
#include <kernel.h>
#include <network.h>#include <ospf.h>
int arp_in(struct netif *, struct ep *);
int rarp_in(struct netif *, struct ep *);
int ip_in(struct netif *, struct ep *);/*————————————————————————
* ni_in – network interface input function 网络接口输入功能
*————————————————————————
*/
int
ni_in(struct netif *pni, struct ep *pep, unsigned len)
{
int rv;pep->ep_ifn = pni – &nif[0]; /* 记录原接口序号 # */
pni->ni_ioctets += len; /*收到的字节累加*/
if (!memcmp(pni->ni_hwa.ha_addr, pep->ep_dst, EP_ALEN))
pni->ni_iucast++; /*比较帧的目的地址与接口的物理地址,相同则单播字节累加*/
else
pni->ni_inucast++; /*非单播字节累加*/
switch (pep->ep_type) { /*分类*/
case EPT_ARP: rv = arp_in(pni, pep); break;
case EPT_RARP: rv = rarp_in(pni, pep); break;
case EPT_IP: rv = ip_in(pni, pep); break;
default:
pni->ni_iunkproto++;
freebuf(pep);
rv = OK;
}
return rv;
}extern struct etblk eth[];