diff options
author | Ido Schimmel <idosch@nvidia.com> | 2023-12-26 17:30:13 +0200 |
---|---|---|
committer | David Ahern <dsahern@kernel.org> | 2023-12-30 14:26:19 -0700 |
commit | ff3e423b9c6bc70b10357e9c856ac5685d7aa19f (patch) | |
tree | 4d6bdf2d0b4bf108bc2b928165020c42bc26105b | |
parent | 4be86f8e278bf24794c9e21994e6466aa04b03fe (diff) | |
download | iproute2-ff3e423b9c6bc70b10357e9c856ac5685d7aa19f.tar.gz |
bridge: mdb: Add flush support
Implement MDB flush functionality, allowing user space to flush MDB
entries from the kernel according to provided parameters.
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.c | 137 | ||||
-rw-r--r-- | man/man8/bridge.8 | 67 |
2 files changed, 203 insertions, 1 deletions
diff --git a/bridge/mdb.c b/bridge/mdb.c index dc8007914..196363a5c 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -37,7 +37,9 @@ static void usage(void) " [ 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 get dev DEV grp GROUP [ src SOURCE ] [ vid VID ] [ src_vni SRC_VNI ]\n"); + " bridge mdb get dev DEV grp GROUP [ src SOURCE ] [ vid VID ] [ src_vni SRC_VNI ]\n" + " bridge mdb flush dev DEV [ port PORT ] [ vid VID ] [ src_vni SRC_VNI ] [ proto PROTO ]\n" + " [ [no]permanent ] [ dst IPADDR ] [ dst_port DST_PORT ] [ vni VNI ]\n"); exit(-1); } @@ -943,6 +945,137 @@ static int mdb_get(int argc, char **argv) return ret; } +static int mdb_flush(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 | NLM_F_BULK, + .n.nlmsg_type = RTM_DELMDB, + .bpm.family = PF_BRIDGE, + }; + char *d = NULL, *p = NULL, *src_vni = NULL, *proto = NULL, *dst = NULL; + char *dst_port = NULL, *vni = NULL; + struct br_mdb_entry entry = {}; + unsigned short state_mask = 0; + bool set_attrs = false; + short vid = 0; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + d = *argv; + } else if (strcmp(*argv, "port") == 0) { + NEXT_ARG(); + p = *argv; + } else if (strcmp(*argv, "vid") == 0) { + NEXT_ARG(); + vid = atoi(*argv); + } else if (strcmp(*argv, "src_vni") == 0) { + NEXT_ARG(); + src_vni = *argv; + set_attrs = true; + } else if (strcmp(*argv, "proto") == 0) { + NEXT_ARG(); + proto = *argv; + set_attrs = true; + } else if (strcmp(*argv, "permanent") == 0) { + entry.state |= MDB_PERMANENT; + state_mask |= MDB_PERMANENT; + set_attrs = true; + } else if (strcmp(*argv, "nopermanent") == 0) { + entry.state &= ~MDB_PERMANENT; + state_mask |= MDB_PERMANENT; + set_attrs = true; + } else if (strcmp(*argv, "dst") == 0) { + NEXT_ARG(); + dst = *argv; + set_attrs = true; + } else if (strcmp(*argv, "dst_port") == 0) { + NEXT_ARG(); + dst_port = *argv; + set_attrs = true; + } else if (strcmp(*argv, "vni") == 0) { + NEXT_ARG(); + vni = *argv; + set_attrs = true; + } else { + if (strcmp(*argv, "help") == 0) + usage(); + } + argc--; argv++; + } + + if (d == NULL) { + fprintf(stderr, "Device is a required argument.\n"); + return -1; + } + + req.bpm.ifindex = ll_name_to_index(d); + if (!req.bpm.ifindex) + return nodev(d); + + if (p) { + entry.ifindex = ll_name_to_index(p); + if (!entry.ifindex) + return nodev(p); + } + + entry.vid = vid; + addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry)); + if (set_attrs) { + struct rtattr *nest = addattr_nest(&req.n, sizeof(req), + MDBA_SET_ENTRY_ATTRS); + + nest->rta_type |= NLA_F_NESTED; + + if (proto && mdb_parse_proto(&req.n, sizeof(req), proto)) { + fprintf(stderr, "Invalid protocol value \"%s\"\n", + proto); + return -1; + } + + if (dst && mdb_parse_dst(&req.n, sizeof(req), dst)) { + fprintf(stderr, "Invalid underlay destination address \"%s\"\n", + dst); + return -1; + } + + if (dst_port && mdb_parse_dst_port(&req.n, sizeof(req), + dst_port)) { + fprintf(stderr, "Invalid destination port \"%s\"\n", dst_port); + return -1; + } + + if (vni && mdb_parse_vni(&req.n, sizeof(req), vni, + MDBE_ATTR_VNI)) { + fprintf(stderr, "Invalid destination VNI \"%s\"\n", + vni); + 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; + } + + if (state_mask) + addattr8(&req.n, sizeof(req), MDBE_ATTR_STATE_MASK, + state_mask); + + addattr_nest_end(&req.n, nest); + } + + if (rtnl_talk(&rth, &req.n, NULL) < 0) + return -1; + + return 0; +} + int do_mdb(int argc, char **argv) { ll_init_map(&rth); @@ -962,6 +1095,8 @@ int do_mdb(int argc, char **argv) return mdb_show(argc-1, argv+1); if (strcmp(*argv, "get") == 0) return mdb_get(argc-1, argv+1); + if (strcmp(*argv, "flush") == 0) + return mdb_flush(argc-1, argv+1); if (matches(*argv, "help") == 0) usage(); } else diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 index a60964bb6..eeea40732 100644 --- a/man/man8/bridge.8 +++ b/man/man8/bridge.8 @@ -188,6 +188,25 @@ bridge \- show / manipulate bridge addresses and devices .IR SRC_VNI " ]" .ti -8 +.B "bridge mdb flush" +.BI dev " DEV " +.RB "[ " port +.IR PORT " ]" +.RB "[ " vid +.IR VID " ]" +.RB "[ " src_vni +.IR SRC_VNI " ]" +.RB "[ " proto +.IR PROTO " ]" +.RB "[ " [no]permanent " ]" +.RB "[ " dst +.IR IPADDR " ]" +.RB "[ " dst_port +.IR DST_PORT " ]" +.RB "[ " vni +.IR VNI " ]" + +.ti -8 .BR "bridge vlan" " { " add " | " del " } " .B dev .I DEV @@ -1172,6 +1191,54 @@ the VLAN ID. Only relevant when the bridge is VLAN-aware. the source VNI Network Identifier. Only relevant when the VXLAN device is in external mode. +.SS bridge mdb flush - flush multicast group database entries. + +This command flushes the matching multicast group database entries. + +.TP +.BI dev " DEV" +the interface where this group address is associated. + +.TP +.BI port " PORT" +the target port for the operation. If the bridge device is specified then only +entries pointing to the bridge itself will be deleted. + +.TP +.BI vid " VID" +the VLAN ID for the operation. Match entries only with the specified VLAN ID. + +.TP +.BI src_vni " SRC_VNI" +the source VNI Network Identifier for the operation. Match entries only with +the specified source VNI. + +.TP +.BI proto " PROTO" +the routing protocol identifier for the operation. Match entries only with the +specified routing protocol. Can be a number or a string from the file +/etc/iproute2/rt_protos. + +.TP +.B [no]permanent +if specified then only permanent entries will be deleted or respectively if +"no" is prepended then only non-permanent (temp) entries will be deleted. + +.TP +.BI dst " IPADDR" +the IP address of the destination VXLAN tunnel endpoint where the multicast +receivers reside. Match entries only with the specified destination IP. + +.TP +.BI dst_port " DST_PORT" +the UDP destination port number to use to connect to the remote VXLAN tunnel +endpoint. Match entries only with the specified destination port number. + +.TP +.BI vni " VNI" +the VXLAN VNI Network Identifier to use to connect to the remote VXLAN tunnel +endpoint. Match entries only with the specified destination VNI. + .SH bridge vlan - VLAN filter list .B vlan |