@@ -5,12 +5,15 @@ extern int print_fdb(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_mdb(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
+extern int print_ageinfo(const struct sockaddr_nl *who,
+ struct nlmsghdr *n, void *arg);
extern int do_fdb(int argc, char **argv);
extern int do_mdb(int argc, char **argv);
extern int do_monitor(int argc, char **argv);
extern int do_vlan(int argc, char **argv);
extern int do_link(int argc, char **argv);
+extern int do_ageing(int argc, char **argv);
extern int preferred_family;
extern int show_stats;
@@ -31,7 +31,7 @@ static void usage(void)
{
fprintf(stderr,
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
-"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
+"where OBJECT := { link | fdb | mdb | vlan | monitor | ageing }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
" -o[neline] | -t[imestamp] | -n[etns] name |\n"
" -c[ompressvlans] }\n");
@@ -53,6 +53,7 @@ static const struct cmd {
{ "mdb", do_mdb },
{ "vlan", do_vlan },
{ "monitor", do_monitor },
+ { "ageing", do_ageing },
{ "help", do_help },
{ 0 }
};
@@ -21,6 +21,7 @@
#include <linux/neighbour.h>
#include <string.h>
#include <limits.h>
+#include <errno.h>
#include "libnetlink.h"
#include "br_common.h"
@@ -371,6 +372,161 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
return 0;
}
+static void ageing_usage(void)
+{
+ fprintf(stderr, "Usage: bridge ageing interval { show | SECONDS | default } dev DEV\n");
+ exit(-1);
+}
+
+int print_ageinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+ FILE *fp = arg;
+ struct admsg *r = NLMSG_DATA(n);
+ int len = n->nlmsg_len;
+
+ len -= NLMSG_LENGTH(sizeof(*r));
+
+ if (len < 0) {
+ fprintf(stderr, "BUG: wrong nlmsg len%d\n", len);
+ return -1;
+ }
+
+ if (r->adm_family != AF_BRIDGE)
+ return 0;
+ fprintf(fp, "dev %s, ageing %d secs\n",
+ ll_index_to_name(r->adm_ifindex), r->adm_ageing_interval);
+ return 0;
+}
+
+static int do_ageing_show(char *dev)
+{
+ struct {
+ struct nlmsghdr n;
+ struct admsg adm;
+ char buf[256];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct admsg));
+ req.n.nlmsg_type = RTM_GETAGEING;
+
+ int br_ifindex = ll_name_to_index(dev);
+
+ if (br_ifindex == 0) {
+ fprintf(stderr, "Cannot find bridge device \"%s\"\n", dev);
+ return -1;
+ }
+
+ req.adm.adm_family = PF_BRIDGE;
+ req.adm.adm_ifindex = br_ifindex;
+
+ if (rtnl_dump_request(&rth, RTM_GETAGEING, &req.adm,
+ sizeof(struct admsg)) < 0) {
+ perror("Cannot send dump request");
+ exit(1);
+ }
+
+ if (rtnl_dump_filter(&rth, print_ageinfo, stdout) < 0) {
+ fprintf(stderr, "Dump terminated\n");
+ exit(1);
+ }
+ return 0;
+}
+
+static int do_ageing_modify(int default_ageing, int interval, char *dev)
+{
+ struct {
+ struct nlmsghdr n;
+ struct admsg adm;
+ char buf[256];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct admsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+
+ if (default_ageing) {
+ req.n.nlmsg_type = RTM_SETDEFAULTAGEING;
+ req.adm.adm_ageing_interval = 0; /* Don't care */
+ } else {
+ req.n.nlmsg_type = RTM_SETAGEING;
+ req.adm.adm_ageing_interval = interval;
+ }
+
+ req.adm.adm_family = PF_BRIDGE;
+ req.adm.adm_ifindex = ll_name_to_index(dev);
+
+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
+ return -1;
+
+ return 0;
+}
+
+int do_ageing(int argc, char **argv)
+{
+ int interval = -1;
+ int default_ageing = 0;
+ char *dev = NULL;
+ int show = 0;
+
+ ll_init_map(&rth);
+
+ if (argc > 0) {
+ if (matches(*argv, "interval") == 0) {
+ argv++;
+ argc--;
+ } else {
+ ageing_usage();
+ exit(-1);
+ }
+ }
+
+ if (argc > 0) {
+ if (matches(*argv, "show") == 0) {
+ show = 1;
+ } else if (matches(*argv, "default") == 0) {
+ default_ageing = 1;
+ interval = 0;
+ } else if (matches(*argv, "help") == 0) {
+ ageing_usage();
+ exit(-1);
+ } else {
+ errno = 0;
+ interval = atoi(*argv);
+ if (errno) {
+ ageing_usage();
+ exit(-1);
+ }
+ }
+ argv++;
+ argc--;
+ } else {
+ ageing_usage();
+ exit(-1);
+ }
+
+ if (argc > 0) {
+ NEXT_ARG();
+ dev = *argv;
+ } else {
+ ageing_usage();
+ exit(-1);
+ }
+
+ if (show) {
+ do_ageing_show(dev);
+ return 0;
+ } else if (default_ageing || (interval > 0)) {
+ do_ageing_modify(default_ageing, interval, dev);
+ return 0;
+ }
+
+ fprintf(stderr, "Command unknown, try \'bridge interval help\'");
+ exit(-1);
+}
+
int do_fdb(int argc, char **argv)
{
ll_init_map(&rth);
@@ -161,6 +161,14 @@ extern int rtnl_from_file(FILE *, rtnl_listen_filter_t handler,
#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
#endif
+#ifndef ADA_RTA
+#define ADA_RTA(r) \
+ ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct admsg))))
+#endif
+#ifndef ADA_PAYLOAD
+#define ADA_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct admsg))
+#endif
+
#ifndef NDTA_RTA
#define NDTA_RTA(r) \
((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndtmsg))))
@@ -198,4 +198,11 @@ enum {
};
#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1)
+struct admsg {
+ __u8 adm_family;
+ __u8 adm_pad1;
+ __u16 adm_pad2;
+ __s32 adm_ifindex;
+ __u16 adm_ageing_interval;
+};
#endif /* _LINUX_IF_BRIDGE_H */
@@ -139,6 +139,13 @@ enum {
RTM_GETNSID = 90,
#define RTM_GETNSID RTM_GETNSID
+ RTM_SETAGEING = 92,
+#define RTM_SETAGEING RTM_SETAGEING
+ RTM_SETDEFAULTAGEING = 93,
+#define RTM_SETDEFAULTAGEING RTM_SETDEFAULTAGEING
+ RTM_GETAGEING = 94,
+#define RTM_GETAGEING RTM_GETAGEING
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
Extend bridge command to configure and retrieve ageing interval for bridge devices. Netlink messaging is used to configure and retrieve the ageing interval. Signed-off-by: Premkumar Jonnala <pjonnala@broadcom.com> --- -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html