linux网络协议栈分析——net_families、inetsw、inetsw_array、inet_protos

来源:互联网 发布:家庭数据存储方案 编辑:程序博客网 时间:2024/05/16 12:46

net_families:保存所有不同类型的协议族的全局链表,net_family_lock用来保护该链表不被并发操作。

创建套接字时使用协议族参数作为偏移量,从net_families数组中获得协议族指针,进而调用该协议族的创建函数。

/*
 * The protocol list. Each protocol is registered in here.
 */

static DEFINE_SPINLOCK(net_family_lock);

static const struct net_proto_family *net_families[NPROTO] __read_mostly;

 

inet_init(void)——sock_register使用inet_family_ops初始化:

/*
  * Tell SOCKET that we are alive...
  */

 (void)sock_register(&inet_family_ops);

/**
 * sock_register - add a socket protocol handler
 * @ops: description of protocol
 *
 * This function is called by a protocol handler that wants to
 * advertise its address family, and have it linked into the
 * socket interface. The value ops->family coresponds to the
 * socket system call protocol family.
 */
int sock_register(const struct net_proto_family *ops)
{
 int err;

 if (ops->family >= NPROTO) {
  printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
         NPROTO);
  return -ENOBUFS;
 }

 spin_lock(&net_family_lock);
 if (net_families[ops->family])
  err = -EEXIST;
 else {
  net_families[ops->family] = ops;
  err = 0;
 }
 spin_unlock(&net_family_lock);

 printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
 return err;
}

再看全局变量:

static struct net_proto_family inet_family_ops = {
 .family = PF_INET,
 .create = inet_create,
 .owner = THIS_MODULE,
};

 

 inetsw_array是持久的初始化在内核代码中的传输层协议数组。

/* Upon startup we insert all the elements in inetsw_array[] into
 * the linked list inetsw.
 */
static struct inet_protosw inetsw_array[] =
{
 {
  .type =       SOCK_STREAM,
  .protocol =   IPPROTO_TCP,
  .prot =       &tcp_prot,
  .ops =        &inet_stream_ops,
  .capability = -1,
  .no_check =   0,
  .flags =      INET_PROTOSW_PERMANENT |
         INET_PROTOSW_ICSK,
 },

 {
  .type =       SOCK_DGRAM,
  .protocol =   IPPROTO_UDP,
  .prot =       &udp_prot,
  .ops =        &inet_dgram_ops,
  .capability = -1,
  .no_check =   UDP_CSUM_DEFAULT,
  .flags =      INET_PROTOSW_PERMANENT,
       },


       {
        .type =       SOCK_RAW,
        .protocol =   IPPROTO_IP, /* wild card */
        .prot =       &raw_prot,
        .ops =        &inet_sockraw_ops,
        .capability = CAP_NET_RAW,
        .no_check =   UDP_CSUM_DEFAULT,
        .flags =      INET_PROTOSW_REUSE,
       }
};

#define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array)

通过下面的代码把上面的全局数组初始化到inetsw

/* Register the socket-side information for inet_create. */
 for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
  INIT_LIST_HEAD(r);

 for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
  inet_register_protosw(q);

 

 

const struct net_protocol *inet_protos[MAX_INET_PROTOS] ____cacheline_aligned_in_smp;

static const struct net_protocol tcp_protocol = {
 .handler = tcp_v4_rcv,
 .err_handler = tcp_v4_err,
 .gso_send_check = tcp_v4_gso_send_check,
 .gso_segment = tcp_tso_segment,
 .gro_receive = tcp4_gro_receive,
 .gro_complete = tcp4_gro_complete,
 .no_policy = 1,
 .netns_ok = 1,
};

static const struct net_protocol udp_protocol = {
 .handler = udp_rcv,
 .err_handler = udp_err,
 .gso_send_check = udp4_ufo_send_check,
 .gso_segment = udp4_ufo_fragment,
 .no_policy = 1,
 .netns_ok = 1,
};

static const struct net_protocol icmp_protocol = {
 .handler = icmp_rcv,
 .no_policy = 1,
 .netns_ok = 1,
};

 

这个变量使用颇多,尚没有搞清楚。

在inet_create函数中使用一次:

 

 

/*
 * IP protocol layer initialiser
 */

static struct packet_type ip_packet_type __read_mostly = {
 .type = cpu_to_be16(ETH_P_IP),
 .func = ip_rcv,
 .gso_send_check = inet_gso_send_check,
 .gso_segment = inet_gso_segment,
 .gro_receive = inet_gro_receive,
 .gro_complete = inet_gro_complete,
};