bridge: mdb: add support for source address
This patch adds the user-space control and dump of mdb entry source address. When setting the new MDBA_SET_ENTRY_ATTRS nested attribute is used and inside is added MDBE_ATTR_SOURCE based on the address family. When dumping we look for MDBA_MDB_EATTR_SOURCE and if present we add the "src x.x.x.x" output. The source address will be always shown as it's needed to match the entry to modify it from user-space. Example: $ bridge mdb add dev bridge port ens13 grp 239.0.0.1 src 1.2.3.4 permanent vid 100 $ bridge mdb show dev bridge port ens13 grp 239.0.0.1 src 1.2.3.4 permanent vid 100 Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com> Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
parent
f905191a48
commit
547b319762
38
bridge/mdb.c
38
bridge/mdb.c
|
|
@ -31,7 +31,7 @@ static unsigned int filter_index, filter_vlan;
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP [permanent | temp] [vid VID]\n"
|
"Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP [src SOURCE] [permanent | temp] [vid VID]\n"
|
||||||
" bridge mdb {show} [ dev DEV ] [ vid VID ]\n");
|
" bridge mdb {show} [ dev DEV ] [ vid VID ]\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
@ -118,16 +118,16 @@ static void br_print_router_ports(FILE *f, struct rtattr *attr,
|
||||||
static void print_mdb_entry(FILE *f, int ifindex, const struct br_mdb_entry *e,
|
static void print_mdb_entry(FILE *f, int ifindex, const struct br_mdb_entry *e,
|
||||||
struct nlmsghdr *n, struct rtattr **tb)
|
struct nlmsghdr *n, struct rtattr **tb)
|
||||||
{
|
{
|
||||||
|
const void *grp, *src;
|
||||||
SPRINT_BUF(abuf);
|
SPRINT_BUF(abuf);
|
||||||
const char *dev;
|
const char *dev;
|
||||||
const void *src;
|
|
||||||
int af;
|
int af;
|
||||||
|
|
||||||
if (filter_vlan && e->vid != filter_vlan)
|
if (filter_vlan && e->vid != filter_vlan)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
af = e->addr.proto == htons(ETH_P_IP) ? AF_INET : AF_INET6;
|
af = e->addr.proto == htons(ETH_P_IP) ? AF_INET : AF_INET6;
|
||||||
src = af == AF_INET ? (const void *)&e->addr.u.ip4 :
|
grp = af == AF_INET ? (const void *)&e->addr.u.ip4 :
|
||||||
(const void *)&e->addr.u.ip6;
|
(const void *)&e->addr.u.ip6;
|
||||||
dev = ll_index_to_name(ifindex);
|
dev = ll_index_to_name(ifindex);
|
||||||
|
|
||||||
|
|
@ -140,8 +140,13 @@ static void print_mdb_entry(FILE *f, int ifindex, const struct br_mdb_entry *e,
|
||||||
|
|
||||||
print_color_string(PRINT_ANY, ifa_family_color(af),
|
print_color_string(PRINT_ANY, ifa_family_color(af),
|
||||||
"grp", " grp %s",
|
"grp", " grp %s",
|
||||||
inet_ntop(af, src, abuf, sizeof(abuf)));
|
inet_ntop(af, grp, abuf, sizeof(abuf)));
|
||||||
|
if (tb && tb[MDBA_MDB_EATTR_SOURCE]) {
|
||||||
|
src = (const void *)RTA_DATA(tb[MDBA_MDB_EATTR_SOURCE]);
|
||||||
|
print_color_string(PRINT_ANY, ifa_family_color(af),
|
||||||
|
"src", " src %s",
|
||||||
|
inet_ntop(af, src, abuf, sizeof(abuf)));
|
||||||
|
}
|
||||||
print_string(PRINT_ANY, "state", " %s",
|
print_string(PRINT_ANY, "state", " %s",
|
||||||
(e->state & MDB_PERMANENT) ? "permanent" : "temp");
|
(e->state & MDB_PERMANENT) ? "permanent" : "temp");
|
||||||
|
|
||||||
|
|
@ -378,8 +383,8 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
|
||||||
.n.nlmsg_type = cmd,
|
.n.nlmsg_type = cmd,
|
||||||
.bpm.family = PF_BRIDGE,
|
.bpm.family = PF_BRIDGE,
|
||||||
};
|
};
|
||||||
|
char *d = NULL, *p = NULL, *grp = NULL, *src = NULL;
|
||||||
struct br_mdb_entry entry = {};
|
struct br_mdb_entry entry = {};
|
||||||
char *d = NULL, *p = NULL, *grp = NULL;
|
|
||||||
short vid = 0;
|
short vid = 0;
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
|
|
@ -400,6 +405,9 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
|
||||||
} else if (strcmp(*argv, "vid") == 0) {
|
} else if (strcmp(*argv, "vid") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
vid = atoi(*argv);
|
vid = atoi(*argv);
|
||||||
|
} else if (strcmp(*argv, "src") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
src = *argv;
|
||||||
} else {
|
} else {
|
||||||
if (matches(*argv, "help") == 0)
|
if (matches(*argv, "help") == 0)
|
||||||
usage();
|
usage();
|
||||||
|
|
@ -431,6 +439,24 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
|
||||||
|
|
||||||
entry.vid = vid;
|
entry.vid = vid;
|
||||||
addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry));
|
addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry));
|
||||||
|
if (src) {
|
||||||
|
struct rtattr *nest = addattr_nest(&req.n, sizeof(req),
|
||||||
|
MDBA_SET_ENTRY_ATTRS);
|
||||||
|
struct in6_addr src_ip6;
|
||||||
|
__be32 src_ip4;
|
||||||
|
|
||||||
|
nest->rta_type |= NLA_F_NESTED;
|
||||||
|
if (!inet_pton(AF_INET, src, &src_ip4)) {
|
||||||
|
if (!inet_pton(AF_INET6, src, &src_ip6)) {
|
||||||
|
fprintf(stderr, "Invalid source address \"%s\"\n", src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
addattr_l(&req.n, sizeof(req), MDBE_ATTR_SOURCE, &src_ip6, sizeof(src_ip6));
|
||||||
|
} else {
|
||||||
|
addattr32(&req.n, sizeof(req), MDBE_ATTR_SOURCE, src_ip4);
|
||||||
|
}
|
||||||
|
addattr_nest_end(&req.n, nest);
|
||||||
|
}
|
||||||
|
|
||||||
if (rtnl_talk(&rth, &req.n, NULL) < 0)
|
if (rtnl_talk(&rth, &req.n, NULL) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,8 @@ bridge \- show / manipulate bridge addresses and devices
|
||||||
.I PORT
|
.I PORT
|
||||||
.B grp
|
.B grp
|
||||||
.IR GROUP " [ "
|
.IR GROUP " [ "
|
||||||
|
.B src
|
||||||
|
.IR SOURCE " ] [ "
|
||||||
.BR permanent " | " temp " ] [ "
|
.BR permanent " | " temp " ] [ "
|
||||||
.B vid
|
.B vid
|
||||||
.IR VID " ] "
|
.IR VID " ] "
|
||||||
|
|
@ -694,6 +696,12 @@ the port.
|
||||||
- the mdb entry is temporary (default)
|
- the mdb entry is temporary (default)
|
||||||
.sp
|
.sp
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI src " SOURCE"
|
||||||
|
optional source IP address of a sender for this multicast group. If IGMPv3 for IPv4, or
|
||||||
|
MLDv2 for IPv6 respectively, are enabled it will be included in the lookup when
|
||||||
|
forwarding multicast traffic.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI vid " VID"
|
.BI vid " VID"
|
||||||
the VLAN ID which is known to have members of this multicast group.
|
the VLAN ID which is known to have members of this multicast group.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue