aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c628
1 files changed, 316 insertions, 312 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 9efbdbde2b08..0c2944fb9ae0 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -45,28 +45,156 @@
45 45
46#include <linux/pkt_sched.h> 46#include <linux/pkt_sched.h>
47 47
48struct tipc_stats {
49 u32 sent_info; /* used in counting # sent packets */
50 u32 recv_info; /* used in counting # recv'd packets */
51 u32 sent_states;
52 u32 recv_states;
53 u32 sent_probes;
54 u32 recv_probes;
55 u32 sent_nacks;
56 u32 recv_nacks;
57 u32 sent_acks;
58 u32 sent_bundled;
59 u32 sent_bundles;
60 u32 recv_bundled;
61 u32 recv_bundles;
62 u32 retransmitted;
63 u32 sent_fragmented;
64 u32 sent_fragments;
65 u32 recv_fragmented;
66 u32 recv_fragments;
67 u32 link_congs; /* # port sends blocked by congestion */
68 u32 deferred_recv;
69 u32 duplicates;
70 u32 max_queue_sz; /* send queue size high water mark */
71 u32 accu_queue_sz; /* used for send queue size profiling */
72 u32 queue_sz_counts; /* used for send queue size profiling */
73 u32 msg_length_counts; /* used for message length profiling */
74 u32 msg_lengths_total; /* used for message length profiling */
75 u32 msg_length_profile[7]; /* used for msg. length profiling */
76};
77
78/**
79 * struct tipc_link - TIPC link data structure
80 * @addr: network address of link's peer node
81 * @name: link name character string
82 * @media_addr: media address to use when sending messages over link
83 * @timer: link timer
84 * @net: pointer to namespace struct
85 * @refcnt: reference counter for permanent references (owner node & timer)
86 * @peer_session: link session # being used by peer end of link
87 * @peer_bearer_id: bearer id used by link's peer endpoint
88 * @bearer_id: local bearer id used by link
89 * @tolerance: minimum link continuity loss needed to reset link [in ms]
90 * @keepalive_intv: link keepalive timer interval
91 * @abort_limit: # of unacknowledged continuity probes needed to reset link
92 * @state: current state of link FSM
93 * @peer_caps: bitmap describing capabilities of peer node
94 * @silent_intv_cnt: # of timer intervals without any reception from peer
95 * @proto_msg: template for control messages generated by link
96 * @pmsg: convenience pointer to "proto_msg" field
97 * @priority: current link priority
98 * @net_plane: current link network plane ('A' through 'H')
99 * @backlog_limit: backlog queue congestion thresholds (indexed by importance)
100 * @exp_msg_count: # of tunnelled messages expected during link changeover
101 * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset
102 * @mtu: current maximum packet size for this link
103 * @advertised_mtu: advertised own mtu when link is being established
104 * @transmitq: queue for sent, non-acked messages
105 * @backlogq: queue for messages waiting to be sent
106 * @snt_nxt: next sequence number to use for outbound messages
107 * @last_retransmitted: sequence number of most recently retransmitted message
108 * @stale_count: # of identical retransmit requests made by peer
109 * @ackers: # of peers that needs to ack each packet before it can be released
110 * @acked: # last packet acked by a certain peer. Used for broadcast.
111 * @rcv_nxt: next sequence number to expect for inbound messages
112 * @deferred_queue: deferred queue saved OOS b'cast message received from node
113 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
114 * @inputq: buffer queue for messages to be delivered upwards
115 * @namedq: buffer queue for name table messages to be delivered upwards
116 * @next_out: ptr to first unsent outbound message in queue
117 * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate
118 * @long_msg_seq_no: next identifier to use for outbound fragmented messages
119 * @reasm_buf: head of partially reassembled inbound message fragments
120 * @bc_rcvr: marks that this is a broadcast receiver link
121 * @stats: collects statistics regarding link activity
122 */
123struct tipc_link {
124 u32 addr;
125 char name[TIPC_MAX_LINK_NAME];
126 struct tipc_media_addr *media_addr;
127 struct net *net;
128
129 /* Management and link supervision data */
130 u32 peer_session;
131 u32 peer_bearer_id;
132 u32 bearer_id;
133 u32 tolerance;
134 unsigned long keepalive_intv;
135 u32 abort_limit;
136 u32 state;
137 u16 peer_caps;
138 bool active;
139 u32 silent_intv_cnt;
140 struct {
141 unchar hdr[INT_H_SIZE];
142 unchar body[TIPC_MAX_IF_NAME];
143 } proto_msg;
144 struct tipc_msg *pmsg;
145 u32 priority;
146 char net_plane;
147
148 /* Failover/synch */
149 u16 drop_point;
150 struct sk_buff *failover_reasm_skb;
151
152 /* Max packet negotiation */
153 u16 mtu;
154 u16 advertised_mtu;
155
156 /* Sending */
157 struct sk_buff_head transmq;
158 struct sk_buff_head backlogq;
159 struct {
160 u16 len;
161 u16 limit;
162 } backlog[5];
163 u16 snd_nxt;
164 u16 last_retransm;
165 u16 window;
166 u32 stale_count;
167
168 /* Reception */
169 u16 rcv_nxt;
170 u32 rcv_unacked;
171 struct sk_buff_head deferdq;
172 struct sk_buff_head *inputq;
173 struct sk_buff_head *namedq;
174
175 /* Congestion handling */
176 struct sk_buff_head wakeupq;
177
178 /* Fragmentation/reassembly */
179 struct sk_buff *reasm_buf;
180
181 /* Broadcast */
182 u16 ackers;
183 u16 acked;
184 struct tipc_link *bc_rcvlink;
185 struct tipc_link *bc_sndlink;
186 int nack_state;
187 bool bc_peer_is_up;
188
189 /* Statistics */
190 struct tipc_stats stats;
191};
192
48/* 193/*
49 * Error message prefixes 194 * Error message prefixes
50 */ 195 */
51static const char *link_co_err = "Link tunneling error, "; 196static const char *link_co_err = "Link tunneling error, ";
52static const char *link_rst_msg = "Resetting link "; 197static 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 198
71/* Properties valid for media, bearar and link */ 199/* Properties valid for media, bearar and link */
72static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { 200static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
@@ -117,8 +245,7 @@ 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, 245static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
118 u16 rcvgap, int tolerance, int priority, 246 u16 rcvgap, int tolerance, int priority,
119 struct sk_buff_head *xmitq); 247 struct sk_buff_head *xmitq);
120static void link_reset_statistics(struct tipc_link *l_ptr); 248static void link_print(struct tipc_link *l, const char *str);
121static void link_print(struct tipc_link *l_ptr, const char *str);
122static void tipc_link_build_nack_msg(struct tipc_link *l, 249static void tipc_link_build_nack_msg(struct tipc_link *l,
123 struct sk_buff_head *xmitq); 250 struct sk_buff_head *xmitq);
124static void tipc_link_build_bc_init_msg(struct tipc_link *l, 251static void tipc_link_build_bc_init_msg(struct tipc_link *l,
@@ -183,6 +310,36 @@ void tipc_link_set_active(struct tipc_link *l, bool active)
183 l->active = active; 310 l->active = active;
184} 311}
185 312
313u32 tipc_link_id(struct tipc_link *l)
314{
315 return l->peer_bearer_id << 16 | l->bearer_id;
316}
317
318int tipc_link_window(struct tipc_link *l)
319{
320 return l->window;
321}
322
323int tipc_link_prio(struct tipc_link *l)
324{
325 return l->priority;
326}
327
328unsigned long tipc_link_tolerance(struct tipc_link *l)
329{
330 return l->tolerance;
331}
332
333struct sk_buff_head *tipc_link_inputq(struct tipc_link *l)
334{
335 return l->inputq;
336}
337
338char tipc_link_plane(struct tipc_link *l)
339{
340 return l->net_plane;
341}
342
186void tipc_link_add_bc_peer(struct tipc_link *snd_l, 343void tipc_link_add_bc_peer(struct tipc_link *snd_l,
187 struct tipc_link *uc_l, 344 struct tipc_link *uc_l,
188 struct sk_buff_head *xmitq) 345 struct sk_buff_head *xmitq)
@@ -191,6 +348,7 @@ void tipc_link_add_bc_peer(struct tipc_link *snd_l,
191 348
192 snd_l->ackers++; 349 snd_l->ackers++;
193 rcv_l->acked = snd_l->snd_nxt - 1; 350 rcv_l->acked = snd_l->snd_nxt - 1;
351 snd_l->state = LINK_ESTABLISHED;
194 tipc_link_build_bc_init_msg(uc_l, xmitq); 352 tipc_link_build_bc_init_msg(uc_l, xmitq);
195} 353}
196 354
@@ -206,6 +364,7 @@ void tipc_link_remove_bc_peer(struct tipc_link *snd_l,
206 rcv_l->state = LINK_RESET; 364 rcv_l->state = LINK_RESET;
207 if (!snd_l->ackers) { 365 if (!snd_l->ackers) {
208 tipc_link_reset(snd_l); 366 tipc_link_reset(snd_l);
367 snd_l->state = LINK_RESET;
209 __skb_queue_purge(xmitq); 368 __skb_queue_purge(xmitq);
210 } 369 }
211} 370}
@@ -225,11 +384,31 @@ int tipc_link_mtu(struct tipc_link *l)
225 return l->mtu; 384 return l->mtu;
226} 385}
227 386
387u16 tipc_link_rcv_nxt(struct tipc_link *l)
388{
389 return l->rcv_nxt;
390}
391
392u16 tipc_link_acked(struct tipc_link *l)
393{
394 return l->acked;
395}
396
397char *tipc_link_name(struct tipc_link *l)
398{
399 return l->name;
400}
401
228static u32 link_own_addr(struct tipc_link *l) 402static u32 link_own_addr(struct tipc_link *l)
229{ 403{
230 return msg_prevnode(l->pmsg); 404 return msg_prevnode(l->pmsg);
231} 405}
232 406
407void tipc_link_reinit(struct tipc_link *l, u32 addr)
408{
409 msg_set_prevnode(l->pmsg, addr);
410}
411
233/** 412/**
234 * tipc_link_create - create a new link 413 * tipc_link_create - create a new link
235 * @n: pointer to associated node 414 * @n: pointer to associated node
@@ -692,7 +871,7 @@ void tipc_link_reset(struct tipc_link *l)
692 l->stats.recv_info = 0; 871 l->stats.recv_info = 0;
693 l->stale_count = 0; 872 l->stale_count = 0;
694 l->bc_peer_is_up = false; 873 l->bc_peer_is_up = false;
695 link_reset_statistics(l); 874 tipc_link_reset_stats(l);
696} 875}
697 876
698/** 877/**
@@ -1085,8 +1264,9 @@ drop:
1085/* 1264/*
1086 * Send protocol message to the other endpoint. 1265 * Send protocol message to the other endpoint.
1087 */ 1266 */
1088void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, int probe_msg, 1267static void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ,
1089 u32 gap, u32 tolerance, u32 priority) 1268 int probe_msg, u32 gap, u32 tolerance,
1269 u32 priority)
1090{ 1270{
1091 struct sk_buff *skb = NULL; 1271 struct sk_buff *skb = NULL;
1092 struct sk_buff_head xmitq; 1272 struct sk_buff_head xmitq;
@@ -1260,6 +1440,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1260 /* fall thru' */ 1440 /* fall thru' */
1261 1441
1262 case ACTIVATE_MSG: 1442 case ACTIVATE_MSG:
1443 skb_linearize(skb);
1444 hdr = buf_msg(skb);
1263 1445
1264 /* Complete own link name with peer's interface name */ 1446 /* Complete own link name with peer's interface name */
1265 if_name = strrchr(l->name, ':') + 1; 1447 if_name = strrchr(l->name, ':') + 1;
@@ -1525,53 +1707,17 @@ void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
1525 l->backlog[TIPC_SYSTEM_IMPORTANCE].limit = max_bulk; 1707 l->backlog[TIPC_SYSTEM_IMPORTANCE].limit = max_bulk;
1526} 1708}
1527 1709
1528/* tipc_link_find_owner - locate owner node of link by link's name
1529 * @net: the applicable net namespace
1530 * @name: pointer to link name string
1531 * @bearer_id: pointer to index in 'node->links' array where the link was found.
1532 *
1533 * Returns pointer to node owning the link, or 0 if no matching link is found.
1534 */
1535static struct tipc_node *tipc_link_find_owner(struct net *net,
1536 const char *link_name,
1537 unsigned int *bearer_id)
1538{
1539 struct tipc_net *tn = net_generic(net, tipc_net_id);
1540 struct tipc_link *l_ptr;
1541 struct tipc_node *n_ptr;
1542 struct tipc_node *found_node = NULL;
1543 int i;
1544
1545 *bearer_id = 0;
1546 rcu_read_lock();
1547 list_for_each_entry_rcu(n_ptr, &tn->node_list, list) {
1548 tipc_node_lock(n_ptr);
1549 for (i = 0; i < MAX_BEARERS; i++) {
1550 l_ptr = n_ptr->links[i].link;
1551 if (l_ptr && !strcmp(l_ptr->name, link_name)) {
1552 *bearer_id = i;
1553 found_node = n_ptr;
1554 break;
1555 }
1556 }
1557 tipc_node_unlock(n_ptr);
1558 if (found_node)
1559 break;
1560 }
1561 rcu_read_unlock();
1562
1563 return found_node;
1564}
1565
1566/** 1710/**
1567 * link_reset_statistics - reset link statistics 1711 * link_reset_stats - reset link statistics
1568 * @l_ptr: pointer to link 1712 * @l: pointer to link
1569 */ 1713 */
1570static void link_reset_statistics(struct tipc_link *l_ptr) 1714void tipc_link_reset_stats(struct tipc_link *l)
1571{ 1715{
1572 memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); 1716 memset(&l->stats, 0, sizeof(l->stats));
1573 l_ptr->stats.sent_info = l_ptr->snd_nxt; 1717 if (!link_is_bc_sndlink(l)) {
1574 l_ptr->stats.recv_info = l_ptr->rcv_nxt; 1718 l->stats.sent_info = l->snd_nxt;
1719 l->stats.recv_info = l->rcv_nxt;
1720 }
1575} 1721}
1576 1722
1577static void link_print(struct tipc_link *l, const char *str) 1723static void link_print(struct tipc_link *l, const char *str)
@@ -1624,84 +1770,6 @@ int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[])
1624 return 0; 1770 return 0;
1625} 1771}
1626 1772
1627int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info)
1628{
1629 int err;
1630 int res = 0;
1631 int bearer_id;
1632 char *name;
1633 struct tipc_link *link;
1634 struct tipc_node *node;
1635 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
1636 struct net *net = sock_net(skb->sk);
1637
1638 if (!info->attrs[TIPC_NLA_LINK])
1639 return -EINVAL;
1640
1641 err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX,
1642 info->attrs[TIPC_NLA_LINK],
1643 tipc_nl_link_policy);
1644 if (err)
1645 return err;
1646
1647 if (!attrs[TIPC_NLA_LINK_NAME])
1648 return -EINVAL;
1649
1650 name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
1651
1652 if (strcmp(name, tipc_bclink_name) == 0)
1653 return tipc_nl_bc_link_set(net, attrs);
1654
1655 node = tipc_link_find_owner(net, name, &bearer_id);
1656 if (!node)
1657 return -EINVAL;
1658
1659 tipc_node_lock(node);
1660
1661 link = node->links[bearer_id].link;
1662 if (!link) {
1663 res = -EINVAL;
1664 goto out;
1665 }
1666
1667 if (attrs[TIPC_NLA_LINK_PROP]) {
1668 struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1669
1670 err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP],
1671 props);
1672 if (err) {
1673 res = err;
1674 goto out;
1675 }
1676
1677 if (props[TIPC_NLA_PROP_TOL]) {
1678 u32 tol;
1679
1680 tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1681 link->tolerance = tol;
1682 tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0);
1683 }
1684 if (props[TIPC_NLA_PROP_PRIO]) {
1685 u32 prio;
1686
1687 prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1688 link->priority = prio;
1689 tipc_link_proto_xmit(link, STATE_MSG, 0, 0, 0, prio);
1690 }
1691 if (props[TIPC_NLA_PROP_WIN]) {
1692 u32 win;
1693
1694 win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1695 tipc_link_set_queue_limits(link, win);
1696 }
1697 }
1698
1699out:
1700 tipc_node_unlock(node);
1701
1702 return res;
1703}
1704
1705static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s) 1773static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s)
1706{ 1774{
1707 int i; 1775 int i;
@@ -1768,8 +1836,8 @@ msg_full:
1768} 1836}
1769 1837
1770/* Caller should hold appropriate locks to protect the link */ 1838/* Caller should hold appropriate locks to protect the link */
1771static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, 1839int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
1772 struct tipc_link *link, int nlflags) 1840 struct tipc_link *link, int nlflags)
1773{ 1841{
1774 int err; 1842 int err;
1775 void *hdr; 1843 void *hdr;
@@ -1838,198 +1906,134 @@ msg_full:
1838 return -EMSGSIZE; 1906 return -EMSGSIZE;
1839} 1907}
1840 1908
1841/* Caller should hold node lock */ 1909static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb,
1842static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg, 1910 struct tipc_stats *stats)
1843 struct tipc_node *node, u32 *prev_link)
1844{ 1911{
1845 u32 i; 1912 int i;
1846 int err; 1913 struct nlattr *nest;
1847
1848 for (i = *prev_link; i < MAX_BEARERS; i++) {
1849 *prev_link = i;
1850
1851 if (!node->links[i].link)
1852 continue;
1853 1914
1854 err = __tipc_nl_add_link(net, msg, 1915 struct nla_map {
1855 node->links[i].link, NLM_F_MULTI); 1916 __u32 key;
1856 if (err) 1917 __u32 val;
1857 return err; 1918 };
1858 }
1859 *prev_link = 0;
1860 1919
1861 return 0; 1920 struct nla_map map[] = {
1862} 1921 {TIPC_NLA_STATS_RX_INFO, stats->recv_info},
1922 {TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments},
1923 {TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented},
1924 {TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles},
1925 {TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled},
1926 {TIPC_NLA_STATS_TX_INFO, stats->sent_info},
1927 {TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments},
1928 {TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented},
1929 {TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles},
1930 {TIPC_NLA_STATS_TX_BUNDLED, stats->sent_bundled},
1931 {TIPC_NLA_STATS_RX_NACKS, stats->recv_nacks},
1932 {TIPC_NLA_STATS_RX_DEFERRED, stats->deferred_recv},
1933 {TIPC_NLA_STATS_TX_NACKS, stats->sent_nacks},
1934 {TIPC_NLA_STATS_TX_ACKS, stats->sent_acks},
1935 {TIPC_NLA_STATS_RETRANSMITTED, stats->retransmitted},
1936 {TIPC_NLA_STATS_DUPLICATES, stats->duplicates},
1937 {TIPC_NLA_STATS_LINK_CONGS, stats->link_congs},
1938 {TIPC_NLA_STATS_MAX_QUEUE, stats->max_queue_sz},
1939 {TIPC_NLA_STATS_AVG_QUEUE, stats->queue_sz_counts ?
1940 (stats->accu_queue_sz / stats->queue_sz_counts) : 0}
1941 };
1863 1942
1864int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) 1943 nest = nla_nest_start(skb, TIPC_NLA_LINK_STATS);
1865{ 1944 if (!nest)
1866 struct net *net = sock_net(skb->sk); 1945 return -EMSGSIZE;
1867 struct tipc_net *tn = net_generic(net, tipc_net_id);
1868 struct tipc_node *node;
1869 struct tipc_nl_msg msg;
1870 u32 prev_node = cb->args[0];
1871 u32 prev_link = cb->args[1];
1872 int done = cb->args[2];
1873 int err;
1874 1946
1875 if (done) 1947 for (i = 0; i < ARRAY_SIZE(map); i++)
1876 return 0; 1948 if (nla_put_u32(skb, map[i].key, map[i].val))
1949 goto msg_full;
1877 1950
1878 msg.skb = skb; 1951 nla_nest_end(skb, nest);
1879 msg.portid = NETLINK_CB(cb->skb).portid;
1880 msg.seq = cb->nlh->nlmsg_seq;
1881
1882 rcu_read_lock();
1883 if (prev_node) {
1884 node = tipc_node_find(net, prev_node);
1885 if (!node) {
1886 /* We never set seq or call nl_dump_check_consistent()
1887 * this means that setting prev_seq here will cause the
1888 * consistence check to fail in the netlink callback
1889 * handler. Resulting in the last NLMSG_DONE message
1890 * having the NLM_F_DUMP_INTR flag set.
1891 */
1892 cb->prev_seq = 1;
1893 goto out;
1894 }
1895 tipc_node_put(node);
1896
1897 list_for_each_entry_continue_rcu(node, &tn->node_list,
1898 list) {
1899 tipc_node_lock(node);
1900 err = __tipc_nl_add_node_links(net, &msg, node,
1901 &prev_link);
1902 tipc_node_unlock(node);
1903 if (err)
1904 goto out;
1905
1906 prev_node = node->addr;
1907 }
1908 } else {
1909 err = tipc_nl_add_bc_link(net, &msg);
1910 if (err)
1911 goto out;
1912
1913 list_for_each_entry_rcu(node, &tn->node_list, list) {
1914 tipc_node_lock(node);
1915 err = __tipc_nl_add_node_links(net, &msg, node,
1916 &prev_link);
1917 tipc_node_unlock(node);
1918 if (err)
1919 goto out;
1920
1921 prev_node = node->addr;
1922 }
1923 }
1924 done = 1;
1925out:
1926 rcu_read_unlock();
1927 1952
1928 cb->args[0] = prev_node; 1953 return 0;
1929 cb->args[1] = prev_link; 1954msg_full:
1930 cb->args[2] = done; 1955 nla_nest_cancel(skb, nest);
1931 1956
1932 return skb->len; 1957 return -EMSGSIZE;
1933} 1958}
1934 1959
1935int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) 1960int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
1936{ 1961{
1937 struct net *net = genl_info_net(info);
1938 struct tipc_nl_msg msg;
1939 char *name;
1940 int err; 1962 int err;
1963 void *hdr;
1964 struct nlattr *attrs;
1965 struct nlattr *prop;
1966 struct tipc_net *tn = net_generic(net, tipc_net_id);
1967 struct tipc_link *bcl = tn->bcl;
1941 1968
1942 msg.portid = info->snd_portid; 1969 if (!bcl)
1943 msg.seq = info->snd_seq; 1970 return 0;
1944
1945 if (!info->attrs[TIPC_NLA_LINK_NAME])
1946 return -EINVAL;
1947 name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]);
1948 1971
1949 msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1972 tipc_bcast_lock(net);
1950 if (!msg.skb)
1951 return -ENOMEM;
1952 1973
1953 if (strcmp(name, tipc_bclink_name) == 0) { 1974 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
1954 err = tipc_nl_add_bc_link(net, &msg); 1975 NLM_F_MULTI, TIPC_NL_LINK_GET);
1955 if (err) { 1976 if (!hdr)
1956 nlmsg_free(msg.skb); 1977 return -EMSGSIZE;
1957 return err;
1958 }
1959 } else {
1960 int bearer_id;
1961 struct tipc_node *node;
1962 struct tipc_link *link;
1963 1978
1964 node = tipc_link_find_owner(net, name, &bearer_id); 1979 attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
1965 if (!node) 1980 if (!attrs)
1966 return -EINVAL; 1981 goto msg_full;
1967 1982
1968 tipc_node_lock(node); 1983 /* The broadcast link is always up */
1969 link = node->links[bearer_id].link; 1984 if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP))
1970 if (!link) { 1985 goto attr_msg_full;
1971 tipc_node_unlock(node);
1972 nlmsg_free(msg.skb);
1973 return -EINVAL;
1974 }
1975 1986
1976 err = __tipc_nl_add_link(net, &msg, link, 0); 1987 if (nla_put_flag(msg->skb, TIPC_NLA_LINK_BROADCAST))
1977 tipc_node_unlock(node); 1988 goto attr_msg_full;
1978 if (err) { 1989 if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name))
1979 nlmsg_free(msg.skb); 1990 goto attr_msg_full;
1980 return err; 1991 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt))
1981 } 1992 goto attr_msg_full;
1982 } 1993 if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt))
1994 goto attr_msg_full;
1983 1995
1984 return genlmsg_reply(msg.skb, info); 1996 prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
1985} 1997 if (!prop)
1998 goto attr_msg_full;
1999 if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window))
2000 goto prop_msg_full;
2001 nla_nest_end(msg->skb, prop);
1986 2002
1987int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info) 2003 err = __tipc_nl_add_bc_link_stat(msg->skb, &bcl->stats);
1988{
1989 int err;
1990 char *link_name;
1991 unsigned int bearer_id;
1992 struct tipc_link *link;
1993 struct tipc_node *node;
1994 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
1995 struct net *net = sock_net(skb->sk);
1996
1997 if (!info->attrs[TIPC_NLA_LINK])
1998 return -EINVAL;
1999
2000 err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX,
2001 info->attrs[TIPC_NLA_LINK],
2002 tipc_nl_link_policy);
2003 if (err) 2004 if (err)
2004 return err; 2005 goto attr_msg_full;
2005
2006 if (!attrs[TIPC_NLA_LINK_NAME])
2007 return -EINVAL;
2008
2009 link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
2010 2006
2011 if (strcmp(link_name, tipc_bclink_name) == 0) { 2007 tipc_bcast_unlock(net);
2012 err = tipc_bclink_reset_stats(net); 2008 nla_nest_end(msg->skb, attrs);
2013 if (err) 2009 genlmsg_end(msg->skb, hdr);
2014 return err;
2015 return 0;
2016 }
2017 2010
2018 node = tipc_link_find_owner(net, link_name, &bearer_id); 2011 return 0;
2019 if (!node)
2020 return -EINVAL;
2021 2012
2022 tipc_node_lock(node); 2013prop_msg_full:
2014 nla_nest_cancel(msg->skb, prop);
2015attr_msg_full:
2016 nla_nest_cancel(msg->skb, attrs);
2017msg_full:
2018 tipc_bcast_unlock(net);
2019 genlmsg_cancel(msg->skb, hdr);
2023 2020
2024 link = node->links[bearer_id].link; 2021 return -EMSGSIZE;
2025 if (!link) { 2022}
2026 tipc_node_unlock(node);
2027 return -EINVAL;
2028 }
2029 2023
2030 link_reset_statistics(link); 2024void tipc_link_set_tolerance(struct tipc_link *l, u32 tol)
2025{
2026 l->tolerance = tol;
2027 tipc_link_proto_xmit(l, STATE_MSG, 0, 0, tol, 0);
2028}
2031 2029
2032 tipc_node_unlock(node); 2030void tipc_link_set_prio(struct tipc_link *l, u32 prio)
2031{
2032 l->priority = prio;
2033 tipc_link_proto_xmit(l, STATE_MSG, 0, 0, 0, prio);
2034}
2033 2035
2034 return 0; 2036void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit)
2037{
2038 l->abort_limit = limit;
2035} 2039}