处理upcall总体框架:



1.由函数handle_upcalls()批量处理(in batches)的是由内核传上来的dpif_upcalls,会解析出upcall的类型。这里主要看在内核中匹配流表失败的MISS_UPCALL。

处理完毕后会得到多个flow_miss。


结构体dpif_upcall代表的是由内核传到用户空间的一个包,包含上传原因,packet data。以及以netlink attr形式存在的键值。
struct dpif_upcall {

    /* All types. */

    enum dpif_upcall_type type;

    struct ofpbuf *packet;      /* Packet data. */

    struct nlattr *key;         /* Flow key. */

    size_t key_len;             /* Length of 'key' in bytes. */



    /* DPIF_UC_ACTION only. */

    uint64_t userdata;          /* Argument to OVS_ACTION_ATTR_USERSPACE. */

};


结构体flow_miss是将具有同样流特征的packets统一起来( batching),性能可能会更优,所以这个结构体要将datapath interface相关的数据队列起来。每一个flow_miss相应的是发送的一个或多个数据包,另外可能会在dpif中安装流项。

struct flow_miss {

    struct hmap_node hmap_node;

    struct flow flow;  //流特征。

    enum odp_key_fitness key_fitness;

    const struct nlattr *key;

    size_t key_len;

    ovs_be16 initial_tci;

    struct list packets;    //具有该流特征的全部的packets;

    enum dpif_upcall_type upcall_type;

};


2. 接下来。函数handle_miss_upcalls()会依次遍历这个flow_misses数组,完毕的工作有:1)得到odp_key_fitness (也就是内核层/用户层在流匹配上的一致程度);2)从packet data中析取出流信息miss->flow。3)然后对miss->flow进行哈希。假设不存在则插入到TO-DO-List中。4)将这个upcall->packet插入到对应的节点上。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdm9uemhvdWZ6/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">


3.然后对于TO-DO-List中的每一个元素,调用handle_flow_miss()函数。它会从这个flow_miss中构造得到flow_miss_op,详细的过程是:1)查询ofproto的facet表ofproto->facets看针对这个flow的facet是否已存在。2)从ofproto的分类表中查找与这个flow相应的分类规则,对于第一个进入系统的包,还没有建立起cls_rule。此时返回ofproto->miss_rule(是怎样初始化的呢?);3)构造一个facet,和当前的flow和rule_dpif关联起来;4)这时候与flow_miss
匹配的facet也有了,接着呼叫函数 handle_flow_miss_with_facet()可能会添加须要的操作到flow_miss_op中。详细过程是:先是通过内核传上来的key找subfacet是否存在,假设不存在就构建一个;然后针对每一个连接到这个flow_miss中的packet进行分别处理;handle_flow_miss_common()会推断假设rule->up.cr.priority = FAIL_OPEN_PRIORITY的话就会发送一个packetin到SDN Controller;对于刚创建的subfacet,其actions为空,所以函数subfacet_make_actions()会依据subfacet中的rule来创建datapath
action,存储在odp_actions中。假设upcall的类型是DPIF_UC_MISS。就创建一个DPIF_OP_FLOW_PUT类型的flow_miss_op(即dpif_flow_put),然后compose_slow_path()会构建一个用户空间的user_action_cookie,它的类型是USER_ACTION_COOKIE_SLOW_PATH 表示这个流得到了用户空间的处理。然后-> odp_put_userspace_action() 会添加一个OVS_ACTION_ATTR_USERSPACE
action到odp_actions中,属性值包含netlink pid 和 刚才的cookie。




struct flow_miss_op {

    struct dpif_op dpif_op;    //据此能够得到操作类型handler;

    struct subfacet *subfacet;    // Subfacet  ,据此能够得到全部的flow和rule等数据。

    void *garbage;              /* Pointer to pass to free(), NULL if none. */

    uint64_t stub[1024 / 8];    /* Temporary buffer. */

};

struct dpif_op {

    enum dpif_op_type type;   

    int error;

    union {

        struct dpif_flow_put flow_put;

        struct dpif_flow_del flow_del;

        struct dpif_execute execute;

    } u;

};
enum dpif_op_type {

    DPIF_OP_FLOW_PUT = 1,

    DPIF_OP_FLOW_DEL,

    DPIF_OP_EXECUTE,

};

结构体facet是openflow flow的全然匹配( exact-match)的实例抽象。它与"struct flow"关联。代表OVS用户空间对于exact match flow的观点。有一个或多个subfacet。每一个subfacet追踪着内核层datapath对于这个exact-match flow 的观点。当内核层和用户空间对一个flow key观点一致的时候,就仅仅有一个subfacet(通常如此)。很多其它理解參考[]。
struct facet {

    /* Owners. */

    struct hmap_node hmap_node;  /* In owning ofproto's 'facets' hmap. */

    struct list list_node;       /* In owning rule's 'facets' list. */

    struct rule_dpif *rule;      /* Owning rule. */



    /* Owned data. */

    struct list subfacets;

    long long int used;         /* Time last used; time created if not used. */



    /* Key. */

    struct flow flow;



