l3fwd_网络可编程数据面——DPDK Graph Library

网络可编程数据面——DPDK Graph Library

——lvyilong316

Graph library是DPDK 20.05版本引入的新特性,最近抽时间把其中关键代码看了一遍,主要希望看下其实现思路是否有可以借鉴的东西。下面将其大概实现进行了总结。

DPDK中的Graph架构将数据的处理抽象成了node和link构成的graph,这种思想并不是新东西,VPP就采用了类似的思路实现,只不过DPDK这里讲graph思想实现为了一个lib框架,提供了graph的创建,删除,查找,node clone,edge update,adge shrink等操作,可供上层应用基于此框架开发。

这种graph架构有什么优势呢?首先graph架构将报文处理的相似逻辑抽象同样到一个node中,这样减少了报文处理过程中的I cache和D cache miss;其次提高了报文处理逻辑的复用性,同样的处理逻辑抽象为node可以在graph路径中多次出现复用;其次提高了报文处理模块的灵活性,通过不同node的任意顺序组合完成不同的报文处理流程。

node的构成

Graph lib中的node构成如下图所示,由以下几部分构成:

(1)process:这是一个callback function,是node的核心处理流程,包含了数据处理的实现,通过rte_graph_walk()函数遍历每个node,然后调用每个node的process函数实现数据的处理,如果数据处理完成后需要交给下一个node处理,则需要在其中调用rte_node_enqueue*()函数。

(2)init:node的初始化函数,在rte_graph_create()函数创建graph时会调用各个node的init函数;

(3)fini:node的析构函数,在rte_graph_destroy()函数销毁graph时会调用各个node的fini函数;

(4)Context memory:存放当前node所需的私有信息的内存空间,process,init,fini等函数都可能会用到;

(5)nb_edges:和当前node关联的边数;

(6)next_node[]:存放当前node的邻居节点,由于graph是一个有向图,所以这里next_node[]其实存放是其下游的邻居节点;

内置node类型

用户可以根据自身需求实现注册自己的node节点,dpdk中的rte_node库中也实现了一些内置的基础node。下面我们以ethdev_tx node为例分析一下一个node的定义和注册过程。

ethdev_tx

ethdev_tx node定义了网卡port的收包行为。在rte_node中每个node的定义是通过注册rte_node_register信息完成的,rte_node_register包含了node所需要的基本信息,包括其process处理函数,ethdev_tx的rte_node_register如下所示:

点击(此处)折叠或打开

static struct rte_node_register ethdev_tx_node_base = {

.process = ethdev_tx_node_process,

.name = "ethdev_tx",

.init = ethdev_tx_node_init,

.nb_edges = ETHDEV_TX_NEXT_MAX,

.next_nodes = {

[ETHDEV_TX_NEXT_PKT_DROP] = "pkt_drop",

},

};

之后通过RTE_NODE_REGISTER进行注册:

RTE_NODE_REGISTER(ethdev_tx_node_base);

RTE_NODE_REGISTER的实现如下,最终调用__rte_node_register。

点击(此处)折叠或打开

#define RTE_NODE_REGISTER(node) \

RTE_INIT(rte_node_register_##node) \

{ \

node.parent_id = RTE_NODE_ID_INVALID; \

node.id = __rte_node_register(&node); \

}

__rte_node_register的主要工作就是分配struct node结构和对应的nodeid,并将其加入到全局链表node_list中。

点击(此处)折叠或打开

rte_node_t

__rte_node_register(const struct rte_node_register *reg)

{

struct node *node;

rte_edge_t i;

size_t sz;

graph_spinlock_lock();

sz = sizeof(struct node) + (reg->nb_edges * RTE_NODE_NAMESIZE);

node = calloc(1, sz);

if (node == NULL) {

rte_errno = ENOMEM;

goto fail;

}

/* Initialize the node */

if (rte_strscpy(node->name, reg->name, RTE_NODE_NAMESIZE) < 0) {

rte_errno = E2BIG;

goto free;

}

node->flags = reg->flags;

node->process = reg->process;

node->init = reg->init;

node->fini = reg->fini;

node->nb_edges = reg->nb_edges;

node->parent_id = reg->parent_id;

for (i = 0; i < reg->nb_edges; i++) {

if (rte_strscpy(node->next_nodes[i], reg->next_nodes[i],

RTE_NODE_NAMESIZE) < 0) {

rte_errno = E2BIG;

goto free;

}

}

node->id = node_id++;

/* Add the node at tail */

STAILQ_INSERT_TAIL(&node_list, node, next);

graph_spinlock_unlock();

return node->id;

free:

free(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值