aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-02-05 08:36:37 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-05 19:00:01 -0500
commit1186adf7df04e3b4298943fe89d9741ab42e30ff (patch)
treedeb0a73e9848722e6f33e41164ed787e59cb1a37 /net/tipc
parentc5898636c440da91d58f10beac00f073e68378df (diff)
tipc: simplify message forwarding and rejection in socket layer
Despite recent improvements, the handling of error codes and return values at reception of messages in the socket layer is still confusing. In this commit, we try to make it more comprehensible. First, we separate between the return values coming from the functions called by tipc_sk_rcv(), -those are TIPC specific error codes, and the return values returned by tipc_sk_rcv() itself. Second, we don't use the returned TIPC error code as indication for whether a buffer should be forwarded/rejected or not; instead we use the buffer pointer passed along with filter_msg(). This separation is necessary because we sometimes want to forward messages even when there is no error (i.e., protocol messages and successfully secondary looked up data messages). Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/socket.c120
1 files changed, 58 insertions, 62 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index b384e658dfeb..f9cd587e4090 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -818,17 +818,14 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf)
818/** 818/**
819 * tipc_sk_proto_rcv - receive a connection mng protocol message 819 * tipc_sk_proto_rcv - receive a connection mng protocol message
820 * @tsk: receiving socket 820 * @tsk: receiving socket
821 * @dnode: node to send response message to, if any 821 * @skb: pointer to message buffer. Set to NULL if buffer is consumed.
822 * @buf: buffer containing protocol message
823 * Returns 0 (TIPC_OK) if message was consumed, 1 (TIPC_FWD_MSG) if
824 * (CONN_PROBE_REPLY) message should be forwarded.
825 */ 822 */
826static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, 823static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff **skb)
827 struct sk_buff *buf)
828{ 824{
829 struct tipc_msg *msg = buf_msg(buf); 825 struct tipc_msg *msg = buf_msg(*skb);
830 int conn_cong; 826 int conn_cong;
831 827 u32 dnode;
828 u32 own_node = tsk_own_node(tsk);
832 /* Ignore if connection cannot be validated: */ 829 /* Ignore if connection cannot be validated: */
833 if (!tsk_peer_msg(tsk, msg)) 830 if (!tsk_peer_msg(tsk, msg))
834 goto exit; 831 goto exit;
@@ -841,15 +838,15 @@ static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode,
841 if (conn_cong) 838 if (conn_cong)
842 tsk->sk.sk_write_space(&tsk->sk); 839 tsk->sk.sk_write_space(&tsk->sk);
843 } else if (msg_type(msg) == CONN_PROBE) { 840 } else if (msg_type(msg) == CONN_PROBE) {
844 if (!tipc_msg_reverse(tsk_own_node(tsk), buf, dnode, TIPC_OK)) 841 if (tipc_msg_reverse(own_node, *skb, &dnode, TIPC_OK)) {
845 return TIPC_OK; 842 msg_set_type(msg, CONN_PROBE_REPLY);
846 msg_set_type(msg, CONN_PROBE_REPLY); 843 return;
847 return TIPC_FWD_MSG; 844 }
848 } 845 }
849 /* Do nothing if msg_type() == CONN_PROBE_REPLY */ 846 /* Do nothing if msg_type() == CONN_PROBE_REPLY */
850exit: 847exit:
851 kfree_skb(buf); 848 kfree_skb(*skb);
852 return TIPC_OK; 849 *skb = NULL;
853} 850}
854 851
855static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) 852static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
@@ -1568,16 +1565,16 @@ static void tipc_data_ready(struct sock *sk)
1568/** 1565/**
1569 * filter_connect - Handle all incoming messages for a connection-based socket 1566 * filter_connect - Handle all incoming messages for a connection-based socket
1570 * @tsk: TIPC socket 1567 * @tsk: TIPC socket
1571 * @msg: message 1568 * @skb: pointer to message buffer. Set to NULL if buffer is consumed
1572 * 1569 *
1573 * Returns 0 (TIPC_OK) if everything ok, -TIPC_ERR_NO_PORT otherwise 1570 * Returns 0 (TIPC_OK) if everything ok, -TIPC_ERR_NO_PORT otherwise
1574 */ 1571 */
1575static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) 1572static int filter_connect(struct tipc_sock *tsk, struct sk_buff **skb)
1576{ 1573{
1577 struct sock *sk = &tsk->sk; 1574 struct sock *sk = &tsk->sk;
1578 struct net *net = sock_net(sk); 1575 struct net *net = sock_net(sk);
1579 struct socket *sock = sk->sk_socket; 1576 struct socket *sock = sk->sk_socket;
1580 struct tipc_msg *msg = buf_msg(*buf); 1577 struct tipc_msg *msg = buf_msg(*skb);
1581 int retval = -TIPC_ERR_NO_PORT; 1578 int retval = -TIPC_ERR_NO_PORT;
1582 1579
1583 if (msg_mcast(msg)) 1580 if (msg_mcast(msg))
@@ -1627,8 +1624,8 @@ static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf)
1627 * connect() routine if sleeping. 1624 * connect() routine if sleeping.
1628 */ 1625 */
1629 if (msg_data_sz(msg) == 0) { 1626 if (msg_data_sz(msg) == 0) {
1630 kfree_skb(*buf); 1627 kfree_skb(*skb);
1631 *buf = NULL; 1628 *skb = NULL;
1632 if (waitqueue_active(sk_sleep(sk))) 1629 if (waitqueue_active(sk_sleep(sk)))
1633 wake_up_interruptible(sk_sleep(sk)); 1630 wake_up_interruptible(sk_sleep(sk));
1634 } 1631 }
@@ -1680,32 +1677,33 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf)
1680/** 1677/**
1681 * filter_rcv - validate incoming message 1678 * filter_rcv - validate incoming message
1682 * @sk: socket 1679 * @sk: socket
1683 * @buf: message 1680 * @skb: pointer to message. Set to NULL if buffer is consumed.
1684 * 1681 *
1685 * Enqueues message on receive queue if acceptable; optionally handles 1682 * Enqueues message on receive queue if acceptable; optionally handles
1686 * disconnect indication for a connected socket. 1683 * disconnect indication for a connected socket.
1687 * 1684 *
1688 * Called with socket lock already taken; port lock may also be taken. 1685 * Called with socket lock already taken
1689 * 1686 *
1690 * Returns 0 (TIPC_OK) if message was consumed, -TIPC error code if message 1687 * Returns 0 (TIPC_OK) if message was ok, -TIPC error code if rejected
1691 * to be rejected, 1 (TIPC_FWD_MSG) if (CONN_MANAGER) message to be forwarded
1692 */ 1688 */
1693static int filter_rcv(struct sock *sk, struct sk_buff *buf) 1689static int filter_rcv(struct sock *sk, struct sk_buff **skb)
1694{ 1690{
1695 struct socket *sock = sk->sk_socket; 1691 struct socket *sock = sk->sk_socket;
1696 struct tipc_sock *tsk = tipc_sk(sk); 1692 struct tipc_sock *tsk = tipc_sk(sk);
1697 struct tipc_msg *msg = buf_msg(buf); 1693 struct tipc_msg *msg = buf_msg(*skb);
1698 unsigned int limit = rcvbuf_limit(sk, buf); 1694 unsigned int limit = rcvbuf_limit(sk, *skb);
1699 u32 onode;
1700 int rc = TIPC_OK; 1695 int rc = TIPC_OK;
1701 1696
1702 if (unlikely(msg_user(msg) == CONN_MANAGER)) 1697 if (unlikely(msg_user(msg) == CONN_MANAGER)) {
1703 return tipc_sk_proto_rcv(tsk, &onode, buf); 1698 tipc_sk_proto_rcv(tsk, skb);
1699 return TIPC_OK;
1700 }
1704 1701
1705 if (unlikely(msg_user(msg) == SOCK_WAKEUP)) { 1702 if (unlikely(msg_user(msg) == SOCK_WAKEUP)) {
1706 kfree_skb(buf); 1703 kfree_skb(*skb);
1707 tsk->link_cong = 0; 1704 tsk->link_cong = 0;
1708 sk->sk_write_space(sk); 1705 sk->sk_write_space(sk);
1706 *skb = NULL;
1709 return TIPC_OK; 1707 return TIPC_OK;
1710 } 1708 }
1711 1709
@@ -1717,21 +1715,22 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf)
1717 if (msg_connected(msg)) 1715 if (msg_connected(msg))
1718 return -TIPC_ERR_NO_PORT; 1716 return -TIPC_ERR_NO_PORT;
1719 } else { 1717 } else {
1720 rc = filter_connect(tsk, &buf); 1718 rc = filter_connect(tsk, skb);
1721 if (rc != TIPC_OK || buf == NULL) 1719 if (rc != TIPC_OK || !*skb)
1722 return rc; 1720 return rc;
1723 } 1721 }
1724 1722
1725 /* Reject message if there isn't room to queue it */ 1723 /* Reject message if there isn't room to queue it */
1726 if (sk_rmem_alloc_get(sk) + buf->truesize >= limit) 1724 if (sk_rmem_alloc_get(sk) + (*skb)->truesize >= limit)
1727 return -TIPC_ERR_OVERLOAD; 1725 return -TIPC_ERR_OVERLOAD;
1728 1726
1729 /* Enqueue message */ 1727 /* Enqueue message */
1730 TIPC_SKB_CB(buf)->handle = NULL; 1728 TIPC_SKB_CB(*skb)->handle = NULL;
1731 __skb_queue_tail(&sk->sk_receive_queue, buf); 1729 __skb_queue_tail(&sk->sk_receive_queue, *skb);
1732 skb_set_owner_r(buf, sk); 1730 skb_set_owner_r(*skb, sk);
1733 1731
1734 sk->sk_data_ready(sk); 1732 sk->sk_data_ready(sk);
1733 *skb = NULL;
1735 return TIPC_OK; 1734 return TIPC_OK;
1736} 1735}
1737 1736
@@ -1746,25 +1745,22 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf)
1746 */ 1745 */
1747static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) 1746static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
1748{ 1747{
1749 int rc; 1748 int err;
1750 u32 onode; 1749 atomic_t *dcnt;
1750 u32 dnode;
1751 struct tipc_sock *tsk = tipc_sk(sk); 1751 struct tipc_sock *tsk = tipc_sk(sk);
1752 struct net *net = sock_net(sk); 1752 struct net *net = sock_net(sk);
1753 uint truesize = skb->truesize; 1753 uint truesize = skb->truesize;
1754 1754
1755 rc = filter_rcv(sk, skb); 1755 err = filter_rcv(sk, &skb);
1756 1756 if (likely(!skb)) {
1757 if (likely(!rc)) { 1757 dcnt = &tsk->dupl_rcvcnt;
1758 if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT) 1758 if (atomic_read(dcnt) < TIPC_CONN_OVERLOAD_LIMIT)
1759 atomic_add(truesize, &tsk->dupl_rcvcnt); 1759 atomic_add(truesize, dcnt);
1760 return 0; 1760 return 0;
1761 } 1761 }
1762 1762 if (!err || tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode, -err))
1763 if ((rc < 0) && !tipc_msg_reverse(tsk_own_node(tsk), skb, &onode, -rc)) 1763 tipc_link_xmit_skb(net, skb, dnode, tsk->portid);
1764 return 0;
1765
1766 tipc_link_xmit_skb(net, skb, onode, 0);
1767
1768 return 0; 1764 return 0;
1769} 1765}
1770 1766
@@ -1780,14 +1776,14 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb)
1780 struct tipc_net *tn; 1776 struct tipc_net *tn;
1781 struct sock *sk; 1777 struct sock *sk;
1782 u32 dport = msg_destport(buf_msg(skb)); 1778 u32 dport = msg_destport(buf_msg(skb));
1783 int rc = TIPC_OK; 1779 int err = TIPC_OK;
1784 uint limit; 1780 uint limit;
1785 u32 dnode; 1781 u32 dnode;
1786 1782
1787 /* Validate destination and message */ 1783 /* Validate destination and message */
1788 tsk = tipc_sk_lookup(net, dport); 1784 tsk = tipc_sk_lookup(net, dport);
1789 if (unlikely(!tsk)) { 1785 if (unlikely(!tsk)) {
1790 rc = tipc_msg_eval(net, skb, &dnode); 1786 err = tipc_msg_eval(net, skb, &dnode);
1791 goto exit; 1787 goto exit;
1792 } 1788 }
1793 sk = &tsk->sk; 1789 sk = &tsk->sk;
@@ -1796,25 +1792,25 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb)
1796 spin_lock_bh(&sk->sk_lock.slock); 1792 spin_lock_bh(&sk->sk_lock.slock);
1797 1793
1798 if (!sock_owned_by_user(sk)) { 1794 if (!sock_owned_by_user(sk)) {
1799 rc = filter_rcv(sk, skb); 1795 err = filter_rcv(sk, &skb);
1800 } else { 1796 } else {
1801 if (sk->sk_backlog.len == 0) 1797 if (sk->sk_backlog.len == 0)
1802 atomic_set(&tsk->dupl_rcvcnt, 0); 1798 atomic_set(&tsk->dupl_rcvcnt, 0);
1803 limit = rcvbuf_limit(sk, skb) + atomic_read(&tsk->dupl_rcvcnt); 1799 limit = rcvbuf_limit(sk, skb) + atomic_read(&tsk->dupl_rcvcnt);
1804 if (sk_add_backlog(sk, skb, limit)) 1800 if (likely(!sk_add_backlog(sk, skb, limit)))
1805 rc = -TIPC_ERR_OVERLOAD; 1801 skb = NULL;
1802 else
1803 err = -TIPC_ERR_OVERLOAD;
1806 } 1804 }
1807 spin_unlock_bh(&sk->sk_lock.slock); 1805 spin_unlock_bh(&sk->sk_lock.slock);
1808 sock_put(sk); 1806 sock_put(sk);
1809 if (likely(!rc))
1810 return 0;
1811exit: 1807exit:
1812 tn = net_generic(net, tipc_net_id); 1808 if (unlikely(skb)) {
1813 if ((rc < 0) && !tipc_msg_reverse(tn->own_addr, skb, &dnode, -rc)) 1809 tn = net_generic(net, tipc_net_id);
1814 return -EHOSTUNREACH; 1810 if (!err || tipc_msg_reverse(tn->own_addr, skb, &dnode, -err))
1815 1811 tipc_link_xmit_skb(net, skb, dnode, 0);
1816 tipc_link_xmit_skb(net, skb, dnode, 0); 1812 }
1817 return (rc < 0) ? -EHOSTUNREACH : 0; 1813 return err ? -EHOSTUNREACH : 0;
1818} 1814}
1819 1815
1820static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) 1816static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)