/* * debug attribute TCA_NETEM_LOSS */ void debug_tca_netem_loss(int lev, struct rtattr *netem, const char *name) { struct rtattr *loss[__NETEM_LOSS_MAX]; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(netem->rta_len)); parse_nested_rtattr(loss, NETEM_LOSS_MAX, netem); if(loss[NETEM_LOSS_GI]) debug_netem_loss_gi(lev+1, loss[NETEM_LOSS_GI], "NETEM_LOSS_GI"); if(loss[NETEM_LOSS_GE]) debug_netem_loss_ge(lev+1, loss[NETEM_LOSS_GE], "NETEM_LOSS_GE"); }
/* * debug attribute TCA_EMATCH_* */ void debug_tca_ematch(int lev, struct rtattr *tca, const char *name) { struct rtattr *em_tree[__TCA_EMATCH_TREE_MAX]; int num = -1; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(tca->rta_len)); parse_nested_rtattr(em_tree, TCA_EMATCH_TREE_MAX, tca); if(em_tree[TCA_EMATCH_TREE_HDR]) num = debug_tca_ematch_tree_hdr(lev+1, em_tree[TCA_EMATCH_TREE_HDR], "TCA_EMATCH_TREE_HDR"); if(em_tree[TCA_EMATCH_TREE_LIST]) debug_tca_ematch_tree_list(lev+1, em_tree[TCA_EMATCH_TREE_LIST], "TCA_EMATCH_TREE_LIST", num); }
/* * parse attribute TCA_EMATCH_* */ int parse_tca_ematch(char *msg, char *mp, struct rtattr *tca) { struct rtattr *em_tree[__TCA_EMATCH_TREE_MAX]; int num = -1; parse_nested_rtattr(em_tree, TCA_EMATCH_TREE_MAX, tca); if(em_tree[TCA_EMATCH_TREE_HDR]) if(parse_tca_ematch_tree_hdr(em_tree[TCA_EMATCH_TREE_HDR], &num)) return(1); if(em_tree[TCA_EMATCH_TREE_LIST]) if(parse_tca_ematch_tree_list(msg, mp, em_tree[TCA_EMATCH_TREE_LIST], num)) return(1); return(0); }
/* * debug attributes IFLA_BRPORT_* */ void debug_ifla_brport(int lev, struct rtattr *ifla) { struct rtattr *brp[__IFLA_BRPORT_MAX]; parse_nested_rtattr(brp, IFLA_BRPORT_MAX, ifla); if(brp[IFLA_BRPORT_STATE]) debug_rta_u8(lev+1, brp[IFLA_BRPORT_STATE], "IFLA_BRPORT_STATE", conv_br_state); if(brp[IFLA_BRPORT_PRIORITY]) debug_rta_u16(lev+1, brp[IFLA_BRPORT_PRIORITY], "IFLA_BRPORT_PRIORITY", NULL); if(brp[IFLA_BRPORT_COST]) debug_rta_u32(lev+1, brp[IFLA_BRPORT_COST], "IFLA_BRPORT_COST", NULL); if(brp[IFLA_BRPORT_MODE]) debug_rta_u8(lev+1, brp[IFLA_BRPORT_MODE], "IFLA_BRPORT_MODE", NULL); if(brp[IFLA_BRPORT_GUARD]) debug_rta_u8(lev+1, brp[IFLA_BRPORT_GUARD], "IFLA_BRPORT_GUARD", NULL); if(brp[IFLA_BRPORT_PROTECT]) debug_rta_u8(lev+1, brp[IFLA_BRPORT_PROTECT], "IFLA_BRPORT_PROTECT", NULL); if(brp[IFLA_BRPORT_FAST_LEAVE]) debug_rta_u8(lev+1, brp[IFLA_BRPORT_FAST_LEAVE], "IFLA_BRPORT_FAST_LEAVE", NULL); #if HAVE_DECL_IFLA_BRPORT_LEARNING if(brp[IFLA_BRPORT_LEARNING]) debug_rta_u8(lev+1, brp[IFLA_BRPORT_LEARNING], "IFLA_BRPORT_LEARNING", NULL); if(brp[IFLA_BRPORT_UNICAST_FLOOD]) debug_rta_u8(lev+1, brp[IFLA_BRPORT_UNICAST_FLOOD], "IFLA_BRPORT_UNICAST_FLOOD", NULL); #endif return; }
/* * parse red options */ int parse_tca_options_red(char *msg, char **mp, struct rtattr *tca) { struct rtattr *red[__TCA_RED_MAX]; parse_nested_rtattr(red, TCA_RED_MAX, tca); if(red[TCA_RED_PARMS]) { struct tc_red_qopt *qopt; char limit[MAX_STR_SIZE] = ""; char min[MAX_STR_SIZE] = ""; char max[MAX_STR_SIZE] = ""; char list[MAX_STR_SIZE] = ""; if(RTA_PAYLOAD(red[TCA_RED_PARMS]) < sizeof(*qopt)) { rec_log("error: %s: TCA_RED_PARMS: payload too short", __func__); return(1); } qopt = (struct tc_red_qopt *)RTA_DATA(red[TCA_RED_PARMS]); conv_unit_size(limit, sizeof(limit), qopt->limit); conv_unit_size(min, sizeof(min), qopt->qth_min); conv_unit_size(max, sizeof(max), qopt->qth_max); *mp = add_log(msg, *mp, "limit=%s min=%s max=%s ", limit, min, max); if(qopt->flags) { conv_tc_red_flags(qopt->flags, list, sizeof(list), 0); *mp = add_log(msg, *mp, "flag=%s ", list); } } #if HAVE_DECL_TCA_RED_MAX_P if(red[TCA_RED_MAX_P]) { if(RTA_PAYLOAD(red[TCA_RED_MAX_P]) < sizeof(unsigned)) { rec_log("error: %s: TCA_RED_MAX_P: payload too short", __func__); return(1); } *mp = add_log(msg, *mp, "probability=%g(%%) ", *(unsigned *)RTA_DATA(red[TCA_RED_MAX_P]) / pow(2, 32) * 100); } #endif return(0); }
/* * debug red options */ void debug_tca_options_red(int lev, struct rtattr *tca, const char *name) { struct rtattr *red[__TCA_RED_MAX]; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(tca->rta_len)); parse_nested_rtattr(red, TCA_RED_MAX, tca); if(red[TCA_RED_PARMS]) debug_tca_red_parms(lev+1, red[TCA_RED_PARMS], "TCA_RED_PARMS"); if(red[TCA_RED_STAB]) debug_rta_ignore(lev+1, red[TCA_RED_STAB], "TCA_RED_STAB"); #if HAVE_DECL_TCA_RED_MAX_P if(red[TCA_RED_MAX_P]) debug_rta_u32(lev+1, red[TCA_RED_MAX_P], "TCA_RED_MAX_P", NULL); #endif }
/* * debug choke options */ void debug_tca_options_choke(int lev, struct rtattr *tca, const char *name) { struct rtattr *choke[__TCA_CHOKE_MAX]; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(tca->rta_len)); parse_nested_rtattr(choke, TCA_CHOKE_MAX, tca); if(choke[TCA_CHOKE_PARMS]) debug_tca_choke_parms(lev+1, choke[TCA_CHOKE_PARMS], "TCA_CHOKE_PARMS"); if(choke[TCA_CHOKE_STAB]) debug_rta_ignore(lev+1, choke[TCA_CHOKE_STAB], "TCA_CHOKE_STAB"); #if HAVE_DECL_TCA_GRED_MAX_P if(choke[TCA_CHOKE_MAX_P]) debug_rta_u32(lev+1, choke[TCA_CHOKE_MAX_P], "TCA_CHOKE_MAX_P", NULL); #endif }
/* * parse rsvp options */ int parse_tca_options_rsvp(char *msg, char **mp, struct tcmsg *tcm, struct rtattr *tca) { struct rtattr *rsvp[__TCA_RSVP_MAX]; char *mp_tmp = *mp; parse_nested_rtattr(rsvp, TCA_RSVP_MAX, tca); if(rsvp[TCA_RSVP_CLASSID]) if(parse_tca_classid(msg, mp, rsvp[TCA_RSVP_CLASSID])) return(1); if(rsvp[TCA_RSVP_DST]) if(parse_tca_rsvp_dst(msg, mp, tcm, rsvp[TCA_RSVP_DST])) return(1); if(rsvp[TCA_RSVP_SRC]) if(parse_tca_rsvp_src(msg, mp, tcm, rsvp[TCA_RSVP_SRC])) return(1); if(rsvp[TCA_RSVP_PINFO]) if(parse_tca_rsvp_pinfo(msg, mp, rsvp[TCA_RSVP_PINFO])) return(1); if(*mp != mp_tmp) rec_log("%s", msg); /* rollback pointer */ *mp = mp_tmp; /* logging for each attribute below */ if(rsvp[TCA_RSVP_POLICE]) if(parse_tca_act_options_police(msg, *mp, rsvp[TCA_RSVP_POLICE])) return(1); if(rsvp[TCA_RSVP_ACT]) if(parse_tca_acts(msg, *mp, rsvp[TCA_RSVP_ACT])) return(1); return(0); }
/* * debug attributes TCA_ACT_* */ void debug_tca_act(int lev, struct rtattr *acts) { struct rtattr *act[__TCA_ACT_MAX]; char kind[IFNAMSIZ]; parse_nested_rtattr(act, __TCA_ACT_MAX-1, acts); if(act[TCA_ACT_KIND]) debug_rta_str(lev+1, act[TCA_ACT_KIND], "TCA_ACT_KIND", kind, sizeof(kind)); if(act[TCA_ACT_OPTIONS]) debug_tca_act_options(lev+1, act[TCA_ACT_OPTIONS], "TCA_ACT_OPTIONS", kind, sizeof(kind)); if(act[TCA_ACT_INDEX]) debug_rta_s32(lev+1, act[TCA_ACT_INDEX], "TCA_ACT_INDEX", NULL); if(act[TCA_ACT_STATS]) debug_tca_act_stats(lev+1, act[TCA_ACT_STATS], "TCA_ACT_STATS"); }
/* * parse choke options */ int parse_tca_options_choke(char *msg, char **mp, struct rtattr *tca) { struct rtattr *choke[__TCA_CHOKE_MAX]; parse_nested_rtattr(choke, TCA_CHOKE_MAX, tca); if(choke[TCA_CHOKE_PARMS]) { struct tc_choke_qopt *qopt; char list[MAX_STR_SIZE] = ""; if(RTA_PAYLOAD(choke[TCA_CHOKE_PARMS]) < sizeof(*qopt)) { rec_log("error: %s: TCA_CHOKE_PARMS: payload too short", __func__); return(1); } qopt = (struct tc_choke_qopt *)RTA_DATA(choke[TCA_CHOKE_PARMS]); *mp = add_log(msg, *mp, "limit=%u(packet) min=%u(packet) max=%u(packet) ", qopt->limit, qopt->qth_min, qopt->qth_max); if(qopt->flags) { conv_tc_red_flags(qopt->flags, list, sizeof(list), 0); *mp = add_log(msg, *mp, "flag=%s ", list); } } #if HAVE_DECL_TCA_CHOKE_MAX_P if(choke[TCA_CHOKE_MAX_P]) { if(RTA_PAYLOAD(choke[TCA_CHOKE_MAX_P]) < sizeof(unsigned)) { rec_log("error: %s: TCA_CHOKE_MAX_P: payload too short", __func__); return(1); } *mp = add_log(msg, *mp, "probability=%g(%%) ", *(unsigned *)RTA_DATA(choke[TCA_CHOKE_MAX_P]) / pow(2, 32) * 100); } #endif return(0); }
/* * debug attribute TCA_EMATCH_TREE_LIST */ void debug_tca_ematch_tree_list(int lev, struct rtattr *em_tree, const char *name, int num) { struct rtattr *em_list[num+1]; struct tcf_ematch_hdr *hdr; int i; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(em_tree->rta_len)); parse_nested_rtattr(em_list, num, em_tree); /* no exist em_list[0] */ for(i = 1; i < num + 1; i++) { if(!em_list[i]) return; if(RTA_PAYLOAD(em_list[i]) < sizeof(*hdr)) { rec_dbg(lev+1, "[ tcf_ematch_hdr[%d](%d) ] -- payload too short --", i, sizeof(*hdr)); return; } hdr = (struct tcf_ematch_hdr *)RTA_DATA(em_list[i]); rec_dbg(lev+1, "[ tcf_ematch_hdr[%d](%d) ]", i, sizeof(*hdr)); rec_dbg(lev+1, " matchid(%d): %hu", sizeof(hdr->matchid), hdr->matchid); rec_dbg(lev+1, " kind(%d): %hu(%s)", sizeof(hdr->kind), hdr->kind, conv_tcf_em_kind(hdr->kind, 1)); rec_dbg(lev+1, " flags(%d): %hu(%s)", sizeof(hdr->flags), hdr->flags, conv_tcf_em_flag(hdr->flags, 1)); rec_dbg(lev+1, " pad(%d): %hu", sizeof(hdr->pad), hdr->pad); /* use (char*)hdr in order to count by one byte */ switch(hdr->kind) { #ifdef HAVE_LINUX_TC_EMATCH_TC_EM_CMP_H case TCF_EM_CMP: debug_ematch_cmp(lev+1, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr)); break; #endif #ifdef HAVE_LINUX_TC_EMATCH_TC_EM_NBYTE_H case TCF_EM_NBYTE: debug_ematch_nbyte(lev+1, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr)); break; #endif case TCF_EM_U32: debug_ematch_u32(lev+1, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr)); break; #ifdef HAVE_LINUX_TC_EMATCH_TC_EM_META_H case TCF_EM_META: debug_ematch_meta(lev+1, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr)); break; #endif /* not implemented yet case TCF_EM_TEXT: case TCF_EM_VLAN: case TCF_EM_CANID: case TCF_EM_IPSET: */ default: break; } } }
/* * parse attribute TCA_EMATCH_TREE_LIST */ int parse_tca_ematch_tree_list(char *msg, char *mp, struct rtattr *em_tree, int num) { struct rtattr *em_list[num+1]; struct tcf_ematch_hdr *hdr; int i; char *mp_tmp = mp; parse_nested_rtattr(em_list, num, em_tree); /* no exist em_list[0] */ for(i = 1; i < num + 1; i++, mp = mp_tmp) { if(!em_list[i]) return(0); if(RTA_PAYLOAD(em_list[i]) < sizeof(*hdr)) { rec_log("error: %s: payload too short", __func__); return(1); } hdr = (struct tcf_ematch_hdr *)RTA_DATA(em_list[i]); mp = add_log(msg, mp, "ematch=%s ", conv_tcf_em_kind(hdr->kind, 0)); /* use (char*)hdr in order to count by one byte */ switch(hdr->kind) { #ifdef HAVE_LINUX_TC_EMATCH_TC_EM_CMP_H case TCF_EM_CMP: if(parse_ematch_cmp(msg, mp, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr))) return(1); break; #endif #ifdef HAVE_LINUX_TC_EMATCH_TC_EM_NBYTE_H case TCF_EM_NBYTE: if(parse_ematch_nbyte(msg, mp, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr))) return(1); break; #endif case TCF_EM_U32: if(parse_ematch_u32(msg, mp, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr))) return(1); break; #ifdef HAVE_LINUX_TC_EMATCH_TC_EM_META_H case TCF_EM_META: if(parse_ematch_meta(msg, mp, (char *)hdr + sizeof(*hdr), RTA_PAYLOAD(em_list[i]) - sizeof(*hdr))) return(1); break; #endif /* not implemented yet case TCF_EM_TEXT: case TCF_EM_VLAN: case TCF_EM_CANID: case TCF_EM_IPSET: */ default: rec_log("%s", msg); } } return(0); }
/* * parse cbq options */ int parse_tca_options_cbq(char *msg, char **mp, struct rtattr *tca) { struct rtattr *cbq[__TCA_CBQ_MAX]; struct tc_ratespec *rspec = NULL; struct tc_cbq_lssopt *lss = NULL; struct tc_cbq_wrropt *wrr = NULL; struct tc_cbq_fopt *fopt = NULL; struct tc_cbq_ovl *ovl = NULL; parse_nested_rtattr(cbq, TCA_CBQ_MAX, tca); if(cbq[TCA_CBQ_LSSOPT]) { if(RTA_PAYLOAD(cbq[TCA_CBQ_LSSOPT]) < sizeof(*lss)) { rec_log("error: %s: TCA_CBQ_LSSOPT: payload too short", __func__); return(1); } lss = (struct tc_cbq_lssopt *)RTA_DATA(cbq[TCA_CBQ_LSSOPT]); } if(cbq[TCA_CBQ_WRROPT]) { if(RTA_PAYLOAD(cbq[TCA_CBQ_WRROPT]) < sizeof(*wrr)) { rec_log("error: %s: TCA_CBQ_WRROPT: payload too short", __func__); return(1); } wrr = (struct tc_cbq_wrropt *)RTA_DATA(cbq[TCA_CBQ_WRROPT]); } if(cbq[TCA_CBQ_FOPT]) { if(RTA_PAYLOAD(cbq[TCA_CBQ_FOPT]) < sizeof(*fopt)) { rec_log("error: %s: TCA_CBQ_FOPT: payload too short", __func__); return(1); } fopt = (struct tc_cbq_fopt *)RTA_DATA(cbq[TCA_CBQ_FOPT]); } if(cbq[TCA_CBQ_OVL_STRATEGY]) { if(RTA_PAYLOAD(cbq[TCA_CBQ_OVL_STRATEGY]) < sizeof(*ovl)) { rec_log("error: %s: TCA_CBQ_OVL_STRATEGY: payload too short", __func__); return(1); } ovl = (struct tc_cbq_ovl *)RTA_DATA(cbq[TCA_CBQ_OVL_STRATEGY]); } if(cbq[TCA_CBQ_RATE]) { if(RTA_PAYLOAD(cbq[TCA_CBQ_RATE]) < sizeof(*rspec)) { rec_log("error: %s: TCA_CBQ_RATE: payload too short", __func__); return(1); } rspec = (struct tc_ratespec *)RTA_DATA(cbq[TCA_CBQ_RATE]); } if(rspec) { char rate[MAX_STR_SIZE]; conv_unit_rate(rate, sizeof(rate), rspec->rate); *mp = add_log(msg, *mp, "rate=%s ", rate); } if(lss) { char maxidle[MAX_STR_SIZE]; char minidle[MAX_STR_SIZE]; get_us2tick(); conv_unit_usec(maxidle, sizeof(maxidle), (lss->maxidle >> lss->ewma_log) / us2tick); *mp = add_log(msg, *mp, "maxidle=%s ", maxidle); if(lss->minidle != 0x7fffffff) { conv_unit_usec(minidle, sizeof(minidle), (lss->minidle >> lss->ewma_log) / us2tick); *mp = add_log(msg, *mp, "minidle=%s ", minidle); } *mp = add_log(msg, *mp, "level=%u avpkt=%u(byte) ", lss->level, lss->avpkt); }
/* * parse flow options */ int parse_tca_options_flow(char *msg, char **mp, struct rtattr *tca) { struct rtattr *flow[__TCA_FLOW_MAX]; char *mp_tmp = *mp; parse_nested_rtattr(flow, TCA_FLOW_MAX, tca); if(flow[TCA_FLOW_BASECLASS]) if(parse_tca_classid(msg, mp, flow[TCA_FLOW_BASECLASS])) return(1); if(flow[TCA_FLOW_KEYS]) if(parse_tca_flow_keys(msg, mp, flow[TCA_FLOW_KEYS])) return(1); if(flow[TCA_FLOW_MODE]) if(parse_tca_flow_mode(msg, mp, flow[TCA_FLOW_MODE])) return(1); if(flow[TCA_FLOW_MASK]) if(parse_tca_mask(msg, mp, flow[TCA_FLOW_MASK])) return(1); if(flow[TCA_FLOW_XOR]) if(parse_tca_flow_xor(msg, mp, flow[TCA_FLOW_XOR])) return(1); if(flow[TCA_FLOW_RSHIFT]) if(parse_tca_flow_rshift(msg, mp, flow[TCA_FLOW_RSHIFT])) return(1); if(flow[TCA_FLOW_ADDEND]) if(parse_tca_flow_addend(msg, mp, flow[TCA_FLOW_ADDEND])) return(1); if(flow[TCA_FLOW_DIVISOR]) if(parse_tca_flow_divisor(msg, mp, flow[TCA_FLOW_DIVISOR])) return(1); if(flow[TCA_FLOW_PERTURB]) if(parse_tca_flow_perturb(msg, mp, flow[TCA_FLOW_PERTURB])) return(1); if(*mp != mp_tmp) rec_log("%s", msg); /* rollback pointer */ *mp = mp_tmp; /* logging for each attribute below */ if(flow[TCA_FLOW_EMATCHES]) if(parse_tca_ematch(msg, *mp, flow[TCA_FLOW_EMATCHES])) return(1); if(flow[TCA_FLOW_POLICE]) if(parse_tca_act_options_police(msg, *mp, flow[TCA_FLOW_POLICE])) return(1); if(flow[TCA_FLOW_ACT]) if(parse_tca_acts(msg, *mp, flow[TCA_FLOW_ACT])) return(1); return(0); }
/* * parse netem options */ int parse_tca_options_netem(char *msg, char **mp, struct rtattr *tca) { struct rtattr *netem[__TCA_NETEM_MAX]; struct tc_netem_qopt *qopt; struct tc_netem_corr *corr = NULL; struct tc_netem_reorder *reorder = NULL; struct tc_netem_corrupt *corrupt = NULL; const double max_percent_value = 0xffffffff; if(RTA_PAYLOAD(tca) < sizeof(*qopt)) { rec_log("error: %s: TCA_OPTIONS: payload too short", __func__); return(1); } qopt = (struct tc_netem_qopt *)RTA_DATA(tca); parse_rtattr(netem, TCA_NETEM_MAX, RTA_DATA(tca) + sizeof(struct tc_netem_qopt), RTA_PAYLOAD(tca) - sizeof(struct tc_netem_qopt)); if(netem[TCA_NETEM_CORR]) { if(RTA_PAYLOAD(netem[TCA_NETEM_CORR]) < sizeof(*corr)) { rec_log("error: %s: TCA_NETEM_CORR: payload too short", __func__); return(1); } corr = (struct tc_netem_corr *)RTA_DATA(netem[TCA_NETEM_CORR]); } if(netem[TCA_NETEM_REORDER]) { if(RTA_PAYLOAD(netem[TCA_NETEM_REORDER]) < sizeof(*reorder)) { rec_log("error: %s: TCA_NETEM_REORDER: payload too short", __func__); return(1); } reorder = (struct tc_netem_reorder *)RTA_DATA(netem[TCA_NETEM_REORDER]); } if(netem[TCA_NETEM_CORRUPT]) { if(RTA_PAYLOAD(netem[TCA_NETEM_REORDER]) < sizeof(*corrupt)) { rec_log("error: %s: TCA_NETEM_REORDER: payload too short", __func__); return(1); } corrupt = (struct tc_netem_corrupt *)RTA_DATA(netem[TCA_NETEM_CORRUPT]); } #if HAVE_DECL_TCA_NETEM_LOSS struct rtattr *loss[__NETEM_LOSS_MAX]; struct tc_netem_gimodel *gimodel = NULL; struct tc_netem_gemodel *gemodel = NULL; if(netem[TCA_NETEM_LOSS]) { parse_nested_rtattr(loss, NETEM_LOSS_MAX, netem[TCA_NETEM_LOSS]); if(loss[NETEM_LOSS_GI]) { if(RTA_PAYLOAD(loss[NETEM_LOSS_GI]) < sizeof(*gimodel)) { rec_log("error: %s: NETEM_LOSS_GI: payload too short", __func__); return(1); } gimodel = (struct tc_netem_gimodel *)RTA_DATA(loss[NETEM_LOSS_GI]); } if(loss[NETEM_LOSS_GE]) { if(RTA_PAYLOAD(loss[NETEM_LOSS_GE]) < sizeof(*gemodel)) { rec_log("error: %s: NETEM_LOSS_GE: payload too short", __func__); return(1); } gemodel = (struct tc_netem_gemodel *)RTA_DATA(loss[NETEM_LOSS_GE]); } } #endif #if HAVE_DECL_TCA_NETEM_RATE struct tc_netem_rate *rate = NULL; if(netem[TCA_NETEM_RATE]) { if(RTA_PAYLOAD(netem[TCA_NETEM_RATE]) < sizeof(*rate)) { rec_log("error: %s: TCA_NETEM_RATE: payload too short", __func__); return(1); } rate = (struct tc_netem_rate *)RTA_DATA(netem[TCA_NETEM_RATE]); } #endif if(qopt->limit) *mp = add_log(msg, *mp, "limit=%u(packet) ", qopt->limit); if(qopt->latency) { char latency[MAX_STR_SIZE]; get_us2tick(); conv_unit_usec(latency, sizeof(latency), qopt->latency / us2tick); *mp = add_log(msg, *mp, "delay=%s ", latency); if(corr && corr->delay_corr) *mp = add_log(msg, *mp, "delay-correlation=%g(%%) ", (double)corr->delay_corr / max_percent_value * 100.); } if(qopt->jitter) { char jitter[MAX_STR_SIZE]; get_us2tick(); conv_unit_usec(jitter, sizeof(jitter), qopt->jitter / us2tick); *mp = add_log(msg, *mp, "jitter=%s ", jitter); } if(qopt->loss) { *mp = add_log(msg, *mp, "loss=%g(%%) ", (double)qopt->loss / max_percent_value * 100.); if(corr && corr->loss_corr) *mp = add_log(msg, *mp, "loss-correlation=%g(%%) ", (double)corr->loss_corr / max_percent_value * 100.); } #if HAVE_DECL_TCA_NETEM_LOSS if(gimodel) *mp = add_log(msg, *mp, "loss-state(p13/p31/p32/p23/p14)=" "%g(%%)/%g(%%)/%g(%%)/%g(%%)/%g(%%) ", (double)gimodel->p13 / max_percent_value * 100., (double)gimodel->p31 / max_percent_value * 100., (double)gimodel->p32 / max_percent_value * 100., (double)gimodel->p23 / max_percent_value * 100., (double)gimodel->p14 / max_percent_value * 100.); if(gemodel) *mp = add_log(msg, *mp, "loss-gemodel(p/r/1-h/1-k)=" "%g(%%)/%g(%%)/%g(%%)/%g(%%) ", (double)gemodel->p / max_percent_value * 100., (double)gemodel->r / max_percent_value * 100., (double)gemodel->h / max_percent_value * 100., (double)gemodel->k1 / max_percent_value * 100.); #endif if(qopt->duplicate) { *mp = add_log(msg, *mp, "duplicate=%g(%%) ", (double)qopt->duplicate / max_percent_value * 100.); if(corr && corr->dup_corr) *mp = add_log(msg, *mp, "duplicate-correlation=%g(%%) ", (double)corr->dup_corr / max_percent_value * 100.); } if(reorder && reorder->probability) { *mp = add_log(msg, *mp, "reorder=%g(%%) ", (double)reorder->probability / max_percent_value * 100.); if(reorder->correlation) *mp = add_log(msg, *mp, "reorder-correlation=%g(%%) ", (double)reorder->correlation / max_percent_value * 100.); } if(corrupt && corrupt->probability) { *mp = add_log(msg, *mp, "corrupt=%g(%%) ", (double)corrupt->probability / max_percent_value * 100.); if(corrupt->correlation) *mp = add_log(msg, *mp, "corrupt-correlation=%g(%%) ", (double)corrupt->correlation / max_percent_value * 100.); } #if HAVE_DECL_TCA_NETEM_RATE if(rate && rate->rate) { char netem_rate[MAX_STR_SIZE]; conv_unit_rate(netem_rate, sizeof(netem_rate), rate->rate); *mp = add_log(msg, *mp, "rate=%s ", netem_rate); if(rate->packet_overhead) *mp = add_log(msg, *mp, "packet-overhead=%u(byte) ", rate->packet_overhead); if(rate->cell_size) *mp = add_log(msg, *mp, "cell-size=%u(byte) ", rate->cell_size); if(rate->cell_overhead) *mp = add_log(msg, *mp, "cell-overhead=%u(byte) ", rate->cell_overhead); } #endif if(qopt->gap) *mp = add_log(msg, *mp, "gap=%u(packet) ", qopt->gap); #if HAVE_DECL_TCA_NETEM_ECN if(netem[TCA_NETEM_ECN] && *(unsigned *)RTA_DATA(netem[TCA_NETEM_ECN])) *mp = add_log(msg, *mp, "ecn=on "); #endif return(0); }