static int tbf_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) { uint32_t rtab[RTNL_TC_RTABLE_SIZE], ptab[RTNL_TC_RTABLE_SIZE]; struct tc_tbf_qopt opts; struct rtnl_tbf *tbf = data; int required = TBF_ATTR_RATE | TBF_ATTR_LIMIT; if (!(tbf->qt_mask & required) != required) return -NLE_MISSING_ATTR; memset(&opts, 0, sizeof(opts)); opts.limit = tbf->qt_limit; opts.buffer = tbf->qt_rate_txtime; rtnl_tc_build_rate_table(tc, &tbf->qt_rate, rtab); rtnl_rcopy_ratespec(&opts.rate, &tbf->qt_rate); if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { opts.mtu = tbf->qt_peakrate_txtime; rtnl_tc_build_rate_table(tc, &tbf->qt_peakrate, ptab); rtnl_rcopy_ratespec(&opts.peakrate, &tbf->qt_peakrate); } NLA_PUT(msg, TCA_TBF_PARMS, sizeof(opts), &opts); NLA_PUT(msg, TCA_TBF_RTAB, sizeof(rtab), rtab); if (tbf->qt_mask & TBF_ATTR_PEAKRATE) NLA_PUT(msg, TCA_TBF_PTAB, sizeof(ptab), ptab); return 0; nla_put_failure: return -NLE_MSGSIZE; }
static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) { struct rtnl_htb_class *htb = data; uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE]; struct tc_htb_opt opts; int buffer, cbuffer; if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE)) BUG(); /* if not set, zero (0) is used as priority */ if (htb->ch_mask & SCH_HTB_HAS_PRIO) opts.prio = htb->ch_prio; memset(&opts, 0, sizeof(opts)); mtu = rtnl_tc_get_mtu(tc); rtnl_tc_build_rate_table(tc, &htb->ch_rate, rtable); rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate); if (htb->ch_mask & SCH_HTB_HAS_CEIL) { rtnl_tc_build_rate_table(tc, &htb->ch_ceil, ctable); rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil); } else { /* * If not set, configured rate is used as ceil, which implies * no borrowing. */ memcpy(&opts.ceil, &opts.rate, sizeof(struct tc_ratespec)); } if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) buffer = htb->ch_rbuffer; else buffer = opts.rate.rate / nl_get_user_hz() + mtu; /* XXX */ opts.buffer = rtnl_tc_calc_txtime(buffer, opts.rate.rate); if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) cbuffer = htb->ch_cbuffer; else cbuffer = opts.ceil.rate / nl_get_user_hz() + mtu; /* XXX */ opts.cbuffer = rtnl_tc_calc_txtime(cbuffer, opts.ceil.rate); if (htb->ch_mask & SCH_HTB_HAS_QUANTUM) opts.quantum = htb->ch_quantum; NLA_PUT(msg, TCA_HTB_PARMS, sizeof(opts), &opts); NLA_PUT(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable); NLA_PUT(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable); return 0; nla_put_failure: return -NLE_MSGSIZE; }
static struct nl_msg *tbf_get_opts(struct rtnl_qdisc *qdisc) { struct tc_tbf_qopt opts; struct rtnl_tbf *tbf; struct nl_msg *msg; uint32_t rtab[RTNL_TC_RTABLE_SIZE]; uint32_t ptab[RTNL_TC_RTABLE_SIZE]; int required = TBF_ATTR_RATE | TBF_ATTR_LIMIT; memset(&opts, 0, sizeof(opts)); tbf = tbf_qdisc(qdisc); if (!tbf) return NULL; if (!(tbf->qt_mask & required) != required) return NULL; opts.limit = tbf->qt_limit; opts.buffer = tbf->qt_rate_txtime; tbf->qt_rate.rs_mpu = tbf->qt_mpu; rtnl_rcopy_ratespec(&opts.rate, &tbf->qt_rate); rtnl_tc_build_rate_table(rtab, tbf->qt_mpu & 0xff, tbf->qt_mpu >> 8, 1 << tbf->qt_rate.rs_cell_log, tbf->qt_rate.rs_rate); if (tbf->qt_mask & TBF_ATTR_PEAKRATE) { opts.mtu = tbf->qt_peakrate_txtime; tbf->qt_peakrate.rs_mpu = tbf->qt_mpu; rtnl_rcopy_ratespec(&opts.peakrate, &tbf->qt_peakrate); rtnl_tc_build_rate_table(ptab, tbf->qt_mpu & 0xff, tbf->qt_mpu >> 8, 1 << tbf->qt_peakrate.rs_cell_log, tbf->qt_peakrate.rs_rate); }