This is NOT a tutorial on how to use openvswitch, this is for developers who want to know the implementation details of openvswitch project, thus, I assume you at least know the basic concepts of openvswitch and know how to use it. If not, see www.openvswitch.org to get some documents or slides.

Let’s start from the user-space part. Openvswitch user-space contains several components: they are a few daemons which actually implements the switch and the flow table, the core of openvswitch, and several utilities to manage the switch, the database, and even talk to the kernel directly.

There are three daemons started by openvswitch service: ovs-vswitchd, which is the core implementation of the switch; ovsdb-server, which manipulates the database of the vswitch configuration and flows; and ovs-brcompatd which keeps the compatibility with the traditional bridges (that is the one you create with ‘brctl’ command) .

Their relationship is shown in the picture below:

Obviously, the most important one is ovs-vswitchd, it implements the switch, it directly talks with kernel via netlink protocol (we will see the details later). And ovs-vsctl is the utility used primarily to manage the switch, which of course needs to talk with ovs-vswitchd. Ovs-vswitchd saves and changes the switch configuration into a database, which is directly managed by ovsdb-server, therefore, ovs-vswitchd will need to talk to ovsdb-server too, via Unix domain socket, in order to retrieve or save the configuration information. This is also why your openvswitch configuration could survive from reboot even you are not using ifcfg* files.

Ovs-brcompatd is omitted here, we are not very interested in it now.

Ovs-vsctl can do lots of things for you, so most of time, you will use ovs-vsctl to manage openvswitch. Ovs-appctl is also available to manage the ovs-vswitchd itself, it sends some internal commands to ovs-vswitchd daemon to change some configurations.

However, sometimes you may need to manage the datapath in the kernel directly by yourself, in this case, assume ovs-vswitchd is not running, you can invoke ovs-dpctl to let ovs-vswitchd to manage the datapath in the kernel space directly, without database.

And, when you need to talk with ovsdb-server directly, to do some database operation, you can run ovsdb-client, or you want to manipulate the database directly without ovsdb-server, ovsdb-tool is handy too.

What’s more, openvswitch can be also administered and monitored by a remote controller. This is why we could define the network by software! sFlow is a protocol for packet sampling and monitoring, while OpenFlow is a protocol to manage the flow table of a switch, bridge, or device. Openvswitch supports both OpenFlow and sFlow. With ovs-ofctl, you can use OpenFlow to connect to the switch and do some monitoring and administering in the remote. sFlowTrend, which is not a part of openvswitch package, is the one that is capable for sFlow.

Now, let’s take a look at the kernel part.

As mentioned previously, the user-space communicates with the kernel-space via netlink protocol, generic netlink is used in this case. So there are several groups of genl commands defined by the kernel, they are used to get/set/add/delete some datapath/flow/vport and execute some actions on a specific packet.

The ones used to control datapatch are:

enum ovs_datapath_cmd {

OVS_DP_CMD_UNSPEC,

OVS_DP_CMD_NEW,

OVS_DP_CMD_DEL,

OVS_DP_CMD_GET,

OVS_DP_CMD_SET

};

and there are corresponding kernel functions which does the job:

ovs_dp_cmd_new()

ovs_dp_cmd_del()

ovs_dp_cmd_get()

ovs_dp_cmd_set()

Similar functions are defined for vport and flow commands too.

Before we talk about the details of the data structures, let’s see how a packet is sent out or received from a port of an ovs bridge. When is packet is send out from the ovs bridge, an internal device defined by openvswitch module, which is viewed, by the kernel, as a struct vport too. The packet will be finally passed to internal_dev_xmit(), which in turn “receives” the packet. Now, the kernel needs to look at the flow table, to see if there is any “cache” for how to forward this packet. This is done by function ovs_flow_tbl_lookup(), which needs a key. The key is extracted by ovs_flow_extract() which briefly collects the details of the packet (L2~L4) and then constructs a unique key for this flow. Assume this is the first packet going out after we create the ovs bridge, so, there is no “cache” in the kernel, and the kernel doesn’t know how to handle this packet! Then it will pass it to the user-space with “upcall” which uses genl too. The user-space daemon, ovs-vswitchd, will check the database and see which is the destination port for this packet, and will response to the kernel with OVS_ACTION_ATTR_OUTPUT to tell kernel which is the port it should forward to, in this case let’s assume it is eth0. and finally a OVS_PACKET_CMD_EXECUTE command is to let the kernel execute the action we just set. That is, the kernel will execute this genl command in function do_execute_actions() and finally forward the packet to the port “eth0” with do_output(). Then it goes to outside!

The receiving side is similar. The openvswitch module registers an rx_handler for the underlying (non-internal) devices, it is netdev_frame_hook(), so once the underlying device receives packets on wire, openvswitch will forward it to user-space to check where it should goes, and what actions it needs to execute on it. For example, if this is a VLAN packet, the VLAN tag should be removed from the packet first, and then forwarded to a right port. The user-space could learn that which is the right port to forward a given packet.

The internal devices are special, when a packet is sent to an internal device, it is be immediately sent up to openvswitch to decide where it should go, instead of really sending it out. There is actually no way out of an internal device directly.

Besides OVS_ACTION_ATTR_OUTPUT, the kernel also defines some other actions:

OVS_ACTION_ATTR_USERSPACE, which tells the kernel to pass the packet to user-space

OVS_ACTION_ATTR_SET: Modify the header of the packet

