Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1206696
  • 博文数量: 56
  • 博客积分: 400
  • 博客等级: 一等列兵
  • 技术积分: 2800
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-30 13:08
个人简介

一个人的差异在于业余时间

文章分类

全部博文(56)

文章存档

2023年(1)

2019年(1)

2018年(1)

2017年(1)

2016年(2)

2015年(20)

2014年(10)

2013年(7)

2012年(12)

2011年(1)

分类: LINUX

2014-04-30 17:25:15

   在做驱动的时候,写网卡驱动,最多会用到register_netdev , alloc_netdev这些常用的接口,然后就是结构体的初始化.至于注册进入内核后,是一个怎么样的流程,一直是一个觉的明白,说起来很模糊的状态.当然我也是一直参考《深入理解Linux网络内幕》作为学习的引导.参考内核2.6.32.60 .
   首先我们看看alloc_netdev :include/linux/netdevice.h 
  #define alloc_netdev(sizeof_priv, name, setup) \
alloc_netdev_mq(sizeof_priv, name, setup, 1)
  

点击(此处)折叠或打开

  1. /**
  2.  *    alloc_netdev_mq - allocate network device
  3.  *    @sizeof_priv:    size of private data to allocate space for
  4.  *    @name:        device name format string
  5.  *    @setup:        callback to initialize device
  6.  *    @queue_count:    the number of subqueues to allocate
  7.  *
  8.  *    Allocates a struct net_device with private data area for driver use
  9.  *    and performs basic initialization. Also allocates subquue structs
  10.  *    for each queue on the device at the end of the netdevice.
  11.  */
  12.   alloc_netdev
  13. struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
  14.         void (*setup)(struct net_device *), unsigned int queue_count)
  15. {
  16.     struct netdev_queue *tx;
  17.     struct net_device *dev;
  18.     size_t alloc_size;
  19.     struct net_device *p;

  20.     BUG_ON(strlen(name) >= sizeof(dev->name));

  21.     alloc_size = sizeof(struct net_device);
  22.     if (sizeof_priv) {
  23.         /* ensure 32-byte alignment of private area */
  24.         alloc_size = ALIGN(alloc_size, NETDEV_ALIGN);
  25.         alloc_size += sizeof_priv;
  26.     }
  27.     /* ensure 32-byte alignment of whole construct */
  28.     alloc_size += NETDEV_ALIGN - 1;

  29.     p = kzalloc(alloc_size, GFP_KERNEL);
  30.     if (!p) {
  31.         printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n");
  32.         return NULL;
  33.     }

  34.     tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);
  35.     if (!tx) {
  36.         printk(KERN_ERR "alloc_netdev: Unable to allocate "
  37.          "tx qdiscs.\n");
  38.         goto free_p;
  39.     }

  40.     dev = PTR_ALIGN(p, NETDEV_ALIGN);
  41.     dev->padded = (char *)dev - (char *)p;

  42.     if (dev_addr_init(dev))
  43.         goto free_tx;

  44.     dev_unicast_init(dev);

  45.     dev_net_set(dev, &init_net);

  46.     dev->_tx = tx;
  47.     dev->num_tx_queues = queue_count;
  48.     dev->real_num_tx_queues = queue_count;

  49.     dev->gso_max_size = GSO_MAX_SIZE;

  50.     netdev_init_queues(dev);

  51.     INIT_LIST_HEAD(&dev->napi_list);
  52.     dev->priv_flags = IFF_XMIT_DST_RELEASE;
  53.     setup(dev);
  54.     strcpy(dev->name, name);
  55.     return dev;

  56. free_tx:
  57.     kfree(tx);

  58. free_p:
  59.     kfree(p);
  60.     return NULL;
  61. }
我们看到这个函数主要申请dev结构,初始化addr,dev->_tx 以及queues(netdev_init_queues(dev);

)。 并初始化dev->napi_list. 还有setup ,以太网默认是ether_setup.
这里我们关心一下

点击(此处)折叠或打开

  1. static void netdev_init_queues(struct net_device *dev)
  2. {
  3.     netdev_init_one_queue(dev, &dev->rx_queue, NULL);
  4.     netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
  5.     spin_lock_init(&dev->tx_global_lock);
  6. }
