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
/*以下定義接口私有信息*/
};