]>
git.proxmox.com Git - mirror_iproute2.git/blob - bridge/fdb.c
2 * Get/set/delete fdb table with netlink
4 * Authors: Stephen Hemminger <shemminger@vyatta.com>
12 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <linux/if_bridge.h>
17 #include <linux/if_ether.h>
18 #include <linux/neighbour.h>
21 #include "libnetlink.h"
22 #include "br_common.h"
27 static void usage(void)
29 fprintf(stderr
, "Usage: br fdb { add | del | replace } ADDR dev DEV\n");
30 fprintf(stderr
, " br fdb {show} [ dev DEV ]\n");
34 static const char *state_n2a(unsigned s
)
38 if (s
& NUD_PERMANENT
)
47 if (s
& NUD_REACHABLE
)
50 sprintf(buf
, "state=%#x", s
);
54 static char *fmt_time(char *b
, size_t l
, unsigned long tick
)
61 snprintf(b
, l
, "%lu.%02lu", tick
/ hz
, ((tick
% hz
) * hz
) / 100);
65 int print_fdb(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
, void *arg
)
67 struct ndmsg
*r
= NLMSG_DATA(n
);
68 int len
= n
->nlmsg_len
;
69 struct rtattr
* tb
[NDA_MAX
+1];
70 const __u8
*addr
= NULL
;
73 len
-= NLMSG_LENGTH(sizeof(*r
));
75 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
79 if (r
->ndm_family
!= AF_BRIDGE
)
82 if (filter_index
&& filter_index
!= r
->ndm_ifindex
)
85 parse_rtattr(tb
, NDA_MAX
, NDA_RTA(r
),
86 n
->nlmsg_len
- NLMSG_LENGTH(sizeof(*r
)));
88 if (n
->nlmsg_type
== RTM_DELNEIGH
)
92 addr
= RTA_DATA(tb
[NDA_LLADDR
]);
94 fprintf(stderr
, "missing lladdr\n");
98 printf("%s\t%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t%s",
99 ll_index_to_name(r
->ndm_ifindex
),
100 addr
[0], addr
[1], addr
[2],
101 addr
[3], addr
[4], addr
[5],
102 state_n2a(r
->ndm_state
));
104 if (show_stats
&& tb
[NDA_CACHEINFO
]) {
105 struct nda_cacheinfo
*ci
= RTA_DATA(tb
[NDA_CACHEINFO
]);
107 printf("\t%8s", fmt_time(b1
, sizeof(b1
), ci
->ndm_updated
));
108 printf(" %8s", fmt_time(b1
, sizeof(b1
), ci
->ndm_used
));
115 static int fdb_show(int argc
, char **argv
)
117 char *filter_dev
= NULL
;
120 if (strcmp(*argv
, "dev") == 0) {
123 duparg("dev", *argv
);
130 if ((filter_index
= if_nametoindex(filter_dev
)) == 0) {
131 fprintf(stderr
, "Cannot find device \"%s\"\n", filter_dev
);
136 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETNEIGH
) < 0) {
137 perror("Cannot send dump request");
141 printf("port\tmac addr\t\tflags%s\n",
142 show_stats
? "\t updated used" : "");
144 if (rtnl_dump_filter(&rth
, print_fdb
, NULL
) < 0) {
145 fprintf(stderr
, "Dump terminated\n");
152 static int fdb_modify(int cmd
, int flags
, int argc
, char **argv
)
163 memset(&req
, 0, sizeof(req
));
165 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
166 req
.n
.nlmsg_flags
= NLM_F_REQUEST
|flags
;
167 req
.n
.nlmsg_type
= cmd
;
168 req
.ndm
.ndm_family
= PF_BRIDGE
;
169 req
.ndm
.ndm_state
= NUD_NOARP
;
172 if (strcmp(*argv
, "dev") == 0) {
175 } else if (strcmp(*argv
, "local") == 0) {
176 req
.ndm
.ndm_state
= NUD_PERMANENT
;
177 } else if (strcmp(*argv
, "temp") == 0) {
178 req
.ndm
.ndm_state
= NUD_REACHABLE
;
180 if (strcmp(*argv
, "to") == 0) {
183 if (matches(*argv
, "help") == 0) {
187 duparg2("to", *argv
);
193 if (d
== NULL
|| addr
== NULL
) {
194 fprintf(stderr
, "Device and address are required arguments.\n");
198 if (sscanf(addr
, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
199 abuf
, abuf
+1, abuf
+2,
200 abuf
+3, abuf
+4, abuf
+5) != 6) {
201 fprintf(stderr
, "Invalid mac address %s\n", addr
);
205 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, abuf
, ETH_ALEN
);
207 req
.ndm
.ndm_ifindex
= ll_name_to_index(d
);
208 if (req
.ndm
.ndm_ifindex
== 0) {
209 fprintf(stderr
, "Cannot find device \"%s\"\n", d
);
213 if (rtnl_talk(&rth
, &req
.n
, 0, 0, NULL
) < 0)
219 int do_fdb(int argc
, char **argv
)
224 if (matches(*argv
, "add") == 0)
225 return fdb_modify(RTM_NEWNEIGH
, NLM_F_CREATE
|NLM_F_EXCL
, argc
-1, argv
+1);
226 if (matches(*argv
, "change") == 0)
227 return fdb_modify(RTM_NEWNEIGH
, NLM_F_REPLACE
, argc
-1, argv
+1);
229 if (matches(*argv
, "replace") == 0)
230 return fdb_modify(RTM_NEWNEIGH
, NLM_F_CREATE
|NLM_F_REPLACE
, argc
-1, argv
+1);
231 if (matches(*argv
, "delete") == 0)
232 return fdb_modify(RTM_DELNEIGH
, 0, argc
-1, argv
+1);
233 if (matches(*argv
, "show") == 0 ||
234 matches(*argv
, "lst") == 0 ||
235 matches(*argv
, "list") == 0)
236 return fdb_show(argc
-1, argv
+1);
237 if (matches(*argv
, "help") == 0)
240 return fdb_show(0, NULL
);
242 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip neigh help\".\n", *argv
);