X-Git-Url: http://git.onelab.eu/?p=libnl.git;a=blobdiff_plain;f=lib%2Froute%2Fsch%2Fnetem.c;fp=lib%2Froute%2Fsch%2Fnetem.c;h=0000000000000000000000000000000000000000;hp=75e33c5ea7fdca04fe46a979d7166a229fafdc4e;hb=332c8b7561dcac7ac95cc0d07328b1cb22d780a6;hpb=eabdd897b75ecc1fac5e255229a899126085e57a diff --git a/lib/route/sch/netem.c b/lib/route/sch/netem.c deleted file mode 100644 index 75e33c5..0000000 --- a/lib/route/sch/netem.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - * lib/route/sch/netem.c Network Emulator Qdisc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2006 Thomas Graf - */ - -/** - * @ingroup qdisc - * @defgroup netem Network Emulator - * @brief - * - * For further documentation see http://linux-net.osdl.org/index.php/Netem - * @{ - */ - -#include -#include -#include -#include -#include -#include -#include - -/** @cond SKIP */ -#define SCH_NETEM_ATTR_LATENCY 0x001 -#define SCH_NETEM_ATTR_LIMIT 0x002 -#define SCH_NETEM_ATTR_LOSS 0x004 -#define SCH_NETEM_ATTR_GAP 0x008 -#define SCH_NETEM_ATTR_DUPLICATE 0x010 -#define SCH_NETEM_ATTR_JITTER 0x020 -#define SCH_NETEM_ATTR_DELAY_CORR 0x040 -#define SCH_NETEM_ATTR_LOSS_CORR 0x080 -#define SCH_NETEM_ATTR_DUP_CORR 0x100 -#define SCH_NETEM_ATTR_RO_PROB 0x200 -#define SCH_NETEM_ATTR_RO_CORR 0x400 -/** @endcond */ - -static inline struct rtnl_netem *netem_qdisc(struct rtnl_qdisc *qdisc) -{ - return (struct rtnl_netem *) qdisc->q_subdata; -} - -static inline struct rtnl_netem *netem_alloc(struct rtnl_qdisc *qdisc) -{ - if (!qdisc->q_subdata) - qdisc->q_subdata = calloc(1, sizeof(struct rtnl_netem)); - - return netem_qdisc(qdisc); -} - -static struct nla_policy netem_policy[TCA_NETEM_MAX+1] = { - [TCA_NETEM_CORR] = { .minlen = sizeof(struct tc_netem_corr) }, - [TCA_NETEM_REORDER] = { .minlen = sizeof(struct tc_netem_reorder) }, -}; - -static int netem_msg_parser(struct rtnl_qdisc *qdisc) -{ - int len, err = 0; - struct rtnl_netem *netem; - struct tc_netem_qopt *opts; - - if (qdisc->q_opts->d_size < sizeof(*opts)) - return nl_error(EINVAL, "Netem specific options size mismatch"); - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - opts = (struct tc_netem_qopt *) qdisc->q_opts->d_data; - netem->qnm_latency = opts->latency; - netem->qnm_limit = opts->limit; - netem->qnm_loss = opts->loss; - netem->qnm_gap = opts->gap; - netem->qnm_duplicate = opts->duplicate; - netem->qnm_jitter = opts->jitter; - - netem->qnm_mask = (SCH_NETEM_ATTR_LATENCY | SCH_NETEM_ATTR_LIMIT | - SCH_NETEM_ATTR_LOSS | SCH_NETEM_ATTR_GAP | - SCH_NETEM_ATTR_DUPLICATE | SCH_NETEM_ATTR_JITTER); - - len = qdisc->q_opts->d_size - sizeof(*opts); - - if (len > 0) { - struct nlattr *tb[TCA_NETEM_MAX+1]; - - err = nla_parse(tb, TCA_NETEM_MAX, (struct nlattr *) - qdisc->q_opts->d_data + sizeof(*opts), - len, netem_policy); - if (err < 0) { - free(netem); - return err; - } - - if (tb[TCA_NETEM_CORR]) { - struct tc_netem_corr cor; - - nla_memcpy(&cor, tb[TCA_NETEM_CORR], sizeof(cor)); - netem->qnm_corr.nmc_delay = cor.delay_corr; - netem->qnm_corr.nmc_loss = cor.loss_corr; - netem->qnm_corr.nmc_duplicate = cor.dup_corr; - - netem->qnm_mask |= (SCH_NETEM_ATTR_DELAY_CORR | - SCH_NETEM_ATTR_LOSS_CORR | - SCH_NETEM_ATTR_DELAY_CORR); - } - - if (tb[TCA_NETEM_REORDER]) { - struct tc_netem_reorder ro; - - nla_memcpy(&ro, tb[TCA_NETEM_REORDER], sizeof(ro)); - netem->qnm_ro.nmro_probability = ro.probability; - netem->qnm_ro.nmro_correlation = ro.correlation; - - netem->qnm_mask |= (SCH_NETEM_ATTR_RO_PROB | - SCH_NETEM_ATTR_RO_CORR); - } - } - - return 0; -} - -static void netem_free_data(struct rtnl_qdisc *qdisc) -{ - free(qdisc->q_subdata); -} - -static int netem_dump_brief(struct rtnl_qdisc *qdisc, struct nl_dump_params *p, - int line) -{ - struct rtnl_netem *netem = netem_qdisc(qdisc); - - if (netem) - dp_dump(p, "limit %d", netem->qnm_limit); - - return line; -} - -static int netem_dump_full(struct rtnl_qdisc *qdisc, struct nl_dump_params *p, - int line) -{ - return line; -} - -static struct nl_msg *netem_get_opts(struct rtnl_qdisc *qdisc) -{ - return NULL; -} - -/** - * @name Queue Limit - * @{ - */ - -/** - * Set limit of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg limit New limit in bytes. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_limit(struct rtnl_qdisc *qdisc, int limit) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_limit = limit; - netem->qnm_mask |= SCH_NETEM_ATTR_LIMIT; - - return 0; -} - -/** - * Get limit of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Limit in bytes or a negative error code. - */ -int rtnl_netem_get_limit(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LIMIT)) - return netem->qnm_limit; - else - return nl_errno(ENOENT); -} - -/** @} */ - -/** - * @name Packet Re-ordering - * @{ - */ - -/** - * Set re-ordering gap of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg gap New gap in number of packets. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_gap(struct rtnl_qdisc *qdisc, int gap) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_gap = gap; - netem->qnm_mask |= SCH_NETEM_ATTR_GAP; - - return 0; -} - -/** - * Get re-ordering gap of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Re-ordering gap in packets or a negative error code. - */ -int rtnl_netem_get_gap(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_GAP)) - return netem->qnm_gap; - else - return nl_errno(ENOENT); -} - -/** - * Set re-ordering probability of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg prob New re-ordering probability. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_reorder_probability(struct rtnl_qdisc *qdisc, int prob) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_ro.nmro_probability = prob; - netem->qnm_mask |= SCH_NETEM_ATTR_RO_PROB; - - return 0; -} - -/** - * Get re-ordering probability of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Re-ordering probability or a negative error code. - */ -int rtnl_netem_get_reorder_probability(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_RO_PROB)) - return netem->qnm_ro.nmro_probability; - else - return nl_errno(ENOENT); -} - -/** - * Set re-order correlation probability of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg prob New re-ordering correlation probability. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *qdisc, int prob) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_ro.nmro_correlation = prob; - netem->qnm_mask |= SCH_NETEM_ATTR_RO_CORR; - - return 0; -} - -/** - * Get re-ordering correlation probability of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Re-ordering correlation probability or a negative error code. - */ -int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_RO_CORR)) - return netem->qnm_ro.nmro_correlation; - else - return nl_errno(ENOENT); -} - -/** @} */ - -/** - * @name Packet Loss - * @{ - */ - -/** - * Set packet loss probability of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg prob New packet loss probability. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_loss(struct rtnl_qdisc *qdisc, int prob) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_loss = prob; - netem->qnm_mask |= SCH_NETEM_ATTR_LOSS; - - return 0; -} - -/** - * Get packet loss probability of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Packet loss probability or a negative error code. - */ -int rtnl_netem_get_loss(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LOSS)) - return netem->qnm_loss; - else - return nl_errno(ENOENT); -} - -/** - * Set packet loss correlation probability of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg prob New packet loss correlation. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_loss_correlation(struct rtnl_qdisc *qdisc, int prob) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_corr.nmc_loss = prob; - netem->qnm_mask |= SCH_NETEM_ATTR_LOSS_CORR; - - return 0; -} - -/** - * Get packet loss correlation probability of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Packet loss correlation probability or a negative error code. - */ -int rtnl_netem_get_loss_correlation(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LOSS_CORR)) - return netem->qnm_corr.nmc_loss; - else - return nl_errno(ENOENT); -} - -/** @} */ - -/** - * @name Packet Duplication - * @{ - */ - -/** - * Set packet duplication probability of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg prob New packet duplication probability. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_duplicate(struct rtnl_qdisc *qdisc, int prob) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_duplicate = prob; - netem->qnm_mask |= SCH_NETEM_ATTR_DUPLICATE; - - return 0; -} - -/** - * Get packet duplication probability of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Packet duplication probability or a negative error code. - */ -int rtnl_netem_get_duplicate(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DUPLICATE)) - return netem->qnm_duplicate; - else - return nl_errno(ENOENT); -} - -/** - * Set packet duplication correlation probability of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg prob New packet duplication correlation probability. - * @return 0 on sucess or a negative error code. - */ -int rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *qdisc, int prob) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_corr.nmc_duplicate = prob; - netem->qnm_mask |= SCH_NETEM_ATTR_DUP_CORR; - - return 0; -} - -/** - * Get packet duplication correlation probability of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Packet duplication correlation probability or a negative error code. - */ -int rtnl_netem_get_duplicate_correlation(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DUP_CORR)) - return netem->qnm_corr.nmc_duplicate; - else - return nl_errno(ENOENT); -} - -/** @} */ - -/** - * @name Packet Delay - * @{ - */ - -/** - * Set packet delay of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg delay New packet delay in micro seconds. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_delay(struct rtnl_qdisc *qdisc, int delay) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_latency = nl_us2ticks(delay); - netem->qnm_mask |= SCH_NETEM_ATTR_LATENCY; - - return 0; -} - -/** - * Get packet delay of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Packet delay in micro seconds or a negative error code. - */ -int rtnl_netem_get_delay(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LATENCY)) - return nl_ticks2us(netem->qnm_latency); - else - return nl_errno(ENOENT); -} - -/** - * Set packet delay jitter of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg jitter New packet delay jitter in micro seconds. - * @return 0 on success or a negative error code. - */ -int rtnl_netem_set_jitter(struct rtnl_qdisc *qdisc, int jitter) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_jitter = nl_us2ticks(jitter); - netem->qnm_mask |= SCH_NETEM_ATTR_JITTER; - - return 0; -} - -/** - * Get packet delay jitter of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Packet delay jitter in micro seconds or a negative error code. - */ -int rtnl_netem_get_jitter(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_JITTER)) - return nl_ticks2us(netem->qnm_jitter); - else - return nl_errno(ENOENT); -} - -/** - * Set packet delay correlation probability of netem qdisc. - * @arg qdisc Netem qdisc to be modified. - * @arg prob New packet delay correlation probability. - */ -int rtnl_netem_set_delay_correlation(struct rtnl_qdisc *qdisc, int prob) -{ - struct rtnl_netem *netem; - - netem = netem_alloc(qdisc); - if (!netem) - return nl_errno(ENOMEM); - - netem->qnm_corr.nmc_delay = prob; - netem->qnm_mask |= SCH_NETEM_ATTR_DELAY_CORR; - - return 0; -} - -/** - * Get packet delay correlation probability of netem qdisc. - * @arg qdisc Netem qdisc. - * @return Packet delay correlation probability or a negative error code. - */ -int rtnl_netem_get_delay_corellation(struct rtnl_qdisc *qdisc) -{ - struct rtnl_netem *netem; - - netem = netem_qdisc(qdisc); - if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DELAY_CORR)) - return netem->qnm_corr.nmc_delay; - else - return nl_errno(ENOENT); -} - -/** @} */ - -static struct rtnl_qdisc_ops netem_ops = { - .qo_kind = "netem", - .qo_msg_parser = netem_msg_parser, - .qo_free_data = netem_free_data, - .qo_dump[NL_DUMP_BRIEF] = netem_dump_brief, - .qo_dump[NL_DUMP_FULL] = netem_dump_full, - .qo_get_opts = netem_get_opts, -}; - -static void __init netem_init(void) -{ - rtnl_qdisc_register(&netem_ops); -} - -static void __exit netem_exit(void) -{ - rtnl_qdisc_unregister(&netem_ops); -} - -/** @} */