其实就是把收发队列里的dev指向当前设备.
当然还有很多变体api

这里我们也应该关注一下struct net_device这个结构体

点击(此处)折叠或打开

  1. /*
  2.  *    The DEVICE structure.
  3.  *    Actually, this whole structure is a big mistake. It mixes I/O
  4.  *    data with strictly "high-level" data, and it has to know about
  5.  *    almost every data structure used in the INET module.
  6.  *
  7.  *    FIXME: cleanup struct net_device such that network protocol info
  8.  *    moves out.
  9.  */

  10. struct net_device
  11. {

  12.     /*
  13.      * This is the first field of the "visible" part of this structure
  14.      * (i.e. as seen by users in the "Space.c" file). It is the name
  15.      * the interface.
  16.      */
  17.     char            name[IFNAMSIZ];
  18.     /* device name hash chain */
  19.     struct hlist_node    name_hlist;
  20.     /* snmp alias */
  21.     char             *ifalias;

  22.     /*
  23.      *    I/O specific fields
  24.      *    FIXME: Merge these and struct ifmap into one
  25.      */
  26.     unsigned long        mem_end;    /* shared mem end    */
  27.     unsigned long        mem_start;    /* shared mem start    */
  28.     unsigned long        base_addr;    /* device I/O address    */
  29.     unsigned int        irq;        /* device IRQ number    */

  30.     /*
  31.      *    Some hardware also needs these fields, but they are not
  32.      *    part of the usual set specified in Space.c.
  33.      */

  34.     unsigned char        if_port;    /* Selectable AUI, TP,..*/
  35.     unsigned char        dma;        /* DMA channel        */

  36.     unsigned long        state;

  37.     struct list_head    dev_list;
  38.     struct list_head    napi_list;

  39.     /* Net device features */
  40.     unsigned long        features;
  41. #define NETIF_F_SG        1    /* Scatter/gather IO. */
  42. #define NETIF_F_IP_CSUM        2    /* Can checksum TCP/UDP over IPv4. */
  43. #define NETIF_F_NO_CSUM        4    /* Does not require checksum. F.e. loopack. */
  44. #define NETIF_F_HW_CSUM        8    /* Can checksum all the packets. */
  45. #define NETIF_F_IPV6_CSUM    16    /* Can checksum TCP/UDP over IPV6 */
  46. #define NETIF_F_HIGHDMA        32    /* Can DMA to high memory. */
  47. #define NETIF_F_FRAGLIST    64    /* Scatter/gather IO. */
  48. #define NETIF_F_HW_VLAN_TX    128    /* Transmit VLAN hw acceleration */
  49. #define NETIF_F_HW_VLAN_RX    256    /* Receive VLAN hw acceleration */
  50. #define NETIF_F_HW_VLAN_FILTER    512    /* Receive filtering on VLAN */
  51. #define NETIF_F_VLAN_CHALLENGED    1024    /* Device cannot handle VLAN packets */
  52. #define NETIF_F_GSO        2048    /* Enable software GSO. */
  53. #define NETIF_F_LLTX        4096    /* LockLess TX - deprecated. Please */
  54.                     /* do not use LLTX in new drivers */
  55. #define NETIF_F_NETNS_LOCAL    8192    /* Does not change network namespaces */
  56. #define NETIF_F_GRO        16384    /* Generic receive offload */
  57. #define NETIF_F_LRO        32768    /* large receive offload */

  58. /* the GSO_MASK reserves bits 16 through 23 */
  59. #define NETIF_F_FCOE_CRC    (1 << 24) /* FCoE CRC32 */
  60. #define NETIF_F_SCTP_CSUM    (1 << 25) /* SCTP checksum offload */
  61. #define NETIF_F_FCOE_MTU    (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/

  62.     /* Segmentation offload features */
  63. #define NETIF_F_GSO_SHIFT    16
  64. #define NETIF_F_GSO_MASK    0x00ff0000
  65. #define NETIF_F_TSO        (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
  66. #define NETIF_F_UFO        (SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
  67. #define NETIF_F_GSO_ROBUST    (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
  68. #define NETIF_F_TSO_ECN        (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
  69. #define NETIF_F_TSO6        (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
  70. #define NETIF_F_FSO        (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)

  71.     /* List of features with software fallbacks. */
  72. #define NETIF_F_GSO_SOFTWARE    (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)


  73. #define NETIF_F_GEN_CSUM    (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
  74. #define NETIF_F_V4_CSUM        (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
  75. #define NETIF_F_V6_CSUM        (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
  76. #define NETIF_F_ALL_CSUM    (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)

  77.     /*
  78.      * If one device supports one of these features, then enable them
  79.      * for all in netdev_increment_features.
  80.      */
  81. #define NETIF_F_ONE_FOR_ALL    (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
  82.                  NETIF_F_SG | NETIF_F_HIGHDMA |        \
  83.                  NETIF_F_FRAGLIST)

  84.     /* Interface index. Unique device identifier    */
  85.     int            ifindex;
  86.     int            iflink;

  87.     struct net_device_stats    stats;

  88. #ifdef CONFIG_WIRELESS_EXT
  89.     /* List of functions to handle Wireless Extensions (instead of ioctl).
  90.      * See <net/iw_handler.h> for details. Jean II */
  91.     const struct iw_handler_def *    wireless_handlers;
  92.     /* Instance data managed by the core of Wireless Extensions. */
  93.     struct iw_public_data *    wireless_data;
  94. #endif
  95.     /* Management operations */
  96.     const struct net_device_ops *netdev_ops;
  97.     const struct ethtool_ops *ethtool_ops;

  98.     /* Hardware header description */
  99.     const struct header_ops *header_ops;

  100.     unsigned int        flags;    /* interface flags (a la BSD)    */
  101.     unsigned short        gflags;
  102.         unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */
  103.     unsigned short        padded;    /* How much padding added by alloc_netdev() */

  104.     unsigned char        operstate; /* RFC2863 operstate */
  105.     unsigned char        link_mode; /* mapping policy to operstate */

  106.     unsigned        mtu;    /* interface MTU value        */
  107.     unsigned short        type;    /* interface hardware type    */
  108.     unsigned short        hard_header_len;    /* hardware hdr length    */

  109.     /* extra head- and tailroom the hardware may need, but not in all cases
  110.      * can this be guaranteed, especially tailroom. Some cases also use
  111.      * LL_MAX_HEADER instead to allocate the skb.
  112.      */
  113.     unsigned short        needed_headroom;
  114.     unsigned short        needed_tailroom;

  115.     struct net_device    *master; /* Pointer to master device of a group,
  116.                      * which this device is member of.
  117.                      */

  118.     /* Interface address info. */
  119.     unsigned char        perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
  120.     unsigned char        addr_len;    /* hardware address length    */
  121.     unsigned short dev_id;        /* for shared network cards */

  122.     struct netdev_hw_addr_list    uc;    /* Secondary unicast
  123.                          mac addresses */
  124.     int            uc_promisc;
  125.     spinlock_t        addr_list_lock;
  126.     struct dev_addr_list    *mc_list;    /* Multicast mac addresses    */
  127.     int            mc_count;    /* Number of installed mcasts    */
  128.     unsigned int        promiscuity;
  129.     unsigned int        allmulti;


  130.     /* Protocol specific pointers */
  131.     
  132. #ifdef CONFIG_NET_DSA
  133.     void            *dsa_ptr;    /* dsa specific data */
  134. #endif
  135.     void             *atalk_ptr;    /* AppleTalk link     */
  136.     void            *ip_ptr;    /* IPv4 specific data    */
  137.     void *dn_ptr; /* DECnet specific data */
  138.     void *ip6_ptr; /* IPv6 specific data */
  139.     void            *ec_ptr;    /* Econet specific data    */
  140.     void            *ax25_ptr;    /* AX.25 specific data */
  141.     struct wireless_dev    *ieee80211_ptr;    /* IEEE 802.11 specific data,
  142.                          assign before registering */

  143. /*
  144.  * Cache line mostly used on receive path (including eth_type_trans())
  145.  */
  146.     unsigned long        last_rx;    /* Time of last Rx    */
  147.     /* Interface address info used in eth_type_trans() */
  148.     unsigned char        *dev_addr;    /* hw address, (before bcast
  149.                          because most packets are
  150.                          unicast) */

  151.     struct netdev_hw_addr_list    dev_addrs; /* list of device
  152.                          hw addresses */

  153.     unsigned char        broadcast[MAX_ADDR_LEN];    /* hw bcast add    */

  154.     struct netdev_queue    rx_queue;

  155.     struct netdev_queue    *_tx ____cacheline_aligned_in_smp;

  156.     /* Number of TX queues allocated at alloc_netdev_mq() time */
  157.     unsigned int        num_tx_queues;

  158.     /* Number of TX queues currently active in device */
  159.     unsigned int        real_num_tx_queues;

  160.     /* root qdisc from userspace point of view */
  161.     struct Qdisc        *qdisc;

  162.     unsigned long        tx_queue_len;    /* Max frames per queue allowed */
  163.     spinlock_t        tx_global_lock;
  164. /*
  165.  * One part is mostly used on xmit path (device)
  166.  */
  167.     /* These may be needed for future network-power-down code. */

  168.     /*
  169.      * trans_start here is expensive for high speed devices on SMP,
  170.      * please use netdev_queue->trans_start instead.
  171.      */
  172.     unsigned long        trans_start;    /* Time (in jiffies) of last Tx    */

  173.     int            watchdog_timeo; /* used by dev_watchdog() */
  174.     struct timer_list    watchdog_timer;

  175.     /* Number of references to this device */
  176.     atomic_t        refcnt ____cacheline_aligned_in_smp;

  177.     /* delayed register/unregister */
  178.     struct list_head    todo_list;
  179.     /* device index hash chain */
  180.     struct hlist_node    index_hlist;

  181.     struct net_device    *link_watch_next;

  182.     /* register/unregister state machine */
  183.     enum { NETREG_UNINITIALIZED=0,
  184.      NETREG_REGISTERED,    /* completed register_netdevice */
  185.      NETREG_UNREGISTERING,    /* called unregister_netdevice */
  186.      NETREG_UNREGISTERED,    /* completed unregister todo */
  187.      NETREG_RELEASED,        /* called free_netdev */
  188.      NETREG_DUMMY,        /* dummy device for NAPI poll */
  189.     } reg_state;

  190.     /* Called from unregister, can be used to call free_netdev */
  191.     void (*destructor)(struct net_device *dev);

  192. #ifdef CONFIG_NETPOLL
  193.     struct netpoll_info    *npinfo;
  194. #endif

  195. #ifdef CONFIG_NET_NS
  196.     /* Network namespace this network device is inside */
  197.     struct net        *nd_net;
  198. #endif

  199.     /* mid-layer private */
  200.     void            *ml_priv;

  201.     /* bridge stuff */
  202.     struct net_bridge_port    *br_port;
  203.     /* macvlan */
  204.     struct macvlan_port    *macvlan_port;
  205.     /* GARP */
  206.     struct garp_port    *garp_port;

  207.     /* class/net/name entry */
  208.     struct device        dev;
  209.     /* space for optional statistics and wireless sysfs groups */
  210.     const struct attribute_group *sysfs_groups[3];

  211.     /* rtnetlink link ops */
  212.     const struct rtnl_link_ops *rtnl_link_ops;

  213.     /* VLAN feature mask */
  214.     unsigned long vlan_features;

  215.     /* for setting kernel sock attribute on TCP connection setup */
  216. #define GSO_MAX_SIZE        65536
  217.     unsigned int        gso_max_size;

  218. #ifdef CONFIG_DCB
  219.     /* Data Center Bridging netlink ops */
  220.     struct dcbnl_rtnl_ops *dcbnl_ops;
  221. #endif

  222. #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
  223.     /* max exchange id for FCoE LRO by ddp */
  224.     unsigned int        fcoe_ddp_xid;
  225. #endif
  226. }
