天天看点

为什么有了sock结构还弄个inet_sock结构?

struct socket 

socket_state state; // 该state用来表明该socket的当前状态 

typedef enum { 

SS_FREE = 0,  

SS_UNCONNECTED,  

SS_CONNECTING,  

SS_CONNECTED,  

SS_DISCONNECTING  

} socket_state; 

unsigned long flags; //该成员可能的值如下,该标志用来设置socket是否正在忙碌 

#define SOCK_ASYNC_NOSPACE 0 

#define SOCK_ASYNC_WAITDATA 1 

#define SOCK_NOSPACE 2 

struct proto_ops *ops; //依据协议邦定到该socket上的特定的协议族的操作函数指针

,例如IPv4 TCP就是inet_stream_ops 

struct inode *inode; //表明该socket所属的inode 

struct fasync_struct *fasync_list; //异步唤醒队列 

struct file *file; //file回指指针 

struct sock *sk; //sock指针 

wait_queue_head_t wait; //sock的等待队列,在TCP需要等待时就sleep在这个队列上 

short type; //表示该socket在特定协议族下的类型例如SOCK_STREAM, 

unsigned char passcred; //在TCP分析中无须考虑 

}; 

struct sock { 

__u32 daddr; // dip,Foreign IPv4 addr 

__u32 rcv_saddr; // 记录套接字所绑定的地址 Bound local IPv4 addr 

__u16 dport; // dport 

unsigned short num;  

int bound_dev_if; // Bound device index if != 0

struct sock *next; 

struct sock **pprev; 

struct sock *bind_next; 

struct sock **bind_pprev; 

struct sock *prev; 

volatile unsigned char state, zapped; // Connection state,zapped在TCP分析中无须考虑 

__u16 sport; // 源端口,见num 

unsigned short family; // 协议族,例如PF_INET 

unsigned char reuse; // 地址是否可重用,只有RAW才使用 

unsigned char shutdown; // 判断该socket连接在某方向或者双向方向上都已经关闭 

#define SHUTDOWN_MASK 3 

#define RCV_SHUTDOWN 1 

#define SEND_SHUTDOWN 2 

atomic_t refcnt; // 引用计数 

socket_lock_t lock; // 锁标志, 每个socket都有一个自旋锁,该锁在用户上下文和软中断

处理时提供了同步机制 

typedef struct { 

spinlock_t slock; 

unsigned int users; 

wait_queue_head_t wq; 

} socket_lock_t; 

wait_queue_head_t *sleep; // Sock所属线程的自身休眠等待队列 

struct dst_entry *dst_cache; // 目的地的路由缓存 

rwlock_t dst_lock; // 为该socket赋dst_entry值时的锁 

int rcvbuf; // 接受缓冲区的大小(按字节) 

int sndbuf; // 发送缓冲区的大小(按字节) 

atomic_t rmem_alloc; // 接受队列中存放的数据的字节数 

atomic_t wmem_alloc; // 发送队列中存放的数据的字节数 

int wmem_queued; // 所有已经发送的数据的总字节数

int forward_alloc; // 预分配剩余字节数 

struct sk_buff_head receive_queue; // 接受队列 

struct sk_buff_head write_queue; // 发送队列

atomic_t omem_alloc; // 在TCP分析中无须考虑 * "o" is "option" or "other" */ 

__u32 saddr;  

unsigned int allocation; // 分配该sock之skb时选择的模式,GFP_ATOMIC还是

GFP_KERNEL等等 

volatile char dead, // tcp_close.tcp_listen_stop.inet_sock_release调用sock_orphan将

该值置1,表示该socket已经和进程分开,变成孤儿 

done, // 用于判断该socket是否已经收到 fin,如果收到则将该成员置1 

urginline, // 如果该值被设置为1,表示将紧急数据放于普通数据流中一起处理,而不在另

外处理 

keepopen, // 是否启动保活定时器 

linger, // lingertime一起,指明了close()后保留的时间 

destroy, // 在TCP分析中无须考虑 

no_check, // 是否对发出的skb做校验和,仅对UDP有效 

broadcast, // 是否允许广播,仅对UPD有效 

bsdism; // 在TCP分析中无须考虑 

unsigned char debug; // 在TCP分析中无须考虑 

unsigned char rcvtstamp; // 是否将收到skb的时间戳发送给app 

unsigned char use_write_queue; // 在init中该值被初始化为1,该值一直没有变化 

unsigned char userlocks; // 包括如下几种值的组合,从而改变收包等操作的执行顺序 

#define SOCK_SNDBUF_LOCK 1 

#define SOCK_RCVBUF_LOCK 2 

#define SOCK_BINDADDR_LOCK 4 

#define SOCK_BINDPORT_LOCK 8 

int route_caps; // 指示本sock用到的路由的信息 

int proc; // 保存用户线程的pid 

unsigned long lingertime; // lingertime一起,指明了close()后保留的时间 

int hashent; // 存放4元的hash值 

struct sock *pair; // 在TCP分析中无须考虑 

struct {

struct sk_buff *head; 

struct sk_buff *tail; 

} backlog; 

rwlock_t callback_lock; // sock相关函数内部操作的保护锁 

struct sk_buff_head error_queue; // 错误报文的队列,很少使用 

struct proto *prot; // 例如指向tcp_prot 

union { // 私有TCP相关数据保存 

struct tcp_opt af_tcp; 

............. 

} tp_pinfo; 

int err, // 保存各种错误,例如ECONNRESET Connection reset by peer,从而会影响到后续

流程的处理 

err_soft; // 保存各种软错误,例如EPROTO Protocol error,从而会影响到后续流程的处

理 

unsigned short ack_backlog; // 当前已经accept的数目 

unsigned short max_ack_backlog; // 当前listen sock能保留多少个待处理TCP连接. 

__u32 priority;  

unsigned short type; // 例如SOCK_STREAM,SOCK_DGRAM或者SOCK_RAW等 

unsigned char localroute; // Route locally only if set – set by SO_DONTROUTE 

option. 

unsigned char protocol; // socket(int family, int type, int protocol)中的

protocol 

struct ucred peercred; // 在TCP分析中无须考虑 

int rcvlowat;  

long rcvtimeo; // 接收时的超时设定, 并在超时时报错 

long sndtimeo; // 发送时的超时设定, 并在超时时报错 

union { // 私有inet相关数据保存 

struct inet_opt af_inet; 

................. 

} protinfo; 

struct timer_list timer;

struct timeval stamp; 

struct socket *socket; // 对应的socket 

void *user_data; // 私有数据,在TCP分析中无须考虑 

void (*state_change)(struct sock *sk); 

void (*data_ready)(struct sock *sk,int bytes); 

void (*write_space)(struct sock *sk); 

void (*error_report)(struct sock *sk); 

int (*backlog_rcv) (struct sock *sk, struct sk_buff *skb); 

void (*destruct)(struct sock *sk); 

}; 

struct inet_opt 

int ttl; // IP的TTL设置 

int tos; // IP的TOS设置 

unsigned cmsg_flags; // 该标志用来决定是否向应用层打印相关信息,包括如下可能

的值 

#define IP_CMSG_PKTINFO 1 

#define IP_CMSG_TTL 2 

#define IP_CMSG_TOS 4 

#define IP_CMSG_RECVOPTS 8 

#define IP_CMSG_RETOPTS 16 

struct ip_options *opt; // IP选项,包括安全和处理限制、记录路径、时间戳、宽松的

源站选路、严格的源站选路 

unsigned char hdrincl; // 用于RAW 

__u8 mc_ttl; // 多播TTL 

__u8 mc_loop; // 多播回环 

unsigned recverr : 1, // 是否允许传递扩展的可靠的错误信息. 

freebind : 1; // 是否允许socket被绑定 

__u16 id; // 用于禁止分片的IP包的ID计数 

__u8 pmtudisc; // 路径MTU发现 

int mc_index; // 多播设备索引 

__u32 mc_addr; // 自己的多播地址 

struct ip_mc_socklist *mc_list; // 多播组 

}; 

struct tcp_opt { 

int tcp_header_len; // tcp首部长度(包括选项) 

__u32 pred_flags;  

__u32 rcv_nxt; // 期望接受到的下一个tcp包的seq 

__u32 snd_nxt; // 要发送的下一个tcp包的seq 

__u32 snd_una; // 表示最近一个尚未确认的但是已经发送过的报文的seq 

__u32 snd_sml; // 最近发送的小包的最后一个字节数,主要用于Nagle算法 

__u32 rcv_tstamp; // 最近收到的ACK的时间,用于保活 

__u32 lsndtime; // 最近发送的数据包的时间,用于窗口restart 

struct { 

__u8 pending;  

enum tcp_ack_state_t 

TCP_ACK_SCHED = 1, 

TCP_ACK_TIMER = 2, 

TCP_ACK_PUSHED= 4 

}; 

__u8 quick;  

__u8 pingpong;  

__u8 blocked; ] 

__u32 ato;  

unsigned long timeout;  

__u32 lrcvtime;  

__u16 last_seg_size;  

__u16 rcv_mss;  

} ack; 

__u16 mss_cache; // 当前提供的有效mss,  

__u16 mss_clamp; // 最大mss,连接建立时协商的mss或者用户通过ioctl指定的mss的两者

之中最大值 

__u16 advmss;  

struct { 

struct sk_buff_head prequeue; // 当前预备队列 

struct task_struct *task; // 当前线程 

struct iovec *iov; // 用户空间接受数据的地址 

int memory; // 当前预备队列中的包总字节数目 

int len; // 用户进程从预备队列中读取的数据字节数 

} ucopy; 

__u32 snd_wl1; // 收到对方返回的skb,记下该包的seq号,用于判断窗口是否需要更新 

__u32 snd_wnd; // 记录对方提供的窗口大小  

