ovs vswitchd的启动

vswitchd启动代码可参考ovs-vswitchd.c的main函数,其中最重要的两个函数是bridge_run以及netdev_run

bridge_run

void bridge_run() {.../* Initialize the ofproto library.  This only needs to run once, but* it must be done after the configuration is set.  If the* initialization has already occurred, bridge_init_ofproto()* returns immediately. */bridge_init_ofproto(cfg);bridge_run__();...
}

bridge_init_ofproto用于初始化ofproto-dpif组件,首先会从ovsdb记录中汇总bridge, port, interfaces等信息,之后针对这些调用ofproto_init

/* Must be called to initialize the ofproto library.** The caller may pass in 'iface_hints', which contains an shash of* "iface_hint" elements indexed by the interface's name.  The provider* may use these hints to describe the startup configuration in order to* reinitialize its state.  The caller owns the provided data, so a* provider will make copies of anything required.  An ofproto provider* will remove any existing state that is not described by the hint, and* may choose to remove it all. */
void
ofproto_init(const struct shash *iface_hints)
{struct shash_node *node;size_t i;ofproto_class_register(&ofproto_dpif_class);/* Make a local copy, since we don't own 'iface_hints' elements. */SHASH_FOR_EACH(node, iface_hints) {const struct iface_hint *orig_hint = node->data;struct iface_hint *new_hint = xmalloc(sizeof *new_hint);const char *br_type = ofproto_normalize_type(orig_hint->br_type);new_hint->br_name = xstrdup(orig_hint->br_name);new_hint->br_type = xstrdup(br_type);new_hint->ofp_port = orig_hint->ofp_port;shash_add(&init_ofp_ports, node->name, new_hint);}for (i = 0; i < n_ofproto_classes; i++) {ofproto_classes[i]->init(&init_ofp_ports);}ofproto_unixctl_init();
}

ofproto_init首先注册ofproto_dpif_class,这个是ovs的ofproto-dpif的默认实现,之后对已经注册的所有ofproto_classes,都会调用ofproto_class->init函数。
ofproto_dpif_class是ovs的ofproto实现,在ofproto/ofproto-dpif.c中,这里先介绍init函数

static void
init(const struct shash *iface_hints)
{struct shash_node *node;/* Make a local copy, since we don't own 'iface_hints' elements. */SHASH_FOR_EACH(node, iface_hints) {const struct iface_hint *orig_hint = node->data;struct iface_hint *new_hint = xmalloc(sizeof *new_hint);new_hint->br_name = xstrdup(orig_hint->br_name);new_hint->br_type = xstrdup(orig_hint->br_type);new_hint->ofp_port = orig_hint->ofp_port;shash_add(&init_ofp_ports, node->name, new_hint);}ofproto_unixctl_init();udpif_init();
}

ofproto_unixctl_init,udpif_init都通过unixctl_command_register注册了多个ovs-appctl的命令参数,

bridge_run___最终都是调用的ofproto_dpif_class里注册的函数

static void
bridge_run__(void)
{struct bridge *br;struct sset types;const char *type;/* Let each datapath type do the work that it needs to do. */sset_init(&types);ofproto_enumerate_types(&types);SSET_FOR_EACH (type, &types) {ofproto_type_run(type);}sset_destroy(&types);/* Let each bridge do the work that it needs to do. */HMAP_FOR_EACH (br, node, &all_bridges) {ofproto_run(br->ofproto);}
}

ofproto_enumerate_types实际调用的是ofproto_dpif_class里注册的enumerate_types函数,里面实际调用了dp_enumerate_types

dp_enumerate_types(struct sset *types)
{struct shash_node *node;dp_initialize();ovs_mutex_lock(&dpif_mutex);SHASH_FOR_EACH(node, &dpif_classes) {const struct registered_dpif_class *registered_class = node->data;sset_add(types, registered_class->dpif_class->type);}ovs_mutex_unlock(&dpif_mutex);
}

dp_enumerate_types列出所有支持的dpif_class,目前主要有dpif_netdev_class以及dpif_netlink_class两类

ofproto_type_run实际调用了ofproto_dpif_class的type_run函数,里面有调用了dpif_class->run,以及udpif_run
struct udpif代表了ofproto_dpif的upcall handler结构体,包含两部分,一是struct handler的数组,用于处理upcall请求,可以看做是一个线程池,二是revalidators的数组,这块我没有细看,应该是一种类似gc机制的线程池,用于回收过期的flow

