br_vlan_options.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright (c) 2020, Nikolay Aleksandrov <[email protected]>
  3. #include <linux/kernel.h>
  4. #include <linux/netdevice.h>
  5. #include <linux/rtnetlink.h>
  6. #include <linux/slab.h>
  7. #include <net/ip_tunnels.h>
  8. #include "br_private.h"
  9. #include "br_private_tunnel.h"
  10. static bool __vlan_tun_put(struct sk_buff *skb, const struct net_bridge_vlan *v)
  11. {
  12. __be32 tid = tunnel_id_to_key32(v->tinfo.tunnel_id);
  13. struct nlattr *nest;
  14. if (!v->tinfo.tunnel_dst)
  15. return true;
  16. nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY_TUNNEL_INFO);
  17. if (!nest)
  18. return false;
  19. if (nla_put_u32(skb, BRIDGE_VLANDB_TINFO_ID, be32_to_cpu(tid))) {
  20. nla_nest_cancel(skb, nest);
  21. return false;
  22. }
  23. nla_nest_end(skb, nest);
  24. return true;
  25. }
  26. static bool __vlan_tun_can_enter_range(const struct net_bridge_vlan *v_curr,
  27. const struct net_bridge_vlan *range_end)
  28. {
  29. return (!v_curr->tinfo.tunnel_dst && !range_end->tinfo.tunnel_dst) ||
  30. vlan_tunid_inrange(v_curr, range_end);
  31. }
  32. /* check if the options' state of v_curr allow it to enter the range */
  33. bool br_vlan_opts_eq_range(const struct net_bridge_vlan *v_curr,
  34. const struct net_bridge_vlan *range_end)
  35. {
  36. u8 range_mc_rtr = br_vlan_multicast_router(range_end);
  37. u8 curr_mc_rtr = br_vlan_multicast_router(v_curr);
  38. return v_curr->state == range_end->state &&
  39. __vlan_tun_can_enter_range(v_curr, range_end) &&
  40. curr_mc_rtr == range_mc_rtr;
  41. }
  42. bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v)
  43. {
  44. if (nla_put_u8(skb, BRIDGE_VLANDB_ENTRY_STATE, br_vlan_get_state(v)) ||
  45. !__vlan_tun_put(skb, v))
  46. return false;
  47. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  48. if (nla_put_u8(skb, BRIDGE_VLANDB_ENTRY_MCAST_ROUTER,
  49. br_vlan_multicast_router(v)))
  50. return false;
  51. #endif
  52. return true;
  53. }
  54. size_t br_vlan_opts_nl_size(void)
  55. {
  56. return nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_STATE */
  57. + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY_TUNNEL_INFO */
  58. + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_TINFO_ID */
  59. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  60. + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_MCAST_ROUTER */
  61. #endif
  62. + 0;
  63. }
  64. static int br_vlan_modify_state(struct net_bridge_vlan_group *vg,
  65. struct net_bridge_vlan *v,
  66. u8 state,
  67. bool *changed,
  68. struct netlink_ext_ack *extack)
  69. {
  70. struct net_bridge *br;
  71. ASSERT_RTNL();
  72. if (state > BR_STATE_BLOCKING) {
  73. NL_SET_ERR_MSG_MOD(extack, "Invalid vlan state");
  74. return -EINVAL;
  75. }
  76. if (br_vlan_is_brentry(v))
  77. br = v->br;
  78. else
  79. br = v->port->br;
  80. if (br->stp_enabled == BR_KERNEL_STP) {
  81. NL_SET_ERR_MSG_MOD(extack, "Can't modify vlan state when using kernel STP");
  82. return -EBUSY;
  83. }
  84. if (br_opt_get(br, BROPT_MST_ENABLED)) {
  85. NL_SET_ERR_MSG_MOD(extack, "Can't modify vlan state directly when MST is enabled");
  86. return -EBUSY;
  87. }
  88. if (v->state == state)
  89. return 0;
  90. if (v->vid == br_get_pvid(vg))
  91. br_vlan_set_pvid_state(vg, state);
  92. br_vlan_set_state(v, state);
  93. *changed = true;
  94. return 0;
  95. }
  96. static const struct nla_policy br_vlandb_tinfo_pol[BRIDGE_VLANDB_TINFO_MAX + 1] = {
  97. [BRIDGE_VLANDB_TINFO_ID] = { .type = NLA_U32 },
  98. [BRIDGE_VLANDB_TINFO_CMD] = { .type = NLA_U32 },
  99. };
  100. static int br_vlan_modify_tunnel(const struct net_bridge_port *p,
  101. struct net_bridge_vlan *v,
  102. struct nlattr **tb,
  103. bool *changed,
  104. struct netlink_ext_ack *extack)
  105. {
  106. struct nlattr *tun_tb[BRIDGE_VLANDB_TINFO_MAX + 1], *attr;
  107. struct bridge_vlan_info *vinfo;
  108. u32 tun_id = 0;
  109. int cmd, err;
  110. if (!p) {
  111. NL_SET_ERR_MSG_MOD(extack, "Can't modify tunnel mapping of non-port vlans");
  112. return -EINVAL;
  113. }
  114. if (!(p->flags & BR_VLAN_TUNNEL)) {
  115. NL_SET_ERR_MSG_MOD(extack, "Port doesn't have tunnel flag set");
  116. return -EINVAL;
  117. }
  118. attr = tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO];
  119. err = nla_parse_nested(tun_tb, BRIDGE_VLANDB_TINFO_MAX, attr,
  120. br_vlandb_tinfo_pol, extack);
  121. if (err)
  122. return err;
  123. if (!tun_tb[BRIDGE_VLANDB_TINFO_CMD]) {
  124. NL_SET_ERR_MSG_MOD(extack, "Missing tunnel command attribute");
  125. return -ENOENT;
  126. }
  127. cmd = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_CMD]);
  128. switch (cmd) {
  129. case RTM_SETLINK:
  130. if (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) {
  131. NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute");
  132. return -ENOENT;
  133. }
  134. /* when working on vlan ranges this is the starting tunnel id */
  135. tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]);
  136. /* vlan info attr is guaranteed by br_vlan_rtm_process_one */
  137. vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]);
  138. /* tunnel ids are mapped to each vlan in increasing order,
  139. * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the
  140. * current vlan, so we compute: tun_id + v - vinfo->vid
  141. */
  142. tun_id += v->vid - vinfo->vid;
  143. break;
  144. case RTM_DELLINK:
  145. break;
  146. default:
  147. NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel command");
  148. return -EINVAL;
  149. }
  150. return br_vlan_tunnel_info(p, cmd, v->vid, tun_id, changed);
  151. }
  152. static int br_vlan_process_one_opts(const struct net_bridge *br,
  153. const struct net_bridge_port *p,
  154. struct net_bridge_vlan_group *vg,
  155. struct net_bridge_vlan *v,
  156. struct nlattr **tb,
  157. bool *changed,
  158. struct netlink_ext_ack *extack)
  159. {
  160. int err;
  161. *changed = false;
  162. if (tb[BRIDGE_VLANDB_ENTRY_STATE]) {
  163. u8 state = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_STATE]);
  164. err = br_vlan_modify_state(vg, v, state, changed, extack);
  165. if (err)
  166. return err;
  167. }
  168. if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]) {
  169. err = br_vlan_modify_tunnel(p, v, tb, changed, extack);
  170. if (err)
  171. return err;
  172. }
  173. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  174. if (tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]) {
  175. u8 val;
  176. val = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]);
  177. err = br_multicast_set_vlan_router(v, val);
  178. if (err)
  179. return err;
  180. *changed = true;
  181. }
  182. #endif
  183. return 0;
  184. }
  185. int br_vlan_process_options(const struct net_bridge *br,
  186. const struct net_bridge_port *p,
  187. struct net_bridge_vlan *range_start,
  188. struct net_bridge_vlan *range_end,
  189. struct nlattr **tb,
  190. struct netlink_ext_ack *extack)
  191. {
  192. struct net_bridge_vlan *v, *curr_start = NULL, *curr_end = NULL;
  193. struct net_bridge_vlan_group *vg;
  194. int vid, err = 0;
  195. u16 pvid;
  196. if (p)
  197. vg = nbp_vlan_group(p);
  198. else
  199. vg = br_vlan_group(br);
  200. if (!range_start || !br_vlan_should_use(range_start)) {
  201. NL_SET_ERR_MSG_MOD(extack, "Vlan range start doesn't exist, can't process options");
  202. return -ENOENT;
  203. }
  204. if (!range_end || !br_vlan_should_use(range_end)) {
  205. NL_SET_ERR_MSG_MOD(extack, "Vlan range end doesn't exist, can't process options");
  206. return -ENOENT;
  207. }
  208. pvid = br_get_pvid(vg);
  209. for (vid = range_start->vid; vid <= range_end->vid; vid++) {
  210. bool changed = false;
  211. v = br_vlan_find(vg, vid);
  212. if (!v || !br_vlan_should_use(v)) {
  213. NL_SET_ERR_MSG_MOD(extack, "Vlan in range doesn't exist, can't process options");
  214. err = -ENOENT;
  215. break;
  216. }
  217. err = br_vlan_process_one_opts(br, p, vg, v, tb, &changed,
  218. extack);
  219. if (err)
  220. break;
  221. if (changed) {
  222. /* vlan options changed, check for range */
  223. if (!curr_start) {
  224. curr_start = v;
  225. curr_end = v;
  226. continue;
  227. }
  228. if (v->vid == pvid ||
  229. !br_vlan_can_enter_range(v, curr_end)) {
  230. br_vlan_notify(br, p, curr_start->vid,
  231. curr_end->vid, RTM_NEWVLAN);
  232. curr_start = v;
  233. }
  234. curr_end = v;
  235. } else {
  236. /* nothing changed and nothing to notify yet */
  237. if (!curr_start)
  238. continue;
  239. br_vlan_notify(br, p, curr_start->vid, curr_end->vid,
  240. RTM_NEWVLAN);
  241. curr_start = NULL;
  242. curr_end = NULL;
  243. }
  244. }
  245. if (curr_start)
  246. br_vlan_notify(br, p, curr_start->vid, curr_end->vid,
  247. RTM_NEWVLAN);
  248. return err;
  249. }
  250. bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,
  251. const struct net_bridge_vlan *r_end)
  252. {
  253. return v_curr->vid - r_end->vid == 1 &&
  254. v_curr->msti == r_end->msti &&
  255. ((v_curr->priv_flags ^ r_end->priv_flags) &
  256. BR_VLFLAG_GLOBAL_MCAST_ENABLED) == 0 &&
  257. br_multicast_ctx_options_equal(&v_curr->br_mcast_ctx,
  258. &r_end->br_mcast_ctx);
  259. }
  260. bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
  261. const struct net_bridge_vlan *v_opts)
  262. {
  263. struct nlattr *nest2 __maybe_unused;
  264. u64 clockval __maybe_unused;
  265. struct nlattr *nest;
  266. nest = nla_nest_start(skb, BRIDGE_VLANDB_GLOBAL_OPTIONS);
  267. if (!nest)
  268. return false;
  269. if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_ID, vid))
  270. goto out_err;
  271. if (vid_range && vid < vid_range &&
  272. nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_RANGE, vid_range))
  273. goto out_err;
  274. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  275. if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING,
  276. !!(v_opts->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED)) ||
  277. nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION,
  278. v_opts->br_mcast_ctx.multicast_igmp_version) ||
  279. nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT,
  280. v_opts->br_mcast_ctx.multicast_last_member_count) ||
  281. nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT,
  282. v_opts->br_mcast_ctx.multicast_startup_query_count) ||
  283. nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
  284. v_opts->br_mcast_ctx.multicast_querier) ||
  285. br_multicast_dump_querier_state(skb, &v_opts->br_mcast_ctx,
  286. BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE))
  287. goto out_err;
  288. clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_last_member_interval);
  289. if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL,
  290. clockval, BRIDGE_VLANDB_GOPTS_PAD))
  291. goto out_err;
  292. clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_membership_interval);
  293. if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL,
  294. clockval, BRIDGE_VLANDB_GOPTS_PAD))
  295. goto out_err;
  296. clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_querier_interval);
  297. if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL,
  298. clockval, BRIDGE_VLANDB_GOPTS_PAD))
  299. goto out_err;
  300. clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_query_interval);
  301. if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL,
  302. clockval, BRIDGE_VLANDB_GOPTS_PAD))
  303. goto out_err;
  304. clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_query_response_interval);
  305. if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL,
  306. clockval, BRIDGE_VLANDB_GOPTS_PAD))
  307. goto out_err;
  308. clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_startup_query_interval);
  309. if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL,
  310. clockval, BRIDGE_VLANDB_GOPTS_PAD))
  311. goto out_err;
  312. if (br_rports_have_mc_router(&v_opts->br_mcast_ctx)) {
  313. nest2 = nla_nest_start(skb,
  314. BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS);
  315. if (!nest2)
  316. goto out_err;
  317. rcu_read_lock();
  318. if (br_rports_fill_info(skb, &v_opts->br_mcast_ctx)) {
  319. rcu_read_unlock();
  320. nla_nest_cancel(skb, nest2);
  321. goto out_err;
  322. }
  323. rcu_read_unlock();
  324. nla_nest_end(skb, nest2);
  325. }
  326. #if IS_ENABLED(CONFIG_IPV6)
  327. if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION,
  328. v_opts->br_mcast_ctx.multicast_mld_version))
  329. goto out_err;
  330. #endif
  331. #endif
  332. if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_MSTI, v_opts->msti))
  333. goto out_err;
  334. nla_nest_end(skb, nest);
  335. return true;
  336. out_err:
  337. nla_nest_cancel(skb, nest);
  338. return false;
  339. }
  340. static size_t rtnl_vlan_global_opts_nlmsg_size(const struct net_bridge_vlan *v)
  341. {
  342. return NLMSG_ALIGN(sizeof(struct br_vlan_msg))
  343. + nla_total_size(0) /* BRIDGE_VLANDB_GLOBAL_OPTIONS */
  344. + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_ID */
  345. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  346. + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING */
  347. + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION */
  348. + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION */
  349. + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT */
  350. + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT */
  351. + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL */
  352. + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL */
  353. + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL */
  354. + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL */
  355. + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL */
  356. + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL */
  357. + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */
  358. + br_multicast_querier_state_size() /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE */
  359. + nla_total_size(0) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
  360. + br_rports_size(&v->br_mcast_ctx) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
  361. #endif
  362. + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_MSTI */
  363. + nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */
  364. }
  365. static void br_vlan_global_opts_notify(const struct net_bridge *br,
  366. u16 vid, u16 vid_range)
  367. {
  368. struct net_bridge_vlan *v;
  369. struct br_vlan_msg *bvm;
  370. struct nlmsghdr *nlh;
  371. struct sk_buff *skb;
  372. int err = -ENOBUFS;
  373. /* right now notifications are done only with rtnl held */
  374. ASSERT_RTNL();
  375. /* need to find the vlan due to flags/options */
  376. v = br_vlan_find(br_vlan_group(br), vid);
  377. if (!v)
  378. return;
  379. skb = nlmsg_new(rtnl_vlan_global_opts_nlmsg_size(v), GFP_KERNEL);
  380. if (!skb)
  381. goto out_err;
  382. err = -EMSGSIZE;
  383. nlh = nlmsg_put(skb, 0, 0, RTM_NEWVLAN, sizeof(*bvm), 0);
  384. if (!nlh)
  385. goto out_err;
  386. bvm = nlmsg_data(nlh);
  387. memset(bvm, 0, sizeof(*bvm));
  388. bvm->family = AF_BRIDGE;
  389. bvm->ifindex = br->dev->ifindex;
  390. if (!br_vlan_global_opts_fill(skb, vid, vid_range, v))
  391. goto out_err;
  392. nlmsg_end(skb, nlh);
  393. rtnl_notify(skb, dev_net(br->dev), 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL);
  394. return;
  395. out_err:
  396. rtnl_set_sk_err(dev_net(br->dev), RTNLGRP_BRVLAN, err);
  397. kfree_skb(skb);
  398. }
  399. static int br_vlan_process_global_one_opts(const struct net_bridge *br,
  400. struct net_bridge_vlan_group *vg,
  401. struct net_bridge_vlan *v,
  402. struct nlattr **tb,
  403. bool *changed,
  404. struct netlink_ext_ack *extack)
  405. {
  406. int err __maybe_unused;
  407. *changed = false;
  408. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  409. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]) {
  410. u8 mc_snooping;
  411. mc_snooping = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]);
  412. if (br_multicast_toggle_global_vlan(v, !!mc_snooping))
  413. *changed = true;
  414. }
  415. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]) {
  416. u8 ver;
  417. ver = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]);
  418. err = br_multicast_set_igmp_version(&v->br_mcast_ctx, ver);
  419. if (err)
  420. return err;
  421. *changed = true;
  422. }
  423. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT]) {
  424. u32 cnt;
  425. cnt = nla_get_u32(tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT]);
  426. v->br_mcast_ctx.multicast_last_member_count = cnt;
  427. *changed = true;
  428. }
  429. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]) {
  430. u32 cnt;
  431. cnt = nla_get_u32(tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]);
  432. v->br_mcast_ctx.multicast_startup_query_count = cnt;
  433. *changed = true;
  434. }
  435. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]) {
  436. u64 val;
  437. val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]);
  438. v->br_mcast_ctx.multicast_last_member_interval = clock_t_to_jiffies(val);
  439. *changed = true;
  440. }
  441. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]) {
  442. u64 val;
  443. val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]);
  444. v->br_mcast_ctx.multicast_membership_interval = clock_t_to_jiffies(val);
  445. *changed = true;
  446. }
  447. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]) {
  448. u64 val;
  449. val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]);
  450. v->br_mcast_ctx.multicast_querier_interval = clock_t_to_jiffies(val);
  451. *changed = true;
  452. }
  453. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]) {
  454. u64 val;
  455. val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]);
  456. br_multicast_set_query_intvl(&v->br_mcast_ctx, val);
  457. *changed = true;
  458. }
  459. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]) {
  460. u64 val;
  461. val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]);
  462. v->br_mcast_ctx.multicast_query_response_interval = clock_t_to_jiffies(val);
  463. *changed = true;
  464. }
  465. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]) {
  466. u64 val;
  467. val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]);
  468. br_multicast_set_startup_query_intvl(&v->br_mcast_ctx, val);
  469. *changed = true;
  470. }
  471. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]) {
  472. u8 val;
  473. val = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]);
  474. err = br_multicast_set_querier(&v->br_mcast_ctx, val);
  475. if (err)
  476. return err;
  477. *changed = true;
  478. }
  479. #if IS_ENABLED(CONFIG_IPV6)
  480. if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) {
  481. u8 ver;
  482. ver = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]);
  483. err = br_multicast_set_mld_version(&v->br_mcast_ctx, ver);
  484. if (err)
  485. return err;
  486. *changed = true;
  487. }
  488. #endif
  489. #endif
  490. if (tb[BRIDGE_VLANDB_GOPTS_MSTI]) {
  491. u16 msti;
  492. msti = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_MSTI]);
  493. err = br_mst_vlan_set_msti(v, msti);
  494. if (err)
  495. return err;
  496. *changed = true;
  497. }
  498. return 0;
  499. }
  500. static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = {
  501. [BRIDGE_VLANDB_GOPTS_ID] = { .type = NLA_U16 },
  502. [BRIDGE_VLANDB_GOPTS_RANGE] = { .type = NLA_U16 },
  503. [BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING] = { .type = NLA_U8 },
  504. [BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION] = { .type = NLA_U8 },
  505. [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL] = { .type = NLA_U64 },
  506. [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER] = { .type = NLA_U8 },
  507. [BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION] = { .type = NLA_U8 },
  508. [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 },
  509. [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT] = { .type = NLA_U32 },
  510. [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL] = { .type = NLA_U64 },
  511. [BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL] = { .type = NLA_U64 },
  512. [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL] = { .type = NLA_U64 },
  513. [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL] = { .type = NLA_U64 },
  514. [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL] = { .type = NLA_U64 },
  515. [BRIDGE_VLANDB_GOPTS_MSTI] = NLA_POLICY_MAX(NLA_U16, VLAN_N_VID - 1),
  516. };
  517. int br_vlan_rtm_process_global_options(struct net_device *dev,
  518. const struct nlattr *attr,
  519. int cmd,
  520. struct netlink_ext_ack *extack)
  521. {
  522. struct net_bridge_vlan *v, *curr_start = NULL, *curr_end = NULL;
  523. struct nlattr *tb[BRIDGE_VLANDB_GOPTS_MAX + 1];
  524. struct net_bridge_vlan_group *vg;
  525. u16 vid, vid_range = 0;
  526. struct net_bridge *br;
  527. int err = 0;
  528. if (cmd != RTM_NEWVLAN) {
  529. NL_SET_ERR_MSG_MOD(extack, "Global vlan options support only set operation");
  530. return -EINVAL;
  531. }
  532. if (!netif_is_bridge_master(dev)) {
  533. NL_SET_ERR_MSG_MOD(extack, "Global vlan options can only be set on bridge device");
  534. return -EINVAL;
  535. }
  536. br = netdev_priv(dev);
  537. vg = br_vlan_group(br);
  538. if (WARN_ON(!vg))
  539. return -ENODEV;
  540. err = nla_parse_nested(tb, BRIDGE_VLANDB_GOPTS_MAX, attr,
  541. br_vlan_db_gpol, extack);
  542. if (err)
  543. return err;
  544. if (!tb[BRIDGE_VLANDB_GOPTS_ID]) {
  545. NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry id");
  546. return -EINVAL;
  547. }
  548. vid = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_ID]);
  549. if (!br_vlan_valid_id(vid, extack))
  550. return -EINVAL;
  551. if (tb[BRIDGE_VLANDB_GOPTS_RANGE]) {
  552. vid_range = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_RANGE]);
  553. if (!br_vlan_valid_id(vid_range, extack))
  554. return -EINVAL;
  555. if (vid >= vid_range) {
  556. NL_SET_ERR_MSG_MOD(extack, "End vlan id is less than or equal to start vlan id");
  557. return -EINVAL;
  558. }
  559. } else {
  560. vid_range = vid;
  561. }
  562. for (; vid <= vid_range; vid++) {
  563. bool changed = false;
  564. v = br_vlan_find(vg, vid);
  565. if (!v) {
  566. NL_SET_ERR_MSG_MOD(extack, "Vlan in range doesn't exist, can't process global options");
  567. err = -ENOENT;
  568. break;
  569. }
  570. err = br_vlan_process_global_one_opts(br, vg, v, tb, &changed,
  571. extack);
  572. if (err)
  573. break;
  574. if (changed) {
  575. /* vlan options changed, check for range */
  576. if (!curr_start) {
  577. curr_start = v;
  578. curr_end = v;
  579. continue;
  580. }
  581. if (!br_vlan_global_opts_can_enter_range(v, curr_end)) {
  582. br_vlan_global_opts_notify(br, curr_start->vid,
  583. curr_end->vid);
  584. curr_start = v;
  585. }
  586. curr_end = v;
  587. } else {
  588. /* nothing changed and nothing to notify yet */
  589. if (!curr_start)
  590. continue;
  591. br_vlan_global_opts_notify(br, curr_start->vid,
  592. curr_end->vid);
  593. curr_start = NULL;
  594. curr_end = NULL;
  595. }
  596. }
  597. if (curr_start)
  598. br_vlan_global_opts_notify(br, curr_start->vid, curr_end->vid);
  599. return err;
  600. }