当协议栈准备将数据交给net_device发送时,它将调用dev_queue_xmit():
点击(此处)折叠或打开
- int dev_queue_xmit(struct sk_buff *skb)
- {
- struct net_device *dev = skb->dev;
- ......
- rc = dev_hard_start_xmit(skb, dev, txq);
- ......
- }
点击(此处)折叠或打开
- int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
- struct netdev_queue *txq)
- {
- ......
- if (!list_empty(&ptype_all))
- dev_queue_xmit_nit(skb, dev);
- ......
- }
由于AF_PACKET套接字注册了prot_hook,将导致dev_queue_xmit_nit()被调用:
点击(此处)折叠或打开
- static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
- {
- struct packet_type *ptype;
- struct sk_buff *skb2 = NULL;
- struct packet_type *pt_prev = NULL;
- rcu_read_lock();
- list_for_each_entry_rcu(ptype, &ptype_all, list) {
- /* Never send packets back to the socket
- * they originated from - MvS (miquels@drinkel.ow.org)
- */
- if ((ptype->dev == dev || !ptype->dev) &&
- (ptype->af_packet_priv == NULL ||
- (struct sock *)ptype->af_packet_priv != skb->sk)) {
- if (pt_prev) {
- deliver_skb(skb2, pt_prev, skb->dev);
- pt_prev = ptype;
- continue;
- }
- skb2 = skb_clone(skb, GFP_ATOMIC);
- if (!skb2)
- break;
- ......
- }
- }
- if (pt_prev)
- pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
- rcu_read_unlock();
- }
1:对于发送的包过滤条件有:
1). net_device是否是prot_hook指定的dev(NULL代表全部匹配)。
2). ptype->af_packet_priv在packet_creat()中被设定为自己,故自己发送的包不会被监听。
2:遍历ptype_all时,第一次会复制skb;只有ptype_all中不止1个entry时,将调用deliver_skb()。
3:当退出遍历时,将调用prot_hook的func成员,即packet_rcv()。
4: deliver_skb()仅仅是在调用prot_hook的func成员前增加skb的引用计算数。
点击(此处)折叠或打开
- static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev)
- {
- ......
- __skb_queue_tail(&sk->sk_receive_queue, skb);
- ......
- }