aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-11-19 14:30:45 -0500
committerDavid S. Miller <davem@davemloft.net>2015-11-20 14:06:10 -0500
commit5be9c086715c10fb9ae3ffc0ef580dc3a165f98a (patch)
tree33ceb909dd758e3b96d48bb5fc8c3e0211c42555 /net/tipc/node.c
parent5405ff6e15f40f2f53e37d2dcd7de521e2b7a96f (diff)
tipc: narrow down exposure of struct tipc_node
In our effort to have less code and include dependencies between entities such as node, link and bearer, we try to narrow down the exposed interface towards the node as much as possible. In this commit, we move the definition of struct tipc_node, along with many of its associated function declarations, from node.h to node.c. We also move some function definitions from link.c and name_distr.c to node.c, since they access fields in struct tipc_node that should not be externally visible. The moved functions are renamed according to new location, and made static whenever possible. There are no functional changes in this commit. Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c449
1 files changed, 444 insertions, 5 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 47d5f84c90c5..e110ba67422e 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -42,6 +42,87 @@
42#include "bcast.h" 42#include "bcast.h"
43#include "discover.h" 43#include "discover.h"
44 44
45/* Out-of-range value for node signature */
46#define INVALID_NODE_SIG 0x10000
47
48#define INVALID_BEARER_ID -1
49
50/* Flags used to take different actions according to flag type
51 * TIPC_NOTIFY_NODE_DOWN: notify node is down
52 * TIPC_NOTIFY_NODE_UP: notify node is up
53 * TIPC_DISTRIBUTE_NAME: publish or withdraw link state name type
54 */
55enum {
56 TIPC_NOTIFY_NODE_DOWN = (1 << 3),
57 TIPC_NOTIFY_NODE_UP = (1 << 4),
58 TIPC_NOTIFY_LINK_UP = (1 << 6),
59 TIPC_NOTIFY_LINK_DOWN = (1 << 7)
60};
61
62struct tipc_link_entry {
63 struct tipc_link *link;
64 spinlock_t lock; /* per link */
65 u32 mtu;
66 struct sk_buff_head inputq;
67 struct tipc_media_addr maddr;
68};
69
70struct tipc_bclink_entry {
71 struct tipc_link *link;
72 struct sk_buff_head inputq1;
73 struct sk_buff_head arrvq;
74 struct sk_buff_head inputq2;
75 struct sk_buff_head namedq;
76};
77
78/**
79 * struct tipc_node - TIPC node structure
80 * @addr: network address of node
81 * @ref: reference counter to node object
82 * @lock: rwlock governing access to structure
83 * @net: the applicable net namespace
84 * @hash: links to adjacent nodes in unsorted hash chain
85 * @inputq: pointer to input queue containing messages for msg event
86 * @namedq: pointer to name table input queue with name table messages
87 * @active_links: bearer ids of active links, used as index into links[] array
88 * @links: array containing references to all links to node
89 * @action_flags: bit mask of different types of node actions
90 * @state: connectivity state vs peer node
91 * @sync_point: sequence number where synch/failover is finished
92 * @list: links to adjacent nodes in sorted list of cluster's nodes
93 * @working_links: number of working links to node (both active and standby)
94 * @link_cnt: number of links to node
95 * @capabilities: bitmap, indicating peer node's functional capabilities
96 * @signature: node instance identifier
97 * @link_id: local and remote bearer ids of changing link, if any
98 * @publ_list: list of publications
99 * @rcu: rcu struct for tipc_node
100 */
101struct tipc_node {
102 u32 addr;
103 struct kref kref;
104 rwlock_t lock;
105 struct net *net;
106 struct hlist_node hash;
107 int active_links[2];
108 struct tipc_link_entry links[MAX_BEARERS];
109 struct tipc_bclink_entry bc_entry;
110 int action_flags;
111 struct list_head list;
112 int state;
113 u16 sync_point;
114 int link_cnt;
115 u16 working_links;
116 u16 capabilities;
117 u32 signature;
118 u32 link_id;
119 struct list_head publ_list;
120 struct list_head conn_sks;
121 unsigned long keepalive_intv;
122 struct timer_list timer;
123 struct rcu_head rcu;
124};
125
45/* Node FSM states and events: 126/* Node FSM states and events:
46 */ 127 */
47enum { 128enum {
@@ -75,6 +156,9 @@ static void node_lost_contact(struct tipc_node *n, struct sk_buff_head *inputq);
75static void tipc_node_delete(struct tipc_node *node); 156static void tipc_node_delete(struct tipc_node *node);
76static void tipc_node_timeout(unsigned long data); 157static void tipc_node_timeout(unsigned long data);
77static void tipc_node_fsm_evt(struct tipc_node *n, int evt); 158static void tipc_node_fsm_evt(struct tipc_node *n, int evt);
159static struct tipc_node *tipc_node_find(struct net *net, u32 addr);
160static void tipc_node_put(struct tipc_node *node);
161static bool tipc_node_is_up(struct tipc_node *n);
78 162
79struct tipc_sock_conn { 163struct tipc_sock_conn {
80 u32 port; 164 u32 port;
@@ -83,12 +167,54 @@ struct tipc_sock_conn {
83 struct list_head list; 167 struct list_head list;
84}; 168};
85 169
170static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = {
171 [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC },
172 [TIPC_NLA_LINK_NAME] = {
173 .type = NLA_STRING,
174 .len = TIPC_MAX_LINK_NAME
175 },
176 [TIPC_NLA_LINK_MTU] = { .type = NLA_U32 },
177 [TIPC_NLA_LINK_BROADCAST] = { .type = NLA_FLAG },
178 [TIPC_NLA_LINK_UP] = { .type = NLA_FLAG },
179 [TIPC_NLA_LINK_ACTIVE] = { .type = NLA_FLAG },
180 [TIPC_NLA_LINK_PROP] = { .type = NLA_NESTED },
181 [TIPC_NLA_LINK_STATS] = { .type = NLA_NESTED },
182 [TIPC_NLA_LINK_RX] = { .type = NLA_U32 },
183 [TIPC_NLA_LINK_TX] = { .type = NLA_U32 }
184};
185
86static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { 186static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
87 [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, 187 [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC },
88 [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, 188 [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 },
89 [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } 189 [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG }
90}; 190};
91 191
192static struct tipc_link *node_active_link(struct tipc_node *n, int sel)
193{
194 int bearer_id = n->active_links[sel & 1];
195
196 if (unlikely(bearer_id == INVALID_BEARER_ID))
197 return NULL;
198
199 return n->links[bearer_id].link;
200}
201
202int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel)
203{
204 struct tipc_node *n;
205 int bearer_id;
206 unsigned int mtu = MAX_MSG_SIZE;
207
208 n = tipc_node_find(net, addr);
209 if (unlikely(!n))
210 return mtu;
211
212 bearer_id = n->active_links[sel & 1];
213 if (likely(bearer_id != INVALID_BEARER_ID))
214 mtu = n->links[bearer_id].mtu;
215 tipc_node_put(n);
216 return mtu;
217}
92/* 218/*
93 * A trivial power-of-two bitmask technique is used for speed, since this 219 * A trivial power-of-two bitmask technique is used for speed, since this
94 * operation is done for every incoming TIPC packet. The number of hash table 220 * operation is done for every incoming TIPC packet. The number of hash table
@@ -107,7 +233,7 @@ static void tipc_node_kref_release(struct kref *kref)
107 tipc_node_delete(node); 233 tipc_node_delete(node);
108} 234}
109 235
110void tipc_node_put(struct tipc_node *node) 236static void tipc_node_put(struct tipc_node *node)
111{ 237{
112 kref_put(&node->kref, tipc_node_kref_release); 238 kref_put(&node->kref, tipc_node_kref_release);
113} 239}
@@ -120,7 +246,7 @@ static void tipc_node_get(struct tipc_node *node)
120/* 246/*
121 * tipc_node_find - locate specified node object, if it exists 247 * tipc_node_find - locate specified node object, if it exists
122 */ 248 */
123struct tipc_node *tipc_node_find(struct net *net, u32 addr) 249static struct tipc_node *tipc_node_find(struct net *net, u32 addr)
124{ 250{
125 struct tipc_net *tn = net_generic(net, tipc_net_id); 251 struct tipc_net *tn = net_generic(net, tipc_net_id);
126 struct tipc_node *node; 252 struct tipc_node *node;
@@ -141,12 +267,12 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr)
141 return NULL; 267 return NULL;
142} 268}
143 269
144void tipc_node_read_lock(struct tipc_node *n) 270static void tipc_node_read_lock(struct tipc_node *n)
145{ 271{
146 read_lock_bh(&n->lock); 272 read_lock_bh(&n->lock);
147} 273}
148 274
149void tipc_node_read_unlock(struct tipc_node *n) 275static void tipc_node_read_unlock(struct tipc_node *n)
150{ 276{
151 read_unlock_bh(&n->lock); 277 read_unlock_bh(&n->lock);
152} 278}
@@ -588,7 +714,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
588 tipc_sk_rcv(n->net, &le->inputq); 714 tipc_sk_rcv(n->net, &le->inputq);
589} 715}
590 716
591bool tipc_node_is_up(struct tipc_node *n) 717static bool tipc_node_is_up(struct tipc_node *n)
592{ 718{
593 return n->active_links[0] != INVALID_BEARER_ID; 719 return n->active_links[0] != INVALID_BEARER_ID;
594} 720}
@@ -1465,3 +1591,316 @@ out:
1465 1591
1466 return skb->len; 1592 return skb->len;
1467} 1593}
1594
1595/* tipc_link_find_owner - locate owner node of link by link's name
1596 * @net: the applicable net namespace
1597 * @name: pointer to link name string
1598 * @bearer_id: pointer to index in 'node->links' array where the link was found.
1599 *
1600 * Returns pointer to node owning the link, or 0 if no matching link is found.
1601 */
1602static struct tipc_node *tipc_link_find_owner(struct net *net,
1603 const char *link_name,
1604 unsigned int *bearer_id)
1605{
1606 struct tipc_net *tn = net_generic(net, tipc_net_id);
1607 struct tipc_link *l_ptr;
1608 struct tipc_node *n_ptr;
1609 struct tipc_node *found_node = NULL;
1610 int i;
1611
1612 *bearer_id = 0;
1613 rcu_read_lock();
1614 list_for_each_entry_rcu(n_ptr, &tn->node_list, list) {
1615 tipc_node_read_lock(n_ptr);
1616 for (i = 0; i < MAX_BEARERS; i++) {
1617 l_ptr = n_ptr->links[i].link;
1618 if (l_ptr && !strcmp(l_ptr->name, link_name)) {
1619 *bearer_id = i;
1620 found_node = n_ptr;
1621 break;
1622 }
1623 }
1624 tipc_node_read_unlock(n_ptr);
1625 if (found_node)
1626 break;
1627 }
1628 rcu_read_unlock();
1629
1630 return found_node;
1631}
1632
1633int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
1634{
1635 int err;
1636 int res = 0;
1637 int bearer_id;
1638 char *name;
1639 struct tipc_link *link;
1640 struct tipc_node *node;
1641 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
1642 struct net *net = sock_net(skb->sk);
1643
1644 if (!info->attrs[TIPC_NLA_LINK])
1645 return -EINVAL;
1646
1647 err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX,
1648 info->attrs[TIPC_NLA_LINK],
1649 tipc_nl_link_policy);
1650 if (err)
1651 return err;
1652
1653 if (!attrs[TIPC_NLA_LINK_NAME])
1654 return -EINVAL;
1655
1656 name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
1657
1658 if (strcmp(name, tipc_bclink_name) == 0)
1659 return tipc_nl_bc_link_set(net, attrs);
1660
1661 node = tipc_link_find_owner(net, name, &bearer_id);
1662 if (!node)
1663 return -EINVAL;
1664
1665 tipc_node_read_lock(node);
1666
1667 link = node->links[bearer_id].link;
1668 if (!link) {
1669 res = -EINVAL;
1670 goto out;
1671 }
1672
1673 if (attrs[TIPC_NLA_LINK_PROP]) {
1674 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1675
1676 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP],
1677 props);
1678 if (err) {
1679 res = err;
1680 goto out;
1681 }
1682
1683 if (props[TIPC_NLA_PROP_TOL]) {
1684 u32 tol;
1685
1686 tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1687 link->tolerance = tol;
1688 tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0);
1689 }
1690 if (props[TIPC_NLA_PROP_PRIO]) {
1691 u32 prio;
1692
1693 prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1694 link->priority = prio;
1695 tipc_link_proto_xmit(link, STATE_MSG, 0, 0, 0, prio);
1696 }
1697 if (props[TIPC_NLA_PROP_WIN]) {
1698 u32 win;
1699
1700 win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1701 tipc_link_set_queue_limits(link, win);
1702 }
1703 }
1704
1705out:
1706 tipc_node_read_unlock(node);
1707
1708 return res;
1709}
1710
1711int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info)
1712{
1713 struct net *net = genl_info_net(info);
1714 struct tipc_nl_msg msg;
1715 char *name;
1716 int err;
1717
1718 msg.portid = info->snd_portid;
1719 msg.seq = info->snd_seq;
1720
1721 if (!info->attrs[TIPC_NLA_LINK_NAME])
1722 return -EINVAL;
1723 name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]);
1724
1725 msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1726 if (!msg.skb)
1727 return -ENOMEM;
1728
1729 if (strcmp(name, tipc_bclink_name) == 0) {
1730 err = tipc_nl_add_bc_link(net, &msg);
1731 if (err) {
1732 nlmsg_free(msg.skb);
1733 return err;
1734 }
1735 } else {
1736 int bearer_id;
1737 struct tipc_node *node;
1738 struct tipc_link *link;
1739
1740 node = tipc_link_find_owner(net, name, &bearer_id);
1741 if (!node)
1742 return -EINVAL;
1743
1744 tipc_node_read_lock(node);
1745 link = node->links[bearer_id].link;
1746 if (!link) {
1747 tipc_node_read_unlock(node);
1748 nlmsg_free(msg.skb);
1749 return -EINVAL;
1750 }
1751
1752 err = __tipc_nl_add_link(net, &msg, link, 0);
1753 tipc_node_read_unlock(node);
1754 if (err) {
1755 nlmsg_free(msg.skb);
1756 return err;
1757 }
1758 }
1759
1760 return genlmsg_reply(msg.skb, info);
1761}
1762
1763int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info)
1764{
1765 int err;
1766 char *link_name;
1767 unsigned int bearer_id;
1768 struct tipc_link *link;
1769 struct tipc_node *node;
1770 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
1771 struct net *net = sock_net(skb->sk);
1772 struct tipc_link_entry *le;
1773
1774 if (!info->attrs[TIPC_NLA_LINK])
1775 return -EINVAL;
1776
1777 err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX,
1778 info->attrs[TIPC_NLA_LINK],
1779 tipc_nl_link_policy);
1780 if (err)
1781 return err;
1782
1783 if (!attrs[TIPC_NLA_LINK_NAME])
1784 return -EINVAL;
1785
1786 link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
1787
1788 if (strcmp(link_name, tipc_bclink_name) == 0) {
1789 err = tipc_bclink_reset_stats(net);
1790 if (err)
1791 return err;
1792 return 0;
1793 }
1794
1795 node = tipc_link_find_owner(net, link_name, &bearer_id);
1796 if (!node)
1797 return -EINVAL;
1798
1799 le = &node->links[bearer_id];
1800 tipc_node_read_lock(node);
1801 spin_lock_bh(&le->lock);
1802 link = node->links[bearer_id].link;
1803 if (!link) {
1804 spin_unlock_bh(&le->lock);
1805 tipc_node_read_unlock(node);
1806 return -EINVAL;
1807 }
1808 link_reset_statistics(link);
1809 spin_unlock_bh(&le->lock);
1810 tipc_node_read_unlock(node);
1811 return 0;
1812}
1813
1814/* Caller should hold node lock */
1815static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg,
1816 struct tipc_node *node, u32 *prev_link)
1817{
1818 u32 i;
1819 int err;
1820
1821 for (i = *prev_link; i < MAX_BEARERS; i++) {
1822 *prev_link = i;
1823
1824 if (!node->links[i].link)
1825 continue;
1826
1827 err = __tipc_nl_add_link(net, msg,
1828 node->links[i].link, NLM_F_MULTI);
1829 if (err)
1830 return err;
1831 }
1832 *prev_link = 0;
1833
1834 return 0;
1835}
1836
1837int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb)
1838{
1839 struct net *net = sock_net(skb->sk);
1840 struct tipc_net *tn = net_generic(net, tipc_net_id);
1841 struct tipc_node *node;
1842 struct tipc_nl_msg msg;
1843 u32 prev_node = cb->args[0];
1844 u32 prev_link = cb->args[1];
1845 int done = cb->args[2];
1846 int err;
1847
1848 if (done)
1849 return 0;
1850
1851 msg.skb = skb;
1852 msg.portid = NETLINK_CB(cb->skb).portid;
1853 msg.seq = cb->nlh->nlmsg_seq;
1854
1855 rcu_read_lock();
1856 if (prev_node) {
1857 node = tipc_node_find(net, prev_node);
1858 if (!node) {
1859 /* We never set seq or call nl_dump_check_consistent()
1860 * this means that setting prev_seq here will cause the
1861 * consistence check to fail in the netlink callback
1862 * handler. Resulting in the last NLMSG_DONE message
1863 * having the NLM_F_DUMP_INTR flag set.
1864 */
1865 cb->prev_seq = 1;
1866 goto out;
1867 }
1868 tipc_node_put(node);
1869
1870 list_for_each_entry_continue_rcu(node, &tn->node_list,
1871 list) {
1872 tipc_node_read_lock(node);
1873 err = __tipc_nl_add_node_links(net, &msg, node,
1874 &prev_link);
1875 tipc_node_read_unlock(node);
1876 if (err)
1877 goto out;
1878
1879 prev_node = node->addr;
1880 }
1881 } else {
1882 err = tipc_nl_add_bc_link(net, &msg);
1883 if (err)
1884 goto out;
1885
1886 list_for_each_entry_rcu(node, &tn->node_list, list) {
1887 tipc_node_read_lock(node);
1888 err = __tipc_nl_add_node_links(net, &msg, node,
1889 &prev_link);
1890 tipc_node_read_unlock(node);
1891 if (err)
1892 goto out;
1893
1894 prev_node = node->addr;
1895 }
1896 }
1897 done = 1;
1898out:
1899 rcu_read_unlock();
1900
1901 cb->args[0] = prev_node;
1902 cb->args[1] = prev_link;
1903 cb->args[2] = done;
1904
1905 return skb->len;
1906}