概述
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 }