对于里面结构体的说明,请看《深入理解linux网络内幕》第二章,关键数据结构.

对于驱动的初始化操作这里不在说明,可以参考drivers/net下.
我们注册的设备,实际上是添加到了dev_base链表,可以通过dev_get_by_name和dev_get_by_index查询.
对于设备的状态,包括它的状态机一直没弄明白,觉的很神秘,这里就来看看.
设备状态:

Net_device

Flags用于存储各种表示的位域。多数标示代表设备的能力。然而,其中之一的IFF_UP是用于指出该设备是开启或关闭,可以在include/linux/if.h中找到IFF_XX

这里实际例子就是dev_queue_xmit函数里

Reg_state  设备注册状态

在 界于netreg_uninitalizednetreg_registered之间。 由netdev_run_todo处理。

点击(此处)折叠或打开

  1. /* register/unregister state machine */
  2.     enum { NETREG_UNINITIALIZED=0,
  3.      NETREG_REGISTERED,    /* completed register_netdevice */
  4.      NETREG_UNREGISTERING,    /* called unregister_netdevice */
  5.      NETREG_UNREGISTERED,    /* completed unregister todo */
  6.      NETREG_RELEASED,        /* called free_netdev */
  7.      NETREG_DUMMY,        /* dummy device for NAPI poll */
  8.     } reg_state;



