switchdev.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /*
  2. * net/switchdev/switchdev.c - Switch device API
  3. * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
  4. * Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/types.h>
  13. #include <linux/init.h>
  14. #include <linux/mutex.h>
  15. #include <linux/notifier.h>
  16. #include <linux/netdevice.h>
  17. #include <net/ip_fib.h>
  18. #include <net/switchdev.h>
  19. /**
  20. * netdev_switch_parent_id_get - Get ID of a switch
  21. * @dev: port device
  22. * @psid: switch ID
  23. *
  24. * Get ID of a switch this port is part of.
  25. */
  26. int netdev_switch_parent_id_get(struct net_device *dev,
  27. struct netdev_phys_item_id *psid)
  28. {
  29. const struct swdev_ops *ops = dev->swdev_ops;
  30. if (!ops || !ops->swdev_parent_id_get)
  31. return -EOPNOTSUPP;
  32. return ops->swdev_parent_id_get(dev, psid);
  33. }
  34. EXPORT_SYMBOL_GPL(netdev_switch_parent_id_get);
  35. /**
  36. * netdev_switch_port_stp_update - Notify switch device port of STP
  37. * state change
  38. * @dev: port device
  39. * @state: port STP state
  40. *
  41. * Notify switch device port of bridge port STP state change.
  42. */
  43. int netdev_switch_port_stp_update(struct net_device *dev, u8 state)
  44. {
  45. const struct swdev_ops *ops = dev->swdev_ops;
  46. struct net_device *lower_dev;
  47. struct list_head *iter;
  48. int err = -EOPNOTSUPP;
  49. if (ops && ops->swdev_port_stp_update)
  50. return ops->swdev_port_stp_update(dev, state);
  51. netdev_for_each_lower_dev(dev, lower_dev, iter) {
  52. err = netdev_switch_port_stp_update(lower_dev, state);
  53. if (err && err != -EOPNOTSUPP)
  54. return err;
  55. }
  56. return err;
  57. }
  58. EXPORT_SYMBOL_GPL(netdev_switch_port_stp_update);
  59. static DEFINE_MUTEX(netdev_switch_mutex);
  60. static RAW_NOTIFIER_HEAD(netdev_switch_notif_chain);
  61. /**
  62. * register_netdev_switch_notifier - Register notifier
  63. * @nb: notifier_block
  64. *
  65. * Register switch device notifier. This should be used by code
  66. * which needs to monitor events happening in particular device.
  67. * Return values are same as for atomic_notifier_chain_register().
  68. */
  69. int register_netdev_switch_notifier(struct notifier_block *nb)
  70. {
  71. int err;
  72. mutex_lock(&netdev_switch_mutex);
  73. err = raw_notifier_chain_register(&netdev_switch_notif_chain, nb);
  74. mutex_unlock(&netdev_switch_mutex);
  75. return err;
  76. }
  77. EXPORT_SYMBOL_GPL(register_netdev_switch_notifier);
  78. /**
  79. * unregister_netdev_switch_notifier - Unregister notifier
  80. * @nb: notifier_block
  81. *
  82. * Unregister switch device notifier.
  83. * Return values are same as for atomic_notifier_chain_unregister().
  84. */
  85. int unregister_netdev_switch_notifier(struct notifier_block *nb)
  86. {
  87. int err;
  88. mutex_lock(&netdev_switch_mutex);
  89. err = raw_notifier_chain_unregister(&netdev_switch_notif_chain, nb);
  90. mutex_unlock(&netdev_switch_mutex);
  91. return err;
  92. }
  93. EXPORT_SYMBOL_GPL(unregister_netdev_switch_notifier);
  94. /**
  95. * call_netdev_switch_notifiers - Call notifiers
  96. * @val: value passed unmodified to notifier function
  97. * @dev: port device
  98. * @info: notifier information data
  99. *
  100. * Call all network notifier blocks. This should be called by driver
  101. * when it needs to propagate hardware event.
  102. * Return values are same as for atomic_notifier_call_chain().
  103. */
  104. int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
  105. struct netdev_switch_notifier_info *info)
  106. {
  107. int err;
  108. info->dev = dev;
  109. mutex_lock(&netdev_switch_mutex);
  110. err = raw_notifier_call_chain(&netdev_switch_notif_chain, val, info);
  111. mutex_unlock(&netdev_switch_mutex);
  112. return err;
  113. }
  114. EXPORT_SYMBOL_GPL(call_netdev_switch_notifiers);
  115. /**
  116. * netdev_switch_port_bridge_setlink - Notify switch device port of bridge
  117. * port attributes
  118. *
  119. * @dev: port device
  120. * @nlh: netlink msg with bridge port attributes
  121. * @flags: bridge setlink flags
  122. *
  123. * Notify switch device port of bridge port attributes
  124. */
  125. int netdev_switch_port_bridge_setlink(struct net_device *dev,
  126. struct nlmsghdr *nlh, u16 flags)
  127. {
  128. const struct net_device_ops *ops = dev->netdev_ops;
  129. if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
  130. return 0;
  131. if (!ops->ndo_bridge_setlink)
  132. return -EOPNOTSUPP;
  133. return ops->ndo_bridge_setlink(dev, nlh, flags);
  134. }
  135. EXPORT_SYMBOL_GPL(netdev_switch_port_bridge_setlink);
  136. /**
  137. * netdev_switch_port_bridge_dellink - Notify switch device port of bridge
  138. * port attribute delete
  139. *
  140. * @dev: port device
  141. * @nlh: netlink msg with bridge port attributes
  142. * @flags: bridge setlink flags
  143. *
  144. * Notify switch device port of bridge port attribute delete
  145. */
  146. int netdev_switch_port_bridge_dellink(struct net_device *dev,
  147. struct nlmsghdr *nlh, u16 flags)
  148. {
  149. const struct net_device_ops *ops = dev->netdev_ops;
  150. if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
  151. return 0;
  152. if (!ops->ndo_bridge_dellink)
  153. return -EOPNOTSUPP;
  154. return ops->ndo_bridge_dellink(dev, nlh, flags);
  155. }
  156. EXPORT_SYMBOL_GPL(netdev_switch_port_bridge_dellink);
  157. /**
  158. * ndo_dflt_netdev_switch_port_bridge_setlink - default ndo bridge setlink
  159. * op for master devices
  160. *
  161. * @dev: port device
  162. * @nlh: netlink msg with bridge port attributes
  163. * @flags: bridge setlink flags
  164. *
  165. * Notify master device slaves of bridge port attributes
  166. */
  167. int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev,
  168. struct nlmsghdr *nlh, u16 flags)
  169. {
  170. struct net_device *lower_dev;
  171. struct list_head *iter;
  172. int ret = 0, err = 0;
  173. if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
  174. return ret;
  175. netdev_for_each_lower_dev(dev, lower_dev, iter) {
  176. err = netdev_switch_port_bridge_setlink(lower_dev, nlh, flags);
  177. if (err && err != -EOPNOTSUPP)
  178. ret = err;
  179. }
  180. return ret;
  181. }
  182. EXPORT_SYMBOL_GPL(ndo_dflt_netdev_switch_port_bridge_setlink);
  183. /**
  184. * ndo_dflt_netdev_switch_port_bridge_dellink - default ndo bridge dellink
  185. * op for master devices
  186. *
  187. * @dev: port device
  188. * @nlh: netlink msg with bridge port attributes
  189. * @flags: bridge dellink flags
  190. *
  191. * Notify master device slaves of bridge port attribute deletes
  192. */
  193. int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev,
  194. struct nlmsghdr *nlh, u16 flags)
  195. {
  196. struct net_device *lower_dev;
  197. struct list_head *iter;
  198. int ret = 0, err = 0;
  199. if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
  200. return ret;
  201. netdev_for_each_lower_dev(dev, lower_dev, iter) {
  202. err = netdev_switch_port_bridge_dellink(lower_dev, nlh, flags);
  203. if (err && err != -EOPNOTSUPP)
  204. ret = err;
  205. }
  206. return ret;
  207. }
  208. EXPORT_SYMBOL_GPL(ndo_dflt_netdev_switch_port_bridge_dellink);
  209. static struct net_device *netdev_switch_get_lowest_dev(struct net_device *dev)
  210. {
  211. const struct swdev_ops *ops = dev->swdev_ops;
  212. struct net_device *lower_dev;
  213. struct net_device *port_dev;
  214. struct list_head *iter;
  215. /* Recusively search down until we find a sw port dev.
  216. * (A sw port dev supports swdev_parent_id_get).
  217. */
  218. if (dev->features & NETIF_F_HW_SWITCH_OFFLOAD &&
  219. ops && ops->swdev_parent_id_get)
  220. return dev;
  221. netdev_for_each_lower_dev(dev, lower_dev, iter) {
  222. port_dev = netdev_switch_get_lowest_dev(lower_dev);
  223. if (port_dev)
  224. return port_dev;
  225. }
  226. return NULL;
  227. }
  228. static struct net_device *netdev_switch_get_dev_by_nhs(struct fib_info *fi)
  229. {
  230. struct netdev_phys_item_id psid;
  231. struct netdev_phys_item_id prev_psid;
  232. struct net_device *dev = NULL;
  233. int nhsel;
  234. /* For this route, all nexthop devs must be on the same switch. */
  235. for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
  236. const struct fib_nh *nh = &fi->fib_nh[nhsel];
  237. if (!nh->nh_dev)
  238. return NULL;
  239. dev = netdev_switch_get_lowest_dev(nh->nh_dev);
  240. if (!dev)
  241. return NULL;
  242. if (netdev_switch_parent_id_get(dev, &psid))
  243. return NULL;
  244. if (nhsel > 0) {
  245. if (prev_psid.id_len != psid.id_len)
  246. return NULL;
  247. if (memcmp(prev_psid.id, psid.id, psid.id_len))
  248. return NULL;
  249. }
  250. prev_psid = psid;
  251. }
  252. return dev;
  253. }
  254. /**
  255. * netdev_switch_fib_ipv4_add - Add IPv4 route entry to switch
  256. *
  257. * @dst: route's IPv4 destination address
  258. * @dst_len: destination address length (prefix length)
  259. * @fi: route FIB info structure
  260. * @tos: route TOS
  261. * @type: route type
  262. * @nlflags: netlink flags passed in (NLM_F_*)
  263. * @tb_id: route table ID
  264. *
  265. * Add IPv4 route entry to switch device.
  266. */
  267. int netdev_switch_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
  268. u8 tos, u8 type, u32 nlflags, u32 tb_id)
  269. {
  270. struct net_device *dev;
  271. const struct swdev_ops *ops;
  272. int err = 0;
  273. /* Don't offload route if using custom ip rules or if
  274. * IPv4 FIB offloading has been disabled completely.
  275. */
  276. #ifdef CONFIG_IP_MULTIPLE_TABLES
  277. if (fi->fib_net->ipv4.fib_has_custom_rules)
  278. return 0;
  279. #endif
  280. if (fi->fib_net->ipv4.fib_offload_disabled)
  281. return 0;
  282. dev = netdev_switch_get_dev_by_nhs(fi);
  283. if (!dev)
  284. return 0;
  285. ops = dev->swdev_ops;
  286. if (ops->swdev_fib_ipv4_add) {
  287. err = ops->swdev_fib_ipv4_add(dev, htonl(dst), dst_len,
  288. fi, tos, type, nlflags,
  289. tb_id);
  290. if (!err)
  291. fi->fib_flags |= RTNH_F_EXTERNAL;
  292. }
  293. return err;
  294. }
  295. EXPORT_SYMBOL_GPL(netdev_switch_fib_ipv4_add);
  296. /**
  297. * netdev_switch_fib_ipv4_del - Delete IPv4 route entry from switch
  298. *
  299. * @dst: route's IPv4 destination address
  300. * @dst_len: destination address length (prefix length)
  301. * @fi: route FIB info structure
  302. * @tos: route TOS
  303. * @type: route type
  304. * @tb_id: route table ID
  305. *
  306. * Delete IPv4 route entry from switch device.
  307. */
  308. int netdev_switch_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
  309. u8 tos, u8 type, u32 tb_id)
  310. {
  311. struct net_device *dev;
  312. const struct swdev_ops *ops;
  313. int err = 0;
  314. if (!(fi->fib_flags & RTNH_F_EXTERNAL))
  315. return 0;
  316. dev = netdev_switch_get_dev_by_nhs(fi);
  317. if (!dev)
  318. return 0;
  319. ops = dev->swdev_ops;
  320. if (ops->swdev_fib_ipv4_del) {
  321. err = ops->swdev_fib_ipv4_del(dev, htonl(dst), dst_len,
  322. fi, tos, type, tb_id);
  323. if (!err)
  324. fi->fib_flags &= ~RTNH_F_EXTERNAL;
  325. }
  326. return err;
  327. }
  328. EXPORT_SYMBOL_GPL(netdev_switch_fib_ipv4_del);
  329. /**
  330. * netdev_switch_fib_ipv4_abort - Abort an IPv4 FIB operation
  331. *
  332. * @fi: route FIB info structure
  333. */
  334. void netdev_switch_fib_ipv4_abort(struct fib_info *fi)
  335. {
  336. /* There was a problem installing this route to the offload
  337. * device. For now, until we come up with more refined
  338. * policy handling, abruptly end IPv4 fib offloading for
  339. * for entire net by flushing offload device(s) of all
  340. * IPv4 routes, and mark IPv4 fib offloading broken from
  341. * this point forward.
  342. */
  343. fib_flush_external(fi->fib_net);
  344. fi->fib_net->ipv4.fib_offload_disabled = true;
  345. }
  346. EXPORT_SYMBOL_GPL(netdev_switch_fib_ipv4_abort);