summaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c337
1 files changed, 3 insertions, 334 deletions
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 */
51static const char *link_co_err = "Link tunneling error, "; 51static const char *link_co_err = "Link tunneling error, ";
52static const char *link_rst_msg = "Resetting link "; 52static const char *link_rst_msg = "Resetting link ";
53static const char tipc_bclink_name[] = "broadcast-link";
54
55static 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 */
72static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { 55static 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,
117static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, 100static 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);
120static void link_reset_statistics(struct tipc_link *l_ptr);
121static void link_print(struct tipc_link *l_ptr, const char *str); 103static void link_print(struct tipc_link *l_ptr, const char *str);
122static void tipc_link_build_nack_msg(struct tipc_link *l, 104static 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 */
1537static 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 */
1572static void link_reset_statistics(struct tipc_link *l_ptr) 1516void 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
1629int 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
1701out:
1702 tipc_node_read_unlock(node);
1703
1704 return res;
1705}
1706
1707static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s) 1573static 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 */
1773static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, 1639int __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 */
1844static 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
1866int 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;
1927out:
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
1937int 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
1989int 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}