go 做视频网站,女装网站建设规划书,wordpress 分类文章置顶,网页设计1920尺寸OVS是open virtual switch的简称#xff0c;是现在广泛使用的软件实现的虚拟网络交换机。
各大云厂商普遍使用OVS来实现自身的虚拟网络#xff0c;各厂商会根据自身需要加以修改使之符合自身需求#xff0c;DPU中也使用OVS来实现流表的offload。OVS中的流表基于多级结构是现在广泛使用的软件实现的虚拟网络交换机。
各大云厂商普遍使用OVS来实现自身的虚拟网络各厂商会根据自身需要加以修改使之符合自身需求DPU中也使用OVS来实现流表的offload。OVS中的流表基于多级结构与用户强相关的是opwnflow下发的流表称为emc flow。
OVS一般存在两种运行模式内核模式和DPDK模式。内核模式下存在一个datapath的内核模块模块会在内核层面维护一份emc flow数据包从网卡接收到时首先在datapath中进行emc flow的匹配如果无匹配结果则通过upcall机制交由核心组件ovs-vswitchd处理。ovs-vswitchd收到upcall的数据包时首先根据数据包查询是否存在emc flow如果存在则根据emc flow的内容对数据包处理如果不存在则对数据包匹配openflow并根据匹配结果创建emc flow并将其下发至datapath中这一过程也称为offload。ovs-vswitchd主要工作就是对收到的数据包进行匹配根据匹配结果对数据包进行处理并转发。
关于OVS的整体结构openflow的结构等会另开文章详细介绍本文主要分析的内容就是OVS的核心组件ovs-vswitchd的整体代码结构由于该组件结构十分复杂数据结构也比较多故此文章会随时间的推移不断的更新如果有不足之处请各位评论留言。
代码结构简单时通过缩进的方式表示各function的隶属关系代码结构复杂时则通过层级编号缩进的方式表示。
ovs-vswitchd的主函数
main()-bridge_init()-lacp_init() //命令注册-bond_init() //命令注册-......-ovs_numa_init()-while true //无线循环执行-memory_run() //内存处理-memory_init()-bridge_run() //网桥处理-netdev_run() //网络设备-memory_wait()-bridge_wait()-netdev_wait()
bridge_run()
该func是主要处理数据包的结构比较复杂会拆分比较细致
bridge_run()-ovsdb_idl_run() // 连接ovsdb-if_notifier_run()-rtnetlink_run()-nln_run() //通过netlink获取interface变化情况-ovsrec_open_vswitch_first() //获取ovsdb配置-dpdk_init()-bridge_init_ofproto() //初始化网桥上的openflow-bridge_run__()-ofproto_enumerate_types() //ofproto_class目前只有ofproto_dpif故枚举的就是dpif_classes中的类型目前是system/netlink和netdev-ofproto_type_run() //执行ofproto_dpif-type_run()-ofproto_run() //对于每一个网桥执行该func-bridge_reconfigure() //网桥信息重新配
dpdk_init()
dpdk_init()-dpdk_init__()-construct_dpdk_args() //dpdk参数-rte_eal_init()-netdev_dpdk_register() //-netdev_register_flow_api_provider() //调用该函数的有tcdpdkdummy
bridge_init_ofproto()
bridge_init_ofproto()- 判断initialized该func只执行一次- //根据cfg配置先遍历一遍网桥获取bridge和port结构放在iface_hints里面-ofproto_init() //对iface_hints的处理-ofproto_class_register(ofproto_dpif_class) // 注册dpif类型的ofproto_class存放在ofproto_classes结构体n_ofproto_classes记录数量结构体会自己扩容-iface_hints的结构存成init_ofp_ports-ofproto_classes[i]-init(init_ofp_ports) //执行ofproto_class的init这里是ofproto_dpif_class-ofproto_unixctl_init() //注册一些命令// 1
init() // ofproto_dpif_class- // 传入的参数添加到init_ofp_ports中-ofproto_unixctl_init/ofproto_dpif_trace_init/udpif_init() // 注册一些unixctl接口// 2
ofproto_unixctl_init()-//注册ofproto_unixctl_dpif_dump_flows-ofproto_dpif_lookup_by_name() // 根据网桥名称查找-unixctl_command_reply() // 往conn写即为回复信息
bridge_run-ofproto_enumerate_types()
ofproto_enumerate_types()
ofproto_enumerate_types()-ofproto_classes[i]-enumerate_types // 以ofproto_dpif_class为例-dp_enumerate_types()
ofproto_type_run()
ofproto_type_run() // ofproto_dpif-ofproto_normalize_type()-ofproto_class_find__()-ofproto_class-type_run()
type_run()
type_run() // ofproto_dpif-shash_find_data() // 找到dpif_backer-dpif_run() // 执行成功之后need_revalidate需要置位-dpif-dpif_class-run() //dpif_netdev_run-udpif_run() // upcall dpifunixctl消息处理- // 特定条件下开启从datapath收包-dpif_recv_set()-need_revalidate需要置位-udpif_set_threads()-udpif_start_threads()-ovs_thread_create(udpif_upcall_handler)-ovs_thread_create(udpif_revalidator)-backer-need_revalidate //需要重新生效 下面有dpif_netdev_run()
// 4
dpif_netdev_run()-dp_netdev_process_rxq_port() //收解释下面有-dp_netdev_pmd_flush_output_packets() //发-reconfigure_datapath() // 后面还有解释-reconfigure_pmd_threads() //根据port变化动态变更线程-ovs_thread_create(pmd_thread_main) // 线程创建-pmd_thread_main() //里面有个无线循环在收和发-ovs_numa_thread_setaffinity_core() //CPU亲和性设定-dp_netdev_process_rxq_port() //处理收-cycle_timer_start() //记录处理时间-dp_packet_batch_init() //batch结构初始化-netdev_rxq_recv() //收-dp_netdev_input() //处理此处的pkt metadata是无效的-dp_netdev_input__()-dp_netdev_pmd_flush_output_packets()-dp_netdev_pmd_flush_output_packets() //发// 5
dp_netdev_input__() //包处理-dfc_processing() // datapath flow cache针对每个包的处理-parse_tcp_flags() // flow director找到对应的flow然后会解析数据包的2 3 4层信息tcp标签-dp_netdev_queue_batches() // 根据解析出的数据表信息放入batch里面或者flow map里面-packet_batch_per_flow_init()-packet_batch_per_flow_update()-packet_enqueue_to_flow_map()-miniflow_extract() //提取miniflow -emc_lookup()-netdev_flow_key_equal_mf() //匹配flow就是memcmp-fast_path_processing()-dp_netdev_pmd_lookup_dpcls()-dpcls_lookup()-dp_netdev_pmd_lookup_flow()-handle_packet_upcall()-dp_netdev_upcall() // 传入两个action一个是正常的流表中的一个貌似是被解析过的-odp_flow_key_from_flow()-dp_netdev-upcall_cb() //netdev有是通过注册设置的func在下面有详细解释-dp_netdev_execute_actions() //执行各action最后可能会将数据包放到队列下面有详细解释-dp_netdev_pmd_lookup_flow()-dp_netdev_flow_add() // 插入dp_netdev_flow-dp_netdev_pmd_find_dpcls()-dpcls_insert()-dpcls_find_subtable()-dpcls_create_subtable()-dp_emc_flow_add() // 移动-queue_netdev_flow_put()-dp_netdev_queue_batches()-packet_batch_per_flow_execute()-dp_netdev_execute_actions() //下面有详细解释-dp_emc_flow_add()-queue_netdev_flow_put() //解释下面有// 6
dpcls_lookup()-//rules重置-遍历cls-subtables-subtable-lookup_func() //这个比较复杂需要随后熟悉-//计算为了这个包匹配所做的子表的检索的次数此举是为了估算每个匹配包的子表的离散程度-//全部匹配了早点返回// 6
dp_netdev_pmd_lookup_flow()-dp_netdev_pmd_lookup_dpcls()-dpcls_lookup()-dp_netdev_flow_cast()
// 6
queue_netdev_flow_put() //上面有用到-ovs_thread_create(dp_netdev_flow_offload_main)-dp_netdev_alloc_flow_offload()-dp_netdev_append_flow_offload() //插入dp_flow_offload这个list中
udpif_upcall_handler()
// 4
udpif_upcall_handler() //线程-recv_upcalls()-dpif_recv()-dpif-dpif_class-recv() //netdev没有, netlink有-upcall_receive() //一般会进入这里匹配流miss-pkt_metadata_from_flow() // 从struct flow的信息回填到pkt metadata-process_upcall() //解释下面有-handle_upcalls()-ukey_install()-dpif_operate()-dpif-dpif_class-operate() // dpif_netdev_operate// 5
dpif_netdev_operate()-dpif_netdev_flow_put()-flow_put_on_pmd()-dp_netdev_flow_add()-dpif_netdev_flow_del()-flow_del_on_pmd()-dp_netdev_pmd_remove_flow()-dpif_netdev_execute()-dp_netdev_execute_actions()-odp_execute_actions(dp_execute_cb) //某个OVS_ACTION_XXX会去调用dp_execute_cb-dp_execute_cb() //分OVS_ACTION_XXX进行处理-dp_netdev_pmd_flush_output_on_port()/dp_packet_batch_add() //OVS_ACTION_OUTPUT时要么发出要么放到发送对列-push_tnl_action() //OVS_ACTION_ATTR_TUNNEL_PUSH-netdev_push_header() //头部添加-conntrack_execute()-ipf_preprocess_conntrack() //ip分片预处理-write_ct_md()-process_one_fast() //这里会处理nat-handle_nat()-un_nat_packet() / nat_packet()-process_one() //下面有-dp_netdev_pmd_flush_output_packets() //其他地方有详情// 6
dp_netdev_flow_offload_main() //处理dp_flow_offload这个list中的请求-dp_netdev_flow_offload_put()-netdev_flow_put()-flow_api-flow_put() // netdev_offload_dpdk_flow_put
// 7
netdev_offload_dpdk_flow_put()-netdev_offload_dpdk_validate_flow()-netdev_offload_dpdk_add_flow()-netdev_offload_dpdk_actions()-netdev_offload_dpdk_mark_rss()-ufid_to_rte_flow_associate()
// 6
ipf_preprocess_conntrack() //ip分片预处理-ipf_extract_frags_from_batch() // 从batch的一堆包里提取出分片的包-ipf_is_valid_v4_frag()/ipf_is_valid_v6_frag() //检查是否是有效的ip分片-ipf_handle_frag() //处理成功之后添加到ipf里面并从batch里面删除不成功refill到batch里面-ipf_v6_key_extract()/ipf_v4_key_extract() //提取ipf key根据key查找一个ipf list-ipf_process_frag()-ipf_execute_reass_pkts()-ipf_dp_packet_batch_add()
// 6
process_one() //执行之前-initial_conn_lookup()-如果已经是natted过的conn_key_reverse() //数据包已经被nat了源、目的IP port更换-conn_key_lookup() //查询conn-//方向错误且可以强制则删除-conn_lookup()-conn_clean()-//conn存在且类型是unnat的-conn_key_hash()-conn_key_lookup()-write_ct_md()-conn_update_state()--//有nat信息且不是新创建的conn-handle_nat-//需要创建新的连接-conn_not_found()-//包不允许创建新conn退出-//pkt-md.ct_state修改ct_state为 CS_NEW-//需要提交即正式创建conntrack-//zone限制直接返回-//数量限制直接返回-//新建一个conn设置主动发起的conn的key和rev_key-//有nat信息-//创建nat conn-//选ip和port可nat的ip和port资源耗尽退出-nat_packet() //对packet做nat处理-//对packet做nat处理nat_conn的key是nc的rev_key反之也是key里的地址是转换后的-nat_conn-conn_type CT_CONN_TYPE_UN_NAT; //这里表示要nat还原-//nat_conn也会插入ct-conns-nc-nat_conn nat_conn; //如果没有nat则nc-nat_conn是空的-nc-conn_type CT_CONN_TYPE_DEFAULT; //正常的连接-write_ct_md() // 只有这一处填写packet metadata的地方
udpif_revalidator()
// 4
udpif_revalidator() //线程-revalidate()-revalidator_sweep()-revalidator_sweep__()// 5
revalidator_sweep__()-push_ukey_ops()-push_dp_ops()-ukey_delete()-ukey_delete__()
// 5
revalidate()-dpif_flow_dump_thread_create()-dpif_emc_flow_dump_next() // 移动版本加的-dpif-dpif_class-emc_flow_dump_next() // dpif_netdev_emc_flow_dump_next-dpif_flow_dump_next()-dpif-dpif_class-flow_dump_next() // dpif_netdev_flow_dump_next-ukey_acquire()-ukey_create_from_dpif_flow() // 不推荐在此创建ukey见代码中注释-ukey_install__()-revalidate_ukey()-revalidate_ukey__()-xlate_ukey()-xlate_push_stats()-reval_op_init()-push_dp_ops()// 6
dpif_netdev_emc_flow_dump_next-dp_netdev_pmd_get_next-cmap_next_position-dpif_emc_flow_timeout-dpif_dp_flow_del_by_emc-dp_pmd_remove_flow_by_emc
// 6
dpif_netdev_flow_dump_next-dp_netdev_pmd_get_next-cmap_next_position(pmd-flow_table)-dp_netdev_flow_to_dpif_flow-get_dpif_emc_flow_status_by_dp_flow
get_dpif_emc_flow_status_by_dp_flow-get_dpif_emc_flow_status
dp_emc_flow_to_dpif_flow-get_dpif_emc_flow_status
get_dpif_emc_flow_status-dpif_netdev_get_emc_flow_offload_status-netdev_ports_get-netdev_emc_flows_get-flow_api-emc_flows_get // netdev_offload_dpdk_emc_flows_get-dp_emc_flow_set_last_stats_attrs-dp_emc_flow_get_last_stats_attrs
netdev_offload_dpdk_emc_flows_get-netdev_dpdk_rte_flow_query_count-rte_flow_query// 6
push_dp_ops()-dpif_operate()-transition_ukey()-xlate_push_stats()-xlate_push_stats_entry()-xlate_push_stats_entry()-rule_dpif_credit_stats()
backer-need_revalidate()
// 4
backer-need_revalidate-//将当前tnl_backers-tnl_backers缓存到tmp_backers-每个ofproto类型 //其实只有ofproto_dpif且需要backer一致-每个ofport_dpif-//非tnl port跳过-netdev_vport_get_dpif_port() // 貌似是tunnle的话才是vport-//tmp_backers中有从中移除添加到backer-tnl_backers-//tmp_backers中没有-dpif_port_add() //添加到backer-dpif分配一个odp_port_t出来-dpif_class-port_add()-tnl_port_reconfigure()-dpif_port_del() //删掉tmp_backers中不需要的-xlate_txn_start()-每个ofproto_dpif-xlate_ofproto_set()-每个ofproto_dpif的bundle-xlate_bundle_set()-每个ofproto_dpif的ports-xlate_ofport_set()-xlate_txn_commit()-udpif_revalidate() //变更序列号// 5
xlate_ofproto_set()-xlate_xbridge_init()-xbridge_addr_create()-xlate_xbridge_set()
ofproto_run()
// 2
ofproto_run()-ofproto_class-run()-bundle_run()-send_pdu_cb()-ofproto_dpif_send_packet()-connmgr_run() // 处理openflow的添加-ofconn_run()-rconn_run()-vconn_run()-vconn_recv()-do_send_packet_ins()-rconn_recv()-vconn_recv()-do_recv()-vconn_stream_recv()-ofptype_decode()-handle_openflow()
// 3
ofproto_dpif_send_packet()-xlate_send_packet()-ofproto_dpif_execute_actions()-ofproto_dpif_execute_actions__()-xlate_actions() //下面有-dpif_execute()-dpif_operate() // 别的地方有
// 3
handle_openflow()-ofptype_decode()-ofpraw_decode() // 解析成OFPRAW_NXT_FLOW_MOD OFPRAW_OFPT10_FLOW_MOD OFPRAW_OFPT11_FLOW_MOD 等 enum ofpraw类型-ofpraw_pull()-ofptype_from_ofpraw() // 从enum ofpraw类型解析成 enum ofptype-raw_info_get()-raw_infos //python生成的结构体-handle_table_features_request()-handle_single_part_openflow()-handle_packet_out() // switch的选项之一-ofproto_packet_out_start()-ofproto-ofproto_class-packet_xlate()-xlate_actions() //下面有-handle_flow_mod() // switch的选项之一-ofputil_decode_flow_mod()-ofpacts_pull_openflow_instructions()-get_actions_from_instruction()-ofpacts_decode()-ofpact_pull_raw()-ofpact_decode_raw()-ofpact_decode() //python生成代码里面调用decode_XXX-handle_flow_mod__()-ofproto_flow_mod_init() //初始化rule-add_flow_init() // OFPFC_ADD-cls_rule_init_from_minimatch()-ofproto_rule_create()-ofproto-ofproto_class-rule_alloc-rule_actions_create() //直接就是一块struct ofpact的内存拷贝-ofproto-ofproto_class-rule_construct()-modify_flows_init_loose() // OFPFC_MODIFY-modify_flow_init_strict() // OFPFC_MODIFY_STRICT-delete_flows_init_loose() // OFPFC_DELETE-rule_criteria_init()-rule_criteria_require_rw()-delete_flows_init_strict() // OFPFC_DELETE_STRICT-ofproto_flow_mod_start() // 开始修改rule-add_flow_start()- // temp rule是之前add_flow_init时候创建的- // 从规则中获取到action-rule_from_cls_rule() //查找是否有老规则- //不存在老规则-choose_rule_to_evict() //超过最大规则数量限制了, 驱逐一条rule- //存在老规则-rule_collection_add(ofm-old_rules) //添加到老规则列表里-rule_collection_add(ofm-new_rules) // 添加到新规则上面都是处理ofm这个数据结构-replace_rule_start() // ofproto-tables-cls/刷新rule的有效期-ofproto_rule_insert__()-cookies_insert() //插入到ofproto-cookies-eviction_group_add_rule() //如果rule允许被驱逐则加入到驱逐列表中-classifier_insert()-classifier_replace()-modify_flow_start_strict()-modify_flows_start__()-replace_rule_start()- //存在旧规则则移除-ofproto_rule_insert__() //将流插入到原始数据结构中以便以后的流与之相关。这是可逆的以防以后的错误需要恢复。-ofproto_flow_mod_finish() // rule修改完成-add_flow_finish()-replace_rule_finish()-ofproto-ofproto_class-rule_insert() //只有old_rule存在时候才做点事情-handle_flow_stats_request()-ofputil_decode_flow_stats_request()-collect_rules_loose()-ofproto-ofproto_class-rule_get_stats-handle_bundle_control()-do_bundle_commit()
bridge_reconfigure()
// 2
bridge_reconfigure()-add_del_bridges()-bridge_delete_ofprotos()-对于all_bridges中的每个bridge-bridge_delete_or_reconfigure_ports()-对于all_bridges中的每个bridge-ofproto_create() //为每个网桥重新配置ofproto信息-对于all_bridges中的每个bridge-bridge_add_ports()-datapath_reconfigure()-对于all_bridges中的每个bridge-对于每一个port-port_configure()// 3
bridge_delete_or_reconfigure_ports()-对于br-ofproto中每个port-netdev_set_config()-netdev-netdev_class-set_config() //netdev_dpdk_set_config、netdev_dpdk_vdpa_set_config-add_ofp_port() //需要删除的port综合到一起-对于每一个需要删除的port-ofproto_port_del() //这里主要是在dp上删除-遍历每一个port// 4
netdev_dpdk_vdpa_set_config()-netdev_dpdk_set_config()-rte_eth_dev_is_valid_port()-netdev_dpdk_process_devargs()-rte_eth_dev_is_valid_port()-rte_dev_probe()-netdev_dpdk_lookup_by_port_id()// 4
ofproto_port_del()-ofproto-ofproto_class-port_del() // port_del// 5
port_del()-dpif_port_del()-dpif-dpif_class-port_del() // dpif_netdev_port_del// 6
dpif_netdev_port_del()-do_del_port()-reconfigure_datapath()-port_destroy()// 7
reconfigure_datapath() //前面还有一部分解释-对于每一个port-netdev_set_tx_multiq()-对于每一个port-检查是否需要重新配置need_reconfigure-对于每一个需要重配的port-port_reconfigure()-netdev_reconfigure()-netdev_class-reconfigure() // netdev_dpdk_reconfigure、netdev_dpdk_vdpa_reconfigure// 8
netdev_dpdk_vdpa_reconfigure()-netdev_dpdk_reconfigure()-rte_eth_dev_reset()/rte_eth_dev_stop()-netdev_dpdk_mempool_configure()-dpdk_mp_get() // 这里会检查是否有重用之类的-dpdk_mp_create()-设定netdev_dpdk的mempool-dpdk_eth_dev_init()-dpdk_eth_dev_port_config()-rte_eth_dev_info_get()-rte_eth_dev_configure()-rte_eth_dev_set_mtu()-rte_eth_dev_get_mtu()-rte_eth_tx_queue_setup()-rte_eth_rx_queue_setup()-rte_eth_dev_start()-rte_eth_promiscuous_enable()-rte_eth_allmulticast_enable()
// 3
add_del_bridges()-bridge_create()
// 3
ofproto_create() // reconfigure时针对每一个网桥调用ofproto, ofport的生成-ofproto_normalize_type()-ofproto_class_find__() //找到对应的ofproto类别-class-alloc()-ofproto-ofproto_class-construct() // ofproto class的构造函数
// 4
ofproto_dpif_class-construct()-open_dpif_backer()-shash_add(all_dpif_backers)-ofproto_init_tables()-hmap_insert(all_ofproto_dpifs_by_name) //按照名称存ofproto_dpif-hmap_insert(all_ofproto_dpifs_by_uuid) //按照uuid存ofproto_dpif
// 5
open_dpif_backer()-dpif_create_and_open()-dpif_create()-do_open()-dpif_class-open() //dpif_netdev_open-netdev_open()-netdev_ports_insert()-dpif_open()-do_open()-udpif_create()-dpif_register_upcall_cb(upcall_cb)-dpif_class-register_upcall_cb() //netlink没有netdev有-check_support()// 6
dpif_netdev_open()-create_dp_netdev()-conntrack_init()// 6
upcall_cb()-upcall_receive() //查找ofproto-classify_upcall() //upcall分类匹配用户态actionmiss或者非法的upcall-xlate_lookup()-xlate_lookup_ofproto_()-//是循环进来的流-recirc_id_node_find() //查询循环信息没有查到循环信息跳出-//非无效入口且不是从controller来的()-xport_lookup_by_uuid() //根据port uuid找-//是非循环进来的流-xport_lookup(tnl_port_should_receive, tnl_port_receive)-ofproto_dpif_lookup_by_uuid() // 用户态action upcall-process_upcall()-upcall_xlate() // case选项之一slow path-//统计-xlate_in_init() /* 默认frozen state是空的但是当flow的recirc_id不为空则根据id查找recirc_id_node然后填充frozen stateodp_actions存放action最终结果 */-xlate_actions()-// 记录为什么进到slowpath里-//用rcu技术将bridge port信息全部存下来-xlate_wc_init() //通配符-tnl_wc_init()-//冻结状态以下都是冻结状态的恢复-//保留下老的重新开始trace-//解冻-//已经有规则了冲突退出-//ofproto的uuid不匹配-//以frozen state中记录的为准-//没有找到bridge退出-//没有被跟踪 -clear_conntrack() -frozen_metadata_to_flow() //恢复frozen state的metadata到flow的metadata-//有栈的话恢复栈-//恢复镜像状态-//有recirc_id但是不是frozen state出错了-//获取近似的input port如果是冻结状态则flow-in_port是最终的input port-//如果是三层port来的非二层包添加伪二层信息用于查询-//没有rule和action查找rule-rule_dpif_lookup_from_table()-rule_dpif_lookup_in_table()-//统计非解冻的包-//不是冻结状态处理特殊的包例如lacpbfdcfm-mirror_ingress_packet()-//丢弃从预留的镜像端口的包-//除此之外的情况-//没有冻结状态-compose_ipfix_action()-tnl_process_ecn() //action转换开始时候调用封装丢弃-mirror_ingress_packet() //包镜像-do_xlate_actions()-freeze_unroll_actions() //需要退出把后续的action给放到ctx-freeze_actions中-// 开启跟踪的话相关跟踪信息打印上-xlate_output_action() //case的选项之一-xlate_controller_action()/ctx_trigger_freeze() //执行控制器行为或者触发冻结和退出-xlate_group_action() //case的选项之一-compose_conntrack_action() //case的选项之一-compose_slow_path()-ukey_create_from_upcall() // upcall是miss的时候才这么干-ukey_create__()-should_install_flow()-ukey_install()// 7
xlate_output_action()-compose_output_action() //case选项之一输出到本地、指定端口或者原路返回-compose_output_action__()-check_output_prerequisites() //检查一系列状态-//如果是以太网则获取三层协议类型-//xport-peer不为空表示是从bridge到bridge的-patch_port_output()-//xport是隧道-netdev_vport_inc_tx() //计数-ovs_native_tunneling_is_on() // 本地隧道和内核隧道-commit_odp_tunnel_action() //额外添加其他的action/* 从一个网桥发到另一个网桥网桥通过patch port或者tunnel port相连。到另一个网桥的输出action触* 发在下一个网桥中转换的继续。这个过程可以是递归的下一个网桥还可以发往再下一个。* 从第二个网桥之后的转换了的action在clone action中被封闭这样任何对包的修改对原本网桥上的剩余action将是可见的 */-xxlate_output_actionlate_commit_actions() // 这里会转换各种set操作-commit_odp_actions()-commit_set_nsh_action()-commit_nsh()-commit_set_nw_action()-commit_set_ipv4_action()-commit_set_ipv6_action()-patch_port_output()-process_special() //process_special处理特殊的协议-native_tunnel_output()-xlate_table_action() //case选项之一跳转到其他表-rule_dpif_lookup_from_table()-//存下原来的四层源目的地址-//从某个table开始网后找跳过internal table-//匹配上了即可退出没有匹配上根据系统配置和传入参数综合判断-//未匹配根据传入参数判断miss之后继续查找或者是发往控制器的话-ofp_port_to_ofport() //从ofproto找到port该port没有设置no_packet_in则rule为ofproto-miss_rule-xlate_normal() //case选项之一 按照内核规则来-flood_packets() //case选项之一洪泛-xlate_controller_action() //case选项之一发往控制器
// 8
native_tunnel_output()-netdev_init_tnl_build_header_params()-tnl_port_build_header()-netdev_build_header()-netdev-netdev_class-build_header() // netdev_vxlan_build_header-odp_put_tnl_push_action()
// 7
xlate_group_action()-// 7
compose_conntrack_action()-xlate_commit_actions()-do_xlate_actions() //内部再次调用do_xlate_actions解析nat和ct_mark,ct_label信息// 3
bridge_add_ports()-bridge_add_ports__()-iface_lookup()-iface_create()-iface_do_create()-ofproto_port_add()-ofproto-ofproto_class-port_add()
// 4
ofproto-ofproto_class-port_add()-dpif_port_add()-dpif-dpif_class-port_add() //dpif_netdev_port_add-netdev_ports_insert()
// 5
dpif_netdev_port_add()-netdev_vport_get_dpif_port()-do_add_port()-port_create()-netdev_open()-reconfigure_datapath() //前面有解释// 3
port_configure() //ofbundle的生成-ofproto_bundle_register()-bundle_set()
netdev_run()
netdev_run()-netdev_initialize()-netdev_vport_tunnel_register()-netdev_register_provider() //netdev_classes-netdev_class-run() //dpdk netdev_class没有netdev class之dpdk_class
static const struct netdev_class dpdk_class {.type dpdk,.init netdev_dpdk_class_init, .destruct netdev_dpdk_destruct, .set_tx_multiq netdev_dpdk_set_tx_multiq, .get_carrier netdev_dpdk_get_carrier, .get_stats netdev_dpdk_get_stats, .get_custom_stats netdev_dpdk_get_custom_stats, .get_features netdev_dpdk_get_features, .get_status netdev_dpdk_get_status, .reconfigure netdev_dpdk_reconfigure, .rxq_recv netdev_dpdk_rxq_recv.construct netdev_dpdk_construct,.set_config netdev_dpdk_set_config,.send netdev_dpdk_send,NETDEV_DPDK_CLASS_COMMON,
};netdev_dpdk_eth_send()-netdev_dpdk_send__()-netdev_dpdk_eth_tx_burst()-rte_eth_tx_burst()netdev_dpdk_rxq_recv()-rte_eth_rx_burst()-dp_packet_batch_init_packet_fields()