aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2014-06-25 21:41:32 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-27 15:50:54 -0400
commit4f1688b2c63cd86f0d7bcf95a9b3040e38bd3c1a (patch)
tree757c43e51ba7260d1745a8d5b2e3bdfb6b0a005a /net/tipc/link.c
parente4de5fab806f74622600ab7fd6ed22b7f911a8c5 (diff)
tipc: introduce send functions for chained buffers in link
The current link implementation provides several different transmit functions, depending on the characteristics of the message to be sent: if it is an iovec or an sk_buff, if it needs fragmentation or not, if the caller holds the node_lock or not. The permutation of these options gives us an unwanted amount of unnecessarily complex code. As a first step towards simplifying the send path for all messages, we introduce two new send functions at link level, tipc_link_xmit2() and __tipc_link_xmit2(). The former looks up a link to the message destination, and if one is found, it grabs the node lock and calls the second function, which works exclusively inside the node lock protection. If no link is found, and the destination is on the same node, it delivers the message directly to the local destination socket. The new functions take a buffer chain where all packet headers are already prepared, and the correct MTU has been used. These two functions will later replace all other link-level transmit functions. The functions are not backwards compatible, so we have added them as new functions with temporary names. They are tested, but have no users yet. Those will be added later in this series. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c140
1 files changed, 139 insertions, 1 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index ad2c57f5868d..68d2afb44f2f 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -850,6 +850,144 @@ int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector)
850 return res; 850 return res;
851} 851}
852 852
853/* tipc_link_cong: determine return value and how to treat the
854 * sent buffer during link congestion.
855 * - For plain, errorless user data messages we keep the buffer and
856 * return -ELINKONG.
857 * - For all other messages we discard the buffer and return -EHOSTUNREACH
858 * - For TIPC internal messages we also reset the link
859 */
860static int tipc_link_cong(struct tipc_link *link, struct sk_buff *buf)
861{
862 struct tipc_msg *msg = buf_msg(buf);
863 uint psz = msg_size(msg);
864 uint imp = tipc_msg_tot_importance(msg);
865 u32 oport = msg_tot_origport(msg);
866
867 if (likely(imp <= TIPC_CRITICAL_IMPORTANCE)) {
868 if (!msg_errcode(msg) && !msg_reroute_cnt(msg)) {
869 link_schedule_port(link, oport, psz);
870 return -ELINKCONG;
871 }
872 } else {
873 pr_warn("%s<%s>, send queue full", link_rst_msg, link->name);
874 tipc_link_reset(link);
875 }
876 kfree_skb_list(buf);
877 return -EHOSTUNREACH;
878}
879
880/**
881 * __tipc_link_xmit2(): same as tipc_link_xmit2, but destlink is known & locked
882 * @link: link to use
883 * @buf: chain of buffers containing message
884 * Consumes the buffer chain, except when returning -ELINKCONG
885 * Returns 0 if success, otherwise errno: -ELINKCONG, -EMSGSIZE (plain socket
886 * user data messages) or -EHOSTUNREACH (all other messages/senders)
887 * Only the socket functions tipc_send_stream() and tipc_send_packet() need
888 * to act on the return value, since they may need to do more send attempts.
889 */
890int __tipc_link_xmit2(struct tipc_link *link, struct sk_buff *buf)
891{
892 struct tipc_msg *msg = buf_msg(buf);
893 uint psz = msg_size(msg);
894 uint qsz = link->out_queue_size;
895 uint sndlim = link->queue_limit[0];
896 uint imp = tipc_msg_tot_importance(msg);
897 uint mtu = link->max_pkt;
898 uint ack = mod(link->next_in_no - 1);
899 uint seqno = link->next_out_no;
900 uint bc_last_in = link->owner->bclink.last_in;
901 struct tipc_media_addr *addr = &link->media_addr;
902 struct sk_buff *next = buf->next;
903
904 /* Match queue limits against msg importance: */
905 if (unlikely(qsz >= link->queue_limit[imp]))
906 return tipc_link_cong(link, buf);
907
908 /* Has valid packet limit been used ? */
909 if (unlikely(psz > mtu)) {
910 kfree_skb_list(buf);
911 return -EMSGSIZE;
912 }
913
914 /* Prepare each packet for sending, and add to outqueue: */
915 while (buf) {
916 next = buf->next;
917 msg = buf_msg(buf);
918 msg_set_word(msg, 2, ((ack << 16) | mod(seqno)));
919 msg_set_bcast_ack(msg, bc_last_in);
920
921 if (!link->first_out) {
922 link->first_out = buf;
923 } else if (qsz < sndlim) {
924 link->last_out->next = buf;
925 } else if (tipc_msg_bundle(link->last_out, buf, mtu)) {
926 link->stats.sent_bundled++;
927 buf = next;
928 next = buf->next;
929 continue;
930 } else if (tipc_msg_make_bundle(&buf, mtu, link->addr)) {
931 link->stats.sent_bundled++;
932 link->stats.sent_bundles++;
933 link->last_out->next = buf;
934 if (!link->next_out)
935 link->next_out = buf;
936 } else {
937 link->last_out->next = buf;
938 if (!link->next_out)
939 link->next_out = buf;
940 }
941
942 /* Send packet if possible: */
943 if (likely(++qsz <= sndlim)) {
944 tipc_bearer_send(link->bearer_id, buf, addr);
945 link->next_out = next;
946 link->unacked_window = 0;
947 }
948 seqno++;
949 link->last_out = buf;
950 buf = next;
951 }
952 link->next_out_no = seqno;
953 link->out_queue_size = qsz;
954 return 0;
955}
956
957/**
958 * tipc_link_xmit2() is the general link level function for message sending
959 * @buf: chain of buffers containing message
960 * @dsz: amount of user data to be sent
961 * @dnode: address of destination node
962 * @selector: a number used for deterministic link selection
963 * Consumes the buffer chain, except when returning -ELINKCONG
964 * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE
965 */
966int tipc_link_xmit2(struct sk_buff *buf, u32 dnode, u32 selector)
967{
968 struct tipc_link *link = NULL;
969 struct tipc_node *node;
970 int rc = -EHOSTUNREACH;
971
972 node = tipc_node_find(dnode);
973 if (node) {
974 tipc_node_lock(node);
975 link = node->active_links[selector & 1];
976 if (link)
977 rc = __tipc_link_xmit2(link, buf);
978 tipc_node_unlock(node);
979 }
980
981 if (link)
982 return rc;
983
984 if (likely(in_own_node(dnode)))
985 return tipc_sk_rcv(buf);
986
987 kfree_skb_list(buf);
988 return rc;
989}
990
853/* 991/*
854 * tipc_link_sync_xmit - synchronize broadcast link endpoints. 992 * tipc_link_sync_xmit - synchronize broadcast link endpoints.
855 * 993 *
@@ -1238,7 +1376,7 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr)
1238 tipc_bearer_send(l_ptr->bearer_id, buf, 1376 tipc_bearer_send(l_ptr->bearer_id, buf,
1239 &l_ptr->media_addr); 1377 &l_ptr->media_addr);
1240 if (msg_user(msg) == MSG_BUNDLER) 1378 if (msg_user(msg) == MSG_BUNDLER)
1241 msg_set_type(msg, CLOSED_MSG); 1379 msg_set_type(msg, BUNDLE_CLOSED);
1242 l_ptr->next_out = buf->next; 1380 l_ptr->next_out = buf->next;
1243 return 0; 1381 return 0;
1244 } 1382 }