高性能网络I/O框架-netmap源码分析(5)-阿里云开发者社区

开发者社区> nothingfinal> 正文

高性能网络I/O框架-netmap源码分析(5)

简介: 高性能网络I/O框架-netmap源码分析(5) 作者:gfree.wind@gmail.com 博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net 微博:weibo.com/glinuxer QQ技术群:4367710 今天继续前面的netmap_ioctl netmap_ioctl 上次分析完了NIOCGINFO和NIOCREGIF两个,剩下的比较简单了。
+关注继续查看

高性能网络I/O框架-netmap源码分析(5)

作者:gfree.wind@gmail.com
博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
微博:weibo.com/glinuxer
QQ技术群:4367710

今天继续前面的netmap_ioctl

netmap_ioctl

上次分析完了NIOCGINFO和NIOCREGIF两个,剩下的比较简单了。那么今天争取干掉剩下所有的case,以及上篇中netmap_ioctl调用的函数

NIOCUNREGIF

case NIOCUNREGIF:
    if (priv == NULL) {
        /* 没有priv肯定是不对的,肯定是没有调用过NIOCREGIF */
        error = ENXIO;
        break;
    }

    /* the interface is unregistered inside the
       destructor of the private data. */
    /* 释放priv内存*/
    devfs_clear_cdevpriv();
    break; 

NIOCTXSYNC和NIOCRXSYNC

这两个使用相同的代码。

case NIOCTXSYNC:
case NIOCRXSYNC:
    /* 检查priv,确保之前调用了NIOCREGIF */
    if (priv == NULL) {
        error = ENXIO;
        break;
    }
    /* 
    记得之前分析NIOCREGIF时,priv->np_ifp保存了net_device指针,所有现在可以直接获得这个指针。
    要不要担心net_device指针的有效性呢?不用,因为NIOCREGIF时,在得到net_device时,已经增加了计数
    */
    ifp = priv->np_ifp; /* we have a reference */
    na = NA(ifp); /* retrieve netmap adapter */

    /* 
    np_qfirst表示需要检查的第一个ring 
    当其值为NETMAP_SW_RING是一个特殊的值,表示处理host的ring
    */
    if (priv->np_qfirst == NETMAP_SW_RING) { /* host rings */
        /* 
        对于host ring处理,这个地方的代码有点奇怪。
        当cmd是NIOCTXSYNC,是将数据包传给host;
        当cmd是NIOCRXSYNC,是将数据包从host发送出去;
        感觉好像写反了。我给作者发了邮件,不知道能不能得到回复。
        反正从语义上,我是觉得有问题。


        现在已经得到了作者的回复——再次感叹外国人的友好。这里的方向,是以netmap的角度去看。
        所以,当cmd是txsync时,是netmap把包送出去,那么自然是交给host。反之亦然。
        */
        if (cmd == NIOCTXSYNC)
            netmap_sync_to_host(na);
        else
            netmap_sync_from_host(na, NULL, NULL);
        break;
    }

    /* find the last ring to scan */
    /* 
    得到需要检查的最后一个ring,如果是NETMAP_HW_RING,那么就是最大ring数值 
    关于np_qfirst和np_qlast,等看到netmap_set_ringid时,大家就明白了
    */
    lim = priv->np_qlast;
    if (lim == NETMAP_HW_RING)
        lim = (cmd == NIOCTXSYNC) ?
            na->num_tx_rings : na->num_rx_rings;

    /* 从第一个开始遍历每个ring */
    for (i = priv->np_qfirst; i tx_rings[i];
            if (netmap_verbose & NM_VERB_TXSYNC)
                D("pre txsync ring %d cur %d hwcur %d",
                    i, kring->ring->cur,
                    kring->nr_hwcur);
            /* 执行发送工作,留到后面分析 */
            na->nm_txsync(ifp, i, 1 /* do lock */);
            if (netmap_verbose & NM_VERB_TXSYNC)
                D("post txsync ring %d cur %d hwcur %d",
                    i, kring->ring->cur,
                    kring->nr_hwcur);
        } else {
            /* 执行接收工作,留到后面分析*/
            na->nm_rxsync(ifp, i, 1 /* do lock */);
            /* 
            在linux平台上,实际上是调用了do_gettimeofday,不知道为什么接收需要的这个时间
            看看以后是不是可以知道原因。
            */
            microtime(&na->rx_rings[i].ring->ts);
        }
    } 

