aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c135
1 files changed, 65 insertions, 70 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 9d7a16fc5ca4..9aaa1bc566ae 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -41,6 +41,7 @@
41#include "socket.h" 41#include "socket.h"
42#include "bcast.h" 42#include "bcast.h"
43#include "discover.h" 43#include "discover.h"
44#include "netlink.h"
44 45
45#define INVALID_NODE_SIG 0x10000 46#define INVALID_NODE_SIG 0x10000
46 47
@@ -164,28 +165,6 @@ struct tipc_sock_conn {
164 struct list_head list; 165 struct list_head list;
165}; 166};
166 167
167static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = {
168 [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC },
169 [TIPC_NLA_LINK_NAME] = {
170 .type = NLA_STRING,
171 .len = TIPC_MAX_LINK_NAME
172 },
173 [TIPC_NLA_LINK_MTU] = { .type = NLA_U32 },
174 [TIPC_NLA_LINK_BROADCAST] = { .type = NLA_FLAG },
175 [TIPC_NLA_LINK_UP] = { .type = NLA_FLAG },
176 [TIPC_NLA_LINK_ACTIVE] = { .type = NLA_FLAG },
177 [TIPC_NLA_LINK_PROP] = { .type = NLA_NESTED },
178 [TIPC_NLA_LINK_STATS] = { .type = NLA_NESTED },
179 [TIPC_NLA_LINK_RX] = { .type = NLA_U32 },
180 [TIPC_NLA_LINK_TX] = { .type = NLA_U32 }
181};
182
183static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
184 [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC },
185 [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 },
186 [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG }
187};
188
189static struct tipc_link *node_active_link(struct tipc_node *n, int sel) 168static struct tipc_link *node_active_link(struct tipc_node *n, int sel)
190{ 169{
191 int bearer_id = n->active_links[sel & 1]; 170 int bearer_id = n->active_links[sel & 1];
@@ -225,9 +204,10 @@ static unsigned int tipc_hashfn(u32 addr)
225 204
226static void tipc_node_kref_release(struct kref *kref) 205static void tipc_node_kref_release(struct kref *kref)
227{ 206{
228 struct tipc_node *node = container_of(kref, struct tipc_node, kref); 207 struct tipc_node *n = container_of(kref, struct tipc_node, kref);
229 208
230 tipc_node_delete(node); 209 kfree(n->bc_entry.link);
210 kfree_rcu(n, rcu);
231} 211}
232 212
233static void tipc_node_put(struct tipc_node *node) 213static void tipc_node_put(struct tipc_node *node)
@@ -245,23 +225,23 @@ static void tipc_node_get(struct tipc_node *node)
245 */ 225 */
246static struct tipc_node *tipc_node_find(struct net *net, u32 addr) 226static struct tipc_node *tipc_node_find(struct net *net, u32 addr)
247{ 227{
248 struct tipc_net *tn = net_generic(net, tipc_net_id); 228 struct tipc_net *tn = tipc_net(net);
249 struct tipc_node *node; 229 struct tipc_node *node;
230 unsigned int thash = tipc_hashfn(addr);
250 231
251 if (unlikely(!in_own_cluster_exact(net, addr))) 232 if (unlikely(!in_own_cluster_exact(net, addr)))
252 return NULL; 233 return NULL;
253 234
254 rcu_read_lock(); 235 rcu_read_lock();
255 hlist_for_each_entry_rcu(node, &tn->node_htable[tipc_hashfn(addr)], 236 hlist_for_each_entry_rcu(node, &tn->node_htable[thash], hash) {
256 hash) { 237 if (node->addr != addr)
257 if (node->addr == addr) { 238 continue;
258 tipc_node_get(node); 239 if (!kref_get_unless_zero(&node->kref))
259 rcu_read_unlock(); 240 node = NULL;
260 return node; 241 break;
261 }
262 } 242 }
263 rcu_read_unlock(); 243 rcu_read_unlock();
264 return NULL; 244 return node;
265} 245}
266 246
267static void tipc_node_read_lock(struct tipc_node *n) 247static void tipc_node_read_lock(struct tipc_node *n)
@@ -395,21 +375,20 @@ static void tipc_node_delete(struct tipc_node *node)
395{ 375{
396 list_del_rcu(&node->list); 376 list_del_rcu(&node->list);
397 hlist_del_rcu(&node->hash); 377 hlist_del_rcu(&node->hash);
398 kfree(node->bc_entry.link); 378 tipc_node_put(node);
399 kfree_rcu(node, rcu); 379
380 del_timer_sync(&node->timer);
381 tipc_node_put(node);
400} 382}
401 383
402void tipc_node_stop(struct net *net) 384void tipc_node_stop(struct net *net)
403{ 385{
404 struct tipc_net *tn = net_generic(net, tipc_net_id); 386 struct tipc_net *tn = tipc_net(net);
405 struct tipc_node *node, *t_node; 387 struct tipc_node *node, *t_node;
406 388
407 spin_lock_bh(&tn->node_list_lock); 389 spin_lock_bh(&tn->node_list_lock);
408 list_for_each_entry_safe(node, t_node, &tn->node_list, list) { 390 list_for_each_entry_safe(node, t_node, &tn->node_list, list)
409 if (del_timer(&node->timer)) 391 tipc_node_delete(node);
410 tipc_node_put(node);
411 tipc_node_put(node);
412 }
413 spin_unlock_bh(&tn->node_list_lock); 392 spin_unlock_bh(&tn->node_list_lock);
414} 393}
415 394
@@ -530,9 +509,7 @@ static void tipc_node_timeout(unsigned long data)
530 if (rc & TIPC_LINK_DOWN_EVT) 509 if (rc & TIPC_LINK_DOWN_EVT)
531 tipc_node_link_down(n, bearer_id, false); 510 tipc_node_link_down(n, bearer_id, false);
532 } 511 }
533 if (!mod_timer(&n->timer, jiffies + n->keepalive_intv)) 512 mod_timer(&n->timer, jiffies + n->keepalive_intv);
534 tipc_node_get(n);
535 tipc_node_put(n);
536} 513}
537 514
538/** 515/**
@@ -845,7 +822,7 @@ void tipc_node_check_dest(struct net *net, u32 onode,
845 memcpy(&le->maddr, maddr, sizeof(*maddr)); 822 memcpy(&le->maddr, maddr, sizeof(*maddr));
846exit: 823exit:
847 tipc_node_write_unlock(n); 824 tipc_node_write_unlock(n);
848 if (reset && !tipc_link_is_reset(l)) 825 if (reset && l && !tipc_link_is_reset(l))
849 tipc_node_link_down(n, b->identity, false); 826 tipc_node_link_down(n, b->identity, false);
850 tipc_node_put(n); 827 tipc_node_put(n);
851} 828}
@@ -1166,7 +1143,7 @@ msg_full:
1166 * @dnode: address of destination node 1143 * @dnode: address of destination node
1167 * @selector: a number used for deterministic link selection 1144 * @selector: a number used for deterministic link selection
1168 * Consumes the buffer chain, except when returning -ELINKCONG 1145 * Consumes the buffer chain, except when returning -ELINKCONG
1169 * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE 1146 * Returns 0 if success, otherwise: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE,-ENOBUF
1170 */ 1147 */
1171int tipc_node_xmit(struct net *net, struct sk_buff_head *list, 1148int tipc_node_xmit(struct net *net, struct sk_buff_head *list,
1172 u32 dnode, int selector) 1149 u32 dnode, int selector)
@@ -1174,33 +1151,43 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list,
1174 struct tipc_link_entry *le = NULL; 1151 struct tipc_link_entry *le = NULL;
1175 struct tipc_node *n; 1152 struct tipc_node *n;
1176 struct sk_buff_head xmitq; 1153 struct sk_buff_head xmitq;
1177 int bearer_id = -1; 1154 int bearer_id;
1178 int rc = -EHOSTUNREACH; 1155 int rc;
1156
1157 if (in_own_node(net, dnode)) {
1158 tipc_sk_rcv(net, list);
1159 return 0;
1160 }
1179 1161
1180 __skb_queue_head_init(&xmitq);
1181 n = tipc_node_find(net, dnode); 1162 n = tipc_node_find(net, dnode);
1182 if (likely(n)) { 1163 if (unlikely(!n)) {
1183 tipc_node_read_lock(n); 1164 skb_queue_purge(list);
1184 bearer_id = n->active_links[selector & 1]; 1165 return -EHOSTUNREACH;
1185 if (bearer_id >= 0) { 1166 }
1186 le = &n->links[bearer_id]; 1167
1187 spin_lock_bh(&le->lock); 1168 tipc_node_read_lock(n);
1188 rc = tipc_link_xmit(le->link, list, &xmitq); 1169 bearer_id = n->active_links[selector & 1];
1189 spin_unlock_bh(&le->lock); 1170 if (unlikely(bearer_id == INVALID_BEARER_ID)) {
1190 }
1191 tipc_node_read_unlock(n); 1171 tipc_node_read_unlock(n);
1192 if (likely(!rc))
1193 tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr);
1194 else if (rc == -ENOBUFS)
1195 tipc_node_link_down(n, bearer_id, false);
1196 tipc_node_put(n); 1172 tipc_node_put(n);
1197 return rc; 1173 skb_queue_purge(list);
1174 return -EHOSTUNREACH;
1198 } 1175 }
1199 1176
1200 if (likely(in_own_node(net, dnode))) { 1177 __skb_queue_head_init(&xmitq);
1201 tipc_sk_rcv(net, list); 1178 le = &n->links[bearer_id];
1202 return 0; 1179 spin_lock_bh(&le->lock);
1203 } 1180 rc = tipc_link_xmit(le->link, list, &xmitq);
1181 spin_unlock_bh(&le->lock);
1182 tipc_node_read_unlock(n);
1183
1184 if (likely(rc == 0))
1185 tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr);
1186 else if (rc == -ENOBUFS)
1187 tipc_node_link_down(n, bearer_id, false);
1188
1189 tipc_node_put(n);
1190
1204 return rc; 1191 return rc;
1205} 1192}
1206 1193
@@ -1457,6 +1444,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
1457 int bearer_id = b->identity; 1444 int bearer_id = b->identity;
1458 struct tipc_link_entry *le; 1445 struct tipc_link_entry *le;
1459 u16 bc_ack = msg_bcast_ack(hdr); 1446 u16 bc_ack = msg_bcast_ack(hdr);
1447 u32 self = tipc_own_addr(net);
1460 int rc = 0; 1448 int rc = 0;
1461 1449
1462 __skb_queue_head_init(&xmitq); 1450 __skb_queue_head_init(&xmitq);
@@ -1473,6 +1461,10 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
1473 return tipc_node_bc_rcv(net, skb, bearer_id); 1461 return tipc_node_bc_rcv(net, skb, bearer_id);
1474 } 1462 }
1475 1463
1464 /* Discard unicast link messages destined for another node */
1465 if (unlikely(!msg_short(hdr) && (msg_destnode(hdr) != self)))
1466 goto discard;
1467
1476 /* Locate neighboring node that sent packet */ 1468 /* Locate neighboring node that sent packet */
1477 n = tipc_node_find(net, msg_prevnode(hdr)); 1469 n = tipc_node_find(net, msg_prevnode(hdr));
1478 if (unlikely(!n)) 1470 if (unlikely(!n))
@@ -1637,9 +1629,12 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
1637 char *name; 1629 char *name;
1638 struct tipc_link *link; 1630 struct tipc_link *link;
1639 struct tipc_node *node; 1631 struct tipc_node *node;
1632 struct sk_buff_head xmitq;
1640 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; 1633 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
1641 struct net *net = sock_net(skb->sk); 1634 struct net *net = sock_net(skb->sk);
1642 1635
1636 __skb_queue_head_init(&xmitq);
1637
1643 if (!info->attrs[TIPC_NLA_LINK]) 1638 if (!info->attrs[TIPC_NLA_LINK])
1644 return -EINVAL; 1639 return -EINVAL;
1645 1640
@@ -1683,13 +1678,13 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
1683 u32 tol; 1678 u32 tol;
1684 1679
1685 tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); 1680 tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1686 tipc_link_set_tolerance(link, tol); 1681 tipc_link_set_tolerance(link, tol, &xmitq);
1687 } 1682 }
1688 if (props[TIPC_NLA_PROP_PRIO]) { 1683 if (props[TIPC_NLA_PROP_PRIO]) {
1689 u32 prio; 1684 u32 prio;
1690 1685
1691 prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); 1686 prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1692 tipc_link_set_prio(link, prio); 1687 tipc_link_set_prio(link, prio, &xmitq);
1693 } 1688 }
1694 if (props[TIPC_NLA_PROP_WIN]) { 1689 if (props[TIPC_NLA_PROP_WIN]) {
1695 u32 win; 1690 u32 win;
@@ -1701,7 +1696,7 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info)
1701 1696
1702out: 1697out:
1703 tipc_node_read_unlock(node); 1698 tipc_node_read_unlock(node);
1704 1699 tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr);
1705 return res; 1700 return res;
1706} 1701}
1707 1702