20个基于DPDL开源项目,带你冲破内核瓶颈(上)

简介: 20个基于DPDL开源项目,带你冲破内核瓶颈

前言:开源(Open Source,开放源码)被非盈利软件组织(美国的Open Source Initiative协会)注册为认证标记,并对其进行了正式的定义,用于描述那些源码可以被公众使用的软件,并且此软件的使用、修改和发行也不受许可证的限制。

一、OVS-DPDK 虚拟交换机

OVS-DPDK(Open vSwitch with DPDK)是一种高性能的虚拟交换机,它将DPDK(Data Plane Development Kit)和Open vSwitch技术相结合,用于在虚拟化环境中加速数据平面处理。OVS-DPDK采用用户空间数据包处理模式,利用DPDK提供高效、低延迟的数据包处理功能,并且可以与传统的内核态网络协议栈进行无缝衔接。

通过使用OVS-DPDK,可以实现更高的吞吐量和更低的延迟,从而提升网络性能。同时,OVS-DPDK还支持灵活配置和管理网络服务,并且可以与其他开源软件如OpenStack等集成使用。因此,在云计算、SDN、NFV等领域中得到了广泛应用。

要使用 ovs-dpdk,需要在node上构建 DPDK 并使用相应的 DPDK flag重新构建 ovs。OVS-DPDK需要从源码编译,因为高度依赖内核等所在机器的环境,并需要配置很多参数以达到高性能。这意味着很难提供一个ovs-dpdk docker镜像来满足所有情况。

OVS-DPDK需要大页内存作为资源。由于 DPDK 会剥夺系统对 nic 的控制权,我们需要一个 ovs-dpdk 专用的 nic 来传输容器网络,另一个 nic 用于普通主机网络。

普通Pod的ovs网络是在 pod 和 ovs 端口之间放置了一个 veth 对。veth 的一端移动到容器网络命名空间。不能用 OVS-DPDK 做到这一点。当我们请求一个新的 DPDK 端口时,我们最终会在 /var/run/openvswitch/ 这样的目录中得到一个类似 vhost-user 套接字文件的东西。它不能在命名空间之间移动,它必须被挂载到 pod 中就像一个普通的文件(由 Userspace-CNI 提供的功能)。所以不能使用 OVS-DPDK 作为默认网络。Pod对K8S API不可达,K8S不能对pod进行健康检查。因此,需要依赖 Multus 来连接多个网络。Kernel-OVS 仍然是默认网络。此外,Multus 允许为Pod提供 OVS-DPDK 网络。这是同一个 OVS 实例,但是 DPDK port位于另一个支持 DPDK 的bridge上。

ovs-dpdk创建br和port, ovs 集成网桥类型更改为 netdev ,端口类型更改为 dpdkvhostuser 并设置其他 ovs-dpdk 参数。

1.1准备工作

[root@backendcloud-fedora27 ~]# dnf groupinstall "Development Tools"
[root@backendcloud-fedora27 ~]# dnf groupinstall "Virtualization"
[root@backendcloud-fedora27 ~]# dnf install qemu
[root@backendcloud-fedora27 ~]# dnf install automake tunctl kernel-tools pciutils hwloc numactl
[root@backendcloud-fedora27 ~]# dnf install libpcap-devel
[root@backendcloud-fedora27 ~]# dnf install numactl-devel
[root@backendcloud-fedora27 ~]# dnf install libtool

1.2编译DPDK

[root@backendcloud-fedora27 ~]# tar xf dpdk-17.08.1.tar.xz 
[root@backendcloud-fedora27 ~]# ls
anaconda-ks.cfg  dpdk-17.08.1.tar.xz  dpdk-stable-17.08.1
[root@backendcloud-fedora27 ~]# cd dpdk-
-bash: cd: dpdk-: No such file or directory
[root@backendcloud-fedora27 ~]# cd dpdk-stable-17.08.1/
[root@backendcloud-fedora27 dpdk-stable-17.08.1]# export DPDK_DIR=`pwd`/build
[root@backendcloud-fedora27 dpdk-stable-17.08.1]# make config T=x86_64-native-linuxapp-gcc
Configuration done using x86_64-native-linuxapp-gcc
[root@backendcloud-fedora27 dpdk-stable-17.08.1]# sed -ri 's,(PMD_PCAP=).*,\1y,' build/.config
[root@backendcloud-fedora27 dpdk-stable-17.08.1]# make

make 报错:

/usr/src/kernels/4.18.19-100.fc27.x86_64/Makefile:945: *** "Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel".  Stop.

安装 elfutils-libelf-devel 解决:

[root@backendcloud-fedora27 dpdk-stable-17.08.1]# yum install -y elfutils-libelf-devel

编译OvS-DPDK