   // 接下来是 一些统计字段;



    /* Storage for a single subfacet, to reduce malloc() time and space

     * overhead.  (A facet always has at least one subfacet and in the common

     * case has exactly one subfacet.) */

    struct subfacet one_subfacet;

};

struct rule_dpif {

    struct rule up;



    uint64_t packet_count;       /* Number of packets received. */

    uint64_t byte_count;         /* Number of bytes received. */



    tag_type tag;                /* Caches rule_calculate_tag() result. */



    struct list facets;          /* List of "struct facet"s. */

};

/* An OpenFlow flow within a "struct ofproto".

*

* With few exceptions, ofproto implementations may look at these fields but

* should not modify them. */

struct rule {

    struct list ofproto_node;    /* Owned by ofproto base code. */

    struct ofproto *ofproto;     /* The ofproto that contains this rule. */

    struct cls_rule cr;          /* In owning ofproto's classifier. */



    struct ofoperation *pending; /* Operation now in progress, if nonnull. */



    ovs_be64 flow_cookie;        /* Controller-issued identifier. */



    long long int created;       /* Creation time. */

    long long int modified;      /* Time of last modification. */

    long long int used;          /* Last use; time created if never used. */

    uint16_t hard_timeout;       /* In seconds from ->modified. */

    uint16_t idle_timeout;       /* In seconds from ->used. */

    uint8_t table_id;            /* Index in ofproto's 'tables' array. */

    bool send_flow_removed;      /* Send a flow removed message? */



    /* Eviction groups. */

    bool evictable;              /* If false, prevents eviction. */

    struct heap_node evg_node;   /* In eviction_group's "rules" heap. */

    struct eviction_group *eviction_group; /* NULL if not in any group. */



    struct ofpact *ofpacts;      /* Sequence of "struct ofpacts". */

    unsigned int ofpacts_len;    /* Size of 'ofpacts', in bytes. */



    /* Flow monitors. */

    enum nx_flow_monitor_flags monitor_flags;

    uint64_t add_seqno;         /* Sequence number when added. */

    uint64_t modify_seqno;      /* Sequence number when changed. */

};


struct subfacet {

    /* Owners. */

    struct hmap_node hmap_node; /* In struct ofproto_dpif 'subfacets' list. */

    struct list list_node;      /* In struct facet's 'facets' list. */

    struct facet *facet;        /* Owning facet. */



    /* Key.

     *

     * To save memory in the common case, 'key' is NULL if 'key_fitness' is

     * ODP_FIT_PERFECT, that is, odp_flow_key_from_flow() can accurately

     * regenerate the ODP flow key from ->facet->flow. */

    enum odp_key_fitness key_fitness;

    struct nlattr *key;

    int key_len;



    long long int used;         /* Time last used; time created if not used. */



    uint64_t dp_packet_count;   /* Last known packet count in the datapath. */

    uint64_t dp_byte_count;     /* Last known byte count in the datapath. */



    /* Datapath actions.

     *

     * These should be essentially identical for every subfacet in a facet, but

     * may differ in trivial ways due to VLAN splinters. */

    size_t actions_len;         /* Number of bytes in actions[]. */

    struct nlattr *actions;     /* Datapath actions. */



    enum slow_path_reason slow; /* 0 if fast path may be used. */

    enum subfacet_path path;    /* Installed in datapath? */

};

枚举体slow_path_reason 列举的是packet没有在内核层被转发的原因(也就是说这个packet是fast path)。

enum slow_path_reason {

    /* These reasons are mutually exclusive. */

    SLOW_CFM = 1 << 0,          /* CFM packets need per-packet processing. */

    SLOW_LACP = 1 << 1,         /* LACP packets need per-packet processing. */

    SLOW_STP = 1 << 2,          /* STP packets need per-packet processing. */

    SLOW_IN_BAND = 1 << 3,      /* In-band control needs every packet. */


    // 和 SLOW_CFM, SLOW_LACP, SLOW_STP相互排斥,能够和SLOW_IN_BAND组合。

    SLOW_CONTROLLER = 1 << 4,   /* Packets must go to OpenFlow controller. */

};

枚举体subfacet_path列举的是其可能的当前状态:1)SF_NOT_INSTALLED表示没有安装在datapath中,这样的情况出如今这个subfacet构建之后,销毁之前,或者当我们在安装一个subfacet到datapath时出错。由于subfacet中相应的有action,所以这里的facet install指的是datapath运行了由用户空间下发的详细action。2)SF_FAST_PATH说明相应的action已经得到了运行,packets能够在内核层直接转发;3)SF_SLOW_PATH是流规则指定了要发往用户空间。


enum subfacet_path {

    SF_NOT_INSTALLED,           /* No datapath flow for this subfacet. */

    SF_FAST_PATH,               /* Full actions are installed. */

    SF_SLOW_PATH,               /* Send-to-userspace action is installed. */

};

