OVS主线流程之ovs-vswitchd主体结构分析

OVS是open virtual switch的简称,是现在广泛使用的软件实现的虚拟网络交换机。

各大云厂商普遍使用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的隶属关系;代码结构复杂时,则通过层级编号+缩进的方式表示。

主要结构依赖关系

主函数主要内容

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()

1. 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() //网桥信息重新配

1.1. dpdk_init()

dpdk_init()
	->dpdk_init__()
		->construct_dpdk_args() //dpdk参数
		->rte_eal_init()
		->netdev_dpdk_register() //
		->netdev_register_flow_api_provider() //调用该函数的有tc,dpdk,dummy

1.2. 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.2.1. init()

init() // ofproto_dpif_class
	-> // 传入的参数添加到init_ofp_ports中
	->ofproto_unixctl_init/ofproto_dpif_trace_init/udpif_init() // 注册一些unixctl接口

1.2.2. ofproto_unixctl_init()

ofproto_unixctl_init()
	->//注册ofproto_unixctl_dpif_dump_flows
		->ofproto_dpif_lookup_by_name() // 根据网桥名称查找
		->unixctl_command_reply() // 往conn写即为回复信息

1.3. ofproto_enumerate_types()

ofproto_enumerate_types()
	->ofproto_classes[i]->enumerate_types // 以ofproto_dpif_class为例
		->dp_enumerate_types() 

1.4. ofproto_type_run()

ofproto_type_run() // ofproto_dpif
	->ofproto_normalize_type()
	->ofproto_class_find__()
	->ofproto_class->type_run()

1.4.1. 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 dpif,unixctl消息处理
	-> // 特定条件下开启从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  //需要重新生效 下面有
1.4.1.1. dpif_netdev_run()
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() //发
1.4.1.1.1. netdev_rxq_recv()
netdev_rxq_recv()
    ->rx->netdev->netdev_class->rxq_recv()
1.4.1.1.2. dp_netdev_input__()
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() //解释下面有
dpcls_lookup()
dpcls_lookup()
	->//rules重置
	->遍历cls->subtables
		->subtable->lookup_func() //这个比较复杂,需要随后熟悉
		->//计算为了这个包匹配所做的子表的检索的次数,此举是为了估算每个匹配包的子表的离散程度
		->//全部匹配了,早点返回
dp_netdev_pmd_lookup_flow()
dp_netdev_pmd_lookup_flow()
	->dp_netdev_pmd_lookup_dpcls()
	->dpcls_lookup()
	->dp_netdev_flow_cast()
queue_netdev_flow_put() 
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中 
1.4.1.2. 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的地方
1.4.1.3. udpif_revalidator()
udpif_revalidator() //线程
	->revalidate()
	->revalidator_sweep()
		->revalidator_sweep__()
1.4.1.3.1. revalidator_sweep__()
revalidator_sweep__()
	->push_ukey_ops()
		->push_dp_ops()
		->ukey_delete()
			->ukey_delete__()
1.4.1.3.2. revalidate()
revalidate()
	->dpif_flow_dump_thread_create()
	->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()
dpif_netdev_emc_flow_dump_next()
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
dpif_netdev_flow_dump_next()
dpif_netdev_flow_dump_next()
	->dp_netdev_pmd_get_next()
	->cmap_next_position(pmd->flow_table)
	->dp_netdev_flow_to_dpif_flow

dp_netdev_flow_to_dpif_flow()
	->get_dpif_flow_status()

get_dpif_flow_status()
	->dpif_netdev_get_flow_offload_status()
		->netdev_ports_get()
		->netdev_flows_get()
			->flow_api->flows_get // netdev_offload_dpdk_flow_get
		->dp_flow_set_last_stats_attrs
		->dp_flow_get_last_stats_attrs

netdev_offload_dpdk_flow_get()
	->netdev_dpdk_rte_flow_query_count()
		->rte_flow_query()
push_dp_ops()
push_dp_ops()
	->dpif_operate()
	->transition_ukey()
	->xlate_push_stats()
		->xlate_push_stats_entry()
			->xlate_push_stats_entry()
 				->rule_dpif_credit_stats()
1.4.1.4. backer->need_revalidate()
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()  //变更序列号
xlate_ofproto_set()
xlate_ofproto_set()
	->xlate_xbridge_init()
	->xbridge_addr_create()
	->xlate_xbridge_set()

1.5. ofproto_run()

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()

ofproto_dpif_send_packet()

ofproto_dpif_send_packet()
	->xlate_send_packet()
		->ofproto_dpif_execute_actions()
			->ofproto_dpif_execute_actions__()
				->xlate_actions() //下面有
				->dpif_execute()
					->dpif_operate() // 别的地方有

handle_openflow()

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()

1.6. bridge_reconfigure()

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()

bridge_delete_or_reconfigure_ports()

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
netdev_dpdk_vdpa_set_config()
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()
ofproto_port_del()
// 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()

add_del_bridges()

add_del_bridges()
	->bridge_create()

ofproto_create()

ofproto_create() // reconfigure时针对每一个网桥调用,ofproto, ofport的生成
	->ofproto_normalize_type()
	->ofproto_class_find__() //找到对应的ofproto类别
	->class->alloc()
	->ofproto->ofproto_class->construct() // ofproto class的构造函数
ofproto_dpif_class->construct()
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分类,匹配用户态action,miss或者非法的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 state
								odp_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()
				->//统计非解冻的包
				->//不是冻结状态,处理特殊的包,例如lacp,bfd,cfm
					->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信息

bridge_add_ports()

bridge_add_ports()
	->bridge_add_ports__()
		->iface_lookup()
		->iface_create()
			->iface_do_create()
				->ofproto_port_add()
					->ofproto->ofproto_class->port_add()
ofproto->ofproto_class->port_add()
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() //前面有解释

port_configure()

port_configure() //ofbundle的生成
	->ofproto_bundle_register()
		->bundle_set()

2.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()

你可能感兴趣的:(网络,OVS)