Skip to content

Commit 6afaae6

Browse files
idoschkuba-moo
authored andcommitted
bridge: mcast: Allow user space to add (*, G) with a source list and filter mode
Add new netlink attributes to the RTM_NEWMDB request that allow user space to add (*, G) with a source list and filter mode. The RTM_NEWMDB message can already dump such entries (created by the kernel) so there is no need to add dump support. However, the message contains a different set of attributes depending if it is a request or a response. The naming and structure of the new attributes try to follow the existing ones used in the response. Request: [ struct nlmsghdr ] [ struct br_port_msg ] [ MDBA_SET_ENTRY ] struct br_mdb_entry [ MDBA_SET_ENTRY_ATTRS ] [ MDBE_ATTR_SOURCE ] struct in_addr / struct in6_addr [ MDBE_ATTR_SRC_LIST ] // new [ MDBE_SRC_LIST_ENTRY ] [ MDBE_SRCATTR_ADDRESS ] struct in_addr / struct in6_addr [ ...] [ MDBE_ATTR_GROUP_MODE ] // new u8 Response: [ struct nlmsghdr ] [ struct br_port_msg ] [ MDBA_MDB ] [ MDBA_MDB_ENTRY ] [ MDBA_MDB_ENTRY_INFO ] struct br_mdb_entry [ MDBA_MDB_EATTR_TIMER ] u32 [ MDBA_MDB_EATTR_SOURCE ] struct in_addr / struct in6_addr [ MDBA_MDB_EATTR_RTPROT ] u8 [ MDBA_MDB_EATTR_SRC_LIST ] [ MDBA_MDB_SRCLIST_ENTRY ] [ MDBA_MDB_SRCATTR_ADDRESS ] struct in_addr / struct in6_addr [ MDBA_MDB_SRCATTR_TIMER ] u8 [...] [ MDBA_MDB_EATTR_GROUP_MODE ] u8 Signed-off-by: Ido Schimmel <[email protected]> Acked-by: Nikolay Aleksandrov <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent b1c8fec commit 6afaae6

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