/* An upcall handler for ofproto_dpif.** udpif keeps records of two kind of logically separate units:** upcall handling* ---------------**    - An array of 'struct handler's for upcall handling and flow*      installation.** flow revalidation* -----------------**    - Revalidation threads which read the datapath flow table and maintains*      them.*/
struct udpif {struct ovs_list list_node;         /* In all_udpifs list. */struct dpif *dpif;                 /* Datapath handle. */struct dpif_backer *backer;        /* Opaque dpif_backer pointer. */struct handler *handlers;          /* Upcall handlers. */size_t n_handlers;struct revalidator *revalidators;  /* Flow revalidators. */size_t n_revalidators;struct latch exit_latch;           /* Tells child threads to exit. *//* Revalidation. */struct seq *reval_seq;             /* Incremented to force revalidation. */bool reval_exit;                   /* Set by leader on 'exit_latch. */struct ovs_barrier reval_barrier;  /* Barrier used by revalidators. */struct dpif_flow_dump *dump;       /* DPIF flow dump state. */long long int dump_duration;       /* Duration of the last flow dump. */struct seq *dump_seq;              /* Increments each dump iteration. */atomic_bool enable_ufid;           /* If true, skip dumping flow attrs. *//* These variables provide a mechanism for the main thread to pause* all revalidation without having to completely shut the threads down.* 'pause_latch' is shared between the main thread and the lead* revalidator thread, so when it is desirable to halt revalidation, the* main thread will set the latch. 'pause' and 'pause_barrier' are shared* by revalidator threads. The lead revalidator will set 'pause' when it* observes the latch has been set, and this will cause all revalidator* threads to wait on 'pause_barrier' at the beginning of the next* revalidation round. */bool pause;                        /* Set by leader on 'pause_latch. */struct latch pause_latch;          /* Set to force revalidators pause. */struct ovs_barrier pause_barrier;  /* Barrier used to pause all *//* revalidators by main thread. *//* Following fields are accessed and modified by different threads. */atomic_uint flow_limit;            /* Datapath flow hard limit. *//* n_flows_mutex prevents multiple threads updating these concurrently. */atomic_uint n_flows;               /* Number of flows in the datapath. */atomic_llong n_flows_timestamp;    /* Last time n_flows was updated. */struct ovs_mutex n_flows_mutex;/* Following fields are accessed and modified only from the main thread. */struct unixctl_conn **conns;       /* Connections waiting on dump_seq. */uint64_t conn_seq;                 /* Corresponds to 'dump_seq' whenconns[n_conns-1] was stored. */size_t n_conns;                    /* Number of connections waiting. */
};

struct handler以及struct revalidator

/* A thread that reads upcalls from dpif, forwards each upcall's packet,* and possibly sets up a kernel flow as a cache. */
struct handler {struct udpif *udpif;               /* Parent udpif. */pthread_t thread;                  /* Thread ID. */uint32_t handler_id;               /* Handler id. */
};/* A thread that processes datapath flows, updates OpenFlow statistics, and* updates or removes them if necessary.** Revalidator threads operate in two phases: "dump" and "sweep". In between* each phase, all revalidators sync up so that all revalidator threads are* either in one phase or the other, but not a combination.**     During the dump phase, revalidators fetch flows from the datapath and*     attribute the statistics to OpenFlow rules. Each datapath flow has a*     corresponding ukey which caches the most recently seen statistics. If*     a flow needs to be deleted (for example, because it is unused over a*     period of time), revalidator threads may delete the flow during the*     dump phase. The datapath is not guaranteed to reliably dump all flows*     from the datapath, and there is no mapping between datapath flows to*     revalidators, so a particular flow may be handled by zero or more*     revalidators during a single dump phase. To avoid duplicate attribution*     of statistics, ukeys are never deleted during this phase.*     During the sweep phase, each revalidator takes ownership of a different*     slice of umaps and sweeps through all ukeys in those umaps to figure out*     whether they need to be deleted. During this phase, revalidators may*     fetch individual flows which were not dumped during the dump phase to*     validate them and attribute statistics.*/
struct revalidator {struct udpif *udpif;               /* Parent udpif. */pthread_t thread;                  /* Thread ID. */unsigned int id;                   /* ovsthread_id_self(). */
};

