总体概览如下:

假设upcall handler线程有两个,vport有四个,那么每个vport下都将持有两个NetLink连接的信息,这两个NetLink连接将被用来上送upcall消息。
每个NetLink连接被对应的upcall handler线程接管,多个vport在同一线程中的NetLink连接被epoll管理。
1:每个vport下都挂多个NetLink连接,数量等同于upcall处理线程的数量
2:线程中routine函数为udpif_upcall_handler,伪码如下:
     routine {
          while(线程不设自杀标记) {
               if(从epoll中收到了一些upcall消息,则进一步处理upcall) {
                    continue; 
               } else {
                    注册poll:当epoll_fd有骚动时解除当前线程的block
               }
               block当前线程
          }
     }
3:每个NetLink连接被称为一个upcall channel
 
1:upcall处理线程的创建
upcall处理线程随着vswitchd进程的启动而被创建,概览如下:

最终所有线程信息会被记录在 ofproto_dpif->backer->udpif下
 
2:vport的创建与channels的创建
在基于本机内核的datapath实现的openflow交换机场景下,用户态的datapath接口将采用dpif_netlink_***系列函数。vport的创建在用户态最终将调用到dpif_netlink_port_add,这是dpif_netlink_port_add__的包裹函数。
 
先说一点我对NetLink连接的理解
     1:创建socket
     2:可选的bind步骤,在这一步,应当在本端地址结构中赋值nl_pid为当前进程ID,并bind之。
     3:建立连接connect,这一步对端地址结构的nl_pid值如果为非0值 ,那么连接的就是一个用户态进程。如果nl_pid值为0,则连接的是内核。
     如果没有第2步,那么在connect之后,内核会为这个NetLink连接的本端bind地址结构自动指定一个nl_pid值,以标识该连接。此时通过getsockname取到的本端地址结构中的nl_pid字段将不是发起连接一方的进程ID。

3:内核cache miss
内核cache miss后,会发送upcall消息,
 
netdev_frame_hook(pskb)
    |
    \-> netdev_port_receive(skb, NULL/skb_tunnel_info(skb))
        |
        \-> ovs_vport_receive(ovs_netdev_get_vport(skb->dev), skb, tun_info = NULL/skb_tunnel_info(skb))
            |
            \-> error = ovs_flow_key_extract(tun_info, skb, &key)
            |
            \-> ovs_dp_process_packet(skb, &key)
                |
                \-> flow = ovs_flow_tbl_lookup_stats(&dp->table, key, skb_get_hash(skb), &n_mask_hit)
                    if(unlikely(!flow)) {
                        ...
                        upcall.cmd = OVS_PACKET_CMD_MISS;
                        upcall.portid = ovs_vport_find_upcall_portid(p, skb);
                        |
                        \-> 在vport下的upcall_portids里钦定一个port号,作为NetLink的目的地
                        ...
                        error = ovs_dp_upcall(dp, skb, key, &upcall, 0);
                    }
即是从upcall的vport下挂的socksp中选择一个nl_pid,以这个nl_pid做为upcall消息发送的目的地址
由上面的图能看出来,在vport下选择不同的socksp中的nl_pid,会导致消息被发往不同的epoll
 
 
4:dpif_handler[]->epoll_fd与用户态线程间的关联

那么在udpif_upcall_handler() -> recv_upcalls() -> dpif_recv() -> dpif_netlink_recv() -> dpif_netlink_recv__()中有以下代码:
 

这里的参数handler_id来自于线程routine函数的入参handler实例下的handler_id。
即对于x号线程,它会取dpif_handler[]数组中的x号元素下的epoll_fd去处理。

body,td { font-family: Consolas; font-size: 10pt }

OVS 中的 upcall 线程的更多相关文章

  1. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  2. Java中的守护线程和非守护线程(转载)

    <什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...

  3. springmvc中request的线程安全问题

    SpringMvc学习心得(四)springmvc中request的线程安全问题 标签: springspring mvc框架线程安全 2016-03-19 11:25 611人阅读 评论(1) 收藏 ...

  4. Unity 中 使用c#线程

    使用条件   天下没有免费的午餐,在我使用unity的那一刻,我就感觉到不自在,因为开源所以不知道底层实现,如果只是简单的做点简单游戏,那就无所谓的了,但真正用到实际地方的时候,就会发现一个挨着一个坑 ...

  5. Java中的守护线程 & 非守护线程(简介)

    Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...

  6. HttpApplication中的异步线程

    一.Asp.net中的线程池设置 在Asp.net的服务处理中,每当服务器收到一个请求,HttpRuntime将从HttpApplication池中获取一个HttpApplication对象处理此请求 ...

  7. c#中如何跨线程调用windows窗体控件

    c#中如何跨线程调用windows窗体控件?   我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍.首 ...

  8. c#中如何跨线程调用windows窗体控件?

    我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍.首先来看传统方法: public partial c ...

  9. C#如何判断线程池中所有的线程是否已经完成之Demo

    start: System.Threading.RegisteredWaitHandle rhw = null; new Action(() => { ; i < ; i++) { new ...

随机推荐

  1. Android系统--输入系统(六)模拟输入驱动程序

    Android系统--输入系统(六)模拟输入驱动程序 1. 回顾输入子系统 简单字符设备驱动:应用程序通过调用驱动所实现的函数使能硬件. 输入子系统:由于有多个应用程序使用输入子系统,故肯定使用的是早 ...

  2. JS获取URL中参数值(QueryString)的4种方法

    方法一:正则法 function getQueryString(name) {    var reg = new RegExp('(^|&)' + name + '=([^&]*)(& ...

  3. Android学习探索之运用MVP设计模式实现项目解耦

    前言: 一直致力于提高开发效率降低项目耦合,今天想抽空学习一下MVP架构设计模式,学习一下如何运用到项目中. MVP架构设计模式 MVP模式是一种架构设计模式,也是一种经典的界面模式.MVP中的M代表 ...

  4. Go 并发随机打印1-n

    package main import (     "fmt"     "math/rand"     "sync"     "t ...

  5. NSString 为什么要使用copy,而不是retain

    NSString 为什么要使用copy,而不是retain1.首先如果使用retain,只是引用计数+1,并没有生成新的对象,所以效率好2.但是使用copy安全.因为NSString 为 NSMuta ...

  6. CF #April Fools Day Contest 2016 E Out of Controls

    题目连接:http://codeforces.com/problemset/problem/656/E 愚人节专场的E,整个其实就是个Floyd算法,但是要求代码中不能包含 definedoforfo ...

  7. 数据仓库Hive数据导入导出

    Hive库数据导入导出 1.新建表data hive (ebank)> create table data(id int,name string) > ROW FORMAT DELIMIT ...

  8. Python 操作 MySQL 的正确姿势

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:邵建永 使用Python进行MySQL的库主要有三个,Python-MySQL(更熟悉的名字可能是MyS ...

  9. Java中四种遍历List的方法

    package com.ietree.basic.collection.loop; import java.util.ArrayList; import java.util.Iterator; imp ...

  10. 通过 jdbc 分析数据库中的表结构和主键外键

    文章转自:http://ivan4126.blog.163.com/blog/static/20949109220137753214811/ 在某项目中用到了 hibernate ,大家都知道 hib ...