History

tipc: clean up socket layer message reception

When a message is received in a socket, one of the call chains tipc_sk_rcv()->tipc_sk_enqueue()->filter_rcv()(->tipc_sk_proto_rcv()) or tipc_sk_backlog_rcv()->filter_rcv()(->tipc_sk_proto_rcv()) are followed. At each of these levels we may encounter situations where the message may need to be rejected, or a new message produced for transfer back to the sender. Despite recent improvements, the current code for doing this is perceived as awkward and hard to follow. Leveraging the two previous commits in this series, we now introduce a more uniform handling of such situations. We let each of the functions in the chain itself produce/reverse the message to be returned to the sender, but also perform the actual forwarding. This simplifies the necessary logics within each function.

Jon Paul Maloy committed 11 years ago

Commit cda36961 parent bcd3ffd4 files · +134 −146Browse files

Unified · Split

4 files
  1. net/tipc/msg.c +9 −11
  2. net/tipc/msg.h +1 −2
  3. net/tipc/socket.c +123 −132
  4. net/tipc/socket.h +1 −1
net/tipc/msg.c+9−11
@@ -520,17 +520,15 @@ exit: · 519 unmodified lines
520520 /**
521521 * tipc_msg_lookup_dest(): try to find new destination for named message
522522 * @skb: the buffer containing the message.
523− * @dnode: return value: next-hop node, if destination found
524− * @err: return value: error code to use, if message to be rejected
523+ * @err: error code to be used by caller if lookup fails
525524 * Does not consume buffer
526525 * Returns true if a destination is found, false otherwise
527526 */
528−bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb,
529− u32 *dnode, int *err)
527+bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
530528 {
531529 struct tipc_msg *msg = buf_msg(skb);
532− u32 dport;
533− u32 own_addr = tipc_own_addr(net);
530+ u32 dport, dnode;
531+ u32 onode = tipc_own_addr(net);
534532
535533 if (!msg_isdata(msg))
536534 return false;
@@ -543,15 +541,15 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, · 6 unmodified lines
543541 return false;
544542 if (msg_reroute_cnt(msg))
545543 return false;
546− *dnode = addr_domain(net, msg_lookup_scope(msg));
544+ dnode = addr_domain(net, msg_lookup_scope(msg));
547545 dport = tipc_nametbl_translate(net, msg_nametype(msg),
548− msg_nameinst(msg), dnode);
546+ msg_nameinst(msg), &dnode);
549547 if (!dport)
550548 return false;
551549 msg_incr_reroute_cnt(msg);
552− if (*dnode != own_addr)
553− msg_set_prevnode(msg, own_addr);
554− msg_set_destnode(msg, *dnode);
550+ if (dnode != onode)
551+ msg_set_prevnode(msg, onode);
552+ msg_set_destnode(msg, dnode);
555553 msg_set_destport(msg, dport);
556554 *err = TIPC_OK;
557555 return true;
net/tipc/msg.h+1−2
@@ -798,8 +798,7 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg, · 797 unmodified lines
798798 bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos);
799799 int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
800800 int offset, int dsz, int mtu, struct sk_buff_head *list);
801−bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode,
802− int *err);
801+bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err);
803802 struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list);
804803
805804 static inline u16 buf_seqno(struct sk_buff *skb)
net/tipc/socket.c+123−132
@@ -1520,82 +1520,81 @@ static void tipc_data_ready(struct sock *sk) · 1519 unmodified lines
15201520 * @tsk: TIPC socket
15211521 * @skb: pointer to message buffer. Set to NULL if buffer is consumed
15221522 *
1523− * Returns 0 (TIPC_OK) if everything ok, -TIPC_ERR_NO_PORT otherwise
1523+ * Returns true if everything ok, false otherwise
15241524 */
1525−static int filter_connect(struct tipc_sock *tsk, struct sk_buff **skb)
1525+static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
15261526 {
15271527 struct sock *sk = &tsk->sk;
15281528 struct net *net = sock_net(sk);
15291529 struct socket *sock = sk->sk_socket;
1530− struct tipc_msg *msg = buf_msg(*skb);
1531− int retval = -TIPC_ERR_NO_PORT;
1530+ struct tipc_msg *hdr = buf_msg(skb);
15321531
1533− if (msg_mcast(msg))
1534− return retval;
1532+ if (unlikely(msg_mcast(hdr)))
1533+ return false;
15351534
15361535 switch ((int)sock->state) {
15371536 case SS_CONNECTED:
1537+
15381538 /* Accept only connection-based messages sent by peer */
1539− if (tsk_peer_msg(tsk, msg)) {
1540− if (unlikely(msg_errcode(msg))) {
1541− sock->state = SS_DISCONNECTING;
1542− tsk->connected = 0;
1543− /* let timer expire on it's own */
1544− tipc_node_remove_conn(net, tsk_peer_node(tsk),
1545− tsk->portid);
1546− }
1547− retval = TIPC_OK;
1539+ if (unlikely(!tsk_peer_msg(tsk, hdr)))
1540+ return false;
1541+
1542+ if (unlikely(msg_errcode(hdr))) {
1543+ sock->state = SS_DISCONNECTING;
1544+ tsk->connected = 0;
1545+ /* Let timer expire on it's own */
1546+ tipc_node_remove_conn(net, tsk_peer_node(tsk),
1547+ tsk->portid);
15481548 }
1549− break;
1549+ return true;
1550+
15501551 case SS_CONNECTING:
1551− /* Accept only ACK or NACK message */
15521552
1553− if (unlikely(!msg_connected(msg)))
1554− break;
1553+ /* Accept only ACK or NACK message */
1554+ if (unlikely(!msg_connected(hdr)))
1555+ return false;
15551556
1556− if (unlikely(msg_errcode(msg))) {
1557+ if (unlikely(msg_errcode(hdr))) {
15571558 sock->state = SS_DISCONNECTING;
15581559 sk->sk_err = ECONNREFUSED;
1559− retval = TIPC_OK;
1560− break;
1560+ return true;
15611561 }
15621562
1563− if (unlikely(msg_importance(msg) > TIPC_CRITICAL_IMPORTANCE)) {
1563+ if (unlikely(!msg_isdata(hdr))) {
15641564 sock->state = SS_DISCONNECTING;
15651565 sk->sk_err = EINVAL;
1566− retval = TIPC_OK;
1567− break;
1566+ return true;
15681567 }
15691568
1570− tipc_sk_finish_conn(tsk, msg_origport(msg), msg_orignode(msg));
1571− msg_set_importance(&tsk->phdr, msg_importance(msg));
1569+ tipc_sk_finish_conn(tsk, msg_origport(hdr), msg_orignode(hdr));
1570+ msg_set_importance(&tsk->phdr, msg_importance(hdr));
15721571 sock->state = SS_CONNECTED;
15731572
1574− /* If an incoming message is an 'ACK-', it should be
1575− * discarded here because it doesn't contain useful
1576− * data. In addition, we should try to wake up
1577− * connect() routine if sleeping.
1578− */
1579− if (msg_data_sz(msg) == 0) {
1580− kfree_skb(*skb);
1581− *skb = NULL;
1582− if (waitqueue_active(sk_sleep(sk)))
1583− wake_up_interruptible(sk_sleep(sk));
1584− }
1585− retval = TIPC_OK;
1586− break;
1573+ /* If 'ACK+' message, add to socket receive queue */
1574+ if (msg_data_sz(hdr))
1575+ return true;
1576+
1577+ /* If empty 'ACK-' message, wake up sleeping connect() */
1578+ if (waitqueue_active(sk_sleep(sk)))
1579+ wake_up_interruptible(sk_sleep(sk));
1580+
1581+ /* 'ACK-' message is neither accepted nor rejected: */
1582+ msg_set_dest_droppable(hdr, 1);
1583+ return false;
1584+
15871585 case SS_LISTENING:
15881586 case SS_UNCONNECTED:
1587+
15891588 /* Accept only SYN message */
1590− if (!msg_connected(msg) && !(msg_errcode(msg)))
1591− retval = TIPC_OK;
1589+ if (!msg_connected(hdr) && !(msg_errcode(hdr)))
1590+ return true;
15921591 break;
15931592 case SS_DISCONNECTING:
15941593 break;
15951594 default:
15961595 pr_err("Unknown socket state %u\n", sock->state);
15971596 }
1598− return retval;
1597+ return false;
15991598 }
16001599
16011600 /**
@@ -1630,61 +1629,70 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) · 28 unmodified lines
16301629 /**
16311630 * filter_rcv - validate incoming message
16321631 * @sk: socket
1633− * @skb: pointer to message. Set to NULL if buffer is consumed.
1632+ * @skb: pointer to message.
16341633 *
16351634 * Enqueues message on receive queue if acceptable; optionally handles
16361635 * disconnect indication for a connected socket.
16371636 *
16381637 * Called with socket lock already taken
16391638 *
1640− * Returns 0 (TIPC_OK) if message was ok, -TIPC error code if rejected
1639+ * Returns true if message was added to socket receive queue, otherwise false
16411640 */
1642−static int filter_rcv(struct sock *sk, struct sk_buff **skb)
1641+static bool filter_rcv(struct sock *sk, struct sk_buff *skb)
16431642 {
16441643 struct socket *sock = sk->sk_socket;
16451644 struct tipc_sock *tsk = tipc_sk(sk);
1646− struct tipc_msg *msg = buf_msg(*skb);
1647− unsigned int limit = rcvbuf_limit(sk, *skb);
1648− int rc = TIPC_OK;
1645+ struct tipc_msg *hdr = buf_msg(skb);
1646+ unsigned int limit = rcvbuf_limit(sk, skb);
1647+ int err = TIPC_OK;
1648+ int usr = msg_user(hdr);
16491649
1650− if (unlikely(msg_user(msg) == CONN_MANAGER)) {
1651− tipc_sk_proto_rcv(tsk, *skb);
1652− return TIPC_OK;
1650+ if (unlikely(msg_user(hdr) == CONN_MANAGER)) {
1651+ tipc_sk_proto_rcv(tsk, skb);
1652+ return false;
16531653 }
16541654
1655− if (unlikely(msg_user(msg) == SOCK_WAKEUP)) {
1656− kfree_skb(*skb);
1655+ if (unlikely(usr == SOCK_WAKEUP)) {
1656+ kfree_skb(skb);
16571657 tsk->link_cong = 0;
16581658 sk->sk_write_space(sk);
1659− *skb = NULL;
1660− return TIPC_OK;
1659+ return false;
16611660 }
16621661
1663− /* Reject message if it is wrong sort of message for socket */
1664− if (msg_type(msg) > TIPC_DIRECT_MSG)
1665− return -TIPC_ERR_NO_PORT;
1662+ /* Drop if illegal message type */
1663+ if (unlikely(msg_type(hdr) > TIPC_DIRECT_MSG)) {
1664+ kfree_skb(skb);
1665+ return false;
1666+ }
16661667
1667− if (sock->state == SS_READY) {
1668− if (msg_connected(msg))
1669− return -TIPC_ERR_NO_PORT;
1670− } else {
1671− rc = filter_connect(tsk, skb);
1672− if (rc != TIPC_OK || !*skb)
1673− return rc;
1668+ /* Reject if wrong message type for current socket state */
1669+ if (unlikely(sock->state == SS_READY)) {
1670+ if (msg_connected(hdr)) {
1671+ err = TIPC_ERR_NO_PORT;
1672+ goto reject;
1673+ }
1674+ } else if (unlikely(!filter_connect(tsk, skb))) {
1675+ err = TIPC_ERR_NO_PORT;
1676+ goto reject;
16741677 }
16751678
16761679 /* Reject message if there isn't room to queue it */
1677− if (sk_rmem_alloc_get(sk) + (*skb)->truesize >= limit)
1678− return -TIPC_ERR_OVERLOAD;
1680+ if (unlikely(sk_rmem_alloc_get(sk) + skb->truesize >= limit)) {
1681+ err = TIPC_ERR_OVERLOAD;
1682+ goto reject;
1683+ }
16791684
16801685 /* Enqueue message */
1681− TIPC_SKB_CB(*skb)->handle = NULL;
1682− __skb_queue_tail(&sk->sk_receive_queue, *skb);
1683− skb_set_owner_r(*skb, sk);
1686+ TIPC_SKB_CB(skb)->handle = NULL;
1687+ __skb_queue_tail(&sk->sk_receive_queue, skb);
1688+ skb_set_owner_r(skb, sk);
16841689
16851690 sk->sk_data_ready(sk);
1686− *skb = NULL;
1687− return TIPC_OK;
1691+ return true;
1692+
1693+reject:
1694+ tipc_sk_respond(sk, skb, err);
1695+ return false;
16881696 }
16891697
16901698 /**
@@ -1698,22 +1706,10 @@ static int filter_rcv(struct sock *sk, struct sk_buff **skb) · 7 unmodified lines
16981706 */
16991707 static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
17001708 {
1701− int err;
1702− atomic_t *dcnt;
1703− u32 dnode = msg_prevnode(buf_msg(skb));
1704− struct tipc_sock *tsk = tipc_sk(sk);
1705− struct net *net = sock_net(sk);
1706− uint truesize = skb->truesize;
1709+ unsigned int truesize = skb->truesize;
17071710
1708− err = filter_rcv(sk, &skb);
1709− if (likely(!skb)) {
1710− dcnt = &tsk->dupl_rcvcnt;
1711− if (atomic_read(dcnt) < TIPC_CONN_OVERLOAD_LIMIT)
1712− atomic_add(truesize, dcnt);
1713− return 0;
1714− }
1715− if (!err || tipc_msg_reverse(tsk_own_node(tsk), &skb, -err))
1716− tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
1711+ if (likely(filter_rcv(sk, skb)))
1712+ atomic_add(truesize, &tipc_sk(sk)->dupl_rcvcnt);
17171713 return 0;
17181714 }
17191715
@@ -1723,45 +1719,43 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) · 3 unmodified lines
17231719 * @inputq: list of incoming buffers with potentially different destinations
17241720 * @sk: socket where the buffers should be enqueued
17251721 * @dport: port number for the socket
1726− * @_skb: returned buffer to be forwarded or rejected, if applicable
17271722 *
17281723 * Caller must hold socket lock
1729− *
1730− * Returns TIPC_OK if all buffers enqueued, otherwise -TIPC_ERR_OVERLOAD
1731− * or -TIPC_ERR_NO_PORT
17321724 */
1733−static int tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
1734− u32 dport, struct sk_buff **_skb)
1725+static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
1726+ u32 dport)
17351727 {
17361728 unsigned int lim;
17371729 atomic_t *dcnt;
1738− int err;
17391730 struct sk_buff *skb;
17401731 unsigned long time_limit = jiffies + 2;
17411732
17421733 while (skb_queue_len(inputq)) {
17431734 if (unlikely(time_after_eq(jiffies, time_limit)))
1744− return TIPC_OK;
1735+ return;
1736+
17451737 skb = tipc_skb_dequeue(inputq, dport);
17461738 if (unlikely(!skb))
1747− return TIPC_OK;
1739+ return;
1740+
1741+ /* Add message directly to receive queue if possible */
17481742 if (!sock_owned_by_user(sk)) {
1749− err = filter_rcv(sk, &skb);
1750− if (likely(!skb))
1751− continue;
1752− *_skb = skb;
1753− return err;
1743+ filter_rcv(sk, skb);
1744+ continue;
17541745 }
1746+
1747+ /* Try backlog, compensating for double-counted bytes */
17551748 dcnt = &tipc_sk(sk)->dupl_rcvcnt;
17561749 if (sk->sk_backlog.len)
17571750 atomic_set(dcnt, 0);
17581751 lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt);
17591752 if (likely(!sk_add_backlog(sk, skb, lim)))
17601753 continue;
1761− *_skb = skb;
1762− return -TIPC_ERR_OVERLOAD;
1754+
1755+ /* Overload => reject message back to sender */
1756+ tipc_sk_respond(sk, skb, TIPC_ERR_OVERLOAD);
1757+ break;
17631758 }
1764− return TIPC_OK;
17651759 }
17661760
17671761 /**
@@ -1769,51 +1763,46 @@ static int tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, · 1 unmodified line
17691763 * @inputq: buffer list containing the buffers
17701764 * Consumes all buffers in list until inputq is empty
17711765 * Note: may be called in multiple threads referring to the same queue
1772− * Returns 0 if last buffer was accepted, otherwise -EHOSTUNREACH
1773− * Only node local calls check the return value, sending single-buffer queues
17741766 */
1775−int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
1767+void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
17761768 {
17771769 u32 dnode, dport = 0;
17781770 int err;
1779− struct sk_buff *skb;
17801771 struct tipc_sock *tsk;
1781− struct tipc_net *tn;
17821772 struct sock *sk;
1773+ struct sk_buff *skb;
17831774
17841775 while (skb_queue_len(inputq)) {
1785− err = -TIPC_ERR_NO_PORT;
1786− skb = NULL;
17871776 dport = tipc_skb_peek_port(inputq, dport);
17881777 tsk = tipc_sk_lookup(net, dport);
1778+
17891779 if (likely(tsk)) {
17901780 sk = &tsk->sk;
17911781 if (likely(spin_trylock_bh(&sk->sk_lock.slock))) {
1792− err = tipc_sk_enqueue(inputq, sk, dport, &skb);
1782+ tipc_sk_enqueue(inputq, sk, dport);
17931783 spin_unlock_bh(&sk->sk_lock.slock);
1794− dport = 0;
17951784 }
17961785 sock_put(sk);
1797− } else {
1798− skb = tipc_skb_dequeue(inputq, dport);
1799− }
1800− if (likely(!skb))
18011786 continue;
1802− if (tipc_msg_lookup_dest(net, skb, &dnode, &err))
1803− goto xmit;
1804− if (!err) {
1805− dnode = msg_destnode(buf_msg(skb));
1806− goto xmit;
1807− } else {
1808− dnode = msg_prevnode(buf_msg(skb));
18091787 }
1810− tn = net_generic(net, tipc_net_id);
1811− if (!tipc_msg_reverse(tn->own_addr, &skb, -err))
1788+
1789+ /* No destination socket => dequeue skb if still there */
1790+ skb = tipc_skb_dequeue(inputq, dport);
1791+ if (!skb)
1792+ return;
1793+
1794+ /* Try secondary lookup if unresolved named message */
1795+ err = TIPC_ERR_NO_PORT;
1796+ if (tipc_msg_lookup_dest(net, skb, &err))
1797+ goto xmit;
1798+
1799+ /* Prepare for message rejection */
1800+ if (!tipc_msg_reverse(tipc_own_addr(net), &skb, err))
18121801 continue;
18131802 xmit:
1803+ dnode = msg_destnode(buf_msg(skb));
18141804 tipc_node_xmit_skb(net, skb, dnode, dport);
18151805 }
1816− return err ? -EHOSTUNREACH : 0;
18171806 }
18181807
18191808 static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
@@ -2082,7 +2071,10 @@ static int tipc_shutdown(struct socket *sock, int how) · 262 unmodified lines
20822071 struct net *net = sock_net(sk);
20832072 struct tipc_sock *tsk = tipc_sk(sk);
20842073 struct sk_buff *skb;
2085− u32 dnode;
2074+ u32 dnode = tsk_peer_node(tsk);
2075+ u32 dport = tsk_peer_port(tsk);
2076+ u32 onode = tipc_own_addr(net);
2077+ u32 oport = tsk->portid;
20862078 int res;
20872079
20882080 if (how != SHUT_RDWR)
@@ -2108,9 +2100,8 @@ restart: · 19 unmodified lines
21082100 } else {
21092101 skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
21102102 TIPC_CONN_MSG, SHORT_H_SIZE,
2111− 0, dnode, tsk_own_node(tsk),
2112− tsk_peer_port(tsk),
2113− tsk->portid, TIPC_CONN_SHUTDOWN);
2103+ 0, dnode, onode, dport, oport,
2104+ TIPC_CONN_SHUTDOWN);
21142105 tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
21152106 }
21162107 tsk->connected = 0;
net/tipc/socket.h+1−1
@@ -44,7 +44,7 @@ · 43 unmodified lines
4444 SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE))
4545 int tipc_socket_init(void);
4646 void tipc_socket_stop(void);
47−int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq);
47+void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq);
4848 void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
4949 struct sk_buff_head *inputq);
5050 void tipc_sk_reinit(struct net *net);