本篇分析,sflow的消息处理,处理入口函数是在process_upcall函数。
1、process_upcall函数
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); //读取user data信息
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 action
&sflow_actions);
}
}
if (actions_len == 0) {
/* Lookup actions in userspace cache. */
struct udpif_key *ukey = ukey_lookup(udpif, upcall->ufid); //用户态cache,加速
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, //sflow消息处理
flow->in_port.odp_port, &cookie,
actions_len > 0 ? &sflow_actions : NULL);
}
break;
2、dpif_sflow_received函数
void
dpif_sflow_received(struct dpif_sflow *ds, const struct dp_packet *packet,
const struct flow *flow, odp_port_t odp_in_port,
const union user_action_cookie *cookie,
const struct dpif_sflow_actions *sflow_actions)
OVS_EXCLUDED(mutex)
{
SFL_FLOW_SAMPLE_TYPE fs;
SFLFlow_sample_element hdrElem;
SFLSampled_header *header;
SFLFlow_sample_element switchElem;
uint8_t tnlInProto, tnlOutProto;
SFLFlow_sample_element tnlInElem, tnlOutElem;
SFLFlow_sample_element vniInElem, vniOutElem;
SFLFlow_sample_element mplsElem;
uint32_t mpls_lse_buf[FLOW_MAX_MPLS_LABELS];
SFLSampler *sampler;
struct dpif_sflow_port *in_dsp;
struct dpif_sflow_port *out_dsp;
ovs_be16 vlan_tci;
ovs_mutex_lock(&mutex);
sampler = ds->sflow_agent->samplers; //获取第一个sampler
if (!sampler) {
goto out;
}
/* Build a flow sample. */
memset(&fs, 0, sizeof fs);
/* Look up the input ifIndex if this port has one. Otherwise just
* leave it as 0 (meaning 'unknown') and continue. */
in_dsp = dpif_sflow_find_port(ds, odp_in_port);
if (in_dsp) {
fs.input = SFL_DS_INDEX(in_dsp->dsi);
}
/* Make the assumption that the random number generator in the datapath converges
* to the configured mean, and just increment the samplePool by the configured
* sampling rate every time. */
sampler->samplePool += sfl_sampler_get_sFlowFsPacketSamplingRate(sampler);
/* Sampled header. */
memset(&hdrElem, 0, sizeof hdrElem);
hdrElem.tag = SFLFLOW_HEADER;
header = &hdrElem.flowType.header;
header->header_protocol = SFLH