]>
git.proxmox.com Git - mirror_iproute2.git/blob - bridge/mdb.c
600596c94969b91d8db4432d3264168494f10df1
2 * Get mdb table with netlink
9 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <linux/if_bridge.h>
13 #include <linux/if_ether.h>
15 #include <arpa/inet.h>
17 #include "libnetlink.h"
18 #include "br_common.h"
24 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct br_port_msg))))
27 static unsigned int filter_index
;
29 static void usage(void)
31 fprintf(stderr
, "Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP [permanent | temp] [vid VID]\n");
32 fprintf(stderr
, " bridge mdb {show} [ dev DEV ]\n");
36 static void br_print_router_ports(FILE *f
, struct rtattr
*attr
)
38 uint32_t *port_ifindex
;
42 rem
= RTA_PAYLOAD(attr
);
43 for (i
= RTA_DATA(attr
); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
)) {
44 port_ifindex
= RTA_DATA(i
);
45 fprintf(f
, "%s ", ll_index_to_name(*port_ifindex
));
51 static void print_mdb_entry(FILE *f
, int ifindex
, struct br_mdb_entry
*e
,
52 struct nlmsghdr
*n
, struct rtattr
**tb
)
58 af
= e
->addr
.proto
== htons(ETH_P_IP
) ? AF_INET
: AF_INET6
;
59 src
= af
== AF_INET
? (const void *)&e
->addr
.u
.ip4
:
60 (const void *)&e
->addr
.u
.ip6
;
61 if (n
->nlmsg_type
== RTM_DELMDB
)
62 fprintf(f
, "Deleted ");
63 fprintf(f
, "dev %s port %s grp %s %s %s", ll_index_to_name(ifindex
),
64 ll_index_to_name(e
->ifindex
),
65 inet_ntop(af
, src
, abuf
, sizeof(abuf
)),
66 (e
->state
& MDB_PERMANENT
) ? "permanent" : "temp",
67 (e
->flags
& MDB_FLAGS_OFFLOAD
) ? "offload" : "");
69 fprintf(f
, " vid %hu", e
->vid
);
70 if (show_stats
&& tb
&& tb
[MDBA_MDB_EATTR_TIMER
]) {
73 __jiffies_to_tv(&tv
, rta_getattr_u32(tb
[MDBA_MDB_EATTR_TIMER
]));
74 fprintf(f
, "%4i.%.2i", (int)tv
.tv_sec
, (int)tv
.tv_usec
/10000);
79 static void br_print_mdb_entry(FILE *f
, int ifindex
, struct rtattr
*attr
,
82 struct rtattr
*etb
[MDBA_MDB_EATTR_MAX
+ 1];
83 struct br_mdb_entry
*e
;
87 rem
= RTA_PAYLOAD(attr
);
88 for (i
= RTA_DATA(attr
); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
)) {
90 parse_rtattr(etb
, MDBA_MDB_EATTR_MAX
, MDB_RTA(RTA_DATA(i
)),
91 RTA_PAYLOAD(i
) - RTA_ALIGN(sizeof(*e
)));
92 print_mdb_entry(f
, ifindex
, e
, n
, etb
);
96 int print_mdb(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
, void *arg
)
99 struct br_port_msg
*r
= NLMSG_DATA(n
);
100 int len
= n
->nlmsg_len
;
101 struct rtattr
*tb
[MDBA_MAX
+1], *i
;
103 if (n
->nlmsg_type
!= RTM_GETMDB
&& n
->nlmsg_type
!= RTM_NEWMDB
&& n
->nlmsg_type
!= RTM_DELMDB
) {
104 fprintf(stderr
, "Not RTM_GETMDB, RTM_NEWMDB or RTM_DELMDB: %08x %08x %08x\n",
105 n
->nlmsg_len
, n
->nlmsg_type
, n
->nlmsg_flags
);
110 len
-= NLMSG_LENGTH(sizeof(*r
));
112 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
116 if (filter_index
&& filter_index
!= r
->ifindex
)
119 parse_rtattr(tb
, MDBA_MAX
, MDBA_RTA(r
), n
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
122 int rem
= RTA_PAYLOAD(tb
[MDBA_MDB
]);
124 for (i
= RTA_DATA(tb
[MDBA_MDB
]); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
))
125 br_print_mdb_entry(fp
, r
->ifindex
, i
, n
);
128 if (tb
[MDBA_ROUTER
]) {
129 if (n
->nlmsg_type
== RTM_GETMDB
) {
131 fprintf(fp
, "router ports on %s: ",
132 ll_index_to_name(r
->ifindex
));
133 br_print_router_ports(fp
, tb
[MDBA_ROUTER
]);
136 uint32_t *port_ifindex
;
138 i
= RTA_DATA(tb
[MDBA_ROUTER
]);
139 port_ifindex
= RTA_DATA(i
);
140 if (n
->nlmsg_type
== RTM_DELMDB
)
141 fprintf(fp
, "Deleted ");
142 fprintf(fp
, "router port dev %s master %s\n",
143 ll_index_to_name(*port_ifindex
),
144 ll_index_to_name(r
->ifindex
));
153 static int mdb_show(int argc
, char **argv
)
155 char *filter_dev
= NULL
;
158 if (strcmp(*argv
, "dev") == 0) {
161 duparg("dev", *argv
);
168 filter_index
= if_nametoindex(filter_dev
);
169 if (filter_index
== 0) {
170 fprintf(stderr
, "Cannot find device \"%s\"\n",
176 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETMDB
) < 0) {
177 perror("Cannot send dump request");
181 if (rtnl_dump_filter(&rth
, print_mdb
, stdout
) < 0) {
182 fprintf(stderr
, "Dump terminated\n");
189 static int mdb_modify(int cmd
, int flags
, int argc
, char **argv
)
193 struct br_port_msg bpm
;
196 struct br_mdb_entry entry
;
197 char *d
= NULL
, *p
= NULL
, *grp
= NULL
;
200 memset(&req
, 0, sizeof(req
));
201 memset(&entry
, 0, sizeof(entry
));
203 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct br_port_msg
));
204 req
.n
.nlmsg_flags
= NLM_F_REQUEST
|flags
;
205 req
.n
.nlmsg_type
= cmd
;
206 req
.bpm
.family
= PF_BRIDGE
;
209 if (strcmp(*argv
, "dev") == 0) {
212 } else if (strcmp(*argv
, "grp") == 0) {
215 } else if (strcmp(*argv
, "port") == 0) {
218 } else if (strcmp(*argv
, "permanent") == 0) {
219 if (cmd
== RTM_NEWMDB
)
220 entry
.state
|= MDB_PERMANENT
;
221 } else if (strcmp(*argv
, "temp") == 0) {
223 } else if (strcmp(*argv
, "vid") == 0) {
227 if (matches(*argv
, "help") == 0)
233 if (d
== NULL
|| grp
== NULL
|| p
== NULL
) {
234 fprintf(stderr
, "Device, group address and port name are required arguments.\n");
238 req
.bpm
.ifindex
= ll_name_to_index(d
);
239 if (req
.bpm
.ifindex
== 0) {
240 fprintf(stderr
, "Cannot find device \"%s\"\n", d
);
244 entry
.ifindex
= ll_name_to_index(p
);
245 if (entry
.ifindex
== 0) {
246 fprintf(stderr
, "Cannot find device \"%s\"\n", p
);
250 if (!inet_pton(AF_INET
, grp
, &entry
.addr
.u
.ip4
)) {
251 if (!inet_pton(AF_INET6
, grp
, &entry
.addr
.u
.ip6
)) {
252 fprintf(stderr
, "Invalid address \"%s\"\n", grp
);
255 entry
.addr
.proto
= htons(ETH_P_IPV6
);
257 entry
.addr
.proto
= htons(ETH_P_IP
);
260 addattr_l(&req
.n
, sizeof(req
), MDBA_SET_ENTRY
, &entry
, sizeof(entry
));
262 if (rtnl_talk(&rth
, &req
.n
, NULL
, 0) < 0)
268 int do_mdb(int argc
, char **argv
)
273 if (matches(*argv
, "add") == 0)
274 return mdb_modify(RTM_NEWMDB
, NLM_F_CREATE
|NLM_F_EXCL
, argc
-1, argv
+1);
275 if (matches(*argv
, "delete") == 0)
276 return mdb_modify(RTM_DELMDB
, 0, argc
-1, argv
+1);
278 if (matches(*argv
, "show") == 0 ||
279 matches(*argv
, "lst") == 0 ||
280 matches(*argv
, "list") == 0)
281 return mdb_show(argc
-1, argv
+1);
282 if (matches(*argv
, "help") == 0)
285 return mdb_show(0, NULL
);
287 fprintf(stderr
, "Command \"%s\" is unknown, try \"bridge mdb help\".\n", *argv
);