hsr_prp_main.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright 2011-2014 Autronica Fire and Security AS
  3. *
  4. * Author(s):
  5. * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
  6. */
  7. #include <linux/netdevice.h>
  8. #include <linux/rculist.h>
  9. #include <linux/timer.h>
  10. #include <linux/etherdevice.h>
  11. #include "hsr_prp_main.h"
  12. #include "hsr_prp_device.h"
  13. #include "hsr_netlink.h"
  14. #include "hsr_prp_framereg.h"
  15. #include "hsr_prp_slave.h"
  16. static int netdev_notify(struct notifier_block *nb, unsigned long event,
  17. void *ptr);
  18. static struct notifier_block hsr_nb = {
  19. .notifier_call = netdev_notify, /* Slave event notifications */
  20. };
  21. static struct notifier_block prp_nb = {
  22. .notifier_call = netdev_notify, /* Slave event notifications */
  23. };
  24. static int netdev_notify(struct notifier_block *nb, unsigned long event,
  25. void *ptr)
  26. {
  27. struct net_device *dev;
  28. struct hsr_prp_port *port, *master;
  29. struct hsr_prp_priv *priv;
  30. int mtu_max;
  31. int res;
  32. dev = netdev_notifier_info_to_dev(ptr);
  33. port = hsr_prp_port_get_rtnl(dev);
  34. if (!port) {
  35. if (!is_hsr_prp_master(dev))
  36. return NOTIFY_DONE; /* Not an HSR device */
  37. priv = netdev_priv(dev);
  38. port = hsr_prp_get_port(priv, HSR_PRP_PT_MASTER);
  39. if (!port) {
  40. /* Resend of notification concerning removed device? */
  41. return NOTIFY_DONE;
  42. }
  43. } else {
  44. priv = port->priv;
  45. }
  46. if (priv->prot_version <= HSR_V1 && nb != &hsr_nb)
  47. return NOTIFY_DONE;
  48. else if (priv->prot_version == PRP_V1 && nb != &prp_nb)
  49. return NOTIFY_DONE;
  50. switch (event) {
  51. case NETDEV_UP: /* Administrative state DOWN */
  52. case NETDEV_DOWN: /* Administrative state UP */
  53. case NETDEV_CHANGE: /* Link (carrier) state changes */
  54. hsr_prp_check_carrier_and_operstate(priv);
  55. break;
  56. case NETDEV_CHANGEADDR:
  57. if (port->type == HSR_PRP_PT_MASTER) {
  58. /* This should not happen since there's no
  59. * ndo_set_mac_address() for HSR devices - i.e. not
  60. * supported.
  61. */
  62. break;
  63. }
  64. master = hsr_prp_get_port(priv, HSR_PRP_PT_MASTER);
  65. if (port->type == HSR_PRP_PT_SLAVE_A) {
  66. ether_addr_copy(master->dev->dev_addr, dev->dev_addr);
  67. call_netdevice_notifiers(NETDEV_CHANGEADDR,
  68. master->dev);
  69. }
  70. /* Make sure we recognize frames from ourselves in hsr_rcv() */
  71. port = hsr_prp_get_port(priv, HSR_PRP_PT_SLAVE_B);
  72. res = hsr_prp_create_self_node(&priv->self_node_db,
  73. master->dev->dev_addr,
  74. port ? port->dev->dev_addr :
  75. master->dev->dev_addr);
  76. if (res)
  77. netdev_warn(master->dev,
  78. "Could not update HSR node address.\n");
  79. break;
  80. case NETDEV_CHANGEMTU:
  81. if (port->type == HSR_PRP_PT_MASTER)
  82. break; /* Handled in ndo_change_mtu() */
  83. mtu_max = hsr_prp_get_max_mtu(port->priv);
  84. master = hsr_prp_get_port(port->priv, HSR_PRP_PT_MASTER);
  85. master->dev->mtu = mtu_max;
  86. break;
  87. case NETDEV_UNREGISTER:
  88. hsr_prp_del_port(port);
  89. break;
  90. case NETDEV_PRE_TYPE_CHANGE:
  91. /* HSR works only on Ethernet devices. Refuse slave to change
  92. * its type.
  93. */
  94. return NOTIFY_BAD;
  95. }
  96. return NOTIFY_DONE;
  97. }
  98. struct hsr_prp_port *hsr_prp_get_port(struct hsr_prp_priv *priv,
  99. enum hsr_prp_port_type pt)
  100. {
  101. struct hsr_prp_port *port;
  102. hsr_prp_for_each_port(priv, port)
  103. if (port->type == pt)
  104. return port;
  105. return NULL;
  106. }
  107. int hsr_prp_register_notifier(u8 proto)
  108. {
  109. if (proto == PRP)
  110. return register_netdevice_notifier(&prp_nb);
  111. return register_netdevice_notifier(&hsr_nb);
  112. }
  113. void hsr_prp_unregister_notifier(u8 proto)
  114. {
  115. if (proto == PRP) {
  116. unregister_netdevice_notifier(&prp_nb);
  117. return;
  118. }
  119. unregister_netdevice_notifier(&hsr_nb);
  120. }