aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@nvidia.com>2023-11-01 09:45:10 +0200
committerDavid Ahern <dsahern@kernel.org>2023-11-06 10:08:50 -0700
commit77138a2f947763de872edb41507a93a292139812 (patch)
treec61504981f1cd87cbc74b02c2c0a23896a02fa45
parent34d5458cfb1cc8474248ca61da426b47f4c806de (diff)
downloadiproute2-77138a2f947763de872edb41507a93a292139812.tar.gz
bridge: mdb: Add get support
Implement MDB get functionality, allowing user space to query a single MDB entry from the kernel instead of dumping all the entries. Example usage: # bridge mdb add dev br0 port swp1 grp 239.1.1.1 vid 10 # bridge mdb add dev br0 port swp2 grp 239.1.1.1 vid 10 # bridge mdb add dev br0 port swp2 grp 239.1.1.5 vid 10 # bridge mdb get dev br0 grp 239.1.1.1 vid 10 dev br0 port swp1 grp 239.1.1.1 temp vid 10 dev br0 port swp2 grp 239.1.1.1 temp vid 10 # bridge -j -p mdb get dev br0 grp 239.1.1.1 vid 10 [ { "index": 10, "dev": "br0", "port": "swp1", "grp": "239.1.1.1", "state": "temp", "flags": [ ], "vid": 10 },{ "index": 10, "dev": "br0", "port": "swp2", "grp": "239.1.1.1", "state": "temp", "flags": [ ], "vid": 10 } ] # bridge mdb get dev br0 grp 239.1.1.1 vid 20 Error: bridge: MDB entry not found. # bridge mdb get dev br0 grp 239.1.1.2 vid 10 Error: bridge: MDB entry not found. Signed-off-by: Ido Schimmel <idosch@nvidia.com> Acked-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: David Ahern <dsahern@kernel.org>
-rw-r--r--bridge/mdb.c99
-rw-r--r--man/man8/bridge.835
2 files changed, 133 insertions, 1 deletions
diff --git a/bridge/mdb.c b/bridge/mdb.c
index 18793458e..dc8007914 100644
--- a/bridge/mdb.c
+++ b/bridge/mdb.c
@@ -36,7 +36,8 @@ static void usage(void)
"Usage: bridge mdb { add | del | replace } dev DEV port PORT grp GROUP [src SOURCE] [permanent | temp] [vid VID]\n"
" [ filter_mode { include | exclude } ] [ source_list SOURCE_LIST ] [ proto PROTO ] [ dst IPADDR ]\n"
" [ dst_port DST_PORT ] [ vni VNI ] [ src_vni SRC_VNI ] [ via DEV ]\n"
- " bridge mdb {show} [ dev DEV ] [ vid VID ]\n");
+ " bridge mdb {show} [ dev DEV ] [ vid VID ]\n"
+ " bridge mdb get dev DEV grp GROUP [ src SOURCE ] [ vid VID ] [ src_vni SRC_VNI ]\n");
exit(-1);
}
@@ -848,6 +849,100 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
return 0;
}
+static int mdb_get(int argc, char **argv)
+{
+ struct {
+ struct nlmsghdr n;
+ struct br_port_msg bpm;
+ char buf[1024];
+ } req = {
+ .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct br_port_msg)),
+ .n.nlmsg_flags = NLM_F_REQUEST,
+ .n.nlmsg_type = RTM_GETMDB,
+ .bpm.family = PF_BRIDGE,
+ };
+ char *d = NULL, *grp = NULL, *src = NULL, *src_vni = NULL;
+ struct br_mdb_entry entry = {};
+ struct nlmsghdr *answer;
+ bool get_attrs = false;
+ short vid = 0;
+ int ret = 0;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ d = *argv;
+ } else if (strcmp(*argv, "grp") == 0) {
+ NEXT_ARG();
+ grp = *argv;
+ } else if (strcmp(*argv, "vid") == 0) {
+ NEXT_ARG();
+ vid = atoi(*argv);
+ } else if (strcmp(*argv, "src") == 0) {
+ NEXT_ARG();
+ src = *argv;
+ get_attrs = true;
+ } else if (strcmp(*argv, "src_vni") == 0) {
+ NEXT_ARG();
+ src_vni = *argv;
+ get_attrs = true;
+ } else {
+ if (strcmp(*argv, "help") == 0)
+ usage();
+ }
+ argc--; argv++;
+ }
+
+ if (d == NULL || grp == NULL) {
+ fprintf(stderr, "Device and group address are required arguments.\n");
+ return -1;
+ }
+
+ req.bpm.ifindex = ll_name_to_index(d);
+ if (!req.bpm.ifindex)
+ return nodev(d);
+
+ if (mdb_parse_grp(grp, &entry)) {
+ fprintf(stderr, "Invalid address \"%s\"\n", grp);
+ return -1;
+ }
+
+ entry.vid = vid;
+ addattr_l(&req.n, sizeof(req), MDBA_GET_ENTRY, &entry, sizeof(entry));
+ if (get_attrs) {
+ struct rtattr *nest = addattr_nest(&req.n, sizeof(req),
+ MDBA_GET_ENTRY_ATTRS);
+
+ nest->rta_type |= NLA_F_NESTED;
+
+ if (src && mdb_parse_src(&req.n, sizeof(req), src)) {
+ fprintf(stderr, "Invalid source address \"%s\"\n", src);
+ return -1;
+ }
+
+ if (src_vni && mdb_parse_vni(&req.n, sizeof(req), src_vni,
+ MDBE_ATTR_SRC_VNI)) {
+ fprintf(stderr, "Invalid source VNI \"%s\"\n", src_vni);
+ return -1;
+ }
+
+ addattr_nest_end(&req.n, nest);
+ }
+
+ if (rtnl_talk(&rth, &req.n, &answer) < 0)
+ return -2;
+
+ new_json_obj(json);
+
+ if (print_mdbs(answer, stdout) < 0)
+ ret = -1;
+
+ delete_json_obj();
+ free(answer);
+
+ return ret;
+}
+
int do_mdb(int argc, char **argv)
{
ll_init_map(&rth);
@@ -865,6 +960,8 @@ int do_mdb(int argc, char **argv)
matches(*argv, "lst") == 0 ||
matches(*argv, "list") == 0)
return mdb_show(argc-1, argv+1);
+ if (strcmp(*argv, "get") == 0)
+ return mdb_get(argc-1, argv+1);
if (matches(*argv, "help") == 0)
usage();
} else
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index 07bb97878..7c1b22f64 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -178,6 +178,16 @@ bridge \- show / manipulate bridge addresses and devices
.IR DEV " ]"
.ti -8
+.B "bridge mdb get"
+.BI dev " DEV " grp " GROUP "
+.RB "[ " src
+.IR SOURCE " ]"
+.RB "[ " vid
+.IR VID " ]"
+.RB "[ " src_vni
+.IR SRC_VNI " ]"
+
+.ti -8
.BR "bridge vlan" " { " add " | " del " } "
.B dev
.I DEV
@@ -1137,6 +1147,31 @@ With the
.B -statistics
option, the command displays timer values for mdb and router port entries.
+.SS bridge mdb get - get multicast group database entry.
+
+This command retrieves a multicast group database entry based on its key.
+
+.TP
+.BI dev " DEV"
+the interface where this group address is associated.
+
+.TP
+.BI grp " GROUP"
+the multicast group address (IPv4, IPv6 or L2 multicast).
+
+.TP
+.BI src " SOURCE"
+the source IP address. Only relevant when retrieving an (S, G) entry.
+
+.TP
+.BI vid " VID"
+the VLAN ID. Only relevant when the bridge is VLAN-aware.
+
+.TP
+.BI src_vni " SRC_VNI"
+the source VNI Network Identifier. Only relevant when the VXLAN device is in
+external mode.
+
.SH bridge vlan - VLAN filter list
.B vlan