总体概览如下:

假设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. struts2 之 ThreadLocal 和 ActionContext

    1. ThreadLocal:该类提供了线程局部(thtead-local)变量.threadLocal是一个容器,该容器中存放的数据可以保证线程安全. 案例如: public class Threa ...

  2. C#图解教程-方法参数笔记(上)

    一晃大学四年要过去了,期间乱点了很多技能点, 导致每一项技能都只是处于入门阶段.为了将C#作为我的主要技能,准备恶补相关姿势(知识),通过各种技术论坛的推荐,找到了<C#图解教程>这本书. ...

  3. 如何用unity3d实现发送带附件的邮件

    以Gmail为例.点击屏幕的Capture按钮得到当前屏幕截图,点击Send按钮将之前的截图作为附件发送邮件. using UnityEngine; using System.Collections; ...

  4. java复习(8)---I/O

    本节复习java常用i/o,输入输出流. 先放上样例代码.方便参考,可以轻松看懂. package re08; import java.io.*; import java.util.Scanner; ...

  5. CF #CROC 2016 - Elimination Round D. Robot Rapping Results Report 二分+拓扑排序

    题目链接:http://codeforces.com/contest/655/problem/D 大意是给若干对偏序,问最少需要前多少对关系,可以确定所有的大小关系. 解法是二分答案,利用拓扑排序看是 ...

  6. HTTP长连接、短连接使用及测试

    概念 HTTP短连接(非持久连接)是指,客户端和服务端进行一次HTTP请求/响应之后,就关闭连接.所以,下一次的HTTP请求/响应操作就需要重新建立连接. HTTP长连接(持久连接)是指,客户端和服务 ...

  7. mySql 安装教程

    看了好久别人的文章,今天就开始自己写第一篇.希望给别人能提供帮助,也可以方便自己查阅. 前两天自己安装了mysql,感觉是比oracle好装多了. mysql安装有两种方式,一种是安装包安装方式,一种 ...

  8. ELK菜鸟手记 (三) - X-Pack权限控制之给Kibana加上登录控制以及index_not_found_exception问题解决

    0. 背景 我们在使用ELK进行日志记录的时候,通过网址在Kibana中查看我们的应用程序(eg: Java Web)记录的日志, 但是默认是任何客户端都可以访问Kibana的, 这样就会造成很不安全 ...

  9. Jedis连接池使用

    构建redis连接池,返还到连接池 private static JedisPool jedisPool = null; private static Jedis jedis; static { je ...

  10. Java Map List 的使用

    项目中有一个需求是将年月分两行显示: java后台代码 创建一个demo,使用Map List 拆分年月: package demo; import java.util.ArrayList;impor ...