[root@backendcloud-fedora27 ~]# wget http://openvswitch.org/releases/openvswitch-2.8.1.tar.gz
[root@backendcloud-fedora27 ~]# tar -xzvf openvswitch-2.8.1.tar.gz
[root@backendcloud-fedora27 ~]# cd openvswitch-2.8.1/
[root@backendcloud-fedora27 openvswitch-2.8.1]# export OVS_DIR=`pwd`
[root@backendcloud-fedora27 openvswitch-2.8.1]# sudo ./boot.sh
[root@backendcloud-fedora27 openvswitch-2.8.1]# sudo ./configure --with-dpdk="$DPDK_DIR/" CFLAGS="-g -Ofast"
[root@backendcloud-fedora27 openvswitch-2.8.1]# sudo make 'CFLAGS=-g -Ofast -march=native' -j10

Create OvS DB and Start OvS DB-Server

[root@backendcloud-fedora27 openvswitch-2.8.1]# pkill -9 ovs
[root@backendcloud-fedora27 openvswitch-2.8.1]# rm -rf /usr/local/var/run/openvswitch
[root@backendcloud-fedora27 openvswitch-2.8.1]# rm -rf /usr/local/etc/openvswitch/
[root@backendcloud-fedora27 openvswitch-2.8.1]# rm -f /usr/local/etc/openvswitch/conf.db
[root@backendcloud-fedora27 openvswitch-2.8.1]# mkdir -p /usr/local/etc/openvswitch
[root@backendcloud-fedora27 openvswitch-2.8.1]# mkdir -p /usr/local/var/run/openvswitch
[root@backendcloud-fedora27 openvswitch-2.8.1]# cd $OVS_DIR
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./ovsdb/ovsdb-tool create /usr/local/etc/openvswitch/conf.db ./vswitchd/vswitch.ovsschema
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./ovsdb/ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl --no-wait init

Configure Fedora27 for OvS-DPDK

[root@backendcloud-fedora27 openvswitch-2.8.1]# vim /etc/default/grub
...
GRUB_CMDLINE_LINUX_DEFAULT="default_hugepagesz=1G hugepagesz=1G hugepages=4 hugepagesz=2M hugepages=512 iommu=pt intel_iommu=on"
[root@backendcloud-fedora27 openvswitch-2.8.1]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.18.19-100.fc27.x86_64
Found initrd image: /boot/initramfs-4.18.19-100.fc27.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-98bddbf29a4f40009b8390e2c27a80ac
Found initrd image: /boot/initramfs-0-rescue-98bddbf29a4f40009b8390e2c27a80ac.img
done
[root@backendcloud-fedora27 openvswitch-2.8.1]# reboot

可以设置cpu隔离:GRUB_CMDLINE_LINUX_DEFAULT=”default_hugepagesz=1G hugepagesz=1G hugepages=16 hugepagesz=2M hugepages=2048 iommu=pt intel_iommu=on isolcpus=1-27,29-55”

[root@backendcloud-fedora27 ~]# mkdir -p /mnt/huge
[root@backendcloud-fedora27 ~]# mkdir -p /mnt/huge_2mb
[root@backendcloud-fedora27 ~]# mount -t hugetlbfs hugetlbfs /mnt/huge
[root@backendcloud-fedora27 ~]# mount -t hugetlbfs none /mnt/huge_2mb -o pagesize=2MB
[root@backendcloud-fedora27 ~]# cat /proc/meminfo 
MemTotal:       17650724 kB
MemFree:        11744728 kB
MemAvailable:   11867184 kB
...
HugePages_Total:       4
HugePages_Free:        4
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB
Hugetlb:         5242880 kB
DirectMap4k:      124736 kB
DirectMap2M:     5273600 kB
DirectMap1G:    13631488 kB
[root@backendcloud-fedora27 ~]# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-4.18.19-100.fc27.x86_64 root=/dev/mapper/fedora-root ro rd.lvm.lv=fedora/root rhgb quiet default_hugepagesz=1G hugepagesz=1G hugepages=4 hugepagesz=2M hugepages=512 iommu=pt intel_iommu=on

配置OVS-DPDK

[root@backendcloud-fedora27 ~]# modprobe vfio-pci
[root@backendcloud-fedora27 ~]# modprobe openvswitch
[root@backendcloud-fedora27 ~]# cd openvswitch-2.8.1
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./ovsdb/ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./vswitchd/ovs-vswitchd unix:/usr/local/var/run/openvswitch/db.sock --pidfile --detach
2022-09-22T06:09:08Z|00001|ovs_numa|INFO|Discovered 4 CPU cores on NUMA node 0
2022-09-22T06:09:08Z|00002|ovs_numa|INFO|Discovered 1 NUMA nodes and 4 CPU cores
2022-09-22T06:09:08Z|00003|reconnect|INFO|unix:/usr/local/var/run/openvswitch/db.sock: connecting...
2022-09-22T06:09:08Z|00004|reconnect|INFO|unix:/usr/local/var/run/openvswitch/db.sock: connected
2022-09-22T06:09:08Z|00005|dpdk|INFO|DPDK Disabled - Use other_config:dpdk-init to enable
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true

配置隔离cpu,memory提高DPDK性能,非必须。

