您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > OpenvSwitch源码阅读笔记-SDNLAB
1/30OpenvSwitch源码阅读笔记引言本文主要对OpenvSwitch(基于2.3.90版本)重点模块的源码实现流程做了简要的阅读记录,适合阅读OpenvSwitch源码的初级读者参考使用,任何错误和建议欢迎加作者QQ号38293996沟通交流。1.OVS网络架构Openvswitch是一个虚拟交换机,支持OpenFlow协议(也有一些硬件交换机支持OpenFlow),他们被远端的controller通过OpenFlow协议统一管理着,从而实现对接入的虚拟机(或设备)进行组网和互通,整体组网结构如下图:2.OVS内部架构2/30ovs-vswitchd主要模块,实现vswitch的守候进程daemon;ovsdb-server轻量级数据库服务器,用于ovs的配置信息;ovs-vsctl通过和ovsdb-server通信,查询和更新vswitch的配置;ovs-dpctl用来配置vswitch内核模块的一个工具;ovs-appctl发送命令消息到ovs进程;ovs-ofctl查询和控制OpenFlow虚拟交换机的流表;datapath内核模块,根据流表匹配结果做相应处理;3.OVS代码架构3/30vswitchd是ovs主要的用户态程序,它从ovsdb-server读取配置并发送到ofproto层,也从ofproto读取特定的状态和统计信息并发送到数据库;ofproto是openflow的接口层,负责和Openflowcontroller通信并通过ofproto_class与ofprotoprovider底层交互;ofproto-dpif是ofproto接口类的具体实现;netdev是ovs系统的网络设备抽象(比如linux的net_device或交换机的port),netdev_class定义了netdev-provider的具体实现需要的接口,具体的平台实现需要支持这些统一的接口,从而完成netdev设备的创建、销毁、打开、关闭等一系列操作;3.1datapath由于openvswitch用户态代码相对复杂,首先从内核模块入手分析。datapath为ovs内核模块,负责执行数据处理,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。一个datapath可以对应多个vport,一个vport类似物理交换机的端口概念。一个datapth关联一个flowtable,一个flowtable包含多个条目,每个条目包括两个内容:一个match/key和一个action。3.1.1数据流向4/30eth0eth1用户态接口VportKernelDatapathFlowTableAction一般的数据包在Linux网络协议中的流向为上图中的蓝色箭头流向:网卡eth0收到数据包后判断报文走向,如果是本地报文把数据传送到用户态,如果是转发报文根据选路(二层交换或三层路由)把报文送到另一个网卡如eth1。当有OVS时,数据流向如红色所示:从网卡eth0收到报文后进入ovs的端口,根据key值进行流表匹配,如果匹配成功执行流表对应的action;如果失败通过upcall送入用户态处理。3.1.2模块初始化内核模块采用module_init(dp_init)进行datapath的初始化,代码如下:其中dp的genl_family注册了如下四个类型:5/303.1.3收包处理通过vport注册的回调函数netdev_frame_hook()-netdev_frame_hook()-netdev_port_receive()-ovs_vport_receive()处理接收报文,ovs_flow_key_extract()函数生成flow的key内容用以接下来进行流表匹配,最后调用ovs_dp_process_packet()函数进入真正的ovs数据包处理,代码流程如下:3.1.3流表哈希桶流表采用hash的方式排列存放,流表的hash头结点存储数据结构如下:6/30该hash桶的初始化函数alloc_buckets(),生成的数据格式可参考如下:element_size元素hlist_head大小buckets一页空间大小hlist_headreciprocal_elems用于计算parts数组偏移total_nr_elements元素最大个数TBL_MIN_BUCKETShlist_head……elems_per_part每页元素个数*parts元素空间parts[0]flex_array-parts[]放入元素hlist_headhlist_head……parts[1]parts[n]……如果元素空间超过FLEX_ARRAY_BASE_BYTES_LEFT大小,需要再次分配空间3.1.4流表创建用户态通过netlink进行datapath流表更新的入口函数都定义在dp_flow_genl_ops中,流表创建的入口函数是ovs_flow_cmd_new函数,代码分析如下:7/30根据上述流程给出流表的主要数据结构如下:8/30structflow_tablestructtable_instance__rcu*tistructflow_tablestructmask_cache_entry__percpu*mask_cachestructmask_array__rcu*mask_arrayStructsw_flow_keykeystructsw_flow_maskstructsw_flow_key_rangerangestructmask_arraystructflex_array*bucketsunsignedintn_bucketsstructtable_instancestructhlist_nodenode[]structsw_flow_keykey…structsw_flowintnode_verparts[n]structsw_flow_mask*maskstructtable_instance__rcu*ufid_tiintcount,maxstructsw_flow_mask__rcu*masks[]Structsw_flow_keykeystructsw_flow_maskstructsw_flow_key_rangerangemasks[0]masks[n]u32hashstructflex_arraystructflex_array_part*parts[]elements[offset]inttotal_nr_elementsintelement_sizestructreciprocal_valuereciprocal_elemscharelements[PAGE_SIZE]structflex_array_part3.1.6流表查询流表查找主要是查表关键字的匹配,关键字数据结构如下,根据skb中的Ethernet帧生成key的函数为ovs_flow_key_extract():9/30Au8tun_opts[255]structsw_flow_keyu8tun_opts_lenstructovs_key_ipv4_tunneltun_keyu32skb_marku16in_portu32priorityu32recirc_idu8src[ETH_ALEN]u32ovs_flow_hashu16tciu16typeu8dst[ETH_ALEN]u8protou8ttlu8fragu8tosu16srcu16flagsu16dstu32srcu32dstunionu8sha[ETH_ALEN]u8tha[ETH_ALEN]in6_addrsrcin6_addrdstu32labelin6_addrtargetu8sll[ETH_ALEN]u8tll[ETH_ALEN]u64tun_idu32ipv4_srcu32ipv4_dstu16tun_flagsu8ipv4_tosu8pv4_ttlu16tp_srcu16tp_dststructovs_key_ipv4_tunnelL1:structphyAL2:structethAL3:structipAL4:structtpu32top_lseunionAL3:structmplsAEncapsulatingtunnelkeyAstructarpAstructaddrstructipv4structipv6AstructaddrAstructnd流表查询的入口函数ovs_flow_tbl_lookup_stats(),flow的匹配策略是和流表中所有mask和所有key进行匹配处理,为了加速查询效率,在调用真正的流表查询函数flow_lookup()之前,对于mask的查询采用了缓存机制,实现原理是首先查询缓存的mask_cache_entry,这些cache是查询成功后形成的cache,并针对cache采用分段查询的方式,代码如下:10/30flow_lookup()函数的处理流程如下:11/30masked_flow_lookup()函数处理如下:3.1.7action处理ovs的action类型如下,使用nla_type()函数获取nl_type的值,入口处理函数为do_execute_actions()。OVS_ACTION_ATTR_OUTPUT:获取port号,调用do_output()发送报文到该port;OVS_ACTION_ATTR_USERSPACE:调用output_userspace()发送到用户态;OVS_ACTION_ATTR_HASH:调用execute_hash()获取skb的hash赋值到ovs_flow_hashOVS_ACTION_ATTR_PUSH_VLAN:调用push_vlan()增加vlan头部12/30OVS_ACTION_ATTR_POP_VLAN:调用pop_vlan()移除vlan头OVS_ACTION_ATTR_RECIRC:在action_fifos全局数组中添加一个deferred_action;13/30OVS_ACTION_ATTR_SET:调用execute_set_action()设置相关参数;OVS_ACTION_ATTR_SAMPLE:概率性的发送报文到用户态(详见sflow章节)。3.1.8upcall处理当没有找到匹配的流表时,内核通过netlink发送报文到用户层处理,入口函数ovs_dp_upcall(),该函数调用queue_userspace_packet()构造发往用户层的skb,通过netlink通信机制发送到用户层,其中形成的主要数据格式如下:NLMSG_HDRLENnlmsghdrgenlmsghdrGENL_HDRLENovs_headerOVS_PACKET_ATTR_KEYOVS_PACKET_ATTR_USERDATAOVS_PACKET_ATTR_PACKETnlattrnlattrnlattr……KeyUserdata原始数据包OVS_KEY_ATTR_XXXsw_flow_key各字段data部分采用skb_zerocopy()进行拷贝3.2ovs-vswitchdvswitchd作为守护进程和ovsdb通信以及和controller进行openflow通信,并完成和底层内核的交互。代码在vswitchd/目录下面,可以从main函数入口分析,整体处理流程如下:14/30daemonize_start()开始守候进程模式unixctl_server_create(unixctl_path,&unixctl)bridge_init()初始化桥模型和数据库IDLovsdb_idl_create()创建到数据库的jasonrpc连接ovsdb_idl_omit_alert()ovsdb_idl_omit()unixctl_command_register()bridge_run()处理controll
本文标题:OpenvSwitch源码阅读笔记-SDNLAB
链接地址:https://www.777doc.com/doc-6010085 .html