到此,netmap_ioctl分析学习完毕。

netmap_set_ringid

在上篇文章中,遗留了这个函数。

static int
netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid)
{
    struct ifnet *ifp = priv->np_ifp;
    struct netmap_adapter *na = NA(ifp);

    /*
    从下面三个宏,可以得知ringid是一个“复用”的结构。低24位用于表示id值,高位作为标志。
    #define NETMAP_HW_RING  0x4000      /* low bits indicate one hw ring */
    #define NETMAP_SW_RING  0x2000      /* process the sw ring */
    #define NETMAP_NO_TX_POLL   0x1000  /* no automatic txsync on poll */
    #define NETMAP_RING_MASK 0xfff      /* the ring number */
    */
    u_int i = ringid & NETMAP_RING_MASK;
    /*
    根据注释,在初始化阶段,np_qfirst和np_qlast相等,不需要锁保护。
    关于这点我没想明白。如果两个线程同时进入怎么办?
    */
    /* initially (np_qfirst == np_qlast) we don't want to lock */
    int need_lock = (priv->np_qfirst != priv->np_qlast);
    int lim = na->num_rx_rings;

    /* 上限取发送和接收队列数量的最大值 */
    if (na->num_tx_rings > lim)
        lim = na->num_tx_rings;
    /* 当处理HW ring时,要对id进行有效性判断 */
    if ( (ringid & NETMAP_HW_RING) && i >= lim) {
        D("invalid ring id %d", i);
        return (EINVAL);
    }
    if (need_lock)
        na->nm_lock(ifp, NETMAP_CORE_LOCK, 0);
    priv->np_ringid = ringid;
    /*
    根据三种标志,设置正确的np_qfirst和qlast。从这里也可以看出,只有在初始化时,np_qfirst才可能等于np_qlast。 
    */
    if (ringid & NETMAP_SW_RING) {
        priv->np_qfirst = NETMAP_SW_RING;
        priv->np_qlast = 0;
    } else if (ringid & NETMAP_HW_RING) {
        priv->np_qfirst = i;
        priv->np_qlast = i + 1;
    } else {
        priv->np_qfirst = 0;
        priv->np_qlast = NETMAP_HW_RING ;
    }
    /* 是否在执行接收数据包的poll时,发送数据包 */
    priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1;
    if (need_lock)
        na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0);
    if (ringid & NETMAP_SW_RING)
        D("ringid %s set to SW RING", ifp->if_xname);
    else if (ringid & NETMAP_HW_RING)
        D("ringid %s set to HW RING %d", ifp->if_xname,
            priv->np_qfirst);
    else
        D("ringid %s set to all %d HW RINGS", ifp->if_xname, lim);
    return 0;
} 

(未完待续。。。)

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Linux USB Host-Controller的初始化代码框架分析【转】
转自:http://blog.csdn.net/zkami/article/details/2496770 usb_hcd_omap_probe (const struct hc_driver *driver) (dev/ohci/ohci-omap.
816 0
LinkedHashMap源码分析(基于JDK1.6)
LinkedHashMap类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点;而在迭代访问时反而更快,因为它使用链表维护内部次序(HashMap是基于散列表实现的,相关HashMap的内容可以看《Java集合类》和《HashMap源码分析》)。
589 0
TreeMap源码分析——基础分析(基于JDK1.6)
常见的数据结构有数组、链表,还有一种结构也很常见,那就是树。前面介绍的集合类有基于数组的ArrayList,有基于链表的LinkedList,还有链表和数组结合的HashMap,今天介绍基于树的TreeMap。
410 0
HashMap源码分析(基于JDK1.6)
在Java集合类中最常用的除了ArrayList外,就是HashMap了。本文尽自己所能,尽量详细的解释HashMap的源码。一山还有一山高,有不足之处请之处,定感谢指定并及时修正。     在看HashMap源码之前先复习一下数据结构。
498 0
Flink运行时之基于Netty的网络通信中
PartitionRequestClient 分区请求客户端(PartitionRequestClient)用于发起远程PartitionRequest请求,它也是RemoteChannel跟Netty通信层之间进行衔接的对象。
1854 0
+关注
nothingfinal
软件开发,安全加密
1069
文章
341
问答
文章排行榜
最热
最新
相关电子书
更多
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载
《2021云上架构与运维峰会演讲合集》
立即下载