在ovs-dpdk源码中,若在datapath classifier中未找到相应的flow匹配,则将初始化一个ofpbuf类型的action,然后通过handle_packet_upcall函数进入upcall流程,在ofproto classifier中通过调用xlate_action根据OpenFlow协议为action赋值,最后将该action向下“注入”到datapath classifier以及exact match cache中调用dp_netdev_execute_actions对流进行处理,以及报文转发。
struct ofpbuf {
void *base; /* First byte of allocated space. */
void *data; /* First byte actually in use. */
uint32_t size; /* Number of bytes in use. */
uint32_t allocated; /* Number of bytes allocated. */
void *header; /* OpenFlow header. */
void *msg; /* message's body */
struct ovs_list list_node; /* Private list element for use by owner. */
enum ofpbuf_source source; /* Source of memory allocated as 'base'. */
};
ofpbuf数据结构如下图:
struct nlattr {
uint16_t nla_len;
uint16_t nla_type;
};
nlattr数据结构如下图:
在netlink.c中调用nl_msg_put_*->nl_msg_put_unspec将Netlink属性追加(append)到ofpbuf中
/* Appends a Netlink attribute of the given 'type' and the 'size' bytes of
* 'data' as its payload, to the tail end of 'msg', reallocating and copying
* its data if necessary. Returns a pointer to the first byte of data in the
* attribute, which is left uninitialized. */
void
nl_msg_put_unspec(struct ofpbuf *msg, uint16_t type,
const void *data, size_t size)
{
memcpy(nl_msg_put_unspec_uninit(msg, type, size), data, size);
}
void *
nl_msg_put_unspec_uninit(struct ofpbuf *msg, uint16_t type, size_t size)
{
size_t total_size = NLA_HDRLEN + size;
struct nlattr* nla = nl_msg_put_uninit(msg, total_size);
ovs_assert(!nl_attr_oversized(size));
nla->nla_len = total_size;
nla->nla_type = type;
return nla + 1;
}
void *
nl_msg_put_uninit(struct ofpbuf *msg, size_t size)
{
size_t pad = PAD_SIZE(size, NLMSG_ALIGNTO);
char *p = ofpbuf_put_uninit(msg, size + pad);
if (pad) {
memset(p + size, 0, pad);
}
return p;
}
追加过程ofpbuf内容变动如下图:
在netlink.c中调用nl_msg_push_*->nl_msg_push_unspec将Netlink属性预置(prepend)到ofpbuf中,该过程整体流程与追加相同,区别在于nlattr将置与ofpbuf的headroom中。