zoukankan      html  css  js  c++  java
  • Open vSwitch Datapath浅析

    下图所示是Open vSwitch的组成(摘自Open vSwitch官网):

     

    它分为Kernel部分和User部分。

    安装驱动

    Kerenl部分是从Linux 2.6.32开始何如内核,默认是编译为一个KO,位于/lib/modules/`uname –r`/kernel/net/openvswitch/openvswitch.ko。

     

    应用open vswitch首先要做的就是install这个kernel module。需要注意,GRE Tunneling的支持需要gre.ko, VXLAN的支持需要vxlan.ko, 这两个KO都位于/lib/modules/`uname –r`/kernel/路径下。

    user部分是有两个daemon,一个是ovs-vswitchd,用来管理datapath,另外一个是ovsdb-server,用来维护一个数据库。

    初始化dbserver

    在install好openvswitch.ko后,我们接着需要初始化这个ovsdb-server:

    123

    opendb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock             --remote=Open_vSwitch,Open_vSwitch,manager_option             --pidfile --detach

    此时会生成一个数据库文件(/usr/local/etc/conf.db),该dbserver会将网络状态信息给记录到conf.db里面。这些网络状态使得open vswitch能够适应网络的动态变化,比如可以用来追踪VM的迁移。 
    这个dbserver还可以通过TCP的6632端口跟远端的openflow server进行通信,这个openflow server可以通过remote这个参数来指定。

    启动ovs-vswitchd

    接下来就需要启动ovs-vswitchd:

    ovs-vswitchd —pidfile —detach

    整个OVS的核心就是这个ovs-vswitchd。 
    这样子open vswich就在PC上运行起来了。

    构建网络拓扑

    我们来构建如下图所示的一个网络拓扑:

     

    首先需要增加一个bridge(br0)

    ovs-vsctl add-br br0

    执行这个命令后,

    1. 将br0记录到ovsdb里面

    2. ovs-vswitchd创建一个新的bridge

    3. ovs-vswitchd通过netlink这种方式,发相应的cmd给kernel,执行对应的handler来生成一个datapath以及和其相关的一些结构体。 
    每个bridge都对应于一个datapath结构体。

    接着来将网络结构设备连接到该bridge

    ovs-ctl add-port br0 eth1

    执行这个命令后, 
    1. 将该信息记录到ovsdb 
    2. ovs-vswitchd在bridge上新增一个端口,并将其设置为混杂模式(NETDEV_PROMISC),设置为混杂模式的目的是为了接收非本机MAC地址的包 
    3. ovs-vswitchd通过netlink调用到kernel端的handler,此时:

    1. 找到“eth1”对应的net\_device     

    2.  把该net\_device的handler替换为ovs的handler,这样net\_device的进包就不会进入普通的内核处理流程,而是由OVS接收过来处理。    

    3. 产生一个新的vport结构体    

    整个过程如下图所示:

     


    至此,就初始化完成了kernel module的主要结构体datapath/vport/flow_table。这些主要结构体的关系如下图所示:

     

    设置openflow server

    下面这个命令可以用来设置远端用来和ovs-vswitchd通信的openflow server:

    ovs-vsctl set-controller br0 tcp:XXX.XXX.XXX.XXX:6633

    如下图所示:

     


    根据不同的设备类型,ovs实现了不同的vport以作支持。目前OVS共支持了6种vport:

    1234567

    A. Network device : tap & system deviceB. Network device implemented by datapath: internal deviceinternal device存在的目的是为了给bridge分配IP地址。C. GRE tunnelD. GRE64 tunnelE. VXLAN tunnelF. LISP tunnel

    以ping为例子来看下包处理流程

    VM0来ping VM1. 
    当vm0以ping发送一个ICMP报文给OVS时,OVS会依次进行如下处理:

    1. ping 
    VM0发送报文到tap0, tap0和br0的一个端口相连。br0的端口对应一个vport结构体。

    2. ovs receive 
    ovs执行tap0的receive handler,(即在前面执行ovs-ctl add-port br0 eth1 tag=XXX时注册的那个handler) 
    tag=XXX就是vlan,通过vlan来实现网络隔离的功能。

    3. flow key 
    从sk_buff中解析出来L2~L4的信息生成一个flow_key. 
    flow可以理解为一个以太网包所包含的头部信息的集合,在一个flow table里面的一个flow必须是唯一的,它是包含L2/L3/L4这些头部的一个细粒度的实体。一个TCP连接由两个flow组成,每个方向上有一个。

     


    4. flow lookup 
    使用该key来执行flow_lookup, 去跟kernel module里面维护的flow table进行比较。 
    首先去跟 flow_table里的 mask_cache数组进行比较, mask_cache里面只有 sk_buff的 hash值所以很快速; 
    接着再去跟 mask_array这个数组进行比较,这个数组里面存放是的 sw_flow_key, 查找相对慢一些。 
    如果在 mask_array里面匹配到了这个 flow,就会把该 sk_buff的 hash值给放到 mask_cache里面。 
    在 kenerl里的这部分比较称之为 ovs的 fast path

     


    5. flow action 
    如果在kernel中查找到了对应的flow entry,就去执行对应的flow action。 
    这些action是告诉datapath怎么去处理flow里面的这些packets。 
    action也可以为空,即丢弃这些packets。 
    datapath的这些action跟openflow定义的action是一致的。 
    6. send upcall 
    如果没有match到,就执行upcall通过netlink的方式给ovs-vswitchd发送OVS_PACKET_CMD_MISS命令。 
    UPCALL会包含整个packet,虽然不必要拷贝整个的packet给user space,可以做一些优化,但是由于只是拷贝first packet(比如TCP SYN),所以这种优化意义不大,而且有时候可能真的会用到整个packet。 
    ovs-vswitch一次只处理一个upcall,为了能够让每一个port产生的upcall都能够得到即使处理,datapath是采用的round robin这种方式来让每个port发送upcall。 
    UPCALL发送出去后,dadapath的处理就结束了。 
    一个普通的UPCALL结构如下图所示。

     


    7. handle upcall 
    ovs-vswitchd执行read_upcalls来读取upcall。 
    read_upcalls的主要处理流程如下图所示。

     


    Hash bucket的数据结构是hmap,如下图所示

     


    8. flow table match 在userspace维护着openflowtable。对hmap里面的flow以wildcard的方式来与openflowtable匹配。 
    Openflowtable的匹配过程大致如下图。

     


    9. MAC learning 
    在open vswitch里面配置MAC learning功能

    12345

    ovs-ofctl add-flow br0   "table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11],    NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],    load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]),      resubmit(,3)“

     

     转载地址:http://laoar.net/blog/2015/04/27/open-vswitch/

  • 相关阅读:
    移动开发 Native APP、Hybrid APP和Web APP介绍
    urllib与urllib2的学习总结(python2.7.X)
    fiddler及postman讲解
    接口测试基础
    UiAutomator2.0 和1.x 的区别
    adb shell am instrument 命令详解
    GT问题记录
    HDU 2492 Ping pong (树状数组)
    CF 567C Geometric Progression
    CF 545E Paths and Trees
  • 原文地址:https://www.cnblogs.com/liuhongru/p/11398638.html
Copyright © 2011-2022 走看看