diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.h | 1 | ||||
-rw-r--r-- | net/tipc/link.c | 337 | ||||
-rw-r--r-- | net/tipc/link.h | 9 | ||||
-rw-r--r-- | net/tipc/netlink.c | 6 | ||||
-rw-r--r-- | net/tipc/netlink_compat.c | 4 | ||||
-rw-r--r-- | net/tipc/node.c | 449 | ||||
-rw-r--r-- | net/tipc/node.h | 117 |
7 files changed, 462 insertions, 461 deletions
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 2855b9356a15..1944c6c00bb9 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -43,6 +43,7 @@ struct tipc_node; | |||
43 | struct tipc_msg; | 43 | struct tipc_msg; |
44 | struct tipc_nl_msg; | 44 | struct tipc_nl_msg; |
45 | struct tipc_node_map; | 45 | struct tipc_node_map; |
46 | extern const char tipc_bclink_name[]; | ||
46 | 47 | ||
47 | int tipc_bcast_init(struct net *net); | 48 | int tipc_bcast_init(struct net *net); |
48 | void tipc_bcast_reinit(struct net *net); | 49 | void tipc_bcast_reinit(struct net *net); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 1dda46e5dd83..c513a807b3a1 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -50,23 +50,6 @@ | |||
50 | */ | 50 | */ |
51 | static const char *link_co_err = "Link tunneling error, "; | 51 | static const char *link_co_err = "Link tunneling error, "; |
52 | static const char *link_rst_msg = "Resetting link "; | 52 | static const char *link_rst_msg = "Resetting link "; |
53 | static const char tipc_bclink_name[] = "broadcast-link"; | ||
54 | |||
55 | static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { | ||
56 | [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC }, | ||
57 | [TIPC_NLA_LINK_NAME] = { | ||
58 | .type = NLA_STRING, | ||
59 | .len = TIPC_MAX_LINK_NAME | ||
60 | }, | ||
61 | [TIPC_NLA_LINK_MTU] = { .type = NLA_U32 }, | ||
62 | [TIPC_NLA_LINK_BROADCAST] = { .type = NLA_FLAG }, | ||
63 | [TIPC_NLA_LINK_UP] = { .type = NLA_FLAG }, | ||
64 | [TIPC_NLA_LINK_ACTIVE] = { .type = NLA_FLAG }, | ||
65 | [TIPC_NLA_LINK_PROP] = { .type = NLA_NESTED }, | ||
66 | [TIPC_NLA_LINK_STATS] = { .type = NLA_NESTED }, | ||
67 | [TIPC_NLA_LINK_RX] = { .type = NLA_U32 }, | ||
68 | [TIPC_NLA_LINK_TX] = { .type = NLA_U32 } | ||
69 | }; | ||
70 | 53 | ||
71 | /* Properties valid for media, bearar and link */ | 54 | /* Properties valid for media, bearar and link */ |
72 | static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { | 55 | static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { |
@@ -117,7 +100,6 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
117 | static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | 100 | static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, |
118 | u16 rcvgap, int tolerance, int priority, | 101 | u16 rcvgap, int tolerance, int priority, |
119 | struct sk_buff_head *xmitq); | 102 | struct sk_buff_head *xmitq); |
120 | static void link_reset_statistics(struct tipc_link *l_ptr); | ||
121 | static void link_print(struct tipc_link *l_ptr, const char *str); | 103 | static void link_print(struct tipc_link *l_ptr, const char *str); |
122 | static void tipc_link_build_nack_msg(struct tipc_link *l, | 104 | static void tipc_link_build_nack_msg(struct tipc_link *l, |
123 | struct sk_buff_head *xmitq); | 105 | struct sk_buff_head *xmitq); |
@@ -1527,49 +1509,11 @@ void tipc_link_set_queue_limits(struct tipc_link *l, u32 win) | |||
1527 | l->backlog[TIPC_SYSTEM_IMPORTANCE].limit = max_bulk; | 1509 | l->backlog[TIPC_SYSTEM_IMPORTANCE].limit = max_bulk; |
1528 | } | 1510 | } |
1529 | 1511 | ||
1530 | /* tipc_link_find_owner - locate owner node of link by link's name | ||
1531 | * @net: the applicable net namespace | ||
1532 | * @name: pointer to link name string | ||
1533 | * @bearer_id: pointer to index in 'node->links' array where the link was found. | ||
1534 | * | ||
1535 | * Returns pointer to node owning the link, or 0 if no matching link is found. | ||
1536 | */ | ||
1537 | static struct tipc_node *tipc_link_find_owner(struct net *net, | ||
1538 | const char *link_name, | ||
1539 | unsigned int *bearer_id) | ||
1540 | { | ||
1541 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1542 | struct tipc_link *l_ptr; | ||
1543 | struct tipc_node *n_ptr; | ||
1544 | struct tipc_node *found_node = NULL; | ||
1545 | int i; | ||
1546 | |||
1547 | *bearer_id = 0; | ||
1548 | rcu_read_lock(); | ||
1549 | list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { | ||
1550 | tipc_node_read_lock(n_ptr); | ||
1551 | for (i = 0; i < MAX_BEARERS; i++) { | ||
1552 | l_ptr = n_ptr->links[i].link; | ||
1553 | if (l_ptr && !strcmp(l_ptr->name, link_name)) { | ||
1554 | *bearer_id = i; | ||
1555 | found_node = n_ptr; | ||
1556 | break; | ||
1557 | } | ||
1558 | } | ||
1559 | tipc_node_read_unlock(n_ptr); | ||
1560 | if (found_node) | ||
1561 | break; | ||
1562 | } | ||
1563 | rcu_read_unlock(); | ||
1564 | |||
1565 | return found_node; | ||
1566 | } | ||
1567 | |||
1568 | /** | 1512 | /** |
1569 | * link_reset_statistics - reset link statistics | 1513 | * link_reset_statistics - reset link statistics |
1570 | * @l_ptr: pointer to link | 1514 | * @l_ptr: pointer to link |
1571 | */ | 1515 | */ |
1572 | static void link_reset_statistics(struct tipc_link *l_ptr) | 1516 | void link_reset_statistics(struct tipc_link *l_ptr) |
1573 | { | 1517 | { |
1574 | memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); | 1518 | memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); |
1575 | l_ptr->stats.sent_info = l_ptr->snd_nxt; | 1519 | l_ptr->stats.sent_info = l_ptr->snd_nxt; |
@@ -1626,84 +1570,6 @@ int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]) | |||
1626 | return 0; | 1570 | return 0; |
1627 | } | 1571 | } |
1628 | 1572 | ||
1629 | int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) | ||
1630 | { | ||
1631 | int err; | ||
1632 | int res = 0; | ||
1633 | int bearer_id; | ||
1634 | char *name; | ||
1635 | struct tipc_link *link; | ||
1636 | struct tipc_node *node; | ||
1637 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; | ||
1638 | struct net *net = sock_net(skb->sk); | ||
1639 | |||
1640 | if (!info->attrs[TIPC_NLA_LINK]) | ||
1641 | return -EINVAL; | ||
1642 | |||
1643 | err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, | ||
1644 | info->attrs[TIPC_NLA_LINK], | ||
1645 | tipc_nl_link_policy); | ||
1646 | if (err) | ||
1647 | return err; | ||
1648 | |||
1649 | if (!attrs[TIPC_NLA_LINK_NAME]) | ||
1650 | return -EINVAL; | ||
1651 | |||
1652 | name = nla_data(attrs[TIPC_NLA_LINK_NAME]); | ||
1653 | |||
1654 | if (strcmp(name, tipc_bclink_name) == 0) | ||
1655 | return tipc_nl_bc_link_set(net, attrs); | ||
1656 | |||
1657 | node = tipc_link_find_owner(net, name, &bearer_id); | ||
1658 | if (!node) | ||
1659 | return -EINVAL; | ||
1660 | |||
1661 | tipc_node_read_lock(node); | ||
1662 | |||
1663 | link = node->links[bearer_id].link; | ||
1664 | if (!link) { | ||
1665 | res = -EINVAL; | ||
1666 | goto out; | ||
1667 | } | ||
1668 | |||
1669 | if (attrs[TIPC_NLA_LINK_PROP]) { | ||
1670 | struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; | ||
1671 | |||
1672 | err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], | ||
1673 | props); | ||
1674 | if (err) { | ||
1675 | res = err; | ||
1676 | goto out; | ||
1677 | } | ||
1678 | |||
1679 | if (props[TIPC_NLA_PROP_TOL]) { | ||
1680 | u32 tol; | ||
1681 | |||
1682 | tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); | ||
1683 | link->tolerance = tol; | ||
1684 | tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0); | ||
1685 | } | ||
1686 | if (props[TIPC_NLA_PROP_PRIO]) { | ||
1687 | u32 prio; | ||
1688 | |||
1689 | prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); | ||
1690 | link->priority = prio; | ||
1691 | tipc_link_proto_xmit(link, STATE_MSG, 0, 0, 0, prio); | ||
1692 | } | ||
1693 | if (props[TIPC_NLA_PROP_WIN]) { | ||
1694 | u32 win; | ||
1695 | |||
1696 | win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); | ||
1697 | tipc_link_set_queue_limits(link, win); | ||
1698 | } | ||
1699 | } | ||
1700 | |||
1701 | out: | ||
1702 | tipc_node_read_unlock(node); | ||
1703 | |||
1704 | return res; | ||
1705 | } | ||
1706 | |||
1707 | static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s) | 1573 | static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s) |
1708 | { | 1574 | { |
1709 | int i; | 1575 | int i; |
@@ -1770,8 +1636,8 @@ msg_full: | |||
1770 | } | 1636 | } |
1771 | 1637 | ||
1772 | /* Caller should hold appropriate locks to protect the link */ | 1638 | /* Caller should hold appropriate locks to protect the link */ |
1773 | static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | 1639 | int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, |
1774 | struct tipc_link *link, int nlflags) | 1640 | struct tipc_link *link, int nlflags) |
1775 | { | 1641 | { |
1776 | int err; | 1642 | int err; |
1777 | void *hdr; | 1643 | void *hdr; |
@@ -1839,200 +1705,3 @@ msg_full: | |||
1839 | 1705 | ||
1840 | return -EMSGSIZE; | 1706 | return -EMSGSIZE; |
1841 | } | 1707 | } |
1842 | |||
1843 | /* Caller should hold node lock */ | ||
1844 | static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg, | ||
1845 | struct tipc_node *node, u32 *prev_link) | ||
1846 | { | ||
1847 | u32 i; | ||
1848 | int err; | ||
1849 | |||
1850 | for (i = *prev_link; i < MAX_BEARERS; i++) { | ||
1851 | *prev_link = i; | ||
1852 | |||
1853 | if (!node->links[i].link) | ||
1854 | continue; | ||
1855 | |||
1856 | err = __tipc_nl_add_link(net, msg, | ||
1857 | node->links[i].link, NLM_F_MULTI); | ||
1858 | if (err) | ||
1859 | return err; | ||
1860 | } | ||
1861 | *prev_link = 0; | ||
1862 | |||
1863 | return 0; | ||
1864 | } | ||
1865 | |||
1866 | int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
1867 | { | ||
1868 | struct net *net = sock_net(skb->sk); | ||
1869 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
1870 | struct tipc_node *node; | ||
1871 | struct tipc_nl_msg msg; | ||
1872 | u32 prev_node = cb->args[0]; | ||
1873 | u32 prev_link = cb->args[1]; | ||
1874 | int done = cb->args[2]; | ||
1875 | int err; | ||
1876 | |||
1877 | if (done) | ||
1878 | return 0; | ||
1879 | |||
1880 | msg.skb = skb; | ||
1881 | msg.portid = NETLINK_CB(cb->skb).portid; | ||
1882 | msg.seq = cb->nlh->nlmsg_seq; | ||
1883 | |||
1884 | rcu_read_lock(); | ||
1885 | if (prev_node) { | ||
1886 | node = tipc_node_find(net, prev_node); | ||
1887 | if (!node) { | ||
1888 | /* We never set seq or call nl_dump_check_consistent() | ||
1889 | * this means that setting prev_seq here will cause the | ||
1890 | * consistence check to fail in the netlink callback | ||
1891 | * handler. Resulting in the last NLMSG_DONE message | ||
1892 | * having the NLM_F_DUMP_INTR flag set. | ||
1893 | */ | ||
1894 | cb->prev_seq = 1; | ||
1895 | goto out; | ||
1896 | } | ||
1897 | tipc_node_put(node); | ||
1898 | |||
1899 | list_for_each_entry_continue_rcu(node, &tn->node_list, | ||
1900 | list) { | ||
1901 | tipc_node_read_lock(node); | ||
1902 | err = __tipc_nl_add_node_links(net, &msg, node, | ||
1903 | &prev_link); | ||
1904 | tipc_node_read_unlock(node); | ||
1905 | if (err) | ||
1906 | goto out; | ||
1907 | |||
1908 | prev_node = node->addr; | ||
1909 | } | ||
1910 | } else { | ||
1911 | err = tipc_nl_add_bc_link(net, &msg); | ||
1912 | if (err) | ||
1913 | goto out; | ||
1914 | |||
1915 | list_for_each_entry_rcu(node, &tn->node_list, list) { | ||
1916 | tipc_node_read_lock(node); | ||
1917 | err = __tipc_nl_add_node_links(net, &msg, node, | ||
1918 | &prev_link); | ||
1919 | tipc_node_read_unlock(node); | ||
1920 | if (err) | ||
1921 | goto out; | ||
1922 | |||
1923 | prev_node = node->addr; | ||
1924 | } | ||
1925 | } | ||
1926 | done = 1; | ||
1927 | out: | ||
1928 | rcu_read_unlock(); | ||
1929 | |||
1930 | cb->args[0] = prev_node; | ||
1931 | cb->args[1] = prev_link; | ||
1932 | cb->args[2] = done; | ||
1933 | |||
1934 | return skb->len; | ||
1935 | } | ||
1936 | |||
1937 | int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) | ||
1938 | { | ||
1939 | struct net *net = genl_info_net(info); | ||
1940 | struct tipc_nl_msg msg; | ||
1941 | char *name; | ||
1942 | int err; | ||
1943 | |||
1944 | msg.portid = info->snd_portid; | ||
1945 | msg.seq = info->snd_seq; | ||
1946 | |||
1947 | if (!info->attrs[TIPC_NLA_LINK_NAME]) | ||
1948 | return -EINVAL; | ||
1949 | name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]); | ||
1950 | |||
1951 | msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
1952 | if (!msg.skb) | ||
1953 | return -ENOMEM; | ||
1954 | |||
1955 | if (strcmp(name, tipc_bclink_name) == 0) { | ||
1956 | err = tipc_nl_add_bc_link(net, &msg); | ||
1957 | if (err) { | ||
1958 | nlmsg_free(msg.skb); | ||
1959 | return err; | ||
1960 | } | ||
1961 | } else { | ||
1962 | int bearer_id; | ||
1963 | struct tipc_node *node; | ||
1964 | struct tipc_link *link; | ||
1965 | |||
1966 | node = tipc_link_find_owner(net, name, &bearer_id); | ||
1967 | if (!node) | ||
1968 | return -EINVAL; | ||
1969 | |||
1970 | tipc_node_read_lock(node); | ||
1971 | link = node->links[bearer_id].link; | ||
1972 | if (!link) { | ||
1973 | tipc_node_read_unlock(node); | ||
1974 | nlmsg_free(msg.skb); | ||
1975 | return -EINVAL; | ||
1976 | } | ||
1977 | |||
1978 | err = __tipc_nl_add_link(net, &msg, link, 0); | ||
1979 | tipc_node_read_unlock(node); | ||
1980 | if (err) { | ||
1981 | nlmsg_free(msg.skb); | ||
1982 | return err; | ||
1983 | } | ||
1984 | } | ||
1985 | |||
1986 | return genlmsg_reply(msg.skb, info); | ||
1987 | } | ||
1988 | |||
1989 | int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) | ||
1990 | { | ||
1991 | int err; | ||
1992 | char *link_name; | ||
1993 | unsigned int bearer_id; | ||
1994 | struct tipc_link *link; | ||
1995 | struct tipc_node *node; | ||
1996 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; | ||
1997 | struct net *net = sock_net(skb->sk); | ||
1998 | struct tipc_link_entry *le; | ||
1999 | |||
2000 | if (!info->attrs[TIPC_NLA_LINK]) | ||
2001 | return -EINVAL; | ||
2002 | |||
2003 | err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, | ||
2004 | info->attrs[TIPC_NLA_LINK], | ||
2005 | tipc_nl_link_policy); | ||
2006 | if (err) | ||
2007 | return err; | ||
2008 | |||
2009 | if (!attrs[TIPC_NLA_LINK_NAME]) | ||
2010 | return -EINVAL; | ||
2011 | |||
2012 | link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]); | ||
2013 | |||
2014 | if (strcmp(link_name, tipc_bclink_name) == 0) { | ||
2015 | err = tipc_bclink_reset_stats(net); | ||
2016 | if (err) | ||
2017 | return err; | ||
2018 | return 0; | ||
2019 | } | ||
2020 | |||
2021 | node = tipc_link_find_owner(net, link_name, &bearer_id); | ||
2022 | if (!node) | ||
2023 | return -EINVAL; | ||
2024 | |||
2025 | le = &node->links[bearer_id]; | ||
2026 | tipc_node_read_lock(node); | ||
2027 | spin_lock_bh(&le->lock); | ||
2028 | link = le->link; | ||
2029 | if (!link) { | ||
2030 | spin_unlock_bh(&le->lock); | ||
2031 | tipc_node_read_unlock(node); | ||
2032 | return -EINVAL; | ||
2033 | } | ||
2034 | link_reset_statistics(link); | ||
2035 | spin_unlock_bh(&le->lock); | ||
2036 | tipc_node_read_unlock(node); | ||
2037 | return 0; | ||
2038 | } | ||
diff --git a/net/tipc/link.h b/net/tipc/link.h index 66d859b66c84..a7ee806e1ee4 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -249,14 +249,15 @@ bool tipc_link_is_failingover(struct tipc_link *l); | |||
249 | bool tipc_link_is_blocked(struct tipc_link *l); | 249 | bool tipc_link_is_blocked(struct tipc_link *l); |
250 | void tipc_link_set_active(struct tipc_link *l, bool active); | 250 | void tipc_link_set_active(struct tipc_link *l, bool active); |
251 | void tipc_link_reset(struct tipc_link *l_ptr); | 251 | void tipc_link_reset(struct tipc_link *l_ptr); |
252 | void link_reset_statistics(struct tipc_link *l); | ||
252 | int tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list, | 253 | int tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list, |
253 | struct sk_buff_head *xmitq); | 254 | struct sk_buff_head *xmitq); |
255 | void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, int probe_msg, | ||
256 | u32 gap, u32 tolerance, u32 priority); | ||
254 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 window); | 257 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 window); |
255 | 258 | int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | |
259 | struct tipc_link *link, int nlflags); | ||
256 | int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb); | 260 | int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb); |
257 | int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info); | ||
258 | int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info); | ||
259 | int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info); | ||
260 | int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); | 261 | int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); |
261 | int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq); | 262 | int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq); |
262 | int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, | 263 | int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 7f6475efc984..29dfcc94b6a5 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -101,18 +101,18 @@ static const struct genl_ops tipc_genl_v2_ops[] = { | |||
101 | }, | 101 | }, |
102 | { | 102 | { |
103 | .cmd = TIPC_NL_LINK_GET, | 103 | .cmd = TIPC_NL_LINK_GET, |
104 | .doit = tipc_nl_link_get, | 104 | .doit = tipc_nl_node_get_link, |
105 | .dumpit = tipc_nl_link_dump, | 105 | .dumpit = tipc_nl_link_dump, |
106 | .policy = tipc_nl_policy, | 106 | .policy = tipc_nl_policy, |
107 | }, | 107 | }, |
108 | { | 108 | { |
109 | .cmd = TIPC_NL_LINK_SET, | 109 | .cmd = TIPC_NL_LINK_SET, |
110 | .doit = tipc_nl_link_set, | 110 | .doit = tipc_nl_node_set_link, |
111 | .policy = tipc_nl_policy, | 111 | .policy = tipc_nl_policy, |
112 | }, | 112 | }, |
113 | { | 113 | { |
114 | .cmd = TIPC_NL_LINK_RESET_STATS, | 114 | .cmd = TIPC_NL_LINK_RESET_STATS, |
115 | .doit = tipc_nl_link_reset_stats, | 115 | .doit = tipc_nl_node_reset_link_stats, |
116 | .policy = tipc_nl_policy, | 116 | .policy = tipc_nl_policy, |
117 | }, | 117 | }, |
118 | { | 118 | { |
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 1eadc95e1132..acda1ce57151 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
@@ -1036,12 +1036,12 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) | |||
1036 | case TIPC_CMD_SET_LINK_PRI: | 1036 | case TIPC_CMD_SET_LINK_PRI: |
1037 | case TIPC_CMD_SET_LINK_WINDOW: | 1037 | case TIPC_CMD_SET_LINK_WINDOW: |
1038 | msg->req_type = TIPC_TLV_LINK_CONFIG; | 1038 | msg->req_type = TIPC_TLV_LINK_CONFIG; |
1039 | doit.doit = tipc_nl_link_set; | 1039 | doit.doit = tipc_nl_node_set_link; |
1040 | doit.transcode = tipc_nl_compat_link_set; | 1040 | doit.transcode = tipc_nl_compat_link_set; |
1041 | return tipc_nl_compat_doit(&doit, msg); | 1041 | return tipc_nl_compat_doit(&doit, msg); |
1042 | case TIPC_CMD_RESET_LINK_STATS: | 1042 | case TIPC_CMD_RESET_LINK_STATS: |
1043 | msg->req_type = TIPC_TLV_LINK_NAME; | 1043 | msg->req_type = TIPC_TLV_LINK_NAME; |
1044 | doit.doit = tipc_nl_link_reset_stats; | 1044 | doit.doit = tipc_nl_node_reset_link_stats; |
1045 | doit.transcode = tipc_nl_compat_link_reset_stats; | 1045 | doit.transcode = tipc_nl_compat_link_reset_stats; |
1046 | return tipc_nl_compat_doit(&doit, msg); | 1046 | return tipc_nl_compat_doit(&doit, msg); |
1047 | case TIPC_CMD_SHOW_NAME_TABLE: | 1047 | case TIPC_CMD_SHOW_NAME_TABLE: |
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 | */ | ||
55 | enum { | ||
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 | |||
62 | struct 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 | |||
70 | struct 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 | */ | ||
101 | struct 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 | */ |
47 | enum { | 128 | enum { |
@@ -75,6 +156,9 @@ static void node_lost_contact(struct tipc_node *n, struct sk_buff_head *inputq); | |||
75 | static void tipc_node_delete(struct tipc_node *node); | 156 | static void tipc_node_delete(struct tipc_node *node); |
76 | static void tipc_node_timeout(unsigned long data); | 157 | static void tipc_node_timeout(unsigned long data); |
77 | static void tipc_node_fsm_evt(struct tipc_node *n, int evt); | 158 | static void tipc_node_fsm_evt(struct tipc_node *n, int evt); |
159 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr); | ||
160 | static void tipc_node_put(struct tipc_node *node); | ||
161 | static bool tipc_node_is_up(struct tipc_node *n); | ||
78 | 162 | ||
79 | struct tipc_sock_conn { | 163 | struct 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 | ||
170 | static 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 | |||
86 | static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { | 186 | static 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 | ||
192 | static 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 | |||
202 | int 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 | ||
110 | void tipc_node_put(struct tipc_node *node) | 236 | static 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 | */ |
123 | struct tipc_node *tipc_node_find(struct net *net, u32 addr) | 249 | static 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 | ||
144 | void tipc_node_read_lock(struct tipc_node *n) | 270 | static 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 | ||
149 | void tipc_node_read_unlock(struct tipc_node *n) | 275 | static 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 | ||
591 | bool tipc_node_is_up(struct tipc_node *n) | 717 | static 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 | */ | ||
1602 | static 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 | |||
1633 | int 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 | |||
1705 | out: | ||
1706 | tipc_node_read_unlock(node); | ||
1707 | |||
1708 | return res; | ||
1709 | } | ||
1710 | |||
1711 | int 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 | |||
1763 | int 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 */ | ||
1815 | static 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 | |||
1837 | int 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; | ||
1898 | out: | ||
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 | } | ||
diff --git a/net/tipc/node.h b/net/tipc/node.h index 651a1581a210..1fbed29d9a25 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -42,23 +42,8 @@ | |||
42 | #include "bearer.h" | 42 | #include "bearer.h" |
43 | #include "msg.h" | 43 | #include "msg.h" |
44 | 44 | ||
45 | /* Out-of-range value for node signature */ | ||
46 | #define INVALID_NODE_SIG 0x10000 | ||
47 | |||
48 | #define INVALID_BEARER_ID -1 | 45 | #define INVALID_BEARER_ID -1 |
49 | 46 | ||
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 | */ | ||
55 | enum { | ||
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 | |||
62 | /* Optional capabilities supported by this code version | 47 | /* Optional capabilities supported by this code version |
63 | */ | 48 | */ |
64 | enum { | 49 | enum { |
@@ -67,72 +52,6 @@ enum { | |||
67 | 52 | ||
68 | #define TIPC_NODE_CAPABILITIES TIPC_BCAST_SYNCH | 53 | #define TIPC_NODE_CAPABILITIES TIPC_BCAST_SYNCH |
69 | 54 | ||
70 | struct tipc_link_entry { | ||
71 | struct tipc_link *link; | ||
72 | spinlock_t lock; /* per-link */ | ||
73 | u32 mtu; | ||
74 | struct sk_buff_head inputq; | ||
75 | struct tipc_media_addr maddr; | ||
76 | }; | ||
77 | |||
78 | struct tipc_bclink_entry { | ||
79 | struct tipc_link *link; | ||
80 | struct sk_buff_head inputq1; | ||
81 | struct sk_buff_head arrvq; | ||
82 | struct sk_buff_head inputq2; | ||
83 | struct sk_buff_head namedq; | ||
84 | }; | ||
85 | |||
86 | /** | ||
87 | * struct tipc_node - TIPC node structure | ||
88 | * @addr: network address of node | ||
89 | * @ref: reference counter to node object | ||
90 | * @lock: rwlock governing access to structure | ||
91 | * @net: the applicable net namespace | ||
92 | * @hash: links to adjacent nodes in unsorted hash chain | ||
93 | * @inputq: pointer to input queue containing messages for msg event | ||
94 | * @namedq: pointer to name table input queue with name table messages | ||
95 | * @active_links: bearer ids of active links, used as index into links[] array | ||
96 | * @links: array containing references to all links to node | ||
97 | * @action_flags: bit mask of different types of node actions | ||
98 | * @state: connectivity state vs peer node | ||
99 | * @sync_point: sequence number where synch/failover is finished | ||
100 | * @list: links to adjacent nodes in sorted list of cluster's nodes | ||
101 | * @working_links: number of working links to node (both active and standby) | ||
102 | * @link_cnt: number of links to node | ||
103 | * @capabilities: bitmap, indicating peer node's functional capabilities | ||
104 | * @signature: node instance identifier | ||
105 | * @link_id: local and remote bearer ids of changing link, if any | ||
106 | * @publ_list: list of publications | ||
107 | * @rcu: rcu struct for tipc_node | ||
108 | */ | ||
109 | struct tipc_node { | ||
110 | u32 addr; | ||
111 | struct kref kref; | ||
112 | rwlock_t lock; | ||
113 | struct net *net; | ||
114 | struct hlist_node hash; | ||
115 | int active_links[2]; | ||
116 | struct tipc_link_entry links[MAX_BEARERS]; | ||
117 | struct tipc_bclink_entry bc_entry; | ||
118 | int action_flags; | ||
119 | struct list_head list; | ||
120 | int state; | ||
121 | u16 sync_point; | ||
122 | int link_cnt; | ||
123 | u16 working_links; | ||
124 | u16 capabilities; | ||
125 | u32 signature; | ||
126 | u32 link_id; | ||
127 | struct list_head publ_list; | ||
128 | struct list_head conn_sks; | ||
129 | unsigned long keepalive_intv; | ||
130 | struct timer_list timer; | ||
131 | struct rcu_head rcu; | ||
132 | }; | ||
133 | |||
134 | struct tipc_node *tipc_node_find(struct net *net, u32 addr); | ||
135 | void tipc_node_put(struct tipc_node *node); | ||
136 | void tipc_node_stop(struct net *net); | 55 | void tipc_node_stop(struct net *net); |
137 | void tipc_node_check_dest(struct net *net, u32 onode, | 56 | void tipc_node_check_dest(struct net *net, u32 onode, |
138 | struct tipc_bearer *bearer, | 57 | struct tipc_bearer *bearer, |
@@ -140,13 +59,8 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
140 | struct tipc_media_addr *maddr, | 59 | struct tipc_media_addr *maddr, |
141 | bool *respond, bool *dupl_addr); | 60 | bool *respond, bool *dupl_addr); |
142 | void tipc_node_delete_links(struct net *net, int bearer_id); | 61 | void tipc_node_delete_links(struct net *net, int bearer_id); |
143 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | ||
144 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | ||
145 | bool tipc_node_is_up(struct tipc_node *n); | ||
146 | int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, | 62 | int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, |
147 | char *linkname, size_t len); | 63 | char *linkname, size_t len); |
148 | void tipc_node_read_lock(struct tipc_node *n); | ||
149 | void tipc_node_read_unlock(struct tipc_node *node); | ||
150 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, | 64 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, |
151 | int selector); | 65 | int selector); |
152 | int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, | 66 | int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, |
@@ -156,33 +70,10 @@ void tipc_node_unsubscribe(struct net *net, struct list_head *subscr, u32 addr); | |||
156 | void tipc_node_broadcast(struct net *net, struct sk_buff *skb); | 70 | void tipc_node_broadcast(struct net *net, struct sk_buff *skb); |
157 | int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port); | 71 | int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port); |
158 | void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port); | 72 | void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port); |
73 | int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel); | ||
159 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb); | 74 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb); |
160 | 75 | int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info); | |
161 | static inline struct tipc_link *node_active_link(struct tipc_node *n, int sel) | 76 | int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info); |
162 | { | 77 | int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info); |
163 | int bearer_id = n->active_links[sel & 1]; | ||
164 | |||
165 | if (unlikely(bearer_id == INVALID_BEARER_ID)) | ||
166 | return NULL; | ||
167 | |||
168 | return n->links[bearer_id].link; | ||
169 | } | ||
170 | |||
171 | static inline unsigned int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel) | ||
172 | { | ||
173 | struct tipc_node *n; | ||
174 | int bearer_id; | ||
175 | unsigned int mtu = MAX_MSG_SIZE; | ||
176 | |||
177 | n = tipc_node_find(net, addr); | ||
178 | if (unlikely(!n)) | ||
179 | return mtu; | ||
180 | |||
181 | bearer_id = n->active_links[sel & 1]; | ||
182 | if (likely(bearer_id != INVALID_BEARER_ID)) | ||
183 | mtu = n->links[bearer_id].mtu; | ||
184 | tipc_node_put(n); | ||
185 | return mtu; | ||
186 | } | ||
187 | 78 | ||
188 | #endif | 79 | #endif |