• 邻居子系统 之 输出


    概述

    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 }
  • 相关阅读:
    css选择器的优先级
    ECHO.js 纯javascript轻量级延迟加载
    Chrome测试网站加载时间与流量消耗
    演示:纯CSS实现自适应布局表格
    通过jquery-ui中的sortable来实现拖拽排序
    XAMPP下的composer的安装
    jQuery动态五星评分
    HTML,CSS编码规范
    mysql排序,可以对统计的数据进行排序
    thinkphp中配置信息的二维数组设置与使用
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11755409.html
Copyright © 2020-2023  润新知