OVS_ACTION_ATTR_PUSH_VLAN: Insert a vlan tag into the packet

OVS_ACTION_ATTR_POP_VLAN: Remove the vlan tag from the packet

OVS_ACTION_ATTR_SAMPLE: Do sampling

With these commands combined, the user-space could implement some different policies, like a bridge, a bond or a VLAN device etc. GRE tunnel is not currently in upstream, so we don’t care about it now.

So far, you already know how the packets are handled by openvswitch module. There are much more details, especially about the flow and datapath mentioned previously. A flow in kernel is represented as struct sw_flow, and datapath is defined as struct datapath, and the actions on a flow is defined as struct sw_flow_actions, and plus the one we mentioned, struct vport. These structures are the most important ones for openvswitch kernel module, their relationship is demonstrated in this picture:

The most important one needs to mention is each struct sk_buff is associated with a struct sw_flow, which is via a pointer in ovs control block. And the above actions is associated with each flow, every time when a packet passed to openvswitch module, it first needs to lookup the flow table which is contained in a datapath which in turn either contains in a struct vport or in a global linked-list, with the key we mentioned. If a flow is found, the corresponding actions will be executed. Remember that datapath, flow, vport, all could be changed by the user-space with some specific genl command.

As you can see, the kernel part only implements a mechanism and the fast path (except the first packet), and the user-space implements different policies upon the mechanism provided by the kernel, the slow path. The user-space is much more complicated, so I will not cover its details here.

Update: Ben, one of the most active developers for openvswitch, pointed out some mistakes in the previous version, I updated this article as he suggested. Thanks to Ben!

[转]An overview of Openvswitch implementation的更多相关文章

  1. adb概览及协议參考

    原文:https://github.com/android/platform_system_core/blob/master/adb/OVERVIEW.TXT) Implementation note ...

  2. 使Web Api 支持跨域资源共享(CORS)

    Reference:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api Imp ...

  3. adb概览及协议参考

    原文:https://github.com/android/platform_system_core/blob/master/adb/OVERVIEW.TXT) Implementation note ...

  4. Migrating Oracle on UNIX to SQL Server on Windows

    Appendices Published: April 27, 2005 On This Page Appendix A: SQL Server for Oracle Professionals Ap ...

  5. wxpython wx.windows的API

    wx.Window is the base class for all windows and represents any visible object on screen. All control ...

  6. Object Pascal中文手册 经典教程

    Object Pascal 参考手册 (Ver 0.1)ezdelphi@hotmail.com OverviewOverview(概述)Using object pascal(使用 object p ...

  7. Method of address space layout randomization for windows operating systems

    A system and method for address space layout randomization ("ASLR") for a Windows operatin ...

  8. Overview and Evaluation of Bluetooth Low Energy: An Emerging Low-Power Wireless Technology

    转自:http://www.mdpi.com/1424-8220/12/9/11734/htm Sensors 2012, 12(9), 11734-11753; doi:10.3390/s12091 ...

  9. IMS Global Learning Tools Interoperability™ Implementation Guide

    Final Version 1.1 Date Issued:            13 March 2012 Latest version:         http://www.imsglobal ...

随机推荐

  1. idea 断点上面有x

    背景:确定你的java代码没有问题,并且编译通过 问题:debug 启动项目的时候没有问题,idea打断点的时候左边红色断点上面有x 原因:java文件和class文件不一致, 解决方法:ant cl ...

  2. 不使用 vue-cli 与 vue 模版,使用 Vue2.x + webpack4.x 从零开始一步步搭建项目框架

    说明 这是我根据慕课网上的一个课程 Vue+Webpack打造todo应用 过程一步步搭下来的框架,去掉了业务相关的逻辑. 项目最终的效果包括了引入vue框架:使用CSS预处理器:使用babel:引用 ...

  3. 获取QQ头像接口

    https://q4.qlogo.cn/g?b=qq&nk=QQ号码&s=140

  4. 《JavaScript高级程序设计》读书笔记--ECMAScript中所有函数的参数都是按值传递的

    ECMAScript中所有函数的参数都是按值传递的.也就是说把函数外部的值复制给函数内部的参数(内部参数的值的修改不影响实参的值). 基本类型变量的复制: 基本类型变量的复制,仅仅是值复制,num1和 ...

  5. 使用vs2010编译lua5.1源代码生成lua.lib

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/wangbin_jxust/article/details/37557807 一.打开vs2010 二 ...

  6. BZOJ4300:绝世好题(DP)

    Description 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len). Input 输入文件共2行. 第一行包括一个整数 ...

  7. 构造方法、 This关键字 、static、封装

    1.1 构造方法 构造方法是一种特殊的方法,专门用于构造/实例化对象,形式: [修饰符] 类名(){ } 构造方法根据是否有参数分为无参构造和有参构. 1.1.1 无参构造 无参构造方法就是构造方法没 ...

  8. <数据结构与算法分析>读书笔记--函数对象

    关于函数对象,百度百科对它是这样定义的: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.又称仿函数. 听起来确实很难懂,通过搜索我找到一篇 ...

  9. jsp二(指令)

    一.jsp动作标签: 1)<jsp:forward> 请求转发 相当于之前的request.getRequestDispatcher(..).forward(..); <!--jsp ...

  10. A. Nephren gives a riddle

    What are you doing at the end of the world? Are you busy? Will you save us? Nephren is playing a gam ...