【OVS2.5.0源码分析】upcall处理线程分析(3)

来源:互联网 发布:linux msleep函数 编辑:程序博客网 时间:2024/06/06 00:05

第一篇介绍了netlink消息的接收,接收到的消息是最原始的消息格式,本篇介绍如何把原始的消息,转化为upcall对象。

1、parse_odp_packet函数

static intparse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,                 struct dpif_upcall *upcall, int *dp_ifindex){    static const struct nl_policy ovs_packet_policy[] = {        /* Always present. */        [OVS_PACKET_ATTR_PACKET] = { .type = NL_A_UNSPEC,                                     .min_len = ETH_HEADER_LEN },        [OVS_PACKET_ATTR_KEY] = { .type = NL_A_NESTED },        /* OVS_PACKET_CMD_ACTION only. */        [OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_UNSPEC, .optional = true },        [OVS_PACKET_ATTR_EGRESS_TUN_KEY] = { .type = NL_A_NESTED, .optional = true },        [OVS_PACKET_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },        [OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = true }    };    struct ovs_header *ovs_header;    struct nlattr *a[ARRAY_SIZE(ovs_packet_policy)];    struct nlmsghdr *nlmsg;    struct genlmsghdr *genl;    struct ofpbuf b;    int type;    ofpbuf_use_const(&b, buf->data, buf->size);    nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);   //获取nlmsghdr信息    genl = ofpbuf_try_pull(&b, sizeof *genl);     //获取genlmsghdr信息    ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);  //获取ovs_header信息    if (!nlmsg || !genl || !ovs_header        || nlmsg->nlmsg_type != ovs_packet_family        || !nl_policy_parse(&b, 0, ovs_packet_policy, a,       //获取其他属性信息                            ARRAY_SIZE(ovs_packet_policy))) {        return EINVAL;    }    type = (genl->cmd == OVS_PACKET_CMD_MISS ? DPIF_UC_MISS            : genl->cmd == OVS_PACKET_CMD_ACTION ? DPIF_UC_ACTION            : -1);    if (type < 0) {        return EINVAL;    }    /* (Re)set ALL fields of '*upcall' on successful return. */    upcall->type = type;    upcall->key = CONST_CAST(struct nlattr *,                             nl_attr_get(a[OVS_PACKET_ATTR_KEY]));    upcall->key_len = nl_attr_get_size(a[OVS_PACKET_ATTR_KEY]);    dpif_flow_hash(&dpif->dpif, upcall->key, upcall->key_len, &upcall->ufid);    upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];    upcall->out_tun_key = a[OVS_PACKET_ATTR_EGRESS_TUN_KEY];    upcall->actions = a[OVS_PACKET_ATTR_ACTIONS];    upcall->mru = a[OVS_PACKET_ATTR_MRU];    /* Allow overwriting the netlink attribute header without reallocating. */    dp_packet_use_stub(&upcall->packet,       //构建upcall->packet对象,包括base指针、data指针、长度等信息                    CONST_CAST(struct nlattr *,                               nl_attr_get(a[OVS_PACKET_ATTR_PACKET])) - 1,                    nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]) +                    sizeof(struct nlattr));    dp_packet_set_data(&upcall->packet,                    (char *)dp_packet_data(&upcall->packet) + sizeof(struct nlattr));    dp_packet_set_size(&upcall->packet, nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]));    *dp_ifindex = ovs_header->dp_ifindex;    return 0;}
2、nl_policy_parse函数

/* Parses the 'msg' starting at the given 'nla_offset' as a sequence of Netlink * attributes.  'policy[i]', for 0 <= i < n_attrs, specifies how the attribute * with nla_type == i is parsed; a pointer to attribute i is stored in * attrs[i].  Returns true if successful, false on failure. * * If the Netlink attributes in 'msg' follow a Netlink header and a Generic * Netlink header, then 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN. */boolnl_policy_parse(const struct ofpbuf *msg, size_t nla_offset,                const struct nl_policy policy[],                struct nlattr *attrs[], size_t n_attrs){    struct nlattr *nla;    size_t left;    size_t i;    memset(attrs, 0, n_attrs * sizeof *attrs);    if (msg->size < nla_offset) {        VLOG_DBG_RL(&rl, "missing headers in nl_policy_parse");        return false;    }    NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, nla_offset, 0),    //获取netlink的其他属性                      msg->size - nla_offset)    {        uint16_t type = nl_attr_type(nla);        if (type < n_attrs && policy[type].type != NL_A_NO_ATTR) {            const struct nl_policy *e = &policy[type];            if (!nl_attr_validate(nla, e)) {                return false;            }            if (attrs[type]) {                VLOG_DBG_RL(&rl, "duplicate attr %"PRIu16, type);            }            attrs[type] = nla;        }    }    if (left) {        VLOG_DBG_RL(&rl, "attributes followed by garbage");        return false;    }    for (i = 0; i < n_attrs; i++) {   //检查必须字段是否有值        const struct nl_policy *e = &policy[i];        if (!e->optional && e->type != NL_A_NO_ATTR && !attrs[i]) {            VLOG_DBG_RL(&rl, "required attr %"PRIuSIZE" missing", i);            return false;        }    }    return true;}

0 0