网络接口层 使用的数据结构

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[];

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注