#include <linux/netdevice.h>
#include <linux/if_arp.h>
+#include <linux/if_infiniband.h>
#include <linux/sockios.h>
#include <linux/net_namespace.h>
if (do_link)
iplink_usage();
- fprintf(stderr, "Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]\n");
- fprintf(stderr, " [ CONFFLAG-LIST ]\n");
- fprintf(stderr, " ip address del IFADDR dev IFNAME [mngtmpaddr]\n");
- fprintf(stderr, " ip address {save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n");
- fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n");
- fprintf(stderr, " ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n");
- fprintf(stderr, " [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n");
- fprintf(stderr, " [ label LABEL ] [up] [ vrf NAME ] ]\n");
- fprintf(stderr, " ip address {showdump|restore}\n");
- fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
- fprintf(stderr, " [ broadcast ADDR ] [ anycast ADDR ]\n");
- fprintf(stderr, " [ label IFNAME ] [ scope SCOPE-ID ] [ metric METRIC ]\n");
- fprintf(stderr, "SCOPE-ID := [ host | link | global | NUMBER ]\n");
- fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
- fprintf(stderr, "FLAG := [ permanent | dynamic | secondary | primary |\n");
- fprintf(stderr, " [-]tentative | [-]deprecated | [-]dadfailed | temporary |\n");
- fprintf(stderr, " CONFFLAG-LIST ]\n");
- fprintf(stderr, "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n");
- fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute | autojoin ]\n");
- fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n");
- fprintf(stderr, "LFT := forever | SECONDS\n");
- fprintf(stderr, "TYPE := { vlan | veth | vcan | vxcan | dummy | ifb | macvlan | macvtap |\n");
- fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | lowpan |\n");
- fprintf(stderr, " gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan | vti |\n");
- fprintf(stderr, " nlmon | can | bond_slave | ipvlan | geneve | bridge_slave |\n");
- fprintf(stderr, " hsr | macsec | netdevsim }\n");
+ fprintf(stderr,
+ "Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]\n"
+ " [ CONFFLAG-LIST ]\n"
+ " ip address del IFADDR dev IFNAME [mngtmpaddr]\n"
+ " ip address {save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n"
+ " [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n"
+ " ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n"
+ " [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n"
+ " [ label LABEL ] [up] [ vrf NAME ] ]\n"
+ " ip address {showdump|restore}\n"
+ "IFADDR := PREFIX | ADDR peer PREFIX\n"
+ " [ broadcast ADDR ] [ anycast ADDR ]\n"
+ " [ label IFNAME ] [ scope SCOPE-ID ] [ metric METRIC ]\n"
+ "SCOPE-ID := [ host | link | global | NUMBER ]\n"
+ "FLAG-LIST := [ FLAG-LIST ] FLAG\n"
+ "FLAG := [ permanent | dynamic | secondary | primary |\n"
+ " [-]tentative | [-]deprecated | [-]dadfailed | temporary |\n"
+ " CONFFLAG-LIST ]\n"
+ "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n"
+ "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute | autojoin ]\n"
+ "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n"
+ "LFT := forever | SECONDS\n"
+ "TYPE := { vlan | veth | vcan | vxcan | dummy | ifb | macvlan | macvtap |\n"
+ " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | lowpan |\n"
+ " gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan | vti |\n"
+ " nlmon | can | bond_slave | ipvlan | geneve | bridge_slave |\n"
+ " hsr | macsec | netdevsim }\n");
exit(-1);
}
static void print_vf_stats64(FILE *fp, struct rtattr *vfstats);
-static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
+static void print_vfinfo(FILE *fp, struct ifinfomsg *ifi, struct rtattr *vfinfo)
{
struct ifla_vf_mac *vf_mac;
+ struct ifla_vf_broadcast *vf_broadcast;
struct ifla_vf_tx_rate *vf_tx_rate;
struct rtattr *vf[IFLA_VF_MAX + 1] = {};
parse_rtattr_nested(vf, IFLA_VF_MAX, vfinfo);
vf_mac = RTA_DATA(vf[IFLA_VF_MAC]);
+ vf_broadcast = RTA_DATA(vf[IFLA_VF_BROADCAST]);
vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]);
print_string(PRINT_FP, NULL, "%s ", _SL_);
print_int(PRINT_ANY, "vf", "vf %d ", vf_mac->vf);
- print_string(PRINT_ANY, "mac", "MAC %s",
- ll_addr_n2a((unsigned char *) &vf_mac->mac,
- ETH_ALEN, 0, b1, sizeof(b1)));
+
+ print_string(PRINT_ANY,
+ "link_type",
+ " link/%s ",
+ ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
+
+ print_color_string(PRINT_ANY, COLOR_MAC,
+ "address", "%s",
+ ll_addr_n2a((unsigned char *) &vf_mac->mac,
+ ifi->ifi_type == ARPHRD_ETHER ?
+ ETH_ALEN : INFINIBAND_ALEN,
+ ifi->ifi_type,
+ b1, sizeof(b1)));
+
+ if (vf[IFLA_VF_BROADCAST]) {
+ if (ifi->ifi_flags&IFF_POINTOPOINT) {
+ print_string(PRINT_FP, NULL, " peer ", NULL);
+ print_bool(PRINT_JSON,
+ "link_pointtopoint", NULL, true);
+ } else
+ print_string(PRINT_FP, NULL, " brd ", NULL);
+
+ print_color_string(PRINT_ANY, COLOR_MAC,
+ "broadcast", "%s",
+ ll_addr_n2a((unsigned char *) &vf_broadcast->broadcast,
+ ifi->ifi_type == ARPHRD_ETHER ?
+ ETH_ALEN : INFINIBAND_ALEN,
+ ifi->ifi_type,
+ b1, sizeof(b1)));
+ }
if (vf[IFLA_VF_VLAN_LIST]) {
struct rtattr *i, *vfvlanlist = vf[IFLA_VF_VLAN_LIST];
open_json_array(PRINT_JSON, "vfinfo_list");
for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
open_json_object(NULL);
- print_vfinfo(fp, i);
+ print_vfinfo(fp, ifi, i);
close_json_object();
}
close_json_array(PRINT_JSON, NULL);
if (set_lifetime(&preferred_lft, *argv))
invarg("preferred_lft value", *argv);
} else if (strcmp(*argv, "home") == 0) {
- ifa_flags |= IFA_F_HOMEADDRESS;
+ if (req.ifa.ifa_family == AF_INET6)
+ ifa_flags |= IFA_F_HOMEADDRESS;
+ else
+ fprintf(stderr, "Warning: home option can be set only for IPv6 addresses\n");
} else if (strcmp(*argv, "nodad") == 0) {
- ifa_flags |= IFA_F_NODAD;
+ if (req.ifa.ifa_family == AF_INET6)
+ ifa_flags |= IFA_F_NODAD;
+ else
+ fprintf(stderr, "Warning: nodad option can be set only for IPv6 addresses\n");
} else if (strcmp(*argv, "mngtmpaddr") == 0) {
- ifa_flags |= IFA_F_MANAGETEMPADDR;
+ if (req.ifa.ifa_family == AF_INET6)
+ ifa_flags |= IFA_F_MANAGETEMPADDR;
+ else
+ fprintf(stderr, "Warning: mngtmpaddr option can be set only for IPv6 addresses\n");
} else if (strcmp(*argv, "noprefixroute") == 0) {
ifa_flags |= IFA_F_NOPREFIXROUTE;
} else if (strcmp(*argv, "autojoin") == 0) {
" [ table TABLE_ID ] [ proto RTPROTO ]\n"
" [ scope SCOPE ] [ metric METRIC ]\n"
" [ ttl-propagate { enabled | disabled } ]\n"
- "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n"
+ "INFO_SPEC := { NH | nhid ID } OPTIONS FLAGS [ nexthop NH ]...\n"
"NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n"
" [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"
"FAMILY := [ inet | inet6 | mpls | bridge | link ]\n"
"features", "%#llx ", of);
}
-static void print_rt_flags(FILE *fp, unsigned int flags)
+void print_rt_flags(FILE *fp, unsigned int flags)
{
open_json_array(PRINT_JSON,
is_json_context() ? "flags" : "");
}
}
-static void print_rta_if(FILE *fp, const struct rtattr *rta,
- const char *prefix)
+void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix)
{
const char *ifname = ll_index_to_name(rta_getattr_u32(rta));
}
}
-static void print_rta_gateway(FILE *fp, const struct rtmsg *r,
- const struct rtattr *rta)
+void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta)
{
- const char *gateway = format_host_rta(r->rtm_family, rta);
+ const char *gateway = format_host_rta(family, rta);
if (is_json_context())
print_string(PRINT_JSON, "gateway", NULL, gateway);
else {
fprintf(fp, "via ");
print_color_string(PRINT_FP,
- ifa_family_color(r->rtm_family),
+ ifa_family_color(family),
NULL, "%s ", gateway);
}
}
if (tb[RTA_NEWDST])
print_rta_newdst(fp, r, tb[RTA_NEWDST]);
if (tb[RTA_GATEWAY])
- print_rta_gateway(fp, r, tb[RTA_GATEWAY]);
+ print_rta_gateway(fp, r->rtm_family,
+ tb[RTA_GATEWAY]);
if (tb[RTA_VIA])
print_rta_via(fp, tb[RTA_VIA]);
if (tb[RTA_FLOW])
print_string(PRINT_ANY, "src", "from %s ", b1);
}
+ if (tb[RTA_NH_ID])
+ print_uint(PRINT_ANY, "nhid", "nhid %u ",
+ rta_getattr_u32(tb[RTA_NH_ID]));
+
if (tb[RTA_NEWDST])
print_rta_newdst(fp, r, tb[RTA_NEWDST]);
}
if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len)
- print_rta_gateway(fp, r, tb[RTA_GATEWAY]);
+ print_rta_gateway(fp, r->rtm_family, tb[RTA_GATEWAY]);
if (tb[RTA_VIA])
print_rta_via(fp, tb[RTA_VIA]);
} else if (strcmp(*argv, "encap") == 0) {
int old_len = rta->rta_len;
- if (lwt_parse_encap(rta, len, &argc, &argv))
+ if (lwt_parse_encap(rta, len, &argc, &argv,
+ RTA_ENCAP, RTA_ENCAP_TYPE))
return -1;
rtnh->rtnh_len += rta->rta_len - old_len;
} else if (strcmp(*argv, "as") == 0) {
int table_ok = 0;
int raw = 0;
int type_ok = 0;
+ __u32 nhid = 0;
if (cmd != RTM_DELROUTE) {
req.r.rtm_protocol = RTPROT_BOOT;
} else if (strcmp(*argv, "nexthop") == 0) {
nhs_ok = 1;
break;
+ } else if (!strcmp(*argv, "nhid")) {
+ NEXT_ARG();
+ if (get_u32(&nhid, *argv, 0))
+ invarg("\"id\" value is invalid\n", *argv);
+ addattr32(&req.n, sizeof(req), RTA_NH_ID, nhid);
} else if (matches(*argv, "protocol") == 0) {
__u32 prot;
rta->rta_type = RTA_ENCAP;
rta->rta_len = RTA_LENGTH(0);
- lwt_parse_encap(rta, sizeof(buf), &argc, &argv);
+ lwt_parse_encap(rta, sizeof(buf), &argc, &argv,
+ RTA_ENCAP, RTA_ENCAP_TYPE);
if (rta->rta_len > RTA_LENGTH(0))
addraw_l(&req.n, 1024
req.r.rtm_type == RTN_UNSPEC) {
if (cmd == RTM_DELROUTE)
req.r.rtm_scope = RT_SCOPE_NOWHERE;
- else if (!gw_ok && !nhs_ok)
+ else if (!gw_ok && !nhs_ok && !nhid)
req.r.rtm_scope = RT_SCOPE_LINK;
}
}
return 0;
}
+ static int iproute_dump_filter(struct nlmsghdr *nlh, int reqlen)
+ {
+ struct rtmsg *rtm = NLMSG_DATA(nlh);
+ int err;
+
+ rtm->rtm_protocol = filter.protocol;
+ if (filter.cloned)
+ rtm->rtm_flags |= RTM_F_CLONED;
+
+ if (filter.tb) {
+ err = addattr32(nlh, reqlen, RTA_TABLE, filter.tb);
+ if (err)
+ return err;
+ }
+
+ if (filter.oif) {
+ err = addattr32(nlh, reqlen, RTA_OIF, filter.oif);
+ if (err)
+ return err;
+ }
+
+ return 0;
+ }
+
static int iproute_flush(int family, rtnl_filter_t filter_fn)
{
time_t start = time(0);
filter.flushe = sizeof(flushb);
for (;;) {
- if (rtnl_routedump_req(&rth, family, NULL) < 0) {
+ if (rtnl_routedump_req(&rth, family, iproute_dump_filter) < 0) {
perror("Cannot send dump request");
return -2;
}
}
}
- static int iproute_dump_filter(struct nlmsghdr *nlh, int reqlen)
- {
- struct rtmsg *rtm = NLMSG_DATA(nlh);
- int err;
-
- rtm->rtm_protocol = filter.protocol;
- if (filter.cloned)
- rtm->rtm_flags |= RTM_F_CLONED;
-
- if (filter.tb) {
- err = addattr32(nlh, reqlen, RTA_TABLE, filter.tb);
- if (err)
- return err;
- }
-
- if (filter.oif) {
- err = addattr32(nlh, reqlen, RTA_OIF, filter.oif);
- if (err)
- return err;
- }
-
- return 0;
- }
-
static int iproute_list_flush_or_save(int argc, char **argv, int action)
{
int dump_family = preferred_family;
}
#endif
-static int resolve_services = 1;
int preferred_family = AF_UNSPEC;
static int show_options;
int show_details;
static int sctp_ino;
static int show_tipcinfo;
static int show_tos;
+int numeric;
int oneline;
enum col_id {
return buf;
}
- if (!resolve_services)
+ if (numeric)
goto do_numeric;
if (dg_proto == RAW_PROTO)
static char *sprint_bw(char *buf, double bw)
{
- if (bw > 1000000.)
+ if (!resolve_services)
+ sprintf(buf, "%.0f", bw);
+ else if (bw > 1000000.)
sprintf(buf, "%.1fM", bw / 1000000.);
else if (bw > 1000.)
sprintf(buf, "%.1fK", bw / 1000.);
sock_state_print(&st);
- if (resolve_services)
- prot_name = nl_proto_n2a(prot, prot_buf, sizeof(prot_buf));
- else
- prot_name = int_to_str(prot, prot_buf);
+ prot_name = nl_proto_n2a(prot, prot_buf, sizeof(prot_buf));
if (pid == -1) {
procname[0] = '*';
- } else if (resolve_services) {
+ } else if (!numeric) {
int done = 0;
if (!pid) {
long_opts, NULL)) != EOF) {
switch (ch) {
case 'n':
- resolve_services = 0;
+ numeric = 1;
break;
case 'r':
resolve_hosts = 1;
filter_states_set(¤t_filter, state_filter);
filter_merge_defaults(¤t_filter);
- if (resolve_services && resolve_hosts &&
+ if (!numeric && resolve_hosts &&
(current_filter.dbs & (UNIX_DBM|INET_L4_DBM)))
init_service_resolver();
static void explain(void)
{
fprintf(stderr,
-"Usage: ... netem [ limit PACKETS ]\n" \
-" [ delay TIME [ JITTER [CORRELATION]]]\n" \
-" [ distribution {uniform|normal|pareto|paretonormal} ]\n" \
-" [ corrupt PERCENT [CORRELATION]]\n" \
-" [ duplicate PERCENT [CORRELATION]]\n" \
-" [ loss random PERCENT [CORRELATION]]\n" \
-" [ loss state P13 [P31 [P32 [P23 P14]]]\n" \
-" [ loss gemodel PERCENT [R [1-H [1-K]]]\n" \
-" [ ecn ]\n" \
-" [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n" \
-" [ rate RATE [PACKETOVERHEAD] [CELLSIZE] [CELLOVERHEAD]]\n" \
-" [ slot MIN_DELAY [MAX_DELAY] [packets MAX_PACKETS]" \
-" [bytes MAX_BYTES]]\n" \
-" [ slot distribution" \
-" {uniform|normal|pareto|paretonormal|custom} DELAY JITTER" \
-" [packets MAX_PACKETS] [bytes MAX_BYTES]]\n");
+ "Usage: ... netem [ limit PACKETS ]\n" \
+ " [ delay TIME [ JITTER [CORRELATION]]]\n" \
+ " [ distribution {uniform|normal|pareto|paretonormal} ]\n" \
+ " [ corrupt PERCENT [CORRELATION]]\n" \
+ " [ duplicate PERCENT [CORRELATION]]\n" \
+ " [ loss random PERCENT [CORRELATION]]\n" \
+ " [ loss state P13 [P31 [P32 [P23 P14]]]\n" \
+ " [ loss gemodel PERCENT [R [1-H [1-K]]]\n" \
+ " [ ecn ]\n" \
+ " [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n" \
+ " [ rate RATE [PACKETOVERHEAD] [CELLSIZE] [CELLOVERHEAD]]\n" \
+ " [ slot MIN_DELAY [MAX_DELAY] [packets MAX_PACKETS]" \
+ " [bytes MAX_BYTES]]\n" \
+ " [ slot distribution" \
+ " {uniform|normal|pareto|paretonormal|custom} DELAY JITTER" \
+ " [packets MAX_PACKETS] [bytes MAX_BYTES]]\n");
}
static void explain1(const char *arg)
*/
#define MAX_DIST (16*1024)
+/* Print values only if they are non-zero */
+static void __print_int_opt(const char *label_json, const char *label_fp,
+ int val)
+{
+ print_int(PRINT_ANY, label_json, val ? label_fp : "", val);
+}
+#define PRINT_INT_OPT(label, val) \
+ __print_int_opt(label, " " label " %d", (val))
+
+/* Time print prints normally with varying units, but for JSON prints
+ * in seconds (1ms vs 0.001).
+ */
+static void __print_time64(const char *label_json, const char *label_fp,
+ __u64 val)
+{
+ SPRINT_BUF(b1);
+
+ print_string(PRINT_FP, NULL, label_fp, sprint_time64(val, b1));
+ print_float(PRINT_JSON, label_json, NULL, val / 1000000000.);
+}
+#define __PRINT_TIME64(label_json, label_fp, val) \
+ __print_time64(label_json, label_fp " %s", (val))
+#define PRINT_TIME64(label, val) __PRINT_TIME64(label, " " label, (val))
+
+/* Percent print prints normally in percentage points, but for JSON prints
+ * an absolute value (1% vs 0.01).
+ */
+static void __print_percent(const char *label_json, const char *label_fp,
+ __u32 per)
+{
+ print_float(PRINT_FP, NULL, label_fp, (100. * per) / UINT32_MAX);
+ print_float(PRINT_JSON, label_json, NULL, (1. * per) / UINT32_MAX);
+}
+#define __PRINT_PERCENT(label_json, label_fp, per) \
+ __print_percent(label_json, label_fp " %g%%", (per))
+#define PRINT_PERCENT(label, per) __PRINT_PERCENT(label, " " label, (per))
+
/* scaled value used to percent of maximum. */
static void set_percent(__u32 *percent, double per)
{
return 0;
}
-static void print_percent(char *buf, int len, __u32 per)
-{
- snprintf(buf, len, "%g%%", (100. * per) / UINT32_MAX);
-}
-
-static char *sprint_percent(__u32 per, char *buf)
+static void print_corr(bool present, __u32 value)
{
- print_percent(buf, SPRINT_BSIZE-1, per);
- return buf;
+ if (!is_json_context()) {
+ if (present)
+ __PRINT_PERCENT("", "", value);
+ } else {
+ PRINT_PERCENT("correlation", value);
+ }
}
/*
}
} else if (!strcmp(*argv, "gemodel")) {
+ double p;
+
NEXT_ARG();
- if (get_percent(&gemodel.p, *argv)) {
+ if (parse_percent(&p, *argv)) {
explain1("loss gemodel p");
return -1;
}
+ set_percent(&gemodel.p, p);
/* set defaults */
- set_percent(&gemodel.r, 1.);
+ set_percent(&gemodel.r, 1. - p);
set_percent(&gemodel.h, 0);
set_percent(&gemodel.k1, 0);
loss_type = NETEM_LOSS_GE;
}
}
- fprintf(f, "limit %d", qopt.limit);
+ print_uint(PRINT_ANY, "limit", "limit %d", qopt.limit);
if (qopt.latency) {
- fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1));
-
- if (qopt.jitter) {
- fprintf(f, " %s", sprint_ticks(qopt.jitter, b1));
- if (cor && cor->delay_corr)
- fprintf(f, " %s", sprint_percent(cor->delay_corr, b1));
+ open_json_object("delay");
+ if (!is_json_context()) {
+ print_string(PRINT_FP, NULL, " delay %s",
+ sprint_ticks(qopt.latency, b1));
+
+ if (qopt.jitter)
+ print_string(PRINT_FP, NULL, " %s",
+ sprint_ticks(qopt.jitter, b1));
+ } else {
+ print_float(PRINT_JSON, "delay", NULL,
+ tc_core_tick2time(qopt.latency) /
+ 1000000.);
+ print_float(PRINT_JSON, "jitter", NULL,
+ tc_core_tick2time(qopt.jitter) /
+ 1000000.);
}
+ print_corr(qopt.jitter && cor && cor->delay_corr,
+ cor ? cor->delay_corr : 0);
+ close_json_object();
}
if (qopt.loss) {
- fprintf(f, " loss %s", sprint_percent(qopt.loss, b1));
- if (cor && cor->loss_corr)
- fprintf(f, " %s", sprint_percent(cor->loss_corr, b1));
+ open_json_object("loss-random");
+ PRINT_PERCENT("loss", qopt.loss);
+ print_corr(cor && cor->loss_corr, cor ? cor->loss_corr : 0);
+ close_json_object();
}
if (gimodel) {
- fprintf(f, " loss state p13 %s", sprint_percent(gimodel->p13, b1));
- fprintf(f, " p31 %s", sprint_percent(gimodel->p31, b1));
- fprintf(f, " p32 %s", sprint_percent(gimodel->p32, b1));
- fprintf(f, " p23 %s", sprint_percent(gimodel->p23, b1));
- fprintf(f, " p14 %s", sprint_percent(gimodel->p14, b1));
+ open_json_object("loss-state");
+ __PRINT_PERCENT("p13", " loss state p13", gimodel->p13);
+ PRINT_PERCENT("p31", gimodel->p31);
+ PRINT_PERCENT("p32", gimodel->p32);
+ PRINT_PERCENT("p23", gimodel->p23);
+ PRINT_PERCENT("p14", gimodel->p14);
+ close_json_object();
}
if (gemodel) {
- fprintf(f, " loss gemodel p %s",
- sprint_percent(gemodel->p, b1));
- fprintf(f, " r %s", sprint_percent(gemodel->r, b1));
- fprintf(f, " 1-h %s", sprint_percent(UINT32_MAX -
- gemodel->h, b1));
- fprintf(f, " 1-k %s", sprint_percent(gemodel->k1, b1));
+ open_json_object("loss-gemodel");
+ __PRINT_PERCENT("p", " loss gemodel p", gemodel->p);
+ PRINT_PERCENT("r", gemodel->r);
+ PRINT_PERCENT("1-h", UINT32_MAX - gemodel->h);
+ PRINT_PERCENT("1-k", gemodel->k1);
+ close_json_object();
}
if (qopt.duplicate) {
- fprintf(f, " duplicate %s",
- sprint_percent(qopt.duplicate, b1));
- if (cor && cor->dup_corr)
- fprintf(f, " %s", sprint_percent(cor->dup_corr, b1));
+ open_json_object("duplicate");
+ PRINT_PERCENT("duplicate", qopt.duplicate);
+ print_corr(cor && cor->dup_corr, cor ? cor->dup_corr : 0);
+ close_json_object();
}
if (reorder && reorder->probability) {
- fprintf(f, " reorder %s",
- sprint_percent(reorder->probability, b1));
- if (reorder->correlation)
- fprintf(f, " %s",
- sprint_percent(reorder->correlation, b1));
+ open_json_object("reorder");
+ PRINT_PERCENT("reorder", reorder->probability);
+ print_corr(reorder->correlation, reorder->correlation);
+ close_json_object();
}
if (corrupt && corrupt->probability) {
- fprintf(f, " corrupt %s",
- sprint_percent(corrupt->probability, b1));
- if (corrupt->correlation)
- fprintf(f, " %s",
- sprint_percent(corrupt->correlation, b1));
+ open_json_object("corrupt");
+ PRINT_PERCENT("corrupt", corrupt->probability);
+ print_corr(corrupt->correlation, corrupt->correlation);
+ close_json_object();
}
if (rate && rate->rate) {
- if (rate64)
- fprintf(f, " rate %s", sprint_rate(rate64, b1));
- else
- fprintf(f, " rate %s", sprint_rate(rate->rate, b1));
- if (rate->packet_overhead)
- fprintf(f, " packetoverhead %d", rate->packet_overhead);
- if (rate->cell_size)
- fprintf(f, " cellsize %u", rate->cell_size);
- if (rate->cell_overhead)
- fprintf(f, " celloverhead %d", rate->cell_overhead);
+ open_json_object("rate");
+ rate64 = rate64 ? : rate->rate;
+ print_string(PRINT_FP, NULL, " rate %s",
+ sprint_rate(rate64, b1));
+ print_lluint(PRINT_JSON, "rate", NULL, rate64);
+ PRINT_INT_OPT("packetoverhead", rate->packet_overhead);
+ print_uint(PRINT_ANY, "cellsize",
+ rate->cell_size ? " cellsize %u" : "",
+ rate->cell_size);
+ PRINT_INT_OPT("celloverhead", rate->cell_overhead);
+ close_json_object();
}
if (slot) {
+ open_json_object("slot");
if (slot->dist_jitter > 0) {
- fprintf(f, " slot distribution %s", sprint_time64(slot->dist_delay, b1));
- fprintf(f, " %s", sprint_time64(slot->dist_jitter, b1));
+ __PRINT_TIME64("distribution", " slot distribution",
+ slot->dist_delay);
+ __PRINT_TIME64("jitter", "", slot->dist_jitter);
} else {
- fprintf(f, " slot %s", sprint_time64(slot->min_delay, b1));
- fprintf(f, " %s", sprint_time64(slot->max_delay, b1));
+ __PRINT_TIME64("min-delay", " slot", slot->min_delay);
+ __PRINT_TIME64("max-delay", "", slot->max_delay);
}
- if (slot->max_packets)
- fprintf(f, " packets %d", slot->max_packets);
- if (slot->max_bytes)
- fprintf(f, " bytes %d", slot->max_bytes);
+ PRINT_INT_OPT("packets", slot->max_packets);
+ PRINT_INT_OPT("bytes", slot->max_bytes);
+ close_json_object();
}
- if (ecn)
- fprintf(f, " ecn ");
-
- if (qopt.gap)
- fprintf(f, " gap %lu", (unsigned long)qopt.gap);
-
+ print_bool(PRINT_ANY, "ecn", ecn ? " ecn " : "", ecn);
+ print_luint(PRINT_ANY, "gap", qopt.gap ? " gap %lu" : "",
+ (unsigned long)qopt.gap);
return 0;
}