__u32 max_window; // 对方曾经提供的最大窗口  

__u32 pmtu_cookie; // 将发送mss和当前的pmtu/exthdr设置同步  

__u16 ext_header_len; // 网络层协议选项长度  

__u8 ca_state; // 快速重传状态机  

enum tcp_ca_state 

TCP_CA_Open = 0, 

TCP_CA_Disorder = 1, 

TCP_CA_CWR = 2, 

TCP_CA_Recovery = 3, 

TCP_CA_Loss = 4 

}; 

__u8 retransmits; // 某个还没有被确认的发送TCP包重传的次数  

__u8 reordering;  

__u8 queue_shrunk;  

__u8 defer_accept; // 请参考附录1  

__u8 backoff;  

__u32 srtt;  

__u32 mdev;  

__u32 mdev_max;  

__u32 rttvar;  

__u32 rtt_seq;  

__u32 rto;  

__u32 packets_out;  

__u32 left_out;  

__u32 retrans_out;  

// 慢启动和拥塞控制 Slow start and congestion control (see also Nagle, and Karn & 

Partridge) 

__u32 snd_ssthresh; // 拥塞控制时的慢启动门限  

__u32 snd_cwnd; // 当前采用的拥塞窗口  

__u16 snd_cwnd_cnt; // 线形增加的拥塞窗口计数器  

__u16 snd_cwnd_clamp; // 拥塞窗口的最大值(一般为对方通告的窗口大小)  

__u32 snd_cwnd_used; // 慢启动,每发出去一个包,snd_cwnd_used++ 

__u32 snd_cwnd_stamp; // 该参数可以保证在重传模式下不会改变拥塞窗口的大小 */ 

unsigned long timeout; // 用于重传 

struct timer_list retransmit_timer;  

struct timer_list delack_timer;  

struct sk_buff_head out_of_order_queue; // 乱序的TCP报都存放在该队列中  

struct tcp_func *af_specific; // ipv4/ipv6 相关特定处理函数  

struct tcp_func ipv4_specific = { 

ip_queue_xmit, 

tcp_v4_send_check, 

tcp_v4_rebuild_header, 

tcp_v4_conn_request, 

tcp_v4_syn_recv_sock, 

tcp_v4_remember_stamp, 

sizeof(struct iphdr), 

ip_setsockopt, 

ip_getsockopt, 

v4_addr2sockaddr, 

sizeof(struct sockaddr_in) 

};

struct sk_buff *send_head; // 最先要发送的TCP报文  

struct page *sndmsg_page; // sendmsg所使用的缓冲内存页面  

u32 sndmsg_off; // sendmsg所使用的缓冲偏移  

__u32 rcv_wnd; // 当前接受窗口  

__u32 rcv_wup; // 对方窗口最后一次更新时的rcv_nxt  

__u32 write_seq; // tcp发送总数据字节量+1  

__u32 pushed_seq; // 上次发送带PSH标志的TCP包的seq  

__u32 copied_seq; // 尚未读取的数据第一个字节位置  

// Options received (usually on last packet, some only on SYN packets). 

char tstamp_ok,  

wscale_ok,  

sack_ok;  

char saw_tstamp;  

__u8 snd_wscale;  

__u8 rcv_wscale;  

__u8 nonagle;  

__u8 keepalive_probes;  

__u32 rcv_tsval;  

__u32 rcv_tsecr;  

__u32 ts_recent;  

long ts_recent_stamp;  

__u16 user_mss;  

__u8 dsack;  

__u8 eff_sacks;  

struct tcp_sack_block duplicate_sack[1];  

struct tcp_sack_block selective_acks[4];  

__u32 window_clamp;  

__u32 rcv_ssthresh;  

__u8 probes_out;  

__u8 num_sacks;  

__u8 syn_retries;  

__u8 ecn_flags;  

__u16 prior_ssthresh;  

__u32 lost_out;  

__u32 sacked_out;  

__u32 fackets_out;  

__u32 high_seq;  

__u32 retrans_stamp; // 上次重传的时间,其也会记住第一个syn的时间戳 

__u32 undo_marker;  

int undo_retrans;  

__u32 urg_seq;  

__u16 urg_data;  

__u8 pending;  

#define TCP_TIME_RETRANS 1  

#define TCP_TIME_DACK 2  

#define TCP_TIME_PROBE0 3  

#define TCP_TIME_KEEPOPEN 4  

__u8 urg_mode;  

__u32 snd_up;  

rwlock_t syn_wait_lock; 

struct tcp_listen_opt *listen_opt; 

struct open_request *accept_queue; 

struct open_request *accept_queue_tail; 

int write_pending;  

unsigned int keepalive_time;  

unsigned int keepalive_intvl;  

int linger2; // lingertime一起,指明了close()后保留的时间 

int frto_counter;  

__u32 frto_highmark;  

unsigned long last_synq_overflow; // 用于syn_cookie处理 

}; 

继续阅读