br_mst.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Bridge Multiple Spanning Tree Support
  4. *
  5. * Authors:
  6. * Tobias Waldekranz <tobias@waldekranz.com>
  7. */
  8. #include <linux/kernel.h>
  9. #include <net/switchdev.h>
  10. #include "br_private.h"
  11. DEFINE_STATIC_KEY_FALSE(br_mst_used);
  12. bool br_mst_enabled(const struct net_device *dev)
  13. {
  14. if (!netif_is_bridge_master(dev))
  15. return false;
  16. return br_opt_get(netdev_priv(dev), BROPT_MST_ENABLED);
  17. }
  18. EXPORT_SYMBOL_GPL(br_mst_enabled);
  19. int br_mst_get_info(const struct net_device *dev, u16 msti, unsigned long *vids)
  20. {
  21. const struct net_bridge_vlan_group *vg;
  22. const struct net_bridge_vlan *v;
  23. const struct net_bridge *br;
  24. ASSERT_RTNL();
  25. if (!netif_is_bridge_master(dev))
  26. return -EINVAL;
  27. br = netdev_priv(dev);
  28. if (!br_opt_get(br, BROPT_MST_ENABLED))
  29. return -EINVAL;
  30. vg = br_vlan_group(br);
  31. list_for_each_entry(v, &vg->vlan_list, vlist) {
  32. if (v->msti == msti)
  33. __set_bit(v->vid, vids);
  34. }
  35. return 0;
  36. }
  37. EXPORT_SYMBOL_GPL(br_mst_get_info);
  38. int br_mst_get_state(const struct net_device *dev, u16 msti, u8 *state)
  39. {
  40. const struct net_bridge_port *p = NULL;
  41. const struct net_bridge_vlan_group *vg;
  42. const struct net_bridge_vlan *v;
  43. ASSERT_RTNL();
  44. p = br_port_get_check_rtnl(dev);
  45. if (!p || !br_opt_get(p->br, BROPT_MST_ENABLED))
  46. return -EINVAL;
  47. vg = nbp_vlan_group(p);
  48. list_for_each_entry(v, &vg->vlan_list, vlist) {
  49. if (v->brvlan->msti == msti) {
  50. *state = v->state;
  51. return 0;
  52. }
  53. }
  54. return -ENOENT;
  55. }
  56. EXPORT_SYMBOL_GPL(br_mst_get_state);
  57. static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg,
  58. struct net_bridge_vlan *v,
  59. u8 state)
  60. {
  61. if (br_vlan_get_state(v) == state)
  62. return;
  63. br_vlan_set_state(v, state);
  64. if (v->vid == vg->pvid)
  65. br_vlan_set_pvid_state(vg, state);
  66. }
  67. int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
  68. struct netlink_ext_ack *extack)
  69. {
  70. struct switchdev_attr attr = {
  71. .id = SWITCHDEV_ATTR_ID_PORT_MST_STATE,
  72. .orig_dev = p->dev,
  73. .u.mst_state = {
  74. .msti = msti,
  75. .state = state,
  76. },
  77. };
  78. struct net_bridge_vlan_group *vg;
  79. struct net_bridge_vlan *v;
  80. int err = 0;
  81. rcu_read_lock();
  82. vg = nbp_vlan_group_rcu(p);
  83. if (!vg)
  84. goto out;
  85. /* MSTI 0 (CST) state changes are notified via the regular
  86. * SWITCHDEV_ATTR_ID_PORT_STP_STATE.
  87. */
  88. if (msti) {
  89. err = switchdev_port_attr_set(p->dev, &attr, extack);
  90. if (err && err != -EOPNOTSUPP)
  91. goto out;
  92. }
  93. err = 0;
  94. list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
  95. if (v->brvlan->msti != msti)
  96. continue;
  97. br_mst_vlan_set_state(vg, v, state);
  98. }
  99. out:
  100. rcu_read_unlock();
  101. return err;
  102. }
  103. static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti)
  104. {
  105. struct net_bridge_vlan_group *vg = nbp_vlan_group(pv->port);
  106. struct net_bridge_vlan *v;
  107. list_for_each_entry(v, &vg->vlan_list, vlist) {
  108. /* If this port already has a defined state in this
  109. * MSTI (through some other VLAN membership), inherit
  110. * it.
  111. */
  112. if (v != pv && v->brvlan->msti == msti) {
  113. br_mst_vlan_set_state(vg, pv, v->state);
  114. return;
  115. }
  116. }
  117. /* Otherwise, start out in a new MSTI with all ports disabled. */
  118. return br_mst_vlan_set_state(vg, pv, BR_STATE_DISABLED);
  119. }
  120. int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti)
  121. {
  122. struct switchdev_attr attr = {
  123. .id = SWITCHDEV_ATTR_ID_VLAN_MSTI,
  124. .orig_dev = mv->br->dev,
  125. .u.vlan_msti = {
  126. .vid = mv->vid,
  127. .msti = msti,
  128. },
  129. };
  130. struct net_bridge_vlan_group *vg;
  131. struct net_bridge_vlan *pv;
  132. struct net_bridge_port *p;
  133. int err;
  134. if (mv->msti == msti)
  135. return 0;
  136. err = switchdev_port_attr_set(mv->br->dev, &attr, NULL);
  137. if (err && err != -EOPNOTSUPP)
  138. return err;
  139. mv->msti = msti;
  140. list_for_each_entry(p, &mv->br->port_list, list) {
  141. vg = nbp_vlan_group(p);
  142. pv = br_vlan_find(vg, mv->vid);
  143. if (pv)
  144. br_mst_vlan_sync_state(pv, msti);
  145. }
  146. return 0;
  147. }
  148. void br_mst_vlan_init_state(struct net_bridge_vlan *v)
  149. {
  150. /* VLANs always start out in MSTI 0 (CST) */
  151. v->msti = 0;
  152. if (br_vlan_is_master(v))
  153. v->state = BR_STATE_FORWARDING;
  154. else
  155. v->state = v->port->state;
  156. }
  157. int br_mst_set_enabled(struct net_bridge *br, bool on,
  158. struct netlink_ext_ack *extack)
  159. {
  160. struct switchdev_attr attr = {
  161. .id = SWITCHDEV_ATTR_ID_BRIDGE_MST,
  162. .orig_dev = br->dev,
  163. .u.mst = on,
  164. };
  165. struct net_bridge_vlan_group *vg;
  166. struct net_bridge_port *p;
  167. int err;
  168. list_for_each_entry(p, &br->port_list, list) {
  169. vg = nbp_vlan_group(p);
  170. if (!vg->num_vlans)
  171. continue;
  172. NL_SET_ERR_MSG(extack,
  173. "MST mode can't be changed while VLANs exist");
  174. return -EBUSY;
  175. }
  176. if (br_opt_get(br, BROPT_MST_ENABLED) == on)
  177. return 0;
  178. err = switchdev_port_attr_set(br->dev, &attr, extack);
  179. if (err && err != -EOPNOTSUPP)
  180. return err;
  181. if (on)
  182. static_branch_enable(&br_mst_used);
  183. else
  184. static_branch_disable(&br_mst_used);
  185. br_opt_toggle(br, BROPT_MST_ENABLED, on);
  186. return 0;
  187. }
  188. size_t br_mst_info_size(const struct net_bridge_vlan_group *vg)
  189. {
  190. DECLARE_BITMAP(seen, VLAN_N_VID) = { 0 };
  191. const struct net_bridge_vlan *v;
  192. size_t sz;
  193. /* IFLA_BRIDGE_MST */
  194. sz = nla_total_size(0);
  195. list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
  196. if (test_bit(v->brvlan->msti, seen))
  197. continue;
  198. /* IFLA_BRIDGE_MST_ENTRY */
  199. sz += nla_total_size(0) +
  200. /* IFLA_BRIDGE_MST_ENTRY_MSTI */
  201. nla_total_size(sizeof(u16)) +
  202. /* IFLA_BRIDGE_MST_ENTRY_STATE */
  203. nla_total_size(sizeof(u8));
  204. __set_bit(v->brvlan->msti, seen);
  205. }
  206. return sz;
  207. }
  208. int br_mst_fill_info(struct sk_buff *skb,
  209. const struct net_bridge_vlan_group *vg)
  210. {
  211. DECLARE_BITMAP(seen, VLAN_N_VID) = { 0 };
  212. const struct net_bridge_vlan *v;
  213. struct nlattr *nest;
  214. int err = 0;
  215. list_for_each_entry(v, &vg->vlan_list, vlist) {
  216. if (test_bit(v->brvlan->msti, seen))
  217. continue;
  218. nest = nla_nest_start_noflag(skb, IFLA_BRIDGE_MST_ENTRY);
  219. if (!nest ||
  220. nla_put_u16(skb, IFLA_BRIDGE_MST_ENTRY_MSTI, v->brvlan->msti) ||
  221. nla_put_u8(skb, IFLA_BRIDGE_MST_ENTRY_STATE, v->state)) {
  222. err = -EMSGSIZE;
  223. break;
  224. }
  225. nla_nest_end(skb, nest);
  226. __set_bit(v->brvlan->msti, seen);
  227. }
  228. return err;
  229. }
  230. static const struct nla_policy br_mst_nl_policy[IFLA_BRIDGE_MST_ENTRY_MAX + 1] = {
  231. [IFLA_BRIDGE_MST_ENTRY_MSTI] = NLA_POLICY_RANGE(NLA_U16,
  232. 1, /* 0 reserved for CST */
  233. VLAN_N_VID - 1),
  234. [IFLA_BRIDGE_MST_ENTRY_STATE] = NLA_POLICY_RANGE(NLA_U8,
  235. BR_STATE_DISABLED,
  236. BR_STATE_BLOCKING),
  237. };
  238. static int br_mst_process_one(struct net_bridge_port *p,
  239. const struct nlattr *attr,
  240. struct netlink_ext_ack *extack)
  241. {
  242. struct nlattr *tb[IFLA_BRIDGE_MST_ENTRY_MAX + 1];
  243. u16 msti;
  244. u8 state;
  245. int err;
  246. err = nla_parse_nested(tb, IFLA_BRIDGE_MST_ENTRY_MAX, attr,
  247. br_mst_nl_policy, extack);
  248. if (err)
  249. return err;
  250. if (!tb[IFLA_BRIDGE_MST_ENTRY_MSTI]) {
  251. NL_SET_ERR_MSG_MOD(extack, "MSTI not specified");
  252. return -EINVAL;
  253. }
  254. if (!tb[IFLA_BRIDGE_MST_ENTRY_STATE]) {
  255. NL_SET_ERR_MSG_MOD(extack, "State not specified");
  256. return -EINVAL;
  257. }
  258. msti = nla_get_u16(tb[IFLA_BRIDGE_MST_ENTRY_MSTI]);
  259. state = nla_get_u8(tb[IFLA_BRIDGE_MST_ENTRY_STATE]);
  260. return br_mst_set_state(p, msti, state, extack);
  261. }
  262. int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr,
  263. struct netlink_ext_ack *extack)
  264. {
  265. struct nlattr *attr;
  266. int err, msts = 0;
  267. int rem;
  268. if (!br_opt_get(p->br, BROPT_MST_ENABLED)) {
  269. NL_SET_ERR_MSG_MOD(extack, "Can't modify MST state when MST is disabled");
  270. return -EBUSY;
  271. }
  272. nla_for_each_nested(attr, mst_attr, rem) {
  273. switch (nla_type(attr)) {
  274. case IFLA_BRIDGE_MST_ENTRY:
  275. err = br_mst_process_one(p, attr, extack);
  276. break;
  277. default:
  278. continue;
  279. }
  280. msts++;
  281. if (err)
  282. break;
  283. }
  284. if (!msts) {
  285. NL_SET_ERR_MSG_MOD(extack, "Found no MST entries to process");
  286. err = -EINVAL;
  287. }
  288. return err;
  289. }