exit(-1);
}
-static void br_print_router_ports(FILE *f, struct rtattr *attr)
+static bool is_temp_mcast_rtr(__u8 type)
+{
+ return type == MDB_RTR_TYPE_TEMP_QUERY || type == MDB_RTR_TYPE_TEMP;
+}
+
+static void __print_router_port_stats(FILE *f, struct rtattr *pattr)
+{
+ struct rtattr *tb[MDBA_ROUTER_PATTR_MAX + 1];
+ struct timeval tv;
+ __u8 type;
+
+ parse_rtattr(tb, MDBA_ROUTER_PATTR_MAX, MDB_RTR_RTA(RTA_DATA(pattr)),
+ RTA_PAYLOAD(pattr) - RTA_ALIGN(sizeof(uint32_t)));
+ if (tb[MDBA_ROUTER_PATTR_TIMER]) {
+ __jiffies_to_tv(&tv,
+ rta_getattr_u32(tb[MDBA_ROUTER_PATTR_TIMER]));
+ fprintf(f, " %4i.%.2i",
+ (int)tv.tv_sec, (int)tv.tv_usec/10000);
+ }
+ if (tb[MDBA_ROUTER_PATTR_TYPE]) {
+ type = rta_getattr_u8(tb[MDBA_ROUTER_PATTR_TYPE]);
+ fprintf(f, " %s",
+ is_temp_mcast_rtr(type) ? "temp" : "permanent");
+ }
+}
+
+static void br_print_router_ports(FILE *f, struct rtattr *attr, __u32 brifidx)
{
uint32_t *port_ifindex;
struct rtattr *i;
int rem;
+ if (!show_stats)
+ fprintf(f, "router ports on %s: ", ll_index_to_name(brifidx));
+
rem = RTA_PAYLOAD(attr);
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
port_ifindex = RTA_DATA(i);
- fprintf(f, "%s ", ll_index_to_name(*port_ifindex));
+ if (show_stats) {
+ fprintf(f, "router ports on %s: %s",
+ ll_index_to_name(brifidx),
+ ll_index_to_name(*port_ifindex));
+ __print_router_port_stats(f, i);
+ fprintf(f, "\n");
+ } else {
+ fprintf(f, "%s ", ll_index_to_name(*port_ifindex));
+ }
}
-
- fprintf(f, "\n");
+ if (!show_stats)
+ fprintf(f, "\n");
}
static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e,
- struct nlmsghdr *n)
+ struct nlmsghdr *n, struct rtattr **tb)
{
SPRINT_BUF(abuf);
const void *src;
(const void *)&e->addr.u.ip6;
if (n->nlmsg_type == RTM_DELMDB)
fprintf(f, "Deleted ");
- fprintf(f, "dev %s port %s grp %s %s", ll_index_to_name(ifindex),
+ fprintf(f, "dev %s port %s grp %s %s %s", ll_index_to_name(ifindex),
ll_index_to_name(e->ifindex),
inet_ntop(af, src, abuf, sizeof(abuf)),
- (e->state & MDB_PERMANENT) ? "permanent" : "temp");
+ (e->state & MDB_PERMANENT) ? "permanent" : "temp",
+ (e->flags & MDB_FLAGS_OFFLOAD) ? "offload" : "");
if (e->vid)
fprintf(f, " vid %hu", e->vid);
+ if (show_stats && tb && tb[MDBA_MDB_EATTR_TIMER]) {
+ struct timeval tv;
+
+ __jiffies_to_tv(&tv, rta_getattr_u32(tb[MDBA_MDB_EATTR_TIMER]));
+ fprintf(f, "%4i.%.2i", (int)tv.tv_sec, (int)tv.tv_usec/10000);
+ }
fprintf(f, "\n");
}
static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr,
struct nlmsghdr *n)
{
+ struct rtattr *etb[MDBA_MDB_EATTR_MAX + 1];
+ struct br_mdb_entry *e;
struct rtattr *i;
int rem;
- struct br_mdb_entry *e;
rem = RTA_PAYLOAD(attr);
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
e = RTA_DATA(i);
- print_mdb_entry(f, ifindex, e, n);
+ parse_rtattr(etb, MDBA_MDB_EATTR_MAX, MDB_RTA(RTA_DATA(i)),
+ RTA_PAYLOAD(i) - RTA_ALIGN(sizeof(*e)));
+ print_mdb_entry(f, ifindex, e, n, etb);
}
}
if (tb[MDBA_ROUTER]) {
if (n->nlmsg_type == RTM_GETMDB) {
- if (show_details) {
- fprintf(fp, "router ports on %s: ",
- ll_index_to_name(r->ifindex));
- br_print_router_ports(fp, tb[MDBA_ROUTER]);
- }
+ if (show_details)
+ br_print_router_ports(fp, tb[MDBA_ROUTER],
+ r->ifindex);
} else {
uint32_t *port_ifindex;