浅析ethx网卡发送函数sys_write简易流程

浅析ethx网卡发送函数sys_write简易流程


sys_write= > vfs_write= > do_sync_write= >
filp- > f_op- > aio_write( & kiocb, & iov, 1, kiocb. ki_pos) ;
{ 也就是对应socket_file_ops中的sock_aio_write}
sock_aio_write= > do_sock_write= > __sock_sendmsg= >
sock- > ops- > sendmsg ( iocb, sock, msg, size) ;
{ 也就是对应inetsw_array[ ] 中的inet_stream_ops下的tcp_sendmsg}
tcp_sendmsg= > 经过skb拷贝之后, 最终在退出之前调用tcp_push, 将数据发送到网络= >
tcp_push= > __tcp_push_pending_frames= > tcp_write_xmit= > tcp_transmit_skb= >
icsk- > icsk_af_ops- > queue_xmit( skb, 0) ;
/*
在tcp_v4_init_sock中初始化的如下方法:
icsk->icsk_af_ops = &ipv4_specific;
icsk->icsk_ca_ops = &tcp_init_congestion_ops;
tp->reordering = sysctl_tcp_reordering;
sk->sk_write_space = sk_stream_write_space;
icsk->icsk_sync_mss = tcp_sync_mss;
tp->af_specific = &tcp_sock_ipv4_specific;
所以icsk_af_ops就是ipv4_specific,
struct inet_connection_sock_af_ops ipv4_specific = {
    .queue_xmit     = ip_queue_xmit,
    .send_check     = tcp_v4_send_check,
    .rebuild_header     = inet_sk_rebuild_header,
    .conn_request     = tcp_v4_conn_request,
    .syn_recv_sock     = tcp_v4_syn_recv_sock,
    .remember_stamp     = tcp_v4_remember_stamp,
    .net_header_len     = sizeof(struct iphdr),
    .setsockopt     = ip_setsockopt,
    .getsockopt     = ip_getsockopt,
    .addr2sockaddr     = inet_csk_addr2sockaddr,
    .sockaddr_len     = sizeof(struct sockaddr_in),
#ifdef CONFIG_COMPAT
    .compat_setsockopt = compat_ip_setsockopt,
    .compat_getsockopt = compat_ip_getsockopt,
#endif
};
*/

ip_queue_xmit= >
return NF_HOOK( PF_INET , NF_IP_LOCAL_OUT, skb, NULL , rt- > u. dst. dev,
            dst_output) ;
也就是调用dst_output将package发送到网络中出去.
/* Output packet to network from transport. */
static inline int dst_output( struct sk_buff * skb)
{
    return skb- > dst- > output( skb) ;
}
__mkroute_output= > dst_alloc= >
rth = dst_alloc( & ipv4_dst_ops) ; 然后dst- > ops = ipv4_dst_ops;
rth- > u. dst. output= ip_output;
ip_output= >
return NF_HOOK_COND( PF_INET , NF_IP_POST_ROUTING, skb, NULL , dev,
             ip_finish_output,
             ! ( IPCB( skb) - > flags & IPSKB_REROUTED) ) ;
ip_finish_output= > ip_finish_output2= >
/*
    if (dst->hh)
        return neigh_hh_output(dst->hh, skb);
    else if (dst->neighbour)
        return dst->neighbour->output(skb);
*/


/*
static struct neigh_ops arp_generic_ops = {
    .family =        AF_INET,
    .solicit =        arp_solicit,
    .error_report =        arp_error_report,
    .output =        neigh_resolve_output,
    .connected_output =    neigh_connected_output,
    .hh_output =        dev_queue_xmit,
    .queue_xmit =        dev_queue_xmit,
};

static struct neigh_ops arp_hh_ops = {
    .family =        AF_INET,
    .solicit =        arp_solicit,
    .error_report =        arp_error_report,
    .output =        neigh_resolve_output,
    .connected_output =    neigh_resolve_output,
    .hh_output =        dev_queue_xmit,
    .queue_xmit =        dev_queue_xmit,
};

static struct neigh_ops arp_direct_ops = {
    .family =        AF_INET,
    .output =        dev_queue_xmit,
    .connected_output =    dev_queue_xmit,
    .hh_output =        dev_queue_xmit,
    .queue_xmit =        dev_queue_xmit,
};

struct neigh_ops arp_broken_ops = {
    .family =        AF_INET,
    .solicit =        arp_solicit,
    .error_report =        arp_error_report,
    .output =        neigh_compat_output,
    .connected_output =    neigh_compat_output,
    .hh_output =        dev_queue_xmit,
    .queue_xmit =        dev_queue_xmit,
};
*/

因为ip通信都是以arp开始来获取通信对端的mac地址, 所以arp应该是网络通信的第一步,
这样就调用到了dev_queue_xmit( ) 想物理网卡发送网络数据包,
dev_queue_xmit= > dev_hard_start_xmit= >
return dev- > hard_start_xmit( skb, dev) ;
就是网卡驱动的发送函数wlan_hard_start_xmit, 比较粗糙, 凑活着看吧【gliethttp. Leith】


看看sys_socket( ) 对空间结构的申请步骤:
sk- > sk_prot = tcp_prot;
他的. obj_size = sizeof ( struct tcp_sock) , 所以
struct tcp_sock {
    /* inet_connection_sock has to be the first member of tcp_sock */
    struct inet_connection_sock    inet_conn;
    . . .
}
struct inet_connection_sock {
    /* inet_sock has to be the first member! */
    struct inet_sock     icsk_inet;
    . . .
}
struct inet_sock {
    /* sk and pinet6 has to be the first two members of inet_sock */
    struct sock        sk;
    . . .
}
所以sk_alloc申请到的sk, 指向的是tcp_sock下inet_connection_sock下inet_sock中的sk,
然后
__sock_create= >
pf- > create( net, sock, protocol) ;
inet_create= >
sk- > sk_prot- > init( sk) 也就是调用tcp_prot的init, 也就是tcp_v4_init_sock【gliethttp. Leith】.

你可能感兴趣的:(浅析ethx网卡发送函数sys_write简易流程)