4. 通过上面的操作,flow_miss_op数组就得到了。接下来调用函数 dpif_operate() 依次对dpif运行这些operation。
 for (i = 0; i < n_ops; i++) {

        struct dpif_op *op = ops[i];



        switch (op->type) {

        case DPIF_OP_FLOW_PUT:

            op->error = dpif_flow_put__(dpif, &op->u.flow_put);

            break;



        case DPIF_OP_FLOW_DEL:

            op->error = dpif_flow_del__(dpif, &op->u.flow_del);

            break;



        case DPIF_OP_EXECUTE:

            op->error = dpif_execute__(dpif, &op->u.execute);

            break;



        default:

            NOT_REACHED();
}
这里就看flow put的情况,用户空间会通过genl把对应的动作下发给内核datapath,而且接收响应。













版权声明:本文博主原创文章,博客,未经同意不得转载。

OVS处理upcall流程分析的更多相关文章

  1. openVswitch(OVS)源码分析之工作流程(哈希桶结构体的解释)

    这篇blog是专门解决前篇openVswitch(OVS)源码分析之工作流程(哈希桶结构体的疑惑)中提到的哈希桶结构flex_array结构体成员变量含义的问题. 引用下前篇blog中分析讨论得到的f ...

  2. 8、Struts2 运行流程分析

    1.流程分析: 请求发送给 StrutsPrepareAndExecuteFilter StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 ...

  3. freeswitch呼叫流程分析

    今天翻文档时发现之前整理的关于freeswitch呼叫相关的内容,写成博文分享出来也方便我以后查阅. 整体结构图 FreeswitchCore 模块加载过程 freeswitch主程序初始化时会从mo ...

  4. u-boot 流程分析

    u-boot 介绍: 对于计算机来说 , 从一开始上机通电是无法直接启动操作系统的 , 这中间需要一个引导过程 , 嵌入式Linux系统同样离不开引导程序 ,  这个启动程序就叫启动加载程序(Boot ...

  5. thttpd和cgilua安装与运行流程分析

    安装 参考如下博文安装thttpd软件 http://blog.csdn.net/21aspnet/article/details/7045845 http://blog.csdn.net/drago ...

  6. 【转】Hostapd工作流程分析

    [转]Hostapd工作流程分析 转自:http://blog.chinaunix.net/uid-30081165-id-5290531.html Hostapd是一个运行在用户态的守护进程,可以通 ...

  7. u-boot中nandflash初始化流程分析(转)

    u-boot中nandflash初始化流程分析(转) 原文地址http://zhuairlunjj.blog.163.com/blog/static/80050945201092011249136/ ...

  8. Android7.0 Phone应用源码分析(二) phone来电流程分析

    接上篇博文:Android7.0 Phone应用源码分析(一) phone拨号流程分析 今天我们再来分析下Android7.0 的phone的来电流程 1.1TelephonyFramework 当有 ...

  9. runc start container流程分析

    1.runc/start.go Action: func(context *cli.Context) error 该函数首先调用container, err := getContainer(conte ...

随机推荐

  1. 【Codeforces Round #442 (Div. 2) B】Nikita and string

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举中间那一段从哪里开始.哪里结束就好 注意为空的话,就全是a. 用前缀和优化一下. [代码] #include <bits/ ...

  2. struts2笔记---struts2的执行过程

    1.服务器启动: 加载项目web.xml 创建struts核心过滤器对象,执行filter-->init() struts-default.xml     核心功能的初始化 struts-plu ...

  3. 【习题 5-6 UVA-1595】Symmetry

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 每一个y坐标的点都找中点. 看看中点是不是都一样就好. [代码] #include <bits/stdc++.h> us ...

  4. Java抽象类中的抽象方法的参数对应的子类的方法的参数必须一致吗?

    同学你这个涉及了两个概念. 一个是抽象方法,一个是方法重载. 先说下概念: 抽象方法就是abstract描述的方法,它本身不含实现,必须由子类实现. 方法重载则是同一个方法名,但是参数类型或者参数个数 ...

  5. 怎样在一个fragment or 随意类中操作还有一个fragment中的方法

    1 怎样在acitivty中运行fragment中的方法: 首先获得这个Fragment的对象 xxxFragment fragmentObject = (xxxFragment) getFragme ...

  6. [WPF自定义控件库]排序、筛选以及高亮

    1. 如何让列表的内容更容易查找 假设有这么一个列表(数据源在本地),由于内容太多,要查找到其中某个想要的数据会比较困难.要优化这个列表,无非就是排序.筛选和高亮. 改造过的结果如上. 2. 排序 在 ...

  7. ARM+linux学习过程(2)安装vmware-tool过程与错误解决

    安装: 点击Ubuntu VMware菜单的-VM-Install VMware Tools 这时,在Ubuntu下会自动加载Linux版的VMware Tools的安装光盘镜像.你会看到虚拟机的桌面 ...

  8. [Angular] Alternative Themes - Learn the Host-Context Selector

    To add alernative theme, we can use :host-context() selector from Angular. //au-fa-input-red-theme.c ...

  9. github-vimium-compile-crx

    chrome-62.x版本上安装vimium 1.61.1 https://blog.csdn.net/ZHUJIANWEILI4/article/details/78385346

  10. C++中string类的操作函数。

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...