之后对每个bridge,调用ofproto_run

netdev_run

/* Performs periodic work needed by all the various kinds of netdevs.** If your program opens any netdevs, it must call this function within its* main poll loop. */
void
netdev_run(void)OVS_EXCLUDED(netdev_mutex)
{netdev_initialize();struct netdev_registered_class *rc;CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {if (rc->class->run) {rc->class->run(rc->class);}}
}

netdev_run会首先调用netdev_initialize,该函数用一个struct ovsthread_once代码块来管理,保证只会调用一次。其主要工作是注册了不同的netdev_class和tunnel_class

static void
netdev_initialize(void)OVS_EXCLUDED(netdev_mutex)
{static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;if (ovsthread_once_start(&once)) {fatal_signal_add_hook(restore_all_flags, NULL, NULL, true);netdev_vport_patch_register();netdev_register_provider(&netdev_linux_class);netdev_register_provider(&netdev_internal_class);netdev_register_provider(&netdev_tap_class);netdev_vport_tunnel_register();ovsthread_once_done(&once);}
}

netdev_vport_patch_register注册了patch port这么一类的vport(patch port用于连接不同的bridge,本身没有dpif的任何属性),netdev_vport_tunnel_register则注册了多种tunnel类型,e.g.

    static const struct vport_class vport_classes[] = {TUNNEL_CLASS("geneve", "genev_sys", netdev_geneve_build_header,netdev_tnl_push_udp_header,netdev_geneve_pop_header),TUNNEL_CLASS("gre", "gre_sys", netdev_gre_build_header,netdev_gre_push_header,netdev_gre_pop_header),TUNNEL_CLASS("ipsec_gre", "gre_sys", NULL, NULL, NULL),TUNNEL_CLASS("vxlan", "vxlan_sys", netdev_vxlan_build_header,netdev_tnl_push_udp_header,netdev_vxlan_pop_header),TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL),TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL),};

除此之外,多个类型的netdev_class也被注册进来,包括dpdk的多个netdev_class

const struct netdev_class netdev_linux_class =NETDEV_LINUX_CLASS("system",netdev_linux_construct,netdev_linux_get_stats,netdev_linux_get_features,netdev_linux_get_status);const struct netdev_class netdev_tap_class =NETDEV_LINUX_CLASS("tap",netdev_linux_construct_tap,netdev_tap_get_stats,netdev_linux_get_features,netdev_linux_get_status);const struct netdev_class netdev_internal_class =NETDEV_LINUX_CLASS("internal",netdev_linux_construct,netdev_internal_get_stats,NULL,                  /* get_features */netdev_internal_get_status);static const struct netdev_class dpdk_class =NETDEV_DPDK_CLASS("dpdk",netdev_dpdk_construct,netdev_dpdk_destruct,netdev_dpdk_set_config,netdev_dpdk_set_tx_multiq,netdev_dpdk_eth_send,netdev_dpdk_get_carrier,netdev_dpdk_get_stats,netdev_dpdk_get_features,netdev_dpdk_get_status,netdev_dpdk_reconfigure,netdev_dpdk_rxq_recv);static const struct netdev_class dpdk_ring_class =NETDEV_DPDK_CLASS("dpdkr",netdev_dpdk_ring_construct,netdev_dpdk_destruct,netdev_dpdk_ring_set_config,netdev_dpdk_set_tx_multiq,netdev_dpdk_ring_send,netdev_dpdk_get_carrier,netdev_dpdk_get_stats,netdev_dpdk_get_features,netdev_dpdk_get_status,netdev_dpdk_reconfigure,netdev_dpdk_rxq_recv);static const struct netdev_class dpdk_vhost_class =NETDEV_DPDK_CLASS("dpdkvhostuser",netdev_dpdk_vhost_construct,netdev_dpdk_vhost_destruct,NULL,NULL,netdev_dpdk_vhost_send,netdev_dpdk_vhost_get_carrier,netdev_dpdk_vhost_get_stats,NULL,NULL,netdev_dpdk_vhost_reconfigure,netdev_dpdk_vhost_rxq_recv);

