struct ifnet {
void *if_softc; /* pointer to driver state 指向设备驱动控制体*/
char *if_name; /* name, e.g. ``en'' or ``lo'' */
TAILQ_ENTRY(ifnet) if_link; /* all struct ifnets are chained 构建一个接口链表*/
struct ifaddrhead if_addrhead; /* linked list of addresses per if 接口的ifaddr地址链表*/
char if_xname[IFNAMSIZ]; /* external name (name + unit) */
int if_pcount; /* number of promiscuous listeners 用于分组过滤器*/
struct bpf_if *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 以秒为单位记录时间,直到内核为此接口调用函数 i f _ w a t c h d o g为止。*/
short if_flags; /* up/down, broadcast, etc. 接口状态标识*/
int if_ipending; /* interrupts pending */
void *if_linkmib; /* link-type-specific MIB data */
size_t if_linkmiblen; /* length of above data */
struct if_data if_data;
#define if_mtu if_data.ifi_mtu //是接口传输单元的最大值
#define if_type if_data.ifi_type //指明接口支持的硬件地址类型
#define if_physical if_data.ifi_physical
#define if_addrlen if_data.ifi_addrlen//是数据链路地址的长度
#define if_hdrlen if_data.ifi_hdrlen//是由硬件附加给任何分组的首部的长度
#define if_metric if_data.ifi_metric//通常为0
#define if_baudrate if_data.ifi_baudrate//指定接口的传输速率,只有S L I P接口才设置它
#define if_hwassist if_data.ifi_hwassist
#define if_ipackets if_data.ifi_ipackets//以下是snmp统计信息
#define if_ierrors if_data.ifi_ierrors
#define if_opackets if_data.ifi_opackets
#define if_oerrors if_data.ifi_oerrors
#define if_collisions if_data.ifi_collisions
#define if_ibytes if_data.ifi_ibytes
#define if_obytes if_data.ifi_obytes
#define if_imcasts if_data.ifi_imcasts
#define if_omcasts if_data.ifi_omcasts
#define if_iqdrops if_data.ifi_iqdrops
#define if_noproto if_data.ifi_noproto
#define if_lastchange if_data.ifi_lastchange
#define if_recvquota if_data.ifi_recvquota
#define if_xmitquota if_data.ifi_xmitquota
struct ifmultihead if_multiaddrs; /* multicast addresses configured 接口多播地址表*/
int if_amcount; /* number of all-multicast requests */
/* procedure handles
包含指向标准接口层函数的指针,它们把设备专用的细节从网络层分离出来。每个网络接口实现这些适用于特定设备的函数
*/
int (*if_output) /* output routine (enqueue)对要传输的输出分组进行排队 */
__P((struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *));
void (*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 处理I / O控制命令*/
__P((struct ifnet *, u_long, caddr_t));
void (*if_watchdog) /* timer routine 周期性接口例程*/
__P((struct ifnet *));
int (*if_poll_recv) /* polled receive routine */
__P((struct ifnet *, int *));
int (*if_poll_xmit) /* polled transmit routine */
__P((struct ifnet *, int *));
void (*if_poll_intren) /* polled interrupt reenable routine */
__P((struct ifnet *));
void (*if_poll_slowinput) /* input routine for slow devices */
__P((struct ifnet *, struct mbuf *));
void (*if_init) /* Init routine 初始化接口*/
__P((void *));
int (*if_resolvemulti) /* validate/resolve multicast */
__P((struct ifnet *, struct sockaddr **, struct sockaddr *));
struct ifqueue if_snd; /* output queue 接口输出队列*/
struct ifqueue *if_poll_slowq; /* input queue for slow devices */
struct ifprefixhead if_prefixhead; /* list of prefixes per if */
};
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 位掩码,它用于选择i f a _ a d d r中的网络部分*/
struct if_data if_data; /* not all members are meaningful */
struct ifnet *ifa_ifp; /* back-pointer to interface */
TAILQ_ENTRY(ifaddr) ifa_link; /* queue macro glue */
void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */
__P((int, struct rtentry *, struct sockaddr *));
u_short ifa_flags; /* mostly rt_flags for cloning */
u_int ifa_refcnt; /* references to this structure */
int ifa_metric; /* cost of going out this interface */
#ifdef notdef
struct rtentry *ifa_rt; /* XXXX for ROUTETOIF ????? */
#endif
int (*ifa_claim_addr) /* check if an addr goes to this if */
__P((struct ifaddr *, struct sockaddr *));
};
一个接口的编址信息不仅仅只包括一个主机地址。 N e t / 3在通用的s o c k a d d r结构中维护
主机地址、广播地址和网络掩码。通过使用一个通用的结构,将硬件与协议专用的地址细节
相对于接口层隐藏起来
struct sockaddr {
u_char sa_len; /* total length */
sa_family_t sa_family; /* address family */
char sa_data[30]; /* actually longer; address value */
};
每个协议定义一个专用的s o c k a d d r结构,该结构
复制成员s a _ l e n和s a _ f a m i l y,但按那个协议的要
求来定义成员s a _ d a t a。
/*以太链路层地址存储结构*/
struct sockaddr_dl {
u_char sdl_len; /* Total length of sockaddr */
u_char sdl_family; /* AF_LINK */
u_short sdl_index; /* if != 0, system given index for interface */
u_char sdl_type; /* interface type */
u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */
u_char sdl_alen; /* link level address length */
u_char sdl_slen; /* link layer selector length */
char sdl_data[12]; /* minimum work area, can be larger;
contains both if name and ll address */
u_short sdl_rcf; /* source routing control */
u_short sdl_route[16]; /* source routing information */
};
#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen))
结构i f n e t和i f a d d r包含适用于所有网络接口和协议地址的通用信息。为了容纳其他设
备和协议专用信息,每个设备定义了并且每个协议分配了一个专用化版本的 i f n e t和i f a d d r
结构。这些专用化的结构总是包含一个 i f n e t或i f a d d r结构作为它们的第一个成员,这样
无须考虑其他专用信息就能访问这些公共信息。
struct arpcom {
/*
* The ifnet struct _must_ be at the head of this structure.
*/
struct ifnet ac_if; /* network-visible interface */
u_char ac_enaddr[6]; /* ethernet hardware address */
int ac_multicnt; /* length of ac_multiaddrs list */
void *ac_netgraph; /* ng_ether(4) netgraph node info */
};
/* * Ethernet status, per interface. */ struct le_softc { struct arpcom le_ac; /* Common Ethernet/ARP Structure */ #define le_if le_ac.ac_if
#define le_if le_ac.ac_enaddr
/*以下定义接口私有信息*/
};