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

来源:互联网 发布:java基础面试题 编辑:程序博客网 时间:2024/06/13 09:46

前两篇分析了接收netlink消息和解析netlink消息生成upcall对象,本篇分析upcall的处理。 处理函数为process_upcall。

1、process_upcall函数

static intprocess_upcall(struct udpif *udpif, struct upcall *upcall,               struct ofpbuf *odp_actions, struct flow_wildcards *wc){    const struct nlattr *userdata = upcall->userdata;    const struct dp_packet *packet = upcall->packet;    const struct flow *flow = upcall->flow;    switch (classify_upcall(upcall->type, userdata)) {    case MISS_UPCALL:        upcall_xlate(udpif, upcall, odp_actions, wc);        return 0;    case SFLOW_UPCALL:        if (upcall->sflow) {            union user_action_cookie cookie;            const struct nlattr *actions;            size_t actions_len = 0;            struct dpif_sflow_actions sflow_actions;            memset(&sflow_actions, 0, sizeof sflow_actions);            memset(&cookie, 0, sizeof cookie);            memcpy(&cookie, nl_attr_get(userdata), sizeof cookie.sflow);            if (upcall->actions) {                /* Actions were passed up from datapath. */                actions = nl_attr_get(upcall->actions);                actions_len = nl_attr_get_size(upcall->actions);                if (actions && actions_len) {                    dpif_sflow_read_actions(flow, actions, actions_len,                                            &sflow_actions);                }            }            if (actions_len == 0) {                /* Lookup actions in userspace cache. */                struct udpif_key *ukey = ukey_lookup(udpif, upcall->ufid);                if (ukey) {                    ukey_get_actions(ukey, &actions, &actions_len);                    dpif_sflow_read_actions(flow, actions, actions_len,                                            &sflow_actions);                }            }            dpif_sflow_received(upcall->sflow, packet, flow,                                flow->in_port.odp_port, &cookie,                                actions_len > 0 ? &sflow_actions : NULL);        }        break;    case IPFIX_UPCALL:        if (upcall->ipfix) {            union user_action_cookie cookie;            struct flow_tnl output_tunnel_key;            memset(&cookie, 0, sizeof cookie);            memcpy(&cookie, nl_attr_get(userdata), sizeof cookie.ipfix);            if (upcall->out_tun_key) {                odp_tun_key_from_attr(upcall->out_tun_key, false,                                      &output_tunnel_key);            }            dpif_ipfix_bridge_sample(upcall->ipfix, packet, flow,                                     flow->in_port.odp_port,                                     cookie.ipfix.output_odp_port,                                     upcall->out_tun_key ?                                         &output_tunnel_key : NULL);        }        break;    case FLOW_SAMPLE_UPCALL:        if (upcall->ipfix) {            union user_action_cookie cookie;            memset(&cookie, 0, sizeof cookie);            memcpy(&cookie, nl_attr_get(userdata), sizeof cookie.flow_sample);            /* The flow reflects exactly the contents of the packet.             * Sample the packet using it. */            dpif_ipfix_flow_sample(upcall->ipfix, packet, flow,                                   cookie.flow_sample.collector_set_id,                                   cookie.flow_sample.probability,                                   cookie.flow_sample.obs_domain_id,                                   cookie.flow_sample.obs_point_id);        }        break;    case BAD_UPCALL:        break;    }    return EAGAIN;}

从该函数可见,一共有4中upcall,MISS_UPCALL(未命中流表)、SFLOW_UPCALL(sFlow)、IPFIX_UPCALL和FLOW_SAMPLE_UPCALL。而datapath一共发送两种类型的netlink消息,OVS_PACKET_CMD_MISS和OVS_PACKET_CMD_ACTION。 upcall类型的映射关系通过classify_upcall函数实现:

static enum upcall_typeclassify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata){    union user_action_cookie cookie;    size_t userdata_len;    /* First look at the upcall type. */    switch (type) {    case DPIF_UC_ACTION:              //OVS_PACKET_CMD_ACTION,即通过output_userspace发送netlink消息,需要进一步细化        break;    case DPIF_UC_MISS:        return MISS_UPCALL;            //OVS_PACKET_CMD_MISS对应    case DPIF_N_UC_TYPES:    default:        VLOG_WARN_RL(&rl, "upcall has unexpected type %"PRIu32, type);        return BAD_UPCALL;    }    /* "action" upcalls need a closer look. */    if (!userdata) {        VLOG_WARN_RL(&rl, "action upcall missing cookie");        return BAD_UPCALL;    }    userdata_len = nl_attr_get_size(userdata);    if (userdata_len < sizeof cookie.type        || userdata_len > sizeof cookie) {        VLOG_WARN_RL(&rl, "action upcall cookie has unexpected size %"PRIuSIZE,                     userdata_len);        return BAD_UPCALL;    }    memset(&cookie, 0, sizeof cookie);    memcpy(&cookie, nl_attr_get(userdata), userdata_len);             //根据user data,进一步细分upcall类型    if (userdata_len == MAX(8, sizeof cookie.sflow)        && cookie.type == USER_ACTION_COOKIE_SFLOW) {        return SFLOW_UPCALL;                                          //sflow    } else if (userdata_len == MAX(8, sizeof cookie.slow_path)               && cookie.type == USER_ACTION_COOKIE_SLOW_PATH) {        return MISS_UPCALL;                                           //miss_upcall, 主动重新刷新流表?    } else if (userdata_len == MAX(8, sizeof cookie.flow_sample)               && cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) {        return FLOW_SAMPLE_UPCALL;                                    //sample    } else if (userdata_len == MAX(8, sizeof cookie.ipfix)               && cookie.type == USER_ACTION_COOKIE_IPFIX) {        return IPFIX_UPCALL;                                          //ipfix    } else {        VLOG_WARN_RL(&rl, "invalid user cookie of type %"PRIu16                     " and size %"PRIuSIZE, cookie.type, userdata_len);        return BAD_UPCALL;    }}
关于不同upcall的处理,将以专题的方式开展。 这样可以对某个功能有个全方位的了解,包括配置、upcall处理、流表生成等等。

0 0
原创粉丝点击