iproute2/bridge/fdb.c

396 lines
9.4 KiB
C
Raw Normal View History

/*
* Get/set/delete fdb table with netlink
*
* TODO: merge/replace this with ip neighbour
*
* Authors: Stephen Hemminger <shemminger@vyatta.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <time.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_bridge.h>
#include <linux/if_ether.h>
#include <linux/neighbour.h>
#include <string.h>
#include <limits.h>
#include "libnetlink.h"
#include "br_common.h"
#include "rt_names.h"
#include "utils.h"
bridge: Make filter_index match in signedness Michael Tautschnig wrote: During a rebuild [...]. Please note that we use our research compiler tool-chain (using tools from the cbmc package), which permits extended reporting on type inconsistencies at link time. [...] gcc bridge.o fdb.o monitor.o link.o mdb.o vlan.o ../lib/libnetlink.a ../lib/libutil.a ../lib/libnetlink.a ../lib/libutil.a -o bridge file link.c line 18: error: conflicting types for variable "filter_index" old definition in module fdb file fdb.c line 29 signed int new definition in module link file link.c line 18 unsigned int <builtin>: recipe for target 'bridge' failed make[3]: *** [bridge] Error 64 make[3]: Leaving directory '/srv/jenkins-slave/workspace/sid-goto-cc-iproute2/iproute2-3.14.0/bridge' Makefile:45: recipe for target 'all' failed While practical constraints may limit the value of filter_index to remain within the bounds of a positive signed int, there is certainly no such guarantee here. Also, a plain majority vote suggests that this really just a wrong declaration in link.c as several declarations of filter_index as signed int exist. [...] My followup on this was: I think the majority is wrong. filter_index is assigned exclusively from if_nametoindex or ll_name_to_index which both return unsigned int. Changing it to unsigned everywhere seems better. This has been minimally tested by using the bridge tool to add vids and showing available vids on different devices. Reported-by: Michael Tautschnig <mt@debian.org> Signed-off-by: Andreas Henriksson <andreas@fatal.se>
2014-06-05 01:40:37 +08:00
static unsigned int filter_index;
static void usage(void)
{
fprintf(stderr, "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ]\n"
" [router] [ dst IPADDR] [ vlan VID ]\n"
" [ port PORT] [ vni VNI ] [via DEV]\n");
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
fprintf(stderr, " bridge fdb {show} [ br BRDEV ] [ brport DEV ]\n");
exit(-1);
}
static const char *state_n2a(unsigned s)
{
static char buf[32];
if (s & NUD_PERMANENT)
return "permanent";
if (s & NUD_NOARP)
return "static";
if (s & NUD_STALE)
return "stale";
if (s & NUD_REACHABLE)
return "";
sprintf(buf, "state=%#x", s);
return buf;
}
int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
FILE *fp = arg;
struct ndmsg *r = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr * tb[NDA_MAX+1];
if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n",
n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
return 0;
}
len -= NLMSG_LENGTH(sizeof(*r));
if (len < 0) {
fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
return -1;
}
if (r->ndm_family != AF_BRIDGE)
return 0;
if (filter_index && filter_index != r->ndm_ifindex)
return 0;
parse_rtattr(tb, NDA_MAX, NDA_RTA(r),
n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
if (n->nlmsg_type == RTM_DELNEIGH)
fprintf(fp, "Deleted ");
if (tb[NDA_LLADDR]) {
SPRINT_BUF(b1);
fprintf(fp, "%s ",
ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
RTA_PAYLOAD(tb[NDA_LLADDR]),
ll_index_to_type(r->ndm_ifindex),
b1, sizeof(b1)));
}
2012-10-30 08:48:55 +08:00
if (!filter_index && r->ndm_ifindex)
fprintf(fp, "dev %s ", ll_index_to_name(r->ndm_ifindex));
if (tb[NDA_DST]) {
SPRINT_BUF(abuf);
int family = AF_INET;
if (RTA_PAYLOAD(tb[NDA_DST]) == sizeof(struct in6_addr))
family = AF_INET6;
fprintf(fp, "dst %s ",
format_host(family,
RTA_PAYLOAD(tb[NDA_DST]),
RTA_DATA(tb[NDA_DST]),
abuf, sizeof(abuf)));
}
2012-10-30 08:48:55 +08:00
if (tb[NDA_VLAN]) {
__u16 vid = rta_getattr_u16(tb[NDA_VLAN]);
fprintf(fp, "vlan %hu ", vid);
}
if (tb[NDA_PORT])
fprintf(fp, "port %d ", ntohs(rta_getattr_u16(tb[NDA_PORT])));
if (tb[NDA_VNI])
fprintf(fp, "vni %d ", rta_getattr_u32(tb[NDA_VNI]));
if (tb[NDA_IFINDEX]) {
unsigned int ifindex = rta_getattr_u32(tb[NDA_IFINDEX]);
if (ifindex) {
char ifname[IF_NAMESIZE];
if (!tb[NDA_LINK_NETNSID] &&
if_indextoname(ifindex, ifname))
fprintf(fp, "via %s ", ifname);
else
fprintf(fp, "via ifindex %u ", ifindex);
}
}
if (tb[NDA_LINK_NETNSID])
fprintf(fp, "link-netnsid %d ",
rta_getattr_u32(tb[NDA_LINK_NETNSID]));
if (show_stats && tb[NDA_CACHEINFO]) {
struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
int hz = get_user_hz();
fprintf(fp, "used %d/%d ", ci->ndm_used/hz,
ci->ndm_updated/hz);
}
if (r->ndm_flags & NTF_SELF)
fprintf(fp, "self ");
if (tb[NDA_MASTER])
fprintf(fp, "master %s ",
ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER])));
else if (r->ndm_flags & NTF_MASTER)
fprintf(fp, "master ");
if (r->ndm_flags & NTF_ROUTER)
fprintf(fp, "router ");
if (r->ndm_flags & NTF_EXT_LEARNED)
fprintf(fp, "external ");
fprintf(fp, "%s\n", state_n2a(r->ndm_state));
return 0;
}
static int fdb_show(int argc, char **argv)
{
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
struct {
struct nlmsghdr n;
struct ifinfomsg ifm;
char buf[256];
} req;
char *filter_dev = NULL;
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
char *br = NULL;
int msg_size = sizeof(struct ifinfomsg);
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.ifm.ifi_family = PF_BRIDGE;
while (argc > 0) {
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
if ((strcmp(*argv, "brport") == 0) || strcmp(*argv, "dev") == 0) {
NEXT_ARG();
filter_dev = *argv;
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
} else if (strcmp(*argv, "br") == 0) {
NEXT_ARG();
br = *argv;
} else {
if (matches(*argv, "help") == 0)
usage();
}
argc--; argv++;
}
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
if (br) {
int br_ifindex = ll_name_to_index(br);
if (br_ifindex == 0) {
fprintf(stderr, "Cannot find bridge device \"%s\"\n", br);
return -1;
}
addattr32(&req.n, sizeof(req), IFLA_MASTER, br_ifindex);
msg_size += RTA_LENGTH(4);
}
/*we'll keep around filter_dev for older kernels */
if (filter_dev) {
filter_index = if_nametoindex(filter_dev);
if (filter_index == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n",
filter_dev);
return -1;
}
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
req.ifm.ifi_index = filter_index;
}
iproute2 bridge: bring to above par with brctl show macs root@moja-mojo:bridge# ./bridge fdb help Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ] [router] [ dst IPADDR] [ vlan VID ] [ port PORT] [ vni VNI ] [via DEV] bridge fdb {show} [ br BRDEV ] [ brport DEV ] Lets start with two bridges each with a port... root@moja-mojo:bridge# ./bridge link 10: sw1-p1 state DOWN : <BROADCAST,NOARP> mtu 1500 master sw1 state disabled priority 32 cost 100 11: eth1 state DOWN : <BROADCAST,NOARP> mtu 1500 master br0 state disabled priority 32 cost 100 show all... root@moja-mojo:bridge# ./bridge fdb show 33:33:00:00:00:01 dev ifb0 self permanent 33:33:00:00:00:01 dev ifb1 self permanent 33:33:00:00:00:01 dev eth0 self permanent 01:00:5e:00:00:01 dev eth0 self permanent 33:33:ff:92:c0:60 dev eth0 self permanent 33:33:00:00:00:fb dev eth0 self permanent 01:00:5e:00:00:fb dev eth0 self permanent 01:00:5e:7f:ff:fd dev eth0 self permanent 01:00:5e:00:00:01 dev wlan0 self permanent 33:33:00:00:00:01 dev wlan0 self permanent 33:33:ff:c2:84:3b dev wlan0 self permanent 33:33:00:00:00:fb dev wlan0 self permanent 01:00:5e:00:00:01 dev virbr0 self permanent 01:00:5e:00:00:fb dev virbr0 self permanent 33:33:00:00:00:01 dev br0 self permanent 33:33:00:00:00:01 dev sw1 self permanent 33:33:00:00:00:01 dev dummy0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Lets see a netdev that is *not* attached to a bridge root@moja-mojo:bridge# ./bridge fdb show brport eth0 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent 33:33:ff:92:c0:60 self permanent 33:33:00:00:00:fb self permanent 01:00:5e:00:00:fb self permanent 01:00:5e:7f:ff:fd self permanent Lets see a netdev that is bridge port root@moja-mojo:bridge# ./bridge fdb show brport eth1 hadi@jhs-1:/media/MT1/other-gits/iproute-jul04/bridge$ ./bridge fdb show brport eth1 b6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the correct bridge and you get good stuff root@moja-mojo:bridge# ./bridge fdb show brport eth1 br br0 6:5e:dd:ce:d7:5e vlan 0 master br0 permanent 33:33:00:00:00:01 self permanent Specify the wrong bridge and you get good nada root@moja-mojo:bridge# ./bridge fdb show brport eth1 br sw1 dump br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent dump sw1 root@moja-mojo:bridge# ./bridge fdb show br sw1 33:33:00:00:00:01 dev sw1 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master sw1 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent Lets move a port from one bridge to another for shits-and-giggles (as the New Brunswickians like to say) root@moja-mojo:bridge# ip link set sw1-p1 master br0 Now dump again br0 root@moja-mojo:bridge# ./bridge fdb show br br0 33:33:00:00:00:01 dev br0 self permanent 5e:f4:03:44:da:9a dev sw1-p1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev sw1-p1 self permanent b6:5e:dd:ce:d7:5e dev eth1 vlan 0 master br0 permanent 33:33:00:00:00:01 dev eth1 self permanent Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
2014-07-04 20:37:10 +08:00
if (rtnl_dump_request(&rth, RTM_GETNEIGH, &req.ifm, msg_size) < 0) {
perror("Cannot send dump request");
exit(1);
}
if (rtnl_dump_filter(&rth, print_fdb, stdout) < 0) {
fprintf(stderr, "Dump terminated\n");
exit(1);
}
return 0;
}
static int fdb_modify(int cmd, int flags, int argc, char **argv)
{
struct {
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
char *addr = NULL;
char *d = NULL;
char abuf[ETH_ALEN];
int dst_ok = 0;
inet_prefix dst;
unsigned long port = 0;
unsigned long vni = ~0;
unsigned int via = 0;
char *endptr;
short vid = -1;
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST|flags;
req.n.nlmsg_type = cmd;
req.ndm.ndm_family = PF_BRIDGE;
req.ndm.ndm_state = NUD_NOARP;
while (argc > 0) {
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
d = *argv;
} else if (strcmp(*argv, "dst") == 0) {
NEXT_ARG();
if (dst_ok)
duparg2("dst", *argv);
get_addr(&dst, *argv, preferred_family);
dst_ok = 1;
} else if (strcmp(*argv, "port") == 0) {
NEXT_ARG();
port = strtoul(*argv, &endptr, 0);
if (endptr && *endptr) {
struct servent *pse;
pse = getservbyname(*argv, "udp");
if (!pse)
invarg("invalid port\n", *argv);
port = ntohs(pse->s_port);
} else if (port > 0xffff)
invarg("invalid port\n", *argv);
} else if (strcmp(*argv, "vni") == 0) {
NEXT_ARG();
vni = strtoul(*argv, &endptr, 0);
if ((endptr && *endptr) ||
(vni >> 24) || vni == ULONG_MAX)
invarg("invalid VNI\n", *argv);
} else if (strcmp(*argv, "via") == 0) {
NEXT_ARG();
via = if_nametoindex(*argv);
if (via == 0)
invarg("invalid device\n", *argv);
} else if (strcmp(*argv, "self") == 0) {
req.ndm.ndm_flags |= NTF_SELF;
} else if (matches(*argv, "master") == 0) {
req.ndm.ndm_flags |= NTF_MASTER;
} else if (matches(*argv, "router") == 0) {
req.ndm.ndm_flags |= NTF_ROUTER;
2012-10-30 08:48:55 +08:00
} else if (matches(*argv, "local") == 0||
matches(*argv, "permanent") == 0) {
req.ndm.ndm_state |= NUD_PERMANENT;
} else if (matches(*argv, "temp") == 0) {
req.ndm.ndm_state |= NUD_REACHABLE;
} else if (matches(*argv, "vlan") == 0) {
if (vid >= 0)
duparg2("vlan", *argv);
NEXT_ARG();
vid = atoi(*argv);
} else {
if (strcmp(*argv, "to") == 0) {
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
usage();
if (addr)
duparg2("to", *argv);
addr = *argv;
}
argc--; argv++;
}
if (d == NULL || addr == NULL) {
fprintf(stderr, "Device and address are required arguments.\n");
exit(-1);
}
/* Assume self */
if (!(req.ndm.ndm_flags&(NTF_SELF|NTF_MASTER)))
req.ndm.ndm_flags |= NTF_SELF;
/* Assume permanent */
if (!(req.ndm.ndm_state&(NUD_PERMANENT|NUD_REACHABLE)))
req.ndm.ndm_state |= NUD_PERMANENT;
if (sscanf(addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
abuf, abuf+1, abuf+2,
abuf+3, abuf+4, abuf+5) != 6) {
fprintf(stderr, "Invalid mac address %s\n", addr);
exit(-1);
}
addattr_l(&req.n, sizeof(req), NDA_LLADDR, abuf, ETH_ALEN);
if (dst_ok)
addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen);
if (vid >= 0)
addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
if (port) {
unsigned short dport;
dport = htons((unsigned short)port);
addattr16(&req.n, sizeof(req), NDA_PORT, dport);
}
if (vni != ~0)
addattr32(&req.n, sizeof(req), NDA_VNI, vni);
if (via)
addattr32(&req.n, sizeof(req), NDA_IFINDEX, via);
req.ndm.ndm_ifindex = ll_name_to_index(d);
if (req.ndm.ndm_ifindex == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", d);
return -1;
}
if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
exit(2);
return 0;
}
int do_fdb(int argc, char **argv)
{
ll_init_map(&rth);
if (argc > 0) {
if (matches(*argv, "add") == 0)
return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1);
if (matches(*argv, "append") == 0)
return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_APPEND, argc-1, argv+1);
if (matches(*argv, "replace") == 0)
return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_REPLACE, argc-1, argv+1);
if (matches(*argv, "delete") == 0)
return fdb_modify(RTM_DELNEIGH, 0, argc-1, argv+1);
if (matches(*argv, "show") == 0 ||
matches(*argv, "lst") == 0 ||
matches(*argv, "list") == 0)
return fdb_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
usage();
} else
return fdb_show(0, NULL);
fprintf(stderr, "Command \"%s\" is unknown, try \"bridge fdb help\".\n", *argv);
exit(-1);
}