kni框架及收发数据流程

一、kni框架
1)首先定义一个struct rte_kni 结构体指针*kni
2)rte_kni_init() 初始化
3)设置端口:包含端口有效性检查、配置网卡接收/发送队列、网卡启动等 是否开启混杂模式?(见下)ddos攻击是不是在混杂模式下才可以实现?不是
4)kni = rte_kni_alloc(struct rte_mempool *pktmbuf_pool, const struct rte_kni_conf *conf, struct rte_kni_ops *ops) 需要设置conf和ops

5)在合适的时机向kni收发包 rte_kni_rx/tx_burst()
6)rte_kni_handle_request() // kni 会通过共享队列发送一个控制消息到用户态,在 dpdk 用户态程序中需要轮询获取 kni 共享队列中的消息, 调用函数kni_fifo_get从共享队列中获取消息,获取成功后校验消息是否合法,合法的消息则根据 req_id 进行分发,RTE_KNI_REQ_CFG_NETWORK_IF类型的消息会调用 kni 初始化中注册的 ops 中的 config_network_if 接口来处理。RTE_KNI_REQ_CHANGE_MTU类型的消息会调用 kni 初始化中注册的 ops 中的change_mtu接口来处理。

二、网卡工作模式介绍
广播模式:物理地址(MAC)是0Xffffff的帧为广播帧,工作在广播模式的网卡接收广播帧。
多播模式:如果将网卡设置为多播模式,它可以接收所有的多播传送帧,而不论他是不是组内成员。
直接模式:只接收目的地址是自己MAC地址的帧。
混杂模式:工作在混杂模式下的网卡接收所有流经网卡的帧。
网卡默认工作模式包括广播模式和直接模式,即它只接收广播帧和发给自己的帧。如果采用混杂模式,一个站点的网卡将接收同一网络内所有站点所发送的数据包,这样就可以达到对网络信息监视捕获的目的。
ifconfig eth0 promisc 设置网卡为混杂模式
ifconfig eth0 -promisc 取消网卡为混杂模式
参考:https://blog.youkuaiyun.com/chengqiuming/article/details/89603272

三、kni收发包实现机制
一个网卡可以创建一个和多个kni设备。<应用层自行指定一个创建多少个kni设备>
如果在加载驱动的时候,指定了单线程模型,则kni驱动只会创建一个线程,用于所有的kni设备接收来自应用层的报文。
如果在加载驱动的时候,指定了多线程模型,则kni驱动为每一个kni设备创建一个线程去接收来自应用层的报文。
在这里插入图片描述
应用层使用一个struct rte_kni_memzone_slot数组来存放所有的kni设备,每个数组元素对应一个kni设备。
每个kni设备都有一个独占的发送队列、接收队列、分配队列、释放队列、请求队列、响应队列
在这里插入图片描述
当应用层从网卡收到报文后,将报文放到kni设备的rx接收队队列。Kni启动从rx接收队列中取出mbuf报文,将mbuf报文转为内核协议栈支持的sk_buff,调用netif_rx()内核接口发给内核。报文发给内核以后,会将mbuff报文放到free释放队列,应用层读取释放队列中待释放的mbuf进行释放操作。
当kni驱动收到来自内核的报文后,调用kni_net_tx从alloc分配队列中获取一个应用层已经分配好的mbuf结构,同时将sk_buff报文转换为mbuf报文,存放到mbuf中,之后将mbuf报文发到tx发送队列中。应用层从tx发送队列中获取报文后,将报文通过网卡发送出去。应用层也会开辟mbuf空间,放到alloc队列中,供后续kni驱动发包给应用层操作。
请求和响应队列的作用:应用层调用ifconfig,ethtool等工具设置kni设备的mtu,使得kni设备up/down的时候,kni驱动会构造一个请求报文并将该请求报文放到req请求队列,应用层(dpdk)就会从会调用pmd用户态驱动实现的接口,真正实现对网卡设置mtu以及up/down等操作。之后应用层会构造一个 响应消息,将消息放到resp队列中,驱动从这个resp队列中获取响应消息就知道请求的执行结果。

参考:https://blog.youkuaiyun.com/qq_20817327/article/details/106461298

四、NIC <-> dpdk <-> kni <-> 内核协议栈之间的数据传递过程

接收数据:NIC->dpdk->kni->内核协议栈

  1. NIC->dpdk rte_eth_rx_burst
  2. dpdk->kni rte_kni_tx_burst
  3. kni内核驱动 kni_ioctl -> kni_ioctl_create -> kni_run_thread -> kni_thread_single/multiple -> kni_net_rx -> kni_net_rx_func(默认情况下为kni_net_rx_normal)
    kni_net_rx_normal-> kni_fifo_free_count 获取kni->free_q队列上是否有空闲位置,如果已满,则丢弃数据包
    kni_fifo_get 从kni->rx_q中弹出元素到kni->pa
    dev_alloc_skb 从内存申请skb
    填充skb结构体 将mbuf指针指向的数据内容拷贝到skb中
    netif_rx_ni(skb) 传递skb到内核网络协议栈
    kni_fifo_put 将使用后的kni->va投递到kni->free_q队列中,等待用户态KNI进行释放

发送数据:内核协议栈->kni->dpdk->NIC

  1. 内核协议栈->kni
    kni_net_ops结构体中的ndo_start_xmit回调函数注册为kni_net_tx
    kni_net_tx -> kni_fifp_free_count or kni_fifo_count 检测tx_q队列中的空闲位置和alloc_q队列中的元素
    kni_fifo_get 从alloc_q队列取出一个mbuf到pkt_pa
    将skb中的数据拷贝到pkt_va
    kni_fifo_put 将pkt_va投递到tx_q队列
    释放skb
  2. kni->dpdk rte_kni_rx_burst调用kni_fifo_get从kni->tx_q队列中获取数据
    -> kni_allocate_mbufs -> rte_pktmbuf_alloc 开辟mbuf空间到alloc_q队列中
  3. dpdk -> NIC rte_eth_tx_burst

参考:https://blog.youkuaiyun.com/haolipengzhanshen/article/details/88426482

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值