zoukankan      html  css  js  c++  java
  • PF_PACKET在内核的流程

    PF_PACKET在内核的流程
     
    套接字创建
    packet_create() --> 赋值packet_ops
     
    接收流程
    packet_recvmsg()
    skb_recv_datagram()
    __skb_recv_datagram() --> 检测sk->sk_receive_queue
     
    自下而上
     
    netif_receive_skb()
    __netif_receive_skb()
    list_for_each_entry_rcu(ptype, &ptype_all, list) --> packet_create()时dev_add_pack()添加的("./net/packet/af_packet.c" )
    deliver_skb()
    pt_prev->func()
    packet_rcv()
    __skb_queue_tail()

    发送流程
    packet_sendmsg()
    packet_snd()
    dev_queue_xmit()
    ....

    附注:
    PF_PACKET接口可以操作链路层的数据。
    isock = socket(PF_PACKET, SOCK_DGRAM, 0); //为0,之后会用setsockopt之类的设置
    第二个参数,在使用SOCK_RAW, SOCK_DGRAM和SOCK_PACKET的区别:
    (1)使用SOCK_RAW发送的数据必须包含链路层的协议头,接受得到的数据包,包含链路层协议头。而使用SOCK_DGRAM则都不含链路层的协议头。
    (2)SOCK_PACKET也是可以使用的,但是已经废弃,以后不保证还能支持,不推荐使用。
    (3)在使用SOCK_RAW或SOCK_DGRAM和SOCK_PACKET时,在sendto和recvfrom中使用的地址类型不同,前两者使用sockaddr_ll类型的地址
    而后者使用sockaddr类型的地址。
    (4)如socket的第一个参数使用PF_INET,第二个参数使用SOCK_RAW,则可以得到原始的IP包。
     
     
    相关结构体
     1 struct net_proto_family {
     2         int             family;
     3         int             (*create)(struct net *net, struct socket *sock, int protocol);
     4         struct module   *owner;
     5 };
     6 "include/linux/net.h" 365 lines
     7  
     8  
     9 struct packet_sock {
    10         /* struct sock has to be the first member of packet_sock */
    11         struct sock             sk; 
    12         struct tpacket_stats    stats;
    13 #ifdef CONFIG_PACKET_MMAP
    14         struct packet_ring_buffer       rx_ring;
    15         struct packet_ring_buffer       tx_ring;
    16         int                     copy_thresh;
    17 #endif
    18         struct packet_type      prot_hook;
    19         spinlock_t              bind_lock;
    20         struct mutex            pg_vec_lock;
    21         unsigned int            running:1,      /* prot_hook is attached*/
    22                                 auxdata:1,
    23                                 origdev:1;
    24         int                     ifindex;        /* bound device         */
    25         __be16                  num;
    26         struct packet_mclist    *mclist;
    27 #ifdef CONFIG_PACKET_MMAP
    28         atomic_t                mapped;
    29         enum tpacket_versions   tp_version;
    30         unsigned int            tp_hdrlen;
    31         unsigned int            tp_reserve;
    32         unsigned int            tp_loss:1;
    33 #endif
    34 };
    35 "./net/packet/af_packet.c" 2504 lines
    36  
    37 struct socket {
    38         socket_state            state;
    39  
    40         kmemcheck_bitfield_begin(type);
    41         short                   type;
    42         kmemcheck_bitfield_end(type);
    43  
    44         unsigned long           flags;
    45         /* 
    46          * Please keep fasync_list & wait fields in the same cache line
    47          */
    48         struct fasync_struct    *fasync_list;
    49         wait_queue_head_t       wait;
    50  
    51         struct file             *file;
    52         struct sock             *sk;
    53         const struct proto_ops  *ops;
    54 };
    55 "./include/linux/net.h" 365 lines
  • 相关阅读:
    ionic入门之AngularJS扩展基本布局
    ionic入门之AngularJS扩展(一)
    test
    面试题小整理
    使用Code first 进行更新数据库结构(数据迁移)
    SQL模糊查询与删除多条语句复习
    GridView 根据要求显示指定值
    个人工作记录---工作中遇到的sql查询语句解析
    数据库,inner join,left join right join 的区别
    利用set实现去重
  • 原文地址:https://www.cnblogs.com/shudai/p/3240979.html
Copyright © 2011-2022 走看看