邻居子系统 之 输出

概述

neigh_hh_output-缓存输出,直接拷贝二层头部,然后输出;

neigh_connected_output-快速输出,用于连接状态的输出;需要重新构建二层头部,然后输出;

neigh_resolve_output-慢速输出,用于非连接状态的输出;需要对邻居项状态进行检查,然后重新构造二层头部,最后输出;

neigh_direct_output-直接输出,用于没有二层头部时的输出;

源码分析
 1 /* 拷贝缓存的二层头部,输出 */
 2 static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb)
 3 {
 4     unsigned int seq;
 5     unsigned int hh_len;
 6 
 7     /* 拷贝二层头到skb */
 8     do {
 9         seq = read_seqbegin(&hh->hh_lock);
10         hh_len = hh->hh_len;
11         /* 二层头部<DATA_MOD,直接使用该长度拷贝 */
12         if (likely(hh_len <= HH_DATA_MOD)) {
13             /* this is inlined by gcc */
14             memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD);
15         } 
16         /* >=DATA_MOD,对齐头部,拷贝 */
17         else {
18             unsigned int hh_alen = HH_DATA_ALIGN(hh_len);
19 
20             memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
21         }
22     } while (read_seqretry(&hh->hh_lock, seq));
23 
24     skb_push(skb, hh_len);
25 
26     /* 发送 */
27     return dev_queue_xmit(skb);
28 }
 1 /* CONNECTED状态的发送函数,没有neigh_hh_output快,这个需要重建二层头 */
 2 int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
 3 {
 4     struct net_device *dev = neigh->dev;
 5     unsigned int seq;
 6     int err;
 7 
 8     /* 拷贝二层头 */
 9     do {
10         __skb_pull(skb, skb_network_offset(skb));
11         seq = read_seqbegin(&neigh->ha_lock);
12         err = dev_hard_header(skb, dev, ntohs(skb->protocol),
13                       neigh->ha, NULL, skb->len);
14     } while (read_seqretry(&neigh->ha_lock, seq));
15 
16     /* 发送数据包 */
17     if (err >= 0)
18         err = dev_queue_xmit(skb);
19     else {
20         err = -EINVAL;
21         kfree_skb(skb);
22     }
23     return err;
24 }
 1 /* 非CONNECTED状态的慢速发送 */
 2 int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
 3 {
 4     int rc = 0;
 5 
 6     /* 检测邻居项状态有效性 */
 7     if (!neigh_event_send(neigh, skb)) {
 8         int err;
 9         struct net_device *dev = neigh->dev;
10         unsigned int seq;
11 
12         /* 有二层头缓存函数,则缓存之 */
13         if (dev->header_ops->cache && !neigh->hh.hh_len)
14             neigh_hh_init(neigh);
15 
16         /* 填充二层头 */
17         do {
18             __skb_pull(skb, skb_network_offset(skb));
19             seq = read_seqbegin(&neigh->ha_lock);
20             err = dev_hard_header(skb, dev, ntohs(skb->protocol),
21                           neigh->ha, NULL, skb->len);
22         } while (read_seqretry(&neigh->ha_lock, seq));
23 
24         /* 数据包发送 */
25         if (err >= 0)
26             rc = dev_queue_xmit(skb);
27         else
28             goto out_kfree_skb;
29     }
30 out:
31     return rc;
32 out_kfree_skb:
33     rc = -EINVAL;
34     kfree_skb(skb);
35     goto out;
36 }
1 int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
2 {
3     return dev_queue_xmit(skb);
4 }

猜你喜欢

转载自www.cnblogs.com/wanpengcoder/p/11755409.html