#include "MESA_prof_load.h" #include "cJSON.h" #include "common.h" #include "sc_trace.h" #include #include #include struct dp_trace_config { uint16_t enable; }; int __dp_trace_path_handler(const struct rte_mp_msg * msg, const void * peer); static void dp_trace_telemetry_unregister(struct app_main * app_main, struct app * app, void * arg); void load_dp_trace_config(struct sc_main * sc, struct dp_trace_config * dp_trace_config) { unsigned int enable = 1; MESA_load_profile_uint_nodef(sc->local_dyfile, "dp_trace_rule", "enable", &enable); dp_trace_config->enable = enable; } void dp_trace_config_apply(struct sc_main * sc) { if (sc->trace == NULL) return; struct dp_trace_config dp_trace_config = {}; MR_INFO("Loading data path trace configuration file..."); load_dp_trace_config(sc, &dp_trace_config); if (sc->trace->inst->enable != dp_trace_config.enable) { MR_INFO("Modify trace status from %u to %u", sc->trace->inst->enable, dp_trace_config.enable); sc->trace->inst->enable = dp_trace_config.enable; } MR_INFO("Loading data path trace configuration file is completed."); } void dp_trace_config_update(struct sc_main * sc) { dp_trace_config_apply(sc); } int mr_dp_trace_init(struct sc_main * sc) { struct dp_trace_process * trace = dp_trace_process_create(DP_TRACE_PROCESS_MARSIO); if (trace == NULL) abort(); sc->trace = trace; dp_trace_config_apply(sc); rte_mp_action_register(DP_TRACE_MP_MSG_NAME, __dp_trace_path_handler); app_event_handler_register(sc->app_main, APP_EV_TYPE_UNREGISTER, dp_trace_telemetry_unregister, NULL); return 0; } int __dp_trace_path_handler(const struct rte_mp_msg * msg, const void * peer) { struct dp_trace_instance * inst = sc_main_get()->trace->inst; struct dp_trace_job_ctx * job_ctx = inst->job_ctx; int ret = 0; struct rte_mp_msg resp = {}; snprintf(resp.name, sizeof(resp.name), "%s", DP_TRACE_MP_MSG_NAME); struct dp_trace_resp * dp_trace_resp = (struct dp_trace_resp *)resp.param; resp.len_param = sizeof(struct dp_trace_resp); struct dp_trace_req * dp_trace_req = (struct dp_trace_req *)msg->param; if (dp_trace_req->action == DP_TRACE_INSTANCE_GET) { dp_trace_resp->errcode = DP_TRACE_SUCCESS; dp_trace_resp->trace_instance = inst; goto send_resp; } if (dp_trace_req->action == DP_TRACE_JOB_ID_USED_GET) { job_bitmap_t jobs_id_uesd = 0; for (unsigned int i = 0; i < DP_TRACE_JOB_NUM_MAX; i++) { if (job_ctx[i].used == true) { jobs_id_uesd |= job_ctx[i].job_id; } } dp_trace_resp->jobs_id_used_get = jobs_id_uesd; dp_trace_resp->errcode = DP_TRACE_SUCCESS; goto send_resp; } if (dp_trace_req->action == DP_TRACE_JOB_ADD) { dp_trace_resp->errcode = dp_trace_job_add(sc_main_get()->trace, dp_trace_req->desc); if (dp_trace_resp->errcode == DP_TRACE_SUCCESS) { unsigned int rule_index = dp_trace_req->desc->rule_index; dp_trace_resp->job_id_add = job_ctx[rule_index].job_id; struct app * app_object = app_lookup_by_symbol(sc_main_get(), (const char *)dp_trace_req->appsym); assert(app_object != NULL); app_object->job_id_used = 1; } goto send_resp; } if (dp_trace_req->action == DP_TRACE_JOB_DESTROY) { job_bitmap_t jobs_id = dp_trace_req->jobs_id_destroy; jobs_id = jobs_id & 0xffff; dp_trace_jobs_destroy(sc_main_get()->trace, jobs_id); dp_trace_resp->errcode = DP_TRACE_SUCCESS; } send_resp: ret = rte_mp_reply(&resp, peer); if (ret < 0) { MR_WARNING("Failed to execute rte_mp_reply:%s", rte_strerror(rte_errno)); return -1; } return 0; } static void dp_trace_telemetry_unregister(struct app_main * app_main, struct app * app, void * arg) { if (app->job_id_used == 0) { return; } struct dp_trace_process * dp_trace_process = sc_main_get()->trace; dp_trace_jobs_destroy(dp_trace_process, DP_TRACE_ALL_JOBS); } cJSON * dp_trace_monit_loop(struct sc_main * sc) { cJSON * json_root = cJSON_CreateObject(); struct dp_trace_process * trace = sc->trace; struct dp_trace_stat monit_statistics = {}; uint64_t filter_exec_hit = 0; for (unsigned int i = 0; i < RTE_MAX_LCORE; i++) { struct dp_trace_stat * statistics_i = &trace->statistics[i]; for (unsigned int j = 0; j < DP_TRACE_JOB_NUM_MAX; j++) { filter_exec_hit += statistics_i->filter_exec_hit[j]; } monit_statistics.filter_exec_miss += statistics_i->filter_exec_miss; monit_statistics.reach_pkt_cnt_limit += statistics_i->reach_pkt_cnt_limit; monit_statistics.record_buf_alloc_failed_no_mem += statistics_i->record_buf_alloc_failed_no_mem; monit_statistics.record_buf_alloc_success += statistics_i->record_buf_alloc_success; monit_statistics.ring_enqueue_failed += statistics_i->ring_enqueue_failed; monit_statistics.ring_enqueue_success += statistics_i->ring_enqueue_success; monit_statistics.record_emit_failed_trace_oversize += statistics_i->record_emit_failed_trace_oversize; monit_statistics.record_emit_failed_no_space_in_buf += statistics_i->record_emit_failed_no_space_in_buf; monit_statistics.record_emit_success += statistics_i->record_emit_success; } cJSON_AddBoolToObject(json_root, "trace_enable", trace->inst->enable); cJSON_AddNumberToObject(json_root, "filter_exec_hit", filter_exec_hit); cJSON_AddNumberToObject(json_root, "filter_exec_miss", monit_statistics.filter_exec_miss); cJSON_AddNumberToObject(json_root, "reach_pkt_cnt_limit", monit_statistics.reach_pkt_cnt_limit); cJSON_AddNumberToObject(json_root, "record_buf_alloc_failed_no_mem", monit_statistics.record_buf_alloc_failed_no_mem); cJSON_AddNumberToObject(json_root, "record_buf_alloc_success", monit_statistics.record_buf_alloc_success); cJSON_AddNumberToObject(json_root, "ring_enqueue_failed", monit_statistics.ring_enqueue_failed); cJSON_AddNumberToObject(json_root, "ring_enqueue_success", monit_statistics.ring_enqueue_success); cJSON_AddNumberToObject(json_root, "record_emit_failed_trace_oversize", monit_statistics.record_emit_failed_trace_oversize); cJSON_AddNumberToObject(json_root, "record_emit_failed_no_space_in_buf", monit_statistics.record_emit_failed_no_space_in_buf); cJSON_AddNumberToObject(json_root, "record_emit_success", monit_statistics.record_emit_success); return json_root; } void hook_rte_pktmbuf_free(struct rte_mbuf * m) { if (m == NULL) return; struct dp_trace_process * trace = sc_main_get()->trace; if (unlikely(dp_trace_record_can_emit(m, DP_TRACE_MEASUREMENT_TYPE_TELEMETRY))) { struct dp_trace_record_meta meta = { .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TELEMETRY, .appsym = MR_TRACE_APPSYM, .module = ""}; dp_trace_record_emit_str(sc_main_get()->trace, m, rte_lcore_id(), &meta, "packet dropped"); } if (unlikely(dp_trace_record_can_emit(m, DP_TRACE_MEASUREMENT_TYPE_TRACE))) { struct dp_trace_record_meta meta = { .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE, .appsym = MR_TRACE_APPSYM, .module = ""}; dp_trace_record_emit_str(sc_main_get()->trace, m, rte_lcore_id(), &meta, "packet dropped"); } struct mrb_metadata * mrb_meta = rte_mbuf_to_priv(m); mrb_meta->egress_action = MR_EGRESS_ACTION_DROP; dp_trace_record_write(trace, m, rte_lcore_id()); rte_pktmbuf_free(m); } void hook_rte_pktmbuf_free_bulk(struct rte_mbuf ** mbufs, unsigned int count) { struct dp_trace_process * trace = sc_main_get()->trace; for (unsigned int idx = 0; idx < count; idx++) { struct rte_mbuf * mbuf = mbufs[idx]; if (mbuf == NULL) continue; if (unlikely(dp_trace_record_can_emit(mbuf, DP_TRACE_MEASUREMENT_TYPE_TELEMETRY))) { struct dp_trace_record_meta meta = { .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TELEMETRY, .appsym = MR_TRACE_APPSYM, .module = ""}; dp_trace_record_emit_str(sc_main_get()->trace, mbuf, rte_lcore_id(), &meta, "packet dropped"); } if (unlikely(dp_trace_record_can_emit(mbuf, DP_TRACE_MEASUREMENT_TYPE_TRACE))) { struct dp_trace_record_meta meta = { .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE, .appsym = MR_TRACE_APPSYM, .module = ""}; dp_trace_record_emit_str(sc_main_get()->trace, mbuf, rte_lcore_id(), &meta, "packet dropped"); } struct mrb_metadata * mrb_meta = rte_mbuf_to_priv(mbuf); mrb_meta->egress_action = MR_EGRESS_ACTION_DROP; dp_trace_record_write(trace, mbuf, rte_lcore_id()); } rte_pktmbuf_free_bulk(mbufs, count); }