State和其队列规则有关的设备状态

点击(此处)折叠或打开

  1. /* These flag bits are private to the generic network queueing
  2.  * layer, they may not be explicitly referenced by any other
  3.  * code.
  4.  */

  5. enum netdev_state_t
  6. {
  7.     __LINK_STATE_START,    // 设备开启 由 netif_running检查
  8.     __LINK_STATE_PRESENT,   //设备存在  netif_device_present  挂起到恢复继续时 需要操作
  9.     __LINK_STATE_NOCARRIER,  // 没载波  netif_carrior_ok 检查
  10.     __LINK_STATE_LINKWATCH_PENDING
  11.     __LINK_STATE_DORMANT,
  12. };
实际操作:

点击(此处)折叠或打开

  1. /*
  2.      *    Default initial state at registry is that the
  3.      *    device is present.
  4.      */

  5.     set_bit(__LINK_STATE_PRESENT, &dev->state);

队列规则状态:(个人对这一块比较感兴趣,因为涉及qos等)

每个设备都会被分配一种队列规则,流量控制以此实现其qos机制。

队列规则即qos  是在register_netdevice中初始化的

由函数dev_init_scheduler(dev);来处理.

点击(此处)折叠或打开

  1. void dev_init_scheduler(struct net_device *dev)
  2. {
  3.     dev->qdisc = &noop_qdisc;
  4.     netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc);
  5.     dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);

  6.     setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev);
  7. }
