Add corrupt option for netem
This commit is contained in:
parent
e25d697069
commit
a31a5d5904
|
|
@ -1,3 +1,7 @@
|
||||||
|
2005-12-02 Stephen Hemminger <shemminger@osdl.org>
|
||||||
|
|
||||||
|
* Add corrupt feature to netem
|
||||||
|
|
||||||
2005-12-02 Stephen Hemminger <shemminger@osdl.org
|
2005-12-02 Stephen Hemminger <shemminger@osdl.org
|
||||||
|
|
||||||
* Backout ambigious ip command matches
|
* Backout ambigious ip command matches
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ struct tc_fifo_qopt
|
||||||
/* PRIO section */
|
/* PRIO section */
|
||||||
|
|
||||||
#define TCQ_PRIO_BANDS 16
|
#define TCQ_PRIO_BANDS 16
|
||||||
|
#define TCQ_MIN_PRIO_BANDS 2
|
||||||
|
|
||||||
struct tc_prio_qopt
|
struct tc_prio_qopt
|
||||||
{
|
{
|
||||||
|
|
@ -169,6 +170,7 @@ struct tc_red_qopt
|
||||||
unsigned char Scell_log; /* cell size for idle damping */
|
unsigned char Scell_log; /* cell size for idle damping */
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
#define TC_RED_ECN 1
|
#define TC_RED_ECN 1
|
||||||
|
#define TC_RED_HARDDROP 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tc_red_xstats
|
struct tc_red_xstats
|
||||||
|
|
@ -194,38 +196,34 @@ enum
|
||||||
|
|
||||||
#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
|
#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
|
||||||
|
|
||||||
#define TCA_SET_OFF TCA_GRED_PARMS
|
|
||||||
struct tc_gred_qopt
|
struct tc_gred_qopt
|
||||||
{
|
{
|
||||||
__u32 limit; /* HARD maximal queue length (bytes)
|
__u32 limit; /* HARD maximal queue length (bytes) */
|
||||||
*/
|
__u32 qth_min; /* Min average length threshold (bytes) */
|
||||||
__u32 qth_min; /* Min average length threshold (bytes)
|
__u32 qth_max; /* Max average length threshold (bytes) */
|
||||||
*/
|
__u32 DP; /* upto 2^32 DPs */
|
||||||
__u32 qth_max; /* Max average length threshold (bytes)
|
__u32 backlog;
|
||||||
*/
|
__u32 qave;
|
||||||
__u32 DP; /* upto 2^32 DPs */
|
__u32 forced;
|
||||||
__u32 backlog;
|
__u32 early;
|
||||||
__u32 qave;
|
__u32 other;
|
||||||
__u32 forced;
|
__u32 pdrop;
|
||||||
__u32 early;
|
__u8 Wlog; /* log(W) */
|
||||||
__u32 other;
|
__u8 Plog; /* log(P_max/(qth_max-qth_min)) */
|
||||||
__u32 pdrop;
|
__u8 Scell_log; /* cell size for idle damping */
|
||||||
|
__u8 prio; /* prio of this VQ */
|
||||||
unsigned char Wlog; /* log(W) */
|
__u32 packets;
|
||||||
unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
|
__u32 bytesin;
|
||||||
unsigned char Scell_log; /* cell size for idle damping */
|
|
||||||
__u8 prio; /* prio of this VQ */
|
|
||||||
__u32 packets;
|
|
||||||
__u32 bytesin;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* gred setup */
|
/* gred setup */
|
||||||
struct tc_gred_sopt
|
struct tc_gred_sopt
|
||||||
{
|
{
|
||||||
__u32 DPs;
|
__u32 DPs;
|
||||||
__u32 def_DP;
|
__u32 def_DP;
|
||||||
__u8 grio;
|
__u8 grio;
|
||||||
__u8 pad1;
|
__u8 flags;
|
||||||
__u16 pad2;
|
__u16 pad1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* HTB section */
|
/* HTB section */
|
||||||
|
|
@ -431,6 +429,7 @@ enum
|
||||||
TCA_NETEM_CORR,
|
TCA_NETEM_CORR,
|
||||||
TCA_NETEM_DELAY_DIST,
|
TCA_NETEM_DELAY_DIST,
|
||||||
TCA_NETEM_REORDER,
|
TCA_NETEM_REORDER,
|
||||||
|
TCA_NETEM_CORRUPT,
|
||||||
__TCA_NETEM_MAX,
|
__TCA_NETEM_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -459,6 +458,12 @@ struct tc_netem_reorder
|
||||||
__u32 correlation;
|
__u32 correlation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tc_netem_corrupt
|
||||||
|
{
|
||||||
|
__u32 probability;
|
||||||
|
__u32 correlation;
|
||||||
|
};
|
||||||
|
|
||||||
#define NETEM_DIST_SCALE 8192
|
#define NETEM_DIST_SCALE 8192
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
62
tc/q_netem.c
62
tc/q_netem.c
|
|
@ -32,6 +32,7 @@ static void explain(void)
|
||||||
" [ delay TIME [ JITTER [CORRELATION]]]\n" \
|
" [ delay TIME [ JITTER [CORRELATION]]]\n" \
|
||||||
" [ distribution {uniform|normal|pareto|paretonormal} ]\n" \
|
" [ distribution {uniform|normal|pareto|paretonormal} ]\n" \
|
||||||
" [ drop PERCENT [CORRELATION]] \n" \
|
" [ drop PERCENT [CORRELATION]] \n" \
|
||||||
|
" [ corrupt PERCENT [CORRELATION]] \n" \
|
||||||
" [ duplicate PERCENT [CORRELATION]]\n" \
|
" [ duplicate PERCENT [CORRELATION]]\n" \
|
||||||
" [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n");
|
" [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n");
|
||||||
}
|
}
|
||||||
|
|
@ -128,12 +129,14 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
||||||
struct tc_netem_qopt opt;
|
struct tc_netem_qopt opt;
|
||||||
struct tc_netem_corr cor;
|
struct tc_netem_corr cor;
|
||||||
struct tc_netem_reorder reorder;
|
struct tc_netem_reorder reorder;
|
||||||
__s16 dist_data[MAXDIST];
|
struct tc_netem_corrupt corrupt;
|
||||||
|
__s16 *dist_data = NULL;
|
||||||
|
|
||||||
memset(&opt, 0, sizeof(opt));
|
memset(&opt, 0, sizeof(opt));
|
||||||
opt.limit = 1000;
|
opt.limit = 1000;
|
||||||
memset(&cor, 0, sizeof(cor));
|
memset(&cor, 0, sizeof(cor));
|
||||||
memset(&reorder, 0, sizeof(reorder));
|
memset(&reorder, 0, sizeof(reorder));
|
||||||
|
memset(&corrupt, 0, sizeof(corrupt));
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (matches(*argv, "limit") == 0) {
|
if (matches(*argv, "limit") == 0) {
|
||||||
|
|
@ -193,6 +196,19 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (matches(*argv, "corrupt") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_percent(&corrupt.probability, *argv)) {
|
||||||
|
explain1("corrupt");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (NEXT_IS_NUMBER()) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_percent(&corrupt.correlation, *argv)) {
|
||||||
|
explain1("corrupt");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (matches(*argv, "gap") == 0) {
|
} else if (matches(*argv, "gap") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (get_u32(&opt.gap, *argv, 0)) {
|
if (get_u32(&opt.gap, *argv, 0)) {
|
||||||
|
|
@ -214,6 +230,7 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
||||||
}
|
}
|
||||||
} else if (matches(*argv, "distribution") == 0) {
|
} else if (matches(*argv, "distribution") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
dist_data = alloca(MAXDIST);
|
||||||
dist_size = get_distribution(*argv, dist_data);
|
dist_size = get_distribution(*argv, dist_data);
|
||||||
if (dist_size < 0)
|
if (dist_size < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -242,19 +259,34 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dist_size > 0 && (opt.latency == 0 || opt.jitter == 0)) {
|
if (dist_data && (opt.latency == 0 || opt.jitter == 0)) {
|
||||||
fprintf(stderr, "distribution specified but no latency and jitter values\n");
|
fprintf(stderr, "distribution specified but no latency and jitter values\n");
|
||||||
explain();
|
explain();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
|
if (addattr_l(n, TCA_BUF_MAX, TCA_OPTIONS, &opt, sizeof(opt)) < 0)
|
||||||
addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor));
|
return -1;
|
||||||
addattr_l(n, 1024, TCA_NETEM_REORDER, &reorder, sizeof(reorder));
|
|
||||||
|
|
||||||
if (dist_size > 0) {
|
if (cor.delay_corr || cor.loss_corr || cor.dup_corr) {
|
||||||
addattr_l(n, 32768, TCA_NETEM_DELAY_DIST,
|
if (addattr_l(n, TCA_BUF_MAX, TCA_NETEM_CORR, &cor, sizeof(cor)) < 0)
|
||||||
dist_data, dist_size*sizeof(dist_data[0]));
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reorder.probability) {
|
||||||
|
if (addattr_l(n, TCA_BUF_MAX, TCA_NETEM_REORDER, &reorder, sizeof(reorder)) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (corrupt.probability) {
|
||||||
|
if (addattr_l(n, TCA_BUF_MAX, TCA_NETEM_CORRUPT, &corrupt, sizeof(corrupt)) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dist_data) {
|
||||||
|
if (addattr_l(n, 32768, TCA_NETEM_DELAY_DIST,
|
||||||
|
dist_data, dist_size*sizeof(dist_data[0])) < 0)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
|
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -264,6 +296,7 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||||
{
|
{
|
||||||
const struct tc_netem_corr *cor = NULL;
|
const struct tc_netem_corr *cor = NULL;
|
||||||
const struct tc_netem_reorder *reorder = NULL;
|
const struct tc_netem_reorder *reorder = NULL;
|
||||||
|
const struct tc_netem_corrupt *corrupt = NULL;
|
||||||
struct tc_netem_qopt qopt;
|
struct tc_netem_qopt qopt;
|
||||||
int len = RTA_PAYLOAD(opt) - sizeof(qopt);
|
int len = RTA_PAYLOAD(opt) - sizeof(qopt);
|
||||||
SPRINT_BUF(b1);
|
SPRINT_BUF(b1);
|
||||||
|
|
@ -292,6 +325,11 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||||
return -1;
|
return -1;
|
||||||
reorder = RTA_DATA(tb[TCA_NETEM_REORDER]);
|
reorder = RTA_DATA(tb[TCA_NETEM_REORDER]);
|
||||||
}
|
}
|
||||||
|
if (tb[TCA_NETEM_CORRUPT]) {
|
||||||
|
if (RTA_PAYLOAD(tb[TCA_NETEM_CORRUPT]) < sizeof(*corrupt))
|
||||||
|
return -1;
|
||||||
|
corrupt = RTA_DATA(tb[TCA_NETEM_REORDER]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f, "limit %d", qopt.limit);
|
fprintf(f, "limit %d", qopt.limit);
|
||||||
|
|
@ -327,6 +365,14 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||||
sprint_percent(reorder->correlation, b1));
|
sprint_percent(reorder->correlation, b1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (corrupt && corrupt->probability) {
|
||||||
|
fprintf(f, " corrupt %s",
|
||||||
|
sprint_percent(corrupt->probability, b1));
|
||||||
|
if (corrupt->correlation)
|
||||||
|
fprintf(f, " %s",
|
||||||
|
sprint_percent(corrupt->correlation, b1));
|
||||||
|
}
|
||||||
|
|
||||||
if (qopt.gap)
|
if (qopt.gap)
|
||||||
fprintf(f, " gap %lu", (unsigned long)qopt.gap);
|
fprintf(f, " gap %lu", (unsigned long)qopt.gap);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue