" [ 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"
print_string(PRINT_ANY, NULL, "%s ", "linkdown");
if (flags & RTNH_F_UNRESOLVED)
print_string(PRINT_ANY, NULL, "%s ", "unresolved");
+ if (flags & RTM_F_OFFLOAD)
+ print_string(PRINT_ANY, NULL, "%s ", "rt_offload");
+ if (flags & RTM_F_TRAP)
+ print_string(PRINT_ANY, NULL, "%s ", "rt_trap");
close_json_array(PRINT_JSON, NULL);
}
int i;
open_json_array(PRINT_JSON, "metrics");
+ open_json_object(NULL);
parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta));
print_rtax_features(fp, val);
break;
default:
- fprintf(fp, "%u ", val);
+ print_uint(PRINT_ANY, mx_names[i], "%u ", val);
break;
case RTAX_RTT:
}
}
+ close_json_object();
close_json_array(PRINT_JSON, NULL);
}
int len = RTA_PAYLOAD(rta);
int first = 1;
+ open_json_array(PRINT_JSON, "nexthops");
+
while (len >= sizeof(*nh)) {
struct rtattr *tb[RTA_MAX + 1];
if (nh->rtnh_len > len)
break;
- if (!is_json_context()) {
- if ((r->rtm_flags & RTM_F_CLONED) &&
- r->rtm_type == RTN_MULTICAST) {
- if (first) {
- fprintf(fp, "Oifs: ");
- first = 0;
- } else {
- fprintf(fp, " ");
- }
- } else
- fprintf(fp, "%s\tnexthop ", _SL_);
- }
+ open_json_object(NULL);
+
+ if ((r->rtm_flags & RTM_F_CLONED) &&
+ r->rtm_type == RTN_MULTICAST) {
+ if (first) {
+ print_string(PRINT_FP, NULL, "Oifs: ", NULL);
+ first = 0;
+ } else {
+ print_string(PRINT_FP, NULL, " ", NULL);
+ }
+ } else
+ print_string(PRINT_FP, NULL, "%s\tnexthop ", _SL_);
if (nh->rtnh_len > sizeof(*nh)) {
parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh),
if ((r->rtm_flags & RTM_F_CLONED) &&
r->rtm_type == RTN_MULTICAST) {
- fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex));
+ print_string(PRINT_ANY, "dev",
+ "%s", ll_index_to_name(nh->rtnh_ifindex));
+
if (nh->rtnh_hops != 1)
- fprintf(fp, "(ttl>%d)", nh->rtnh_hops);
- fprintf(fp, " ");
+ print_int(PRINT_ANY, "ttl", "(ttl>%d)", nh->rtnh_hops);
+
+ print_string(PRINT_FP, NULL, " ", NULL);
} else {
- fprintf(fp, "dev %s ", ll_index_to_name(nh->rtnh_ifindex));
+ print_string(PRINT_ANY, "dev",
+ "dev %s ", ll_index_to_name(nh->rtnh_ifindex));
+
if (r->rtm_family != AF_MPLS)
- fprintf(fp, "weight %d ",
- nh->rtnh_hops+1);
+ print_int(PRINT_ANY, "weight",
+ "weight %d ", nh->rtnh_hops + 1);
}
print_rt_flags(fp, nh->rtnh_flags);
len -= NLMSG_ALIGN(nh->rtnh_len);
nh = RTNH_NEXT(nh);
+
+ close_json_object();
}
+ close_json_array(PRINT_JSON, NULL);
}
int print_route(struct nlmsghdr *n, void *arg)
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]);
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;
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;