它最后初始化了dev看门狗.
而关于noop_qdisc. 我们在看netif_recevice_skb时会看到

点击(此处)折叠或打开

  1. #ifdef CONFIG_NET_CLS_ACT
  2.     skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
  3.     if (!skb)
  4.         goto out;
  5. ncls:
  6. #endif

点击(此处)折叠或打开

  1. #ifdef CONFIG_NET_CLS_ACT
  2. /* TODO: Maybe we should just force sch_ingress to be compiled in
  3.  * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
  4.  * a compare and 2 stores extra right now if we dont have it on
  5.  * but have CONFIG_NET_CLS_ACT
  6.  * NOTE: This doesnt stop any functionality; if you dont have
  7.  * the ingress scheduler, you just cant add policies on ingress.
  8.  *
  9.  */
  10. static int ing_filter(struct sk_buff *skb)
  11. {
  12.     struct net_device *dev = skb->dev;
  13.     u32 ttl = G_TC_RTTL(skb->tc_verd);
  14.     struct netdev_queue *rxq;
  15.     int result = TC_ACT_OK;
  16.     struct Qdisc *q;

  17.     if (MAX_RED_LOOP < ttl++) {
  18.         printk(KERN_WARNING
  19.          "Redir loop detected Dropping packet (%d->%d)\n",
  20.          skb->iif, dev->ifindex);
  21.         return TC_ACT_SHOT;
  22.     }

  23.     skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl);
  24.     skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);

  25.     rxq = &dev->rx_queue;

  26.     q = rxq->qdisc;
  27.     if (q != &noop_qdisc) {
  28.         spin_lock(qdisc_lock(q));
  29.         if (likely(!test_bit(__QDISC_STATE_DEACTIVATED, &q->state)))
  30.             result = qdisc_enqueue_root(skb, q);
  31.         spin_unlock(qdisc_lock(q));
  32.     }

  33.     return result;
  34. }

  35. static inline struct sk_buff *handle_ing(struct sk_buff *skb,
  36.                      struct packet_type **pt_prev,
  37.                      int *ret, struct net_device *orig_dev)
  38. {
  39.     if (skb->dev->rx_queue.qdisc == &noop_qdisc)
  40.         goto out;

  41.     if (*pt_prev) {
  42.         *ret = deliver_skb(skb, *pt_prev, orig_dev);
  43.         *pt_prev = NULL;
  44.     } else {
  45.         /* Huh? Why does turning on AF_PACKET affect this? */
  46.         skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
  47.     }

  48.     switch (ing_filter(skb)) {
  49.     case TC_ACT_SHOT:
  50.     case TC_ACT_STOLEN:
  51.         kfree_skb(skb);
  52.         return NULL;
  53.     }

  54. out:
  55.     skb->tc_verd = 0;
  56.     return skb;
  57. }
  58. #endif
我们回到函数dev_init_scheduler,它调用

点击(此处)折叠或打开

  1. static void dev_init_scheduler_queue(struct net_device *dev,
  2.                  struct netdev_queue *dev_queue,
  3.                  void *_qdisc)
  4. {
  5.     struct Qdisc *qdisc = _qdisc;

  6.     dev_queue->qdisc = qdisc;
  7.     dev_queue->qdisc_sleeping = qdisc;
  8. }
对收发队列进行初始化操作. 设备注册后,在dev_open时会由dev_activate(dev);来激活队列.
而队列的最开始初始化是在net/sched/sch_api.c中

点击(此处)折叠或打开

  1. static int __init pktsched_init(void)
  2. {
  3.     register_qdisc(&pfifo_qdisc_ops);
  4.     register_qdisc(&bfifo_qdisc_ops);
  5.     register_qdisc(&mq_qdisc_ops);
  6.     proc_net_fops_create(&init_net, "psched", 0, &psched_fops);

  7.     rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
  8.     rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
  9.     rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc);
  10.     rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL);
  11.     rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL);
  12.     rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass);

  13.     return 0;
  14. }

  15. subsys_initcall(pktsched_init);
这里只是一个小小的开端,准备以后仔细研究下qdisc ^^ 

前面我们看到一个特殊的函数 netdev_run_todo,其实这个函数在设备注册和注销的时候都会用到.

rtnl_unlock时 会调用netdev_run_todo来执行任务.
至于注册中的rtNetlink通知链这里不说!

设备引用计数 Dev->refcnt  初始化值为1 .
操作函数:dev_put 、dev_hold
很多时候,我们会需要动态的注销一些设备,这个时候在注销的时候 会发送通知让其他引用的子系统释放掉引用.
那么就需要netdev_run_todo 定时调用netdev_wait_allrefs来检查.它会主动发送NETREG_UNREGISTERED通知信息给netdev_chain,直到引用为0.

开启和关闭网络设备需要具体做那些工作以及他们之间的顺序?

1.       调用dev->open

2.       设置dev->state __LINK_STATE_START

3.       设置dev->flagsIFF_UP

4.       调用dev_activate初始化由流量控制使用的出口队列规则,然后启动watchdog

5.       传送NETDEV_UP通知链netdev_chain ,告知其他内核组件做出反应

关闭的流程和open相反

当然这里和注册和注销所做是不同的事情。

设备的电源管理:挂起 和恢复

涉及到netif_device_detach的作用 挂起的时候。

恢复的时候 用 netif_device_attach

对网络设备操作的常用工具:
ifconfigethtooliproute2 /mii-tools

ifconfig  工作原理?

Socket  ioctl ----> Dev_ioctl

虚拟设备 

   当然这篇文章很琐碎很杂,不过大部分设备初始化或者注册什么都说到了. 这里写它,只是为了使心中模糊的东西,更加清晰化.

  
阅读(5012) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~