include/uapi/linux/if_bridge.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,10 +723,30 @@ enum {
723723
enum {
724724
MDBE_ATTR_UNSPEC,
725725
MDBE_ATTR_SOURCE,
726+
MDBE_ATTR_SRC_LIST,
727+
MDBE_ATTR_GROUP_MODE,
726728
__MDBE_ATTR_MAX,
727729
};
728730
#define MDBE_ATTR_MAX (__MDBE_ATTR_MAX - 1)
729731

732+
/* per mdb entry source */
733+
enum {
734+
MDBE_SRC_LIST_UNSPEC,
735+
MDBE_SRC_LIST_ENTRY,
736+
__MDBE_SRC_LIST_MAX,
737+
};
738+
#define MDBE_SRC_LIST_MAX (__MDBE_SRC_LIST_MAX - 1)
739+
740+
/* per mdb entry per source attributes
741+
* these are embedded in MDBE_SRC_LIST_ENTRY
742+
*/
743+
enum {
744+
MDBE_SRCATTR_UNSPEC,
745+
MDBE_SRCATTR_ADDRESS,
746+
__MDBE_SRCATTR_MAX,
747+
};
748+
#define MDBE_SRCATTR_MAX (__MDBE_SRCATTR_MAX - 1)
749+
730750
/* Embedded inside LINK_XSTATS_TYPE_BRIDGE */
731751
enum {
732752
BRIDGE_XSTATS_UNSPEC,

net/bridge/br_mdb.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,10 +663,25 @@ void br_rtr_notify(struct net_device *dev, struct net_bridge_mcast_port *pmctx,
663663
rtnl_set_sk_err(net, RTNLGRP_MDB, err);
664664
}
665665

666+
static const struct nla_policy
667+
br_mdbe_src_list_entry_pol[MDBE_SRCATTR_MAX + 1] = {
668+
[MDBE_SRCATTR_ADDRESS] = NLA_POLICY_RANGE(NLA_BINARY,
669+
sizeof(struct in_addr),
670+
sizeof(struct in6_addr)),
671+
};
672+
673+
static const struct nla_policy
674+
br_mdbe_src_list_pol[MDBE_SRC_LIST_MAX + 1] = {
675+
[MDBE_SRC_LIST_ENTRY] = NLA_POLICY_NESTED(br_mdbe_src_list_entry_pol),
676+
};
677+
666678
static const struct nla_policy br_mdbe_attrs_pol[MDBE_ATTR_MAX + 1] = {
667679
[MDBE_ATTR_SOURCE] = NLA_POLICY_RANGE(NLA_BINARY,
668680
sizeof(struct in_addr),
669681
sizeof(struct in6_addr)),
682+
[MDBE_ATTR_GROUP_MODE] = NLA_POLICY_RANGE(NLA_U8, MCAST_EXCLUDE,
683+
MCAST_INCLUDE),
684+
[MDBE_ATTR_SRC_LIST] = NLA_POLICY_NESTED(br_mdbe_src_list_pol),
670685
};
671686

672687
static bool is_valid_mdb_entry(struct br_mdb_entry *entry,
@@ -1051,6 +1066,76 @@ static int __br_mdb_add(const struct br_mdb_config *cfg,
10511066
return ret;
10521067
}
10531068

1069+
static int br_mdb_config_src_entry_init(struct nlattr *src_entry,
1070+
struct br_mdb_src_entry *src,
1071+
__be16 proto,
1072+
struct netlink_ext_ack *extack)
1073+
{
1074+
struct nlattr *tb[MDBE_SRCATTR_MAX + 1];
1075+
int err;
1076+
1077+
err = nla_parse_nested(tb, MDBE_SRCATTR_MAX, src_entry,
1078+
br_mdbe_src_list_entry_pol, extack);
1079+
if (err)
1080+
return err;
1081+
1082+
if (NL_REQ_ATTR_CHECK(extack, src_entry, tb, MDBE_SRCATTR_ADDRESS))
1083+
return -EINVAL;
1084+
1085+
if (!is_valid_mdb_source(tb[MDBE_SRCATTR_ADDRESS], proto, extack))
1086+
return -EINVAL;
1087+
1088+
src->addr.proto = proto;
1089+
nla_memcpy(&src->addr.src, tb[MDBE_SRCATTR_ADDRESS],
1090+
nla_len(tb[MDBE_SRCATTR_ADDRESS]));
1091+
1092+
return 0;
1093+
}
1094+
1095+
static int br_mdb_config_src_list_init(struct nlattr *src_list,
1096+
struct br_mdb_config *cfg,
1097+
struct netlink_ext_ack *extack)
1098+
{
1099+
struct nlattr *src_entry;
1100+
int rem, err;
1101+
int i = 0;
1102+
1103+
nla_for_each_nested(src_entry, src_list, rem)
1104+
cfg->num_src_entries++;
1105+
1106+
if (cfg->num_src_entries >= PG_SRC_ENT_LIMIT) {
1107+
NL_SET_ERR_MSG_FMT_MOD(extack, "Exceeded maximum number of source entries (%u)",
1108+
PG_SRC_ENT_LIMIT - 1);
1109+
return -EINVAL;
1110+
}
1111+
1112+
cfg->src_entries = kcalloc(cfg->num_src_entries,
1113+
sizeof(struct br_mdb_src_entry), GFP_KERNEL);
1114+
if (!cfg->src_entries)
1115+
return -ENOMEM;
1116+
1117+
nla_for_each_nested(src_entry, src_list, rem) {
1118+
err = br_mdb_config_src_entry_init(src_entry,
1119+
&cfg->src_entries[i],
1120+
cfg->entry->addr.proto,
1121+
extack);
1122+
if (err)
1123+
goto err_src_entry_init;
1124+
i++;
1125+
}
1126+
1127+
return 0;
1128+
1129+
err_src_entry_init:
1130+
kfree(cfg->src_entries);
1131+
return err;
1132+
}
1133+
1134+
static void br_mdb_config_src_list_fini(struct br_mdb_config *cfg)
1135+
{
1136+
kfree(cfg->src_entries);
1137+
}
1138+
10541139
static int br_mdb_config_attrs_init(struct nlattr *set_attrs,
10551140
struct br_mdb_config *cfg,
10561141
struct netlink_ext_ack *extack)
@@ -1070,6 +1155,44 @@ static int br_mdb_config_attrs_init(struct nlattr *set_attrs,
10701155

10711156
__mdb_entry_to_br_ip(cfg->entry, &cfg->group, mdb_attrs);
10721157

1158+
if (mdb_attrs[MDBE_ATTR_GROUP_MODE]) {
1159+
if (!cfg->p) {
1160+
NL_SET_ERR_MSG_MOD(extack, "Filter mode cannot be set for host groups");
1161+
return -EINVAL;
1162+
}
1163+
if (!br_multicast_is_star_g(&cfg->group)) {
1164+
NL_SET_ERR_MSG_MOD(extack, "Filter mode can only be set for (*, G) entries");
1165+
return -EINVAL;
1166+
}
1167+
cfg->filter_mode = nla_get_u8(mdb_attrs[MDBE_ATTR_GROUP_MODE]);
1168+
} else {
1169+
cfg->filter_mode = MCAST_EXCLUDE;
1170+
}
1171+
1172+
if (mdb_attrs[MDBE_ATTR_SRC_LIST]) {
1173+
if (!cfg->p) {
1174+
NL_SET_ERR_MSG_MOD(extack, "Source list cannot be set for host groups");
1175+
return -EINVAL;
1176+
}
1177+
if (!br_multicast_is_star_g(&cfg->group)) {
1178+
NL_SET_ERR_MSG_MOD(extack, "Source list can only be set for (*, G) entries");
1179+
return -EINVAL;
1180+
}
1181+
if (!mdb_attrs[MDBE_ATTR_GROUP_MODE]) {
1182+
NL_SET_ERR_MSG_MOD(extack, "Source list cannot be set without filter mode");
1183+
return -EINVAL;
1184+
}
1185+
err = br_mdb_config_src_list_init(mdb_attrs[MDBE_ATTR_SRC_LIST],
1186+
cfg, extack);
1187+
if (err)
1188+
return err;
1189+
}
1190+
1191+
if (!cfg->num_src_entries && cfg->filter_mode == MCAST_INCLUDE) {
1192+
NL_SET_ERR_MSG_MOD(extack, "Cannot add (*, G) INCLUDE with an empty source list");
1193+
return -EINVAL;
1194+
}
1195+
10731196
return 0;
10741197
}
10751198

@@ -1162,6 +1285,11 @@ static int br_mdb_config_init(struct net *net, const struct nlmsghdr *nlh,
11621285
return 0;
11631286
}
11641287

1288+
static void br_mdb_config_fini(struct br_mdb_config *cfg)
1289+
{
1290+
br_mdb_config_src_list_fini(cfg);
1291+
}
1292+
11651293
static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh,
11661294
struct netlink_ext_ack *extack)
11671295
{
@@ -1220,6 +1348,7 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh,
12201348
}
12211349

12221350
out:
1351+
br_mdb_config_fini(&cfg);
12231352
return err;
12241353
}
12251354

@@ -1295,6 +1424,7 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
12951424
err = __br_mdb_del(&cfg);
12961425
}
12971426

1427+
br_mdb_config_fini(&cfg);
12981428
return err;
12991429
}
13001430

0 commit comments

Comments
 (0)