原文鏈接:https://www.dazhuanlan.com/2019/12/31/5e0af1858dada/
最近開始調研網卡的OVS流表offload功能,所以目前查看一下OVS這塊是怎么做的。
從上面可以看到OVS主要通過netlink發送給網口,接下來我們看一下網卡驅動做了一些什么,因為在做Mellanox家的網卡,所以這里查看代碼就查看mlx5_core的驅動代碼。
首先是開啟offload,Mellanox有兩種方案開啟offload,設置方法不一樣,但是實質是一致的,就是把eswitch_mode配置為switchdev,分別看一下:
第一種配置方法為devlink dev eswitch set pci/${PCI_ADDR} mode switchdev,這是中間一些版本的配置,它對應的代碼路徑如下:
eswitch_mode_set-->mlx5_devlink_eswitch_mode_set-->esw_offloads_start-->mlx5_eswitch_enable_sriov,我查看的代碼沒有看到地方調用。
第二種配置方法為echo switchdev > /sys/kernel/debug/mlx5/${PCI_ADDR}/compat/mode,這是后面普遍的一種配置方法,它對應的代碼路徑如下:
esw_compat_fops-->write-->esw_compat_write-->write_u16-->mlx5_devlink_eswitch_mode_set-->esw_offloads_start-->mlx5_eswitch_enable_sriov
mlx5_remove_dev_by_protocol首先從MLX5_INTERFACE_PROTOCOL_IB協議中移除設備mlx5_add_dev_by_protocol將設備添加到協議MLX5_INTERFACE_PROTOCOL_IB中esw_offloads_init初始化offload相關的一些表和repsentor端口esw_create_offloads_fdb_tables創建FDB表esw_create_offloads_table創建轉發表esw_create_vport_rx_group創建接收組esw_offloads_load_reps加載repsentor端口
esw_create_tsarvport的QoS管理esw_enable_vport使能vport
配置OVS支持offload
配置OVS的流表offload功能的命令如下:
1 |
ovs-vsctl set Open_vSwitch . Other_config:hw-offload=true |
utilities/ovs-vsctl.c實現我們不看了。我們主要看一下vswitchd是做了什么操作。
vswitchd/ovs-vswitchd.c
main-->bridge_run-->netdev_set_flow_api_enabled-->netdev_tc_init_flow_api主要是設置去創建或者刪除一條TC規則,如果是添加則類似/sbin/tc qdisc add dev <devname> handle ffff: ingress,如果是刪除則類似/sbin/tc qdisc del dev <devname> handle ffff: ingress。
OVS offload流表下發
OVS相關部分
當報文不匹配的時候,會將報文上報,會調用udpif_upcall_handlerudpif_upcall_handler-->recv_upcalls-->handle_upcalls-->dpif_operate-->dpif_netlink_operate-->try_send_to_netdev-->parse_flow_put-->netdev_flow_put-->netdev_tc_flow_put
- 首先判定是不是tunnel,是的話需要存儲五元組
- 是vlan的話,記錄vid和mask
- 記錄源目的MAC和掩碼
- 記錄五元組及其掩碼
- 檢測以上記錄的信息是否有不支持的,還是有挺多不支持的,具體查看函數
test_key_and_mask - 記錄action,目前支持的是output,push_vlan,pop_vlan,set,set_mask
- 調用
tc_replace_flower將以上記錄的信息進行轉換,然后通過netlink發送給端口。
網卡驅動相關
前面ovs調用tc_replace_flower時候會觸發kernel調用函數tc_ctl_tfilter,路徑如下:
tc_ctl_tfilter-->fl_change-->fl_hw_replace_filter-->mlx5e_rep_ndo_setup_tc-->mlx5e_configure_flower-->mlx5e_tc_add_fdb_flow-->mlx5_eswitch_add_offloaded_rule
mlx5e_configure_flower
parse_cls_flower解析ovs傳遞過來的流表中match的key信息parse_tc_fdb_actions解析ovs傳遞過來的流表中action信息mlx5e_tc_add_fdb_flow主要是講match和action添加到fdb流表- 后面先不看了,multipath的那些操作
mlx5e_tc_add_fdb_flow
- 如果action包含encap,那么調用
mlx5e_attach_encap生成vxlan所需要的報文頭信息 mlx5_eswitch_add_vlan_action添加vlan的actionmlx5_eswitch_add_offloaded_rule添加offloaded規則
mlx5_eswitch_add_offloaded_rule-->mlx5_add_flow_rules-->_mlx5_add_flow_rules 主要是向firmware發送指令添加offload規則。
這塊關聯比較多,不太好看,以后遇到問題再去查看。
dump flows
一般是兩種命令可以展示datapath的流表,他們的區別主要是能不能dump別的datapath,主要實現都是一致的,所以我們只看一個相關的代碼,因為個人認為ovs-appctl命令更好一些,所以就看這個的代碼。
1 |
ovs-dpctl dump-flows [type=offloaded/ovs] |
命令相關的代碼就不看了,因為ovs-appctl調用的命令都需要在ovs-vswitchd中通過函數unixctl_command_register進行注冊。我們這里直接查看注冊的dpctl相關的命令。
代碼路徑如下,文件起始於ovs-vswitchd.c
main-->bridge_run-->bridge_reconfigure-->bridge_add_ports-->bridge_add_ports__-->iface_create-->iface_do_create-->netdev_open-->construct-->dpif_create_and_open-->dpif_open-->do_open-->dp_initialize-->dpctl_unixctl_register-->dpctl_unixctl_handler-->dpctl_dump_flows
dpctl_dump_flows
- 首先做參數檢測,保證參數合理性
dpif_flow_dump_create-->dpif_netlink_flow_dump_create主要有兩個事情,一個就是nl_dump_start,原來的dump ovs的流表,另一個就是dump offloaded流表,用的函數start_netdev_dump- 遍歷所有滿足類型條件的流表,並且根據filter進行過濾。