[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x10000001
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xffffffeffffffe
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="1024,1024"

Creating an OvS-DPDK Bridge and Ports

[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl show
52de1671-20cc-438c-be6a-d41e7923100b
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl add-port br0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl add-port br0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser
[root@backendcloud-fedora27 openvswitch-2.8.1]# ./utilities/ovs-vsctl show
52de1671-20cc-438c-be6a-d41e7923100b
    Bridge "br0"
        Port "vhost-user1"
            Interface "vhost-user1"
                type: dpdkvhostuser
        Port "br0"
            Interface "br0"
                type: internal
        Port "vhost-user2"
            Interface "vhost-user2"
                type: dpdkvhostuser

Binding Nic Device to DPDK

[root@backendcloud-fedora27 openvswitch-2.8.1]# modprobe vfio-pci
[root@backendcloud-fedora27 openvswitch-2.8.1]# cp ~/dpdk-stable-17.08.1/usertools/dpdk-devbind.py /usr/bin/
[root@backendcloud-fedora27 openvswitch-2.8.1]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:7a:c2:a0 brd ff:ff:ff:ff:ff:ff
    inet 192.168.126.143/24 brd 192.168.126.255 scope global dynamic ens33
       valid_lft 1442sec preferred_lft 1442sec
    inet6 fe80::7e7a:3d91:e5b0:4a63/64 scope link 
       valid_lft forever preferred_lft forever
3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:7a:c2:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.126.144/24 brd 192.168.126.255 scope global dynamic ens34
       valid_lft 1398sec preferred_lft 1398sec
    inet6 fe80::49fe:5d8c:8b86:95d8/64 scope link 
       valid_lft forever preferred_lft forever
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:30:d1:c3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
5: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:30:d1:c3 brd ff:ff:ff:ff:ff:ff
6: ovs-netdev: <BROADCAST,PROMISC> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 22:0e:6b:c1:4c:91 brd ff:ff:ff:ff:ff:ff
7: br0: <BROADCAST,PROMISC> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 0e:3b:21:02:03:47 brd ff:ff:ff:ff:ff:ff
[root@backendcloud-fedora27 openvswitch-2.8.1]# dpdk-devbind.py --status
Network devices using DPDK-compatible driver
============================================
<none>
Network devices using kernel driver
===================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=ens33 drv=e1000 unused=vfio-pci *Active*
0000:02:02.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=ens34 drv=e1000 unused=vfio-pci *Active*
...
[root@backendcloud-fedora27 openvswitch-2.8.1]# dpdk-devbind.py --bind=vfio-pci ens34
Routing table indicates that interface 0000:02:02.0 is active. Not modifying
[root@backendcloud-fedora27 openvswitch-2.8.1]# yum install -y net-tools
[root@backendcloud-fedora27 openvswitch-2.8.1]# ifconfig ens34 down
[root@backendcloud-fedora27 openvswitch-2.8.1]# dpdk-devbind.py --bind=vfio-pci ens34
[root@backendcloud-fedora27 openvswitch-2.8.1]# dpdk-devbind.py --status
Network devices using DPDK-compatible driver
============================================
0000:02:02.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' drv=vfio-pci unused=
Network devices using kernel driver
===================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=ens33 drv=e1000 unused=vfio-pci *Active*
...

Using DPDK vhost-user Ports with VMs

去官网下载镜像并修改root密码:

[root@backendcloud-fedora27 ~]# virt-customize -a centos7vm1.qcow2 --root-password password:666666
-bash: virt-customize: command not found
[root@backendcloud-fedora27 ~]# dnf install -y libguestfs-tools
[root@backendcloud-centos9 ~]# virt-customize -a centos7vm1.qcow2 --root-password password:666666
[   0.0] Examining the guest ...
[   6.8] Setting a random seed
[   6.8] Setting passwords
[   8.3] SELinux relabelling
[  12.9] Finishing off
[root@backendcloud-centos9 ~]# virt-customize -a centos7vm2.qcow2 --root-password password:666666

启动两个dpdk vm:

qemu-system-x86_64 -m 1024 -smp 4 -cpu host,pmu=off -hda /root/centos7vm1.qcow2 -boot c -enable-kvm -no-reboot -net none -nographic \
-chardev socket,id=char1,path=/usr/local/var/run/openvswitch/vhost-user1 \
-netdev type=vhost-user,id=mynet1,chardev=char1,vhostforce \
-device virtio-net-pci,mac=00:00:00:00:00:01,netdev=mynet1 \
-object memory-backend-file,id=mem,size=1G,mem-path=/dev/hugepages,share=on \
-numa node,memdev=mem -mem-prealloc
qemu-system-x86_64 -m 1024 -smp 4 -cpu host,pmu=off -hda /root/centos7vm2.qcow2 -boot c -enable-kvm -no-reboot -net none -nographic \
-chardev socket,id=char2,path=/usr/local/var/run/openvswitch/vhost-user2 \
-netdev type=vhost-user,id=mynet2,chardev=char2,vhostforce \
-device virtio-net-pci,mac=00:00:00:00:00:02,netdev=mynet2 \
-object memory-backend-file,id=mem,size=1G,mem-path=/dev/hugepages,share=on \
-numa node,memdev=mem -mem-prealloc

若上面的操作是在vmware上操作,需要加上上面额外的参数pmu=off,为了规避vmware的bug。若不加会报下面的错误:

[root@backendcloud-fedora27 ~]# qemu-system-x86_64 -m 1024 -smp 4 -cpu host -hda /root/centos7vm1.qcow2 -boot c -enable-kvm -no-reboot -net none -nographic \
> -chardev socket,id=char1,path=/usr/local/var/run/openvswitch/vhost-user1 \
> -netdev type=vhost-user,id=mynet1,chardev=char1,vhostforce \
> -device virtio-net-pci,mac=00:00:00:00:00:01,netdev=mynet1 \
> -object memory-backend-file,id=mem,size=1G,mem-path=/dev/hugepages,share=on \
> -numa node,memdev=mem -mem-prealloc
qemu-system-x86_64: error: failed to set MSR 0x38d to 0x0
qemu-system-x86_64: /builddir/build/BUILD/qemu-2.10.2/target/i386/kvm.c:1806: kvm_put_msrs: Assertion `ret == cpu->kvm_msr_buf->nmsrs' failed.
Aborted (core dumped)

1.3安装iperf3,并测试

[root@localhost ~]# iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.0.2, port 48462
[  5] local 192.168.0.1 port 5201 connected to 192.168.0.2 port 48464
[ ID] Interval           Transfer     Bandwidth
[  5]   0.00-1.00   sec   828 MBytes  6.95 Gbits/sec                  
[  5]   1.00-2.00   sec   775 MBytes  6.51 Gbits/sec                  
[  5]   2.00-3.00   sec   852 MBytes  7.15 Gbits/sec                  
[  5]   3.00-4.00   sec  1.03 GBytes  8.85 Gbits/sec                  
[  5]   4.00-5.00   sec   928 MBytes  7.79 Gbits/sec                  
[  5]   5.00-6.00   sec   905 MBytes  7.59 Gbits/sec                  
[  5]   6.00-7.00   sec   824 MBytes  6.91 Gbits/sec                  
[  5]   7.00-8.00   sec   962 MBytes  8.07 Gbits/sec                  
[  5]   8.00-9.00   sec   987 MBytes  8.28 Gbits/sec                  
[  5]   9.00-10.00  sec   856 MBytes  7.19 Gbits/sec                  
[  5]  10.00-10.04  sec  35.2 MBytes  7.97 Gbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  5]   0.00-10.04  sec  0.00 Bytes  0.00 bits/sec                  sender
[  5]   0.00-10.04  sec  8.80 GBytes  7.53 Gbits/sec                  receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
[root@localhost ~]# iperf3 -c 192.168.0.1
Connecting to host 192.168.0.1, port 5201
[  4] local 192.168.0.2 port 48464 connected to 192.168.0.1 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec   861 MBytes  7.22 Gbits/sec  1087    177 KBytes       
[  4]   1.00-2.00   sec   745 MBytes  6.26 Gbits/sec  566    182 KBytes       
[  4]   2.00-3.00   sec   908 MBytes  7.61 Gbits/sec  755    184 KBytes       
[  4]   3.00-4.00   sec  1.01 GBytes  8.66 Gbits/sec  824    212 KBytes       
[  4]   4.00-5.00   sec   935 MBytes  7.85 Gbits/sec  589    165 KBytes       
[  4]   5.00-6.00   sec   875 MBytes  7.34 Gbits/sec  514    194 KBytes       
[  4]   6.00-7.00   sec   850 MBytes  7.13 Gbits/sec  718    188 KBytes       
[  4]   7.00-8.00   sec   983 MBytes  8.25 Gbits/sec  949    158 KBytes       
[  4]   8.00-9.00   sec   930 MBytes  7.80 Gbits/sec  649    180 KBytes       
[  4]   9.00-10.00  sec   892 MBytes  7.48 Gbits/sec  668    147 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  8.80 GBytes  7.56 Gbits/sec  7319             sender
[  4]   0.00-10.00  sec  8.80 GBytes  7.56 Gbits/sec                  receiver
iperf Done.

对比非OVS-DPDK虚拟机

[root@backendcloud-fedora27 ~]# yum -y install wget openssl-devel gcc make python-devel openssl-devel kernel-devel graphviz kernel-debug-devel autoconf automake rpm-build redhat-rpm-config libtool python-twisted-core python-zope-interface PyQt4 desktop-file-utils libcap-ng-devel groff checkpolicy selinux-policy-devel
[root@backendcloud-fedora27 ~]# adduser ovs
[root@backendcloud-fedora27 ~]# su - ovs
[ovs@backendcloud-fedora27 ~]$ mkdir -p ~/rpmbuild/SOURCES
[ovs@backendcloud-fedora27 ~]$ cd ~/rpmbuild/SOURCES
[ovs@backendcloud-fedora27 ~]$ wget http://openvswitch.org/releases/openvswitch-2.5.10.tar.gz
[ovs@backendcloud-fedora27 ~]$ tar -zxvf openvswitch-2.5.10.tar.gz
[ovs@backendcloud-fedora27 ~]$ rpmbuild -bb --nocheck openvswitch-2.5.10/rhel/openvswitch-fedora.spec
[ovs@backendcloud-fedora27 ~]$ exit
[root@backendcloud-fedora27 ~]# yum localinstall yum localinstall /home/ovs/rpmbuild/RPMS/x86_64/openvswitch-2.5.10-1.fc27.x86_64.rpm -y
[root@backendcloud-fedora27 ~]# ovs-vsctl --version
ovs-vsctl (Open vSwitch) 2.5.10
Compiled Sep 22 2022 16:43:31
DB Schema 7.12.1
[root@backendcloud-fedora27 ~]# systemctl start openvswitch.service
[root@backendcloud-fedora27 tmp]# ovs-vsctl show
0425b4a1-cfb0-4cbb-94a8-68bd581ce48e
[root@backendcloud-fedora27 ~]# ovs-vsctl add-br br1
[root@backendcloud-fedora27 tmp]# ovs-vsctl show
0425b4a1-cfb0-4cbb-94a8-68bd581ce48e
    Bridge "br1"
        Port "br1"
            Interface "br1"
                type: internal
    ovs_version: "2.5.10"
[root@backendcloud-fedora27 tmp]# cat test.xml 
<network>
  <name>test</name>
  <forward mode="bridge"/>
  <bridge name="br1"/>
  <virtualport type="openvswitch"/>
</network>
[root@backendcloud-fedora27 tmp]# virsh net-list --all
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 default              active     yes           yes
[root@backendcloud-fedora27 tmp]# virsh net-define test.xml
Network test defined from test.xml
[root@backendcloud-fedora27 tmp]# virsh net-list --all
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 default              active     yes           yes
 test                 inactive   no            yes
[root@backendcloud-fedora27 tmp]# virsh net-start test
Network test started
[root@backendcloud-fedora27 tmp]# virsh net-list --all
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 default              active     yes           yes
 test                 active     no            yes
[root@backendcloud-fedora27 tmp]# ovs-vsctl show
0425b4a1-cfb0-4cbb-94a8-68bd581ce48e
    Bridge "br1"
        Port "br1"
            Interface "br1"
                type: internal
    ovs_version: "2.5.10"
[root@backendcloud-fedora27 tmp]# virt-install --virt-type kvm --name test-vm1 --ram 1024 --boot hd  --disk path=c1.qcow2 --network network=test,mac=52:54:00:aa:69:dd --noautoconsole --keymap=en-us
WARNING  No operating system detected, VM performance may suffer. Specify an OS with --os-variant for optimal results.
Starting install...
Domain creation completed.
[root@backendcloud-fedora27 tmp]# virt-install --virt-type kvm --name test-vm2 --ram 1024 --boot hd  --disk path=c2.qcow2 --network network=test,mac=52:54:00:aa:69:de --noautoconsole --keymap=en-us
WARNING  No operating system detected, VM performance may suffer. Specify an OS with --os-variant for optimal results.
Starting install...
Domain creation completed.
# 不加 "--keymap=en-us" kvm虚拟机会出现键盘乱码
[root@backendcloud-fedora27 tmp]# ovs-vsctl show
0425b4a1-cfb0-4cbb-94a8-68bd581ce48e
    Bridge "br1"
        Port "vnet0"
            Interface "vnet0"
        Port "br1"
            Interface "br1"
                type: internal
        Port "vnet1"
            Interface "vnet1"
    ovs_version: "2.5.10"


640.jpg

640.jpg

二、Lagopus虚拟交换机

Lagopus是一种开源的高性能虚拟交换机软件,由日本国立信息通信技术研究所(NICT)开发。它基于DPDK(Data Plane Development Kit)和OpenFlow协议,并采用了多线程、多核、流水线等技术,以实现高效的数据包处理。

Lagopus支持多种不同类型的网络接口和数据包格式,可以在物理服务器上或虚拟机中运行。它提供灵活的配置选项和API接口,使得用户可以轻松地进行自定义设置和扩展。同时,Lagopus还支持与其他SDN控制器集成使用。

由于其高性能、可定制化以及与其他开源软件兼容等特点,Lagopus在云计算、网络虚拟化、NFV等领域中具有广泛应用价值。

高性能软件 OpenFlow 1.3 交换机和路由器

特征

  • Lagopus 交换机
  • Best OpenFlow 1.3 compliant switch
  • OpenFlow Switch Specification 1.3.4
  • High performance software data plane with DPDK
  • Lagopus 路由器
  • 多个VRF
  • VLAN交换
  • DPDK支持
  • 仍然是测试版

三、MoonGen数据包生成器

MoonGen是建立在一个脚本化的高速数据包生成libmoon。整个负载生成器由 Lua 脚本控制:发送的所有数据包均由用户提供的脚本制作。多亏了令人难以置信的快速 LuaJIT VM 和数据包处理库 DPDK,它可以在仅使用单个 CPU 内核的情况下用 64 字节数据包使 10 Gbit/s 以太网链路饱和。即使每个数据包都被 Lua 脚本修改,MoonGen 也能达到这个速率。它不依赖于重播相同缓冲区之类的技巧。

MoonGen 还可以接收数据包,例如,检查被测系统丢弃了哪些数据包。由于接收也完全由用户的 Lua 脚本控制,因此可用于实现高级测试脚本。例如,可以使用两个相互建立连接的 MoonGen 实例。此设置可用于对防火墙等中间设备进行基准测试。

MoonGen 重点关注四个要点:

  • 高性能和多核扩展:每个 CPU 内核每秒 > 2000 万个数据包
  • 灵活性:每个数据包都是由用户提供的 Lua 脚本实时制作的
  • 精确和准确的时间戳:在商品硬件上以亚微秒精度进行时间戳
  • 精确和准确的速率控制:在商品硬件上可靠地生成任意流量模式

MoonGen 建立在libmoon 之上,它是 DPDK 的 Lua 包装器。

用户可以为他们的实验编写自定义脚本。建议在脚本中使用硬编码的设置特定常量。脚本就是配置,为脚本编写一个复杂的配置界面是无关紧要的。或者,有一个简化(但功能较弱)的命令行界面可用于快速测试。

下图显示了架构以及如何处理多核支持。

执行从必须在用户脚本中定义的主任务开始。此任务在使用的 NIC 上配置队列和过滤器,然后启动一个或多个从属任务。

请注意,Lua 没有任何对多线程的本机支持。因此,MoonGen 会为每个线程启动一个新的且完全独立的 LuaJIT VM。新的 VM 接收序列化参数:要执行的函数和参数,例如要从中发送数据包的队列。线程仅通过底层库共享状态。

示例脚本quality-of-service-test.lua展示了如何使用此线程模型来实现典型的负载生成任务。它通过发送两种不同类型的数据包来实现 QoS 测试并测量它们的吞吐量和延迟。它通过启动两项数据包生成任务来实现:一项用于后台流量,一项用于优先流量。第三个任务用于对传入的数据包进行分类和计数。

四、FastClick处理程序

FastClick是一种高性能的用户空间点击处理程序,用于优化网络应用程序中的数据包接收和处理。它最初由EPFL(瑞士洛桑联邦理工学院)开发,旨在提高网络应用程序的吞吐量和响应时间。

FastClick通过将数据包处理逻辑移动到用户空间,并使用自定义算法来实现快速匹配和过滤,从而实现了比内核中处理更高效的数据包接收和处理。它支持多线程操作,并具有灵活、可配置的流水线模型,可以轻松地进行定制以适应不同类型的网络应用程序。

FastClick已被广泛用于高性能网络设备(例如路由器、交换机等)和分布式系统中,以提供快速、可靠的数据包处理功能。

4.1安装fastclick

安装fastclick可以使用npm,Component和Bower。另外也提供了Ruby版的gem fastclick-rails以及.NET提供了NuGet package。最直接的可以在页面引入fastclick js文件。如:

在页面直接引入fastclick.js

<script type='application/javascript' src='/path/to/fastclick.js'></script>

使用npm安装

npm install fastclick

初始化FastClick实例

初始化FastClick实例建议在页面的DOM文档加载完成后。

纯Javascript版

if ('addEventListener' in document) {
    document.addEventListener('DOMContentLoaded', function() {
        FastClick.attach(document.body);
    }, false);
}

jQuery版

$(function() {
    FastClick.attach(document.body);
});

类似Common JS的模块系统方式

var attachFastClick = require('fastclick');
attachFastClick(document.body);

调用require('fastclick')会返回FastClick.attach函数。

使用needsclick过滤特定的元素

如果页面上有一些特定的元素不需要使用fastclick来立刻触发点击事件,可以在元素的class上添加needsclick:

<a class="needsclick">Ignored by FastClick</a>

不需要使用fastclick的情况

以下这几种情况是不需要使用fastclick:

1、FastClick是不会对PC浏览器添加监听事件

2、Android版Chrome 32+浏览器,如果设置viewport meta的值为width=device-width,这种情况下浏览器会马上出发点击事件,不会延迟300毫秒。

<meta name="viewport" content="width=device-width, initial-scale=1">

3、所有版本的Android Chrome浏览器,如果设置viewport meta的值有user-scalable=no,浏览器也是会马上出发点击事件。

4、IE11+浏览器设置了css的属性touch-action: manipulation,它会在某些标签(a,button等)禁止双击事件,IE10的为-ms-touch-action: manipulation

五、OpenFastPath数据包处理框架

OpenFastPath(OFP)是一个高性能的数据包处理框架,可以用于构建网络应用程序和设备,例如路由器、交换机等。它提供了一个用户空间的数据包处理引擎,可以通过与多种硬件平台和操作系统集成来实现快速、可扩展的网络应用程序。

OFP支持多个协议栈(例如TCP/IP、UDP/IP等),并提供了一系列基本功能模块,如ARP缓存管理、IP地址管理、ACL过滤等。它还支持虚拟化和容器化部署,并具有灵活的API和可扩展的插件架构,可以轻松地定制以适应不同类型的网络应用程序需求。

OFP最初由Linux基金会主导开发,并已成为Linux基金会项目之一。目前,它已经被广泛应用于各种高性能网络设备和云计算环境中。

fastpath 的介绍:

1. 提供了 Workgroup 协议的实现,Workgroup 的概念就是专门对应在线客服这个典型场景了。这是企业或组织机构的客服需求的核心概念和功能,类似于呼叫中心。

2.Server 端的历史记录存储。默认 Openfire 本身是不记录信息历史记录的,只记录离线留言。注意,离线消息和消息历史记录是两个不同的概念,离线消息是对方不在线的情况,server 端先保存起来,等对方上线后再发给他,发完了消息在 server 端就被删除了;而消息历史记录是只 server 端记录的所有对话消息,当然客户端也可以实现在客户端上自己的历史记录。

fasthpath:主要分为两端:agent - 客服,user - 用户,为人工客服实现了排队路由等基本的呼叫中心功能。

fasthpath:实现的原理就是以技能组为标准对用户加入对应的技能组在路由给对应技能组的客服人员,客服人员收到 offer 之后,可以接受,fastpath 就可以创建 openfire 的聊天室邀请用户和 agent 加入进来进行会话,实现客服功能。其中 fastpath 还提供了一些其他的附加功能:比如转接,路由过程指定客服,设置最大聊天室等等,这些功能可以再以后开发过程中有需要的情况下查看源码即可了解。

下面给出最简单的:user 去排队,客服加入技能组,来显示整个的客服功能。

这是 openfire 提供的插件,在 smack 中也提供了对应的 api,这里提供一个 agent 端的实例

/**
   * 加入技能组
   * @param workGroupName
   * @return
   */
  public boolean joinWorkGroup(String workGroupName,int maxChats){
    boolean bResult=false;
    agentSession=new AgentSession(workGroupName,connection);
    agentSession.addInvitationListener(new WorkgroupInvitationListener(){
      public void invitationReceived(WorkgroupInvitation workgroupInvitation) {
//        System.out.println("workgroupInvitation.getWorkgroupName():"+workgroupInvitation.getWorkgroupName());
//        System.out.println("workgroupInvitation.getMessageBody():"+workgroupInvitation.getMessageBody());
//        System.out.println("workgroupInvitation.getMetaData():"+workgroupInvitation.getMetaData());
//        System.out.println("workgroupInvitation.getInvitationSender():"+workgroupInvitation.getInvitationSender());
//        System.out.println("workgroupInvitation.getGroupChatName():"+workgroupInvitation.getGroupChatName());
        joinRoom(workgroupInvitation.getGroupChatName());
//        System.out.println("name:"+workgroupInvitation.getGroupChatName()+",id:"+workgroupInvitation.getSessionID());
        /*try {
          agentSession.sendRoomTransfer(RoomTransfer.Type.user, "10110@kfas1", workgroupInvitation.getSessionID(), "转接");
        } catch (XMPPException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }*/
      }
    });
    agentSession.addOfferListener(new OfferListener(){
      public void offerReceived(Offer offer) {
        System.out.println("offer.getUserJID();"+offer.getUserJID());
        System.out.println("offer.getContent();"+offer.getContent());
        offer.accept();
      }
      public void offerRevoked(RevokedOffer revokedOffer) {
        System.out.println("revokedOffer.getReason():"+revokedOffer.getReason());
        System.out.println("revokedOffer.getUserJID():"+revokedOffer.getUserJID());
            }
    });
    agentSession.addQueueUsersListener(new QueueUsersListener(){
      public void averageWaitTimeUpdated(WorkgroupQueue workgroupQueue, int averageWaitTime) {
//        System.out.println("averageWaitTime:"+averageWaitTime);
//        System.out.println("workgroupQueue.getAverageWaitTime():"+workgroupQueue.getAverageWaitTime());
//        System.out.println("workgroupQueue.getCurrentChats():"+workgroupQueue.getCurrentChats());
//        
      }
      public void oldestEntryUpdated(WorkgroupQueue workgroupQueue, Date oldestEntry) {
//        System.out.println("oldestEntry:"+oldestEntry.toString());
      }
      public void statusUpdated(WorkgroupQueue workgroupQueue, Status status) {
//        System.out.println("status:"+status.toString());
      }
      public void usersUpdated(WorkgroupQueue workgroupQueue, Set uers) {
        for (Iterator iterator = uers.iterator(); iterator
            .hasNext();) {
          Object user = (Object) iterator.next();
          System.out.println("user:"+user.toString());
        }
      }
    });
      try {
      agentSession.setOnline(true);
      /*Presence presence=new Presence(Presence.Type.available);
      presence.setTo("demo@workgroup.kftest2");
      presence.setPriority(1);
      connection.sendPacket(presence);
      System.out.println("presence OK");*/
      agentSession.setStatus(Presence.Mode.available,maxChats,"OK");
      System.out.println(agentSession.getMaxChats());
    } catch (XMPPException e) {
      e.printStackTrace();
    }
    bResult=true;
    return bResult;
  }

用户 user 端的加入排队实例,也是基于 smack 包编写,可以发现 smack 都提供了对应的对象进行编程:

public void joinQueue(String workgroupName, Map metaData) {
      workgroup = new Workgroup(workgroupName, connection);
      //监听技能组中队列的事件
      //这里监听,由于workGroup监听connection的包,如果第二次初始化,第一次的队列的监听还会触发
      this.listenForQueue();
      workgroupInvitationListener = new WorkgroupInvitationListener(){ 
        public void invitationReceived(WorkgroupInvitation workgroupInvitation) {
              String room = workgroupInvitation.getGroupChatName();
              joinRoom(room);
        }
    };
      workgroup.addInvitationListener(workgroupInvitationListener);
        if (workgroup != null) {
            try {
              workgroup.joinQueue(metaData, userid);
            } catch (XMPPException e) {
              //异常的情况也继续排队,由于技能没有agent会service-unavailable(503)
              log.error("[>"+callInfo.getJid()+"<]: Unable to join chat queue.",e);
            }
        }
    }
    /**
     * 监听队列情况
     *
     */
    public void listenForQueue(){
      queueListener =new QueueListener(){
      //加入队列成功返回基础消息
      public void joinedQueue() {
            }
        //离开队列事件
            public void departedQueue() {
            }
            //队列位置变化
            public void queuePositionUpdated(int currentPosition) {
            }
            //队列时间变化
            public void queueWaitTimeUpdated(int secondsRemaining) {
            }
    };
      workgroup.addQueueListener(queueListener);
    }
相关文章
|
安全 架构师 编译器
鲲鹏开发重点-–扭转x86乾坤的挑战,ARM64内存模型
因为X86及其CISC架构生态的封闭性,中国市场对未来处理器的选择,将是更开放、更模块化的RISC架构。 鲲鹏处理器就是符合这个潮流的创新产品和生态,将直面一系列挑战,和Apple一样赢得这场挑战,来扭转X86的封闭性的乾坤,创造出中国的处理器新生态。
1146 0
鲲鹏开发重点-–扭转x86乾坤的挑战,ARM64内存模型
|
4月前
|
算法 调度 UED
揭秘操作系统背后的暗战:进程调度与优先级反转的惊心动魄!
【8月更文挑战第21天】操作系统核心管理计算机资源,进程调度为其关键功能,决定CPU使用权,影响系统性能与用户体验。优先级反转是多任务环境下常见挑战:高优先级进程因等待低优先级进程占用的资源而被阻塞,导致系统效率下降。通过优先级继承或提升机制可解决此问题,确保系统资源高效利用与响应时间优化。
47 1
|
3月前
|
机器学习/深度学习 算法 物联网
探究操作系统的心脏:调度算法的演变与优化
本文旨在深入探讨操作系统中核心组件——调度算法的发展脉络与优化策略。通过分析从单任务到多任务、实时系统的演进过程,揭示调度算法如何作为系统性能瓶颈的解决关键,以及在云计算和物联网新兴领域中的应用前景。不同于传统摘要,本文将注重于概念阐释与实例分析相结合,为读者提供直观且全面的理解视角。
|
3月前
|
存储 安全 算法
探索操作系统的心脏:内核架构与机制的深度剖析
本文旨在深入探讨操作系统的核心——内核,揭示其架构设计与运行机制的内在奥秘。通过对进程管理、内存管理、文件系统、设备控制及网络通信等关键组件的细致分析,展现内核如何高效协调计算机硬件与软件资源,确保系统稳定运行与性能优化。文章融合技术深度与通俗易懂的表述方式,旨在为读者构建一幅清晰、立体的内核运作全景图。
84 0
|
7月前
|
缓存 算法 Java
Linux内核新特性年终大盘点-安卓杀后台现象减少的背后功臣MGLRU算法简介
MGLRU是一种新型内存管理算法,它的出现是为了弥补传统LRU(Least Recently Used)和LFU(Least Frequently Used)算法在缓存替换选择上的不足,LRU和LFU的共同缺点就是在做内存页面替换时,只考虑内存页面在最近一段时间内被访问的次数和最后一次的访问时间,但是一个页面的最近访问次数少或者最近一次的访问时间较早,可能仅仅是因为这个内存页面新近才被创建,属于刚刚完成初始化的年代代页面,它的频繁访问往往会出现在初始化之后的一段时间里,那么这时候就把这种年轻代的页面迁移出去
|
缓存 网络协议 Linux
20个基于DPDL开源项目,带你冲破内核瓶颈(中)
20个基于DPDL开源项目,带你冲破内核瓶颈(中)
|
7月前
|
JSON Linux C语言
内核雏形
内核雏形
49 0
|
网络协议 测试技术 API
20个基于DPDL开源项目,带你冲破内核瓶颈(下)
20个基于DPDL开源项目,带你冲破内核瓶颈(下)
|
存储 算法 Linux
探索Linux内核内存伙伴算法:优化系统性能的关键技术!
探索Linux内核内存伙伴算法:优化系统性能的关键技术!
|
Linux 芯片
【优化技术专题】这绝对是你的知识盲点,NUMA的为什么存在
【优化技术专题】这绝对是你的知识盲点,NUMA的为什么存在
260 0
【优化技术专题】这绝对是你的知识盲点,NUMA的为什么存在