BSD net源码分析(1)

来源:互联网 发布:python init 函数 编辑:程序博客网 时间:2024/06/01 10:13

本节从ifnet结构开始解析,ifnet结构包含了接口的通用信息,每个接口都以该结构开始,末尾附带不同接口的特殊信息。
系统初始化的时候将所有接口的ifnet结构构成一个链表。

struct ifnet {
char    *if_name;        /* name, e.g. “en” or “lo” */
struct    ifnet *if_next;        /* all struct ifnets are chained */
struct    ifaddr *if_addrlist;    /* linked list of addresses per if */
int    if_pcount;        /* number of promiscuous listeners */
caddr_t    if_bpf;            /* packet filter structure */
u_short    if_index;        /* numeric abbreviation for this if  */
short    if_unit;        /* sub-unit for lower level driver */
short    if_timer;        /* time ’til if_watchdog called */
short    if_flags;        /* up/down, broadcast, etc. */
struct    if_data {
/* generic interface information */
u_char    ifi_type;    /* ethernet, tokenring, etc */
u_char    ifi_addrlen;    /* media address length */
u_char    ifi_hdrlen;    /* media header length */
u_long    ifi_mtu;    /* maximum transmission unit */
u_long    ifi_metric;    /* routing metric (external only) */
u_long    ifi_baudrate;    /* linespeed */
/* volatile statistics */
u_long    ifi_ipackets;    /* packets received on interface */
u_long    ifi_ierrors;    /* input errors on interface */
u_long    ifi_opackets;    /* packets sent on interface */
u_long    ifi_oerrors;    /* output errors on interface */
u_long    ifi_collisions;    /* collisions on csma interfaces */
u_long    ifi_ibytes;    /* total number of octets received */
u_long    ifi_obytes;    /* total number of octets sent */
u_long    ifi_imcasts;    /* packets received via multicast */
u_long    ifi_omcasts;    /* packets sent via multicast */
u_long    ifi_iqdrops;    /* dropped on input, this interface */
u_long    ifi_noproto;    /* destined for unsupported protocol */
struct    timeval ifi_lastchange;/* last updated */
}    if_data;
/* procedure handles */
int    (*if_init)        /* init routine */
__P((int));
int    (*if_output)        /* output routine (enqueue) */
__P((struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *));
int    (*if_start)        /* initiate output routine */
__P((struct ifnet *));
int    (*if_done)        /* output complete routine */
__P((struct ifnet *));    /* (XXX not used; fake prototype) */
int    (*if_ioctl)        /* ioctl routine */
__P((struct ifnet *, u_long, caddr_t));
int    (*if_reset)
__P((int));        /* new autoconfig will permit removal */
int    (*if_watchdog)        /* timer routine */
__P((int));
struct    ifqueue {
struct    mbuf *ifq_head;
struct    mbuf *ifq_tail;
int    ifq_len;
int    ifq_maxlen;
int    ifq_drops;
} if_snd;            /* output queue */
};

接口基本信息
if_next;接口指针链接所有的接口结构体,指向下一个结构体。
if_addrlist; 指向接口的地址链表,链接该接口的所有地址信息。
if_name; 标示接口的类型,如:le,sl
if_unit区别同类型的多个接口
if_flags表明接口的操作状态和属性
if_timer以秒为单位的定时器,到期后调用if_watchdog
if_pcount和if_bpf用于进程接收接口接收和传输数据的备份

接口的硬件属性
if_data结构体存放接口的硬件属性
ifi_type指明接口支持的硬件地址类型。
ifi_addrlen接口硬件地址的长度
ifi_hdrlen接口附加给分组数据的首都长度
ifi_mtu接口最大传输单元
ifi_metric用于接口路由

接口的统计信息
ifi_baudrate接口的数据速率,用于SLIP接口
ifi_ipackets接口接收的数据包数
ifi_ierrors接收错误的数据包
ifi_opackets接口发送的数据包数
ifi_oerrors发送的错误的数据包
ifi_collisions接口CSMA冲突的数据包个数
ifi_ibytes接收的字节数
ifi_obytes发送的字节数
ifi_imcasts通过多播地址接收的包
ifi_omcasts通过多播地址发送的包
ifi_iqdrops丢弃的接收包数
ifi_noproto不支持的协议包个数
ifi_lastchange最后一次修改统计值的时间

接口层的函数指针
if_init 接口初始化函数
if_output 接口数据输出函数
if_start 接口启动函数
if_done 传输结束函数
if_ioctl 处理I/O控制的函数
if_reset 接口重置函数
if_watchdog 接口定时器处理函数

接口数据输出队列信息
if_queue包含接口数据输出队列的信息
ifq_head mbuf指针,指向数据队列的首部
ifq_tail mbuf指针,指向数据队列的尾部
ifq_len 队列的长度
ifq_maxlen 队列的最大长度
ifq_drops 由于队列满造成的包丢弃数

介绍完接口结构体,再来介绍一下接口地址结构ifaddr。
由于接口可能支持多个协议地址,因此每个接口会维护一个接口地址链表。
struct ifaddr {
struct    sockaddr *ifa_addr;    /* address of interface */
struct    sockaddr *ifa_dstaddr;    /* other end of p-to-p link */
#define    ifa_broadaddr    ifa_dstaddr    /* broadcast address interface */
struct    sockaddr *ifa_netmask;    /* used to determine subnet */
struct    ifnet *ifa_ifp;        /* back-pointer to interface */
struct    ifaddr *ifa_next;    /* next address for interface */
void    (*ifa_rtrequest)();    /* check or clean routes (+ or -)’d */
u_short    ifa_flags;        /* mostly rt_flags for cloning */
short    ifa_refcnt;        /* extra to malloc for link info */
int    ifa_metric;        /* cost of going out this interface */
#ifdef notdef
struct    rtentry *ifa_rt;    /* XXXX for ROUTETOIF ????? */
#endif
};

ifa_ifp 指向接口结构体的方向指针
ifa_next 下一个接口地址
ifa_addr 指向接口地址的指针,接口地址是一个通用的结构体sockaddr
ifa_dstaddr / ifa_broadaddr 广播地址或点对点连接的对端地址,有接口的类型参数决定该值
ifa_netmask 子网掩码,获取接口地址的子网地址
ifa_rtrequest ifa_flags ifa_metric 接口的路由查找信息
ifa_refcnt 接口地址被引用的次数

接口通用地址结构体sockaddr
该通用接口为不同的协议地址使用,通过指定协议地址的类型和长度表示不同的地址
struct sockaddr {
u_char    sa_len;            /* total length */
u_char    sa_family;        /* address family */
char    sa_data[14];        /* actually longer; address value */
};

sa_len 地址的长度,包括sa_len和sa_family的长度
sa_family 地址类型
sa_data 实际地址

原创粉丝点击