diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index 19729645d494..ad759bb034e7 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -563,6 +563,84 @@ msg_full: | |||
563 | return -EMSGSIZE; | 563 | return -EMSGSIZE; |
564 | } | 564 | } |
565 | 565 | ||
566 | static struct tipc_link *tipc_node_select_link(struct tipc_node *n, int sel, | ||
567 | int *bearer_id, | ||
568 | struct tipc_media_addr **maddr) | ||
569 | { | ||
570 | int id = n->active_links[sel & 1]; | ||
571 | |||
572 | if (unlikely(id < 0)) | ||
573 | return NULL; | ||
574 | |||
575 | *bearer_id = id; | ||
576 | *maddr = &n->links[id].maddr; | ||
577 | return n->links[id].link; | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * tipc_node_xmit() is the general link level function for message sending | ||
582 | * @net: the applicable net namespace | ||
583 | * @list: chain of buffers containing message | ||
584 | * @dnode: address of destination node | ||
585 | * @selector: a number used for deterministic link selection | ||
586 | * Consumes the buffer chain, except when returning -ELINKCONG | ||
587 | * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE | ||
588 | */ | ||
589 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, | ||
590 | u32 dnode, int selector) | ||
591 | { | ||
592 | struct tipc_link *l = NULL; | ||
593 | struct tipc_node *n; | ||
594 | struct sk_buff_head xmitq; | ||
595 | struct tipc_media_addr *maddr; | ||
596 | int bearer_id; | ||
597 | int rc = -EHOSTUNREACH; | ||
598 | |||
599 | __skb_queue_head_init(&xmitq); | ||
600 | n = tipc_node_find(net, dnode); | ||
601 | if (likely(n)) { | ||
602 | tipc_node_lock(n); | ||
603 | l = tipc_node_select_link(n, selector, &bearer_id, &maddr); | ||
604 | if (likely(l)) | ||
605 | rc = tipc_link_xmit(l, list, &xmitq); | ||
606 | if (unlikely(rc == -ENOBUFS)) | ||
607 | tipc_link_reset(l); | ||
608 | tipc_node_unlock(n); | ||
609 | tipc_node_put(n); | ||
610 | } | ||
611 | if (likely(!rc)) { | ||
612 | tipc_bearer_xmit(net, bearer_id, &xmitq, maddr); | ||
613 | return 0; | ||
614 | } | ||
615 | if (likely(in_own_node(net, dnode))) { | ||
616 | tipc_sk_rcv(net, list); | ||
617 | return 0; | ||
618 | } | ||
619 | return rc; | ||
620 | } | ||
621 | |||
622 | /* tipc_node_xmit_skb(): send single buffer to destination | ||
623 | * Buffers sent via this functon are generally TIPC_SYSTEM_IMPORTANCE | ||
624 | * messages, which will not be rejected | ||
625 | * The only exception is datagram messages rerouted after secondary | ||
626 | * lookup, which are rare and safe to dispose of anyway. | ||
627 | * TODO: Return real return value, and let callers use | ||
628 | * tipc_wait_for_sendpkt() where applicable | ||
629 | */ | ||
630 | int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode, | ||
631 | u32 selector) | ||
632 | { | ||
633 | struct sk_buff_head head; | ||
634 | int rc; | ||
635 | |||
636 | skb_queue_head_init(&head); | ||
637 | __skb_queue_tail(&head, skb); | ||
638 | rc = tipc_node_xmit(net, &head, dnode, selector); | ||
639 | if (rc == -ELINKCONG) | ||
640 | kfree_skb(skb); | ||
641 | return 0; | ||
642 | } | ||
643 | |||
566 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) | 644 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) |
567 | { | 645 | { |
568 | int err; | 646 | int err; |