最后对于每一类注册的netdev_class,都会调用run函数,以netdev_linux_class为例(dpdk_class的run函数为空),主要是通过netlink sock来定期做一些更新的工作,不细说了

原文链接:https://blog.csdn.net/majieyue/article/details/52801322

OVS vswitchd启动(三十九)相关推荐

  1. javaweb学习总结(三十九)——数据库连接池

    javaweb学习总结(三十九)--数据库连接池 一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10 ...

  2. 【正点原子STM32连载】第三十九章 DS18B20数字温度传感器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  3. 孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(三十九)——数据库连接池 一、应用程序直接获取数据库连接的缺点   用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要

    孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(三十九)--数据库连接池 一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对 ...

  4. 【正点原子MP157连载】第三十九章 LCD驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  5. NeHe OpenGL第三十九课:物理模拟

    NeHe OpenGL第三十九课:物理模拟 物理模拟简介: 还记得高中的物理吧,直线运动,自由落体运动,弹簧.在这一课里,我们将创造这一切.   物理模拟介绍 如果你很熟悉物理规律,并且想实现它,这篇 ...

  6. Python编程基础:第三十九节 面向对象编程Object Oriented Programming

    第三十九节 面向对象编程Object Oriented Programming 前言 实践 前言 到目前为止我们都是函数式编程,也即将每一个功能块写为一个函数.其实还有一种更常用的编程方式被称为面向对 ...

  7. 三十九、Java集合中的HashSet和TreeSet

    @Author:Runsen @Date:2020/6/6 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业排名 ...

  8. WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形

    原文:WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形 说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘> ...

  9. 【零基础学Java】—List集合(三十九)

    [零基础学Java]-List集合(三十九) java.util.list接口 extends Collection接口 list接口的特点: 1.有序的集合,存储元素和取出元素的顺序是一致的(存储1 ...

  10. JavaScript学习(三十九)—对象中内容的操作

    JavaScript学习(三十九)-对象中内容的操作 一.对象中内容的操作:增.删.改.查 (一).增:给对象添加属性或者方法 1)方式1:对象名称.属性名=属性值: 2)方式2:对象名称['属性名' ...

最新文章

  1. Android API中文系列总结
  2. 最大字段和_使对易失性字段的操作原子化
  3. feignclient url_Spring Cloud Feign 请求动态URL
  4. 鸿蒙系统是单任务还是多任务,在鸿蒙系统上使用MQTT编程
  5. 驱动框架1——什么是驱动框架?
  6. ztree在刷新时第一个父节点消失_从反向传播推导到梯度消失and爆炸的原因及解决方案(从DNN到RNN,内附详细反向传播公式推导)...
  7. Thin的DateChooser代码学习(getScrollPosition)(原创,转载请声明)
  8. ES6 — 箭头函数
  9. 在3dmax中打开文件时,显示路径无效,如何处理?
  10. 条形码扫描仪行业调研报告 - 市场现状分析与发展前景预测
  11. C#写简单HTML报表
  12. Java、JSP在线问卷调查系统
  13. 什么是小规模纳税人、小型微利企业、小微企业
  14. Typhoon-v1.02 靶机入侵
  15. KMS命令激活office2016
  16. Deepin-TIM / QQ / WeChat调整界面DPI字体大小的方法
  17. easyexcel结合zip 导出压缩文件(包含多个excel)
  18. 新华三:助力IPv6部署,我们责无旁贷
  19. 一个简单的BitTorrent客户端实现(六):peer manager和peer实现
  20. linux系统运行flash3d,在Linux上运行STM32,快来试试!

热门文章

  1. python语言学了有用吗-转行学习Python开发有什么优势
  2. python中文叫什么意思-在python中%是什么意思
  3. python数据处理实例-Python数据处理numpy.median的实例讲解
  4. python处理流程-在python异步协程中处理流程分析(一)
  5. 从零开始学python微课视频版-从零开始学Python(微课视频版)
  6. python银行系统-python银行系统实现源码
  7. 怎么自学python软件-Python入门学习难吗,新手如何学习
  8. 为什么要叫python-为什么我们要学习Python?
  9. python基础知识选择题-python基础知识练习题(二)
  10. SPOJ Supernumbers in a permutation(LIS)