^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Copyright 2011-2014 Autronica Fire and Security AS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Routines for handling Netlink messages for HSR and PRP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "hsr_netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <net/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "hsr_main.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "hsr_device.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "hsr_framereg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) [IFLA_HSR_SLAVE1] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) [IFLA_HSR_SLAVE2] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) [IFLA_HSR_MULTICAST_SPEC] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) [IFLA_HSR_VERSION] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) [IFLA_HSR_SUPERVISION_ADDR] = { .len = ETH_ALEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) [IFLA_HSR_SEQ_NR] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) [IFLA_HSR_PROTOCOL] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Here, it seems a netdevice has already been allocated for us, and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * hsr_dev_setup routine has been executed. Nice!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int hsr_newlink(struct net *src_net, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct nlattr *tb[], struct nlattr *data[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum hsr_version proto_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned char multicast_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u8 proto = HSR_PROTOCOL_HSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct net_device *link[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (!data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) NL_SET_ERR_MSG_MOD(extack, "No slave devices specified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (!data[IFLA_HSR_SLAVE1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) NL_SET_ERR_MSG_MOD(extack, "Slave1 device not specified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) link[0] = __dev_get_by_index(src_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) nla_get_u32(data[IFLA_HSR_SLAVE1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (!link[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) NL_SET_ERR_MSG_MOD(extack, "Slave1 does not exist");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!data[IFLA_HSR_SLAVE2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) NL_SET_ERR_MSG_MOD(extack, "Slave2 device not specified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) link[1] = __dev_get_by_index(src_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) nla_get_u32(data[IFLA_HSR_SLAVE2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!link[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) NL_SET_ERR_MSG_MOD(extack, "Slave2 does not exist");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (link[0] == link[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) NL_SET_ERR_MSG_MOD(extack, "Slave1 and Slave2 are same");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!data[IFLA_HSR_MULTICAST_SPEC])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) multicast_spec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (data[IFLA_HSR_PROTOCOL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) proto = nla_get_u8(data[IFLA_HSR_PROTOCOL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (proto >= HSR_PROTOCOL_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) NL_SET_ERR_MSG_MOD(extack, "Unsupported protocol");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!data[IFLA_HSR_VERSION]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) proto_version = HSR_V0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (proto == HSR_PROTOCOL_PRP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) NL_SET_ERR_MSG_MOD(extack, "PRP version unsupported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) proto_version = nla_get_u8(data[IFLA_HSR_VERSION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (proto_version > HSR_V1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) NL_SET_ERR_MSG_MOD(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) "Only HSR version 0/1 supported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (proto == HSR_PROTOCOL_PRP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) proto_version = PRP_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return hsr_dev_finalize(dev, link, multicast_spec, proto_version, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static void hsr_dellink(struct net_device *dev, struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct hsr_priv *hsr = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) del_timer_sync(&hsr->prune_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) del_timer_sync(&hsr->announce_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) hsr_debugfs_term(hsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) hsr_del_ports(hsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) hsr_del_self_node(hsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) hsr_del_nodes(&hsr->node_db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unregister_netdevice_queue(dev, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct hsr_priv *hsr = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u8 proto = HSR_PROTOCOL_HSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct hsr_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (nla_put_u32(skb, IFLA_HSR_SLAVE1, port->dev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (nla_put_u32(skb, IFLA_HSR_SLAVE2, port->dev->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hsr->sup_multicast_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr->sequence_nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (hsr->prot_version == PRP_V1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) proto = HSR_PROTOCOL_PRP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (nla_put_u8(skb, IFLA_HSR_PROTOCOL, proto))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static struct rtnl_link_ops hsr_link_ops __read_mostly = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .kind = "hsr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .maxtype = IFLA_HSR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .policy = hsr_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .priv_size = sizeof(struct hsr_priv),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .setup = hsr_dev_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .newlink = hsr_newlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .dellink = hsr_dellink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .fill_info = hsr_fill_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* attribute policy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) [HSR_A_NODE_ADDR] = { .len = ETH_ALEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) [HSR_A_NODE_ADDR_B] = { .len = ETH_ALEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) [HSR_A_IFINDEX] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) [HSR_A_IF1_AGE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) [HSR_A_IF2_AGE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) [HSR_A_IF1_SEQ] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) [HSR_A_IF2_SEQ] = { .type = NLA_U16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct genl_family hsr_genl_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static const struct genl_multicast_group hsr_mcgrps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { .name = "hsr-network", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* This is called if for some node with MAC address addr, we only get frames
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * over one of the slave interfaces. This would indicate an open network ring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * (i.e. a link has failed somewhere).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct hsr_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) void *msg_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct hsr_port *master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) HSR_C_RING_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!msg_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) res = nla_put_u32(skb, HSR_A_IFINDEX, port->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) genlmsg_end(skb, msg_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) netdev_warn(master->dev, "Could not send HSR ring error message\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* This is called when we haven't heard from the node with MAC address addr for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * some time (just before the node is removed from the node table/list).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void *msg_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct hsr_port *master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0, HSR_C_NODE_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (!msg_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) genlmsg_end(skb, msg_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) netdev_warn(master->dev, "Could not send HSR node down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* HSR_C_GET_NODE_STATUS lets userspace query the internal HSR node table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * about the status of a specific node in the network, defined by its MAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * Input: hsr ifindex, node mac address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Output: hsr ifindex, node mac address (copied from request),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * age of latest frame from node over slave 1, slave 2 [ms]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* For receiving */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct nlattr *na;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct net_device *hsr_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* For sending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct sk_buff *skb_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) void *msg_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct hsr_priv *hsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct hsr_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) unsigned char hsr_node_addr_b[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int hsr_node_if1_age;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u16 hsr_node_if1_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int hsr_node_if2_age;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u16 hsr_node_if2_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int addr_b_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) na = info->attrs[HSR_A_IFINDEX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!na)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) na = info->attrs[HSR_A_NODE_ADDR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!na)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) hsr_dev = dev_get_by_index_rcu(genl_info_net(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) nla_get_u32(info->attrs[HSR_A_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (!hsr_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) goto rcu_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!is_hsr_master(hsr_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) goto rcu_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Send reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!skb_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) res = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) info->snd_seq, &hsr_genl_family, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) HSR_C_SET_NODE_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (!msg_head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) res = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) hsr = netdev_priv(hsr_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) res = hsr_get_node_data(hsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) (unsigned char *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) nla_data(info->attrs[HSR_A_NODE_ADDR]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) hsr_node_addr_b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) &addr_b_ifindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) &hsr_node_if1_age,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) &hsr_node_if1_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) &hsr_node_if2_age,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) &hsr_node_if2_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) nla_data(info->attrs[HSR_A_NODE_ADDR]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (addr_b_ifindex > -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) res = nla_put(skb_out, HSR_A_NODE_ADDR_B, ETH_ALEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) hsr_node_addr_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) res = nla_put_u32(skb_out, HSR_A_ADDR_B_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) addr_b_ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) res = nla_put_u32(skb_out, HSR_A_IF1_AGE, hsr_node_if1_age);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) port->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) res = nla_put_u32(skb_out, HSR_A_IF2_AGE, hsr_node_if2_age);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) port->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) genlmsg_end(skb_out, msg_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) rcu_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) kfree_skb(skb_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* Fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* Get a list of MacAddressA of all nodes known to this node (including self).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) unsigned char addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct net_device *hsr_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct sk_buff *skb_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct hsr_priv *hsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) bool restart = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct nlattr *na;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) void *pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) void *msg_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) na = info->attrs[HSR_A_IFINDEX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (!na)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) hsr_dev = dev_get_by_index_rcu(genl_info_net(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) nla_get_u32(info->attrs[HSR_A_IFINDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (!hsr_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) goto rcu_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!is_hsr_master(hsr_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) goto rcu_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) restart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* Send reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) skb_out = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (!skb_out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) res = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) info->snd_seq, &hsr_genl_family, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) HSR_C_SET_NODE_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!msg_head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) res = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!restart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) hsr = netdev_priv(hsr_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pos = hsr_get_next_node(hsr, NULL, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) while (pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (res < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (res == -EMSGSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) genlmsg_end(skb_out, msg_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) genlmsg_unicast(genl_info_net(info), skb_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) info->snd_portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) restart = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) pos = hsr_get_next_node(hsr, pos, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) genlmsg_end(skb_out, msg_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) rcu_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) nlmsg_free(skb_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static const struct genl_small_ops hsr_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) .cmd = HSR_C_GET_NODE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .doit = hsr_get_node_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .dumpit = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .cmd = HSR_C_GET_NODE_LIST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .doit = hsr_get_node_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .dumpit = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static struct genl_family hsr_genl_family __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) .hdrsize = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .name = "HSR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) .version = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) .maxattr = HSR_A_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) .policy = hsr_genl_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) .netnsok = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) .small_ops = hsr_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) .n_small_ops = ARRAY_SIZE(hsr_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) .mcgrps = hsr_mcgrps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) .n_mcgrps = ARRAY_SIZE(hsr_mcgrps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int __init hsr_netlink_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) rc = rtnl_link_register(&hsr_link_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto fail_rtnl_link_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) rc = genl_register_family(&hsr_genl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto fail_genl_register_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) hsr_debugfs_create_root();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) fail_genl_register_family:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) rtnl_link_unregister(&hsr_link_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) fail_rtnl_link_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) void __exit hsr_netlink_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) genl_unregister_family(&hsr_genl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) rtnl_link_unregister(&hsr_link_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) MODULE_ALIAS_RTNL_LINK("hsr");