• 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/

  • 相关阅读:
    JAVA共通関数文字列の長さを求める
    JAVA共通関数文字コード変換
    JAVA共通関数文字列に空白を追加する
    JAVA共通関数 半角英数字チェック
    JAVA共通関数項目が半角09か判断する
    JAVA共通関数 指定日の曜日を算出する
    linux添加静态路由(rhel5.4)
    ubuntu编译opencapwap报错解决
    Wireshark网络抓包(二)——过滤器
    net.ipv4.tcp_tw_recycle、net.ipv4.tcp_tw_reuse回收tcp连接总结
  • 原文地址:https://www.cnblogs.com/liuhongru/p/11398638.html
Copyright © 2020-2023  润新知