From 5a379074a7dd6d288ec9e6472769ba0e0c54dd85 Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Wed, 25 Jun 2014 20:41:36 -0500 Subject: tipc: introduce message evaluation function When a message arrives in a node and finds no destination socket, we may need to drop it, reject it, or forward it after a secondary destination lookup. The latter two cases currently results in a code path that is perceived as complex, because it follows a deep call chain via obscure functions such as net_route_named_msg() and net_route_msg(). We now introduce a function, tipc_msg_eval(), that takes the decision about whether such a message should be rejected or forwarded, but leaves it to the caller to actually perform the indicated action. If the decision is 'reject', it is still the task of the recently introduced function tipc_msg_reverse() to take the final decision about whether the message is rejectable or not. In the latter case it drops the message. As a result of this change, we can finally eliminate the function net_route_named_msg(), and hence become independent of net_route_msg(). Signed-off-by: Jon Maloy Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Signed-off-by: David S. Miller --- net/tipc/net.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) (limited to 'net/tipc/net.c') diff --git a/net/tipc/net.c b/net/tipc/net.c index f64375e7f99f..5f7d6ffb5465 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -1,7 +1,7 @@ /* * net/tipc/net.c: TIPC network routing code * - * Copyright (c) 1995-2006, Ericsson AB + * Copyright (c) 1995-2006, 2014, Ericsson AB * Copyright (c) 2005, 2010-2011, Wind River Systems * All rights reserved. * @@ -103,29 +103,6 @@ * This is always used within the scope of a tipc_nametbl_lock(read). * - A local spin_lock protecting the queue of subscriber events. */ - -static void net_route_named_msg(struct sk_buff *buf) -{ - struct tipc_msg *msg = buf_msg(buf); - u32 dnode; - u32 dport; - - if (!msg_named(msg)) { - kfree_skb(buf); - return; - } - - dnode = addr_domain(msg_lookup_scope(msg)); - dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); - if (dport) { - msg_set_destnode(msg, dnode); - msg_set_destport(msg, dport); - tipc_net_route_msg(buf); - return; - } - tipc_reject_msg(buf, TIPC_ERR_NO_NAME); -} - void tipc_net_route_msg(struct sk_buff *buf) { struct tipc_msg *msg; @@ -141,10 +118,12 @@ void tipc_net_route_msg(struct sk_buff *buf) if (msg_isdata(msg)) { if (msg_mcast(msg)) tipc_port_mcast_rcv(buf, NULL); - else if (msg_destport(msg)) + else if (msg_destport(msg)) { tipc_sk_rcv(buf); - else - net_route_named_msg(buf); + } else { + pr_warn("Cannot route msg; no destination\n"); + kfree_skb(buf); + } return; } switch (msg_user(msg)) { -- cgit v1.2.3 From ec8a2e5621db2da24badb3969eda7fd359e1869f Mon Sep 17 00:00:00 2001 From: Jon Paul Maloy Date: Wed, 25 Jun 2014 20:41:40 -0500 Subject: tipc: same receive code path for connection protocol and data messages As a preparation to eliminate port_lock we need to bring reception of connection protocol messages under proper protection of bh_lock_sock or socket owner. We fix this by letting those messages follow the same code path as incoming data messages. As a side effect of this change, the last reference to the function net_route_msg() disappears, and we can eliminate that function. Signed-off-by: Jon Maloy Reviewed-by: Erik Hugne Reviewed-by: Ying Xue Signed-off-by: David S. Miller --- net/tipc/link.c | 18 ++++++++++++------ net/tipc/net.c | 40 ---------------------------------------- net/tipc/net.h | 2 -- net/tipc/port.c | 7 +------ net/tipc/port.h | 2 +- net/tipc/socket.c | 5 +++++ 6 files changed, 19 insertions(+), 55 deletions(-) (limited to 'net/tipc/net.c') diff --git a/net/tipc/link.c b/net/tipc/link.c index 93a8033263c0..96a8072f73cc 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1479,6 +1479,7 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) case TIPC_MEDIUM_IMPORTANCE: case TIPC_HIGH_IMPORTANCE: case TIPC_CRITICAL_IMPORTANCE: + case CONN_MANAGER: tipc_node_unlock(n_ptr); tipc_sk_rcv(buf); continue; @@ -1493,10 +1494,6 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) tipc_node_unlock(n_ptr); tipc_named_rcv(buf); continue; - case CONN_MANAGER: - tipc_node_unlock(n_ptr); - tipc_port_proto_rcv(buf); - continue; case BCAST_PROTOCOL: tipc_link_sync_rcv(n_ptr, buf); break; @@ -2106,6 +2103,7 @@ void tipc_link_bundle_rcv(struct sk_buff *buf) u32 msgcount = msg_msgcnt(buf_msg(buf)); u32 pos = INT_H_SIZE; struct sk_buff *obuf; + struct tipc_msg *omsg; while (msgcount--) { obuf = buf_extract(buf, pos); @@ -2113,8 +2111,16 @@ void tipc_link_bundle_rcv(struct sk_buff *buf) pr_warn("Link unable to unbundle message(s)\n"); break; } - pos += align(msg_size(buf_msg(obuf))); - tipc_net_route_msg(obuf); + omsg = buf_msg(obuf); + pos += align(msg_size(omsg)); + if (msg_isdata(omsg) || (msg_user(omsg) == CONN_MANAGER)) { + tipc_sk_rcv(obuf); + } else if (msg_user(omsg) == NAME_DISTRIBUTOR) { + tipc_named_rcv(obuf); + } else { + pr_warn("Illegal bundled msg: %u\n", msg_user(omsg)); + kfree_skb(obuf); + } } kfree_skb(buf); } diff --git a/net/tipc/net.c b/net/tipc/net.c index 5f7d6ffb5465..7fcc94998fea 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -103,46 +103,6 @@ * This is always used within the scope of a tipc_nametbl_lock(read). * - A local spin_lock protecting the queue of subscriber events. */ -void tipc_net_route_msg(struct sk_buff *buf) -{ - struct tipc_msg *msg; - u32 dnode; - - if (!buf) - return; - msg = buf_msg(buf); - - /* Handle message for this node */ - dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); - if (tipc_in_scope(dnode, tipc_own_addr)) { - if (msg_isdata(msg)) { - if (msg_mcast(msg)) - tipc_port_mcast_rcv(buf, NULL); - else if (msg_destport(msg)) { - tipc_sk_rcv(buf); - } else { - pr_warn("Cannot route msg; no destination\n"); - kfree_skb(buf); - } - return; - } - switch (msg_user(msg)) { - case NAME_DISTRIBUTOR: - tipc_named_rcv(buf); - break; - case CONN_MANAGER: - tipc_port_proto_rcv(buf); - break; - default: - kfree_skb(buf); - } - return; - } - - /* Handle message for another node */ - skb_trim(buf, msg_size(msg)); - tipc_link_xmit(buf, dnode, msg_link_selector(msg)); -} int tipc_net_start(u32 addr) { diff --git a/net/tipc/net.h b/net/tipc/net.h index c6c2b46f7c28..59ef3388be2c 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -37,8 +37,6 @@ #ifndef _TIPC_NET_H #define _TIPC_NET_H -void tipc_net_route_msg(struct sk_buff *buf); - int tipc_net_start(u32 addr); void tipc_net_stop(void); diff --git a/net/tipc/port.c b/net/tipc/port.c index 60aede075b52..dcc630948e04 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -365,16 +365,14 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er return buf; } -void tipc_port_proto_rcv(struct sk_buff *buf) +void tipc_port_proto_rcv(struct tipc_port *p_ptr, struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); - struct tipc_port *p_ptr; struct sk_buff *r_buf = NULL; u32 destport = msg_destport(msg); int wakeable; /* Validate connection */ - p_ptr = tipc_port_lock(destport); if (!p_ptr || !p_ptr->connected || !tipc_port_peer_msg(p_ptr, msg)) { r_buf = tipc_buf_acquire(BASIC_H_SIZE); if (r_buf) { @@ -385,8 +383,6 @@ void tipc_port_proto_rcv(struct sk_buff *buf) msg_set_origport(msg, destport); msg_set_destport(msg, msg_origport(msg)); } - if (p_ptr) - tipc_port_unlock(p_ptr); goto exit; } @@ -409,7 +405,6 @@ void tipc_port_proto_rcv(struct sk_buff *buf) break; } p_ptr->probing_state = CONFIRMED; - tipc_port_unlock(p_ptr); exit: tipc_link_xmit2(r_buf, msg_destnode(msg), msg_link_selector(msg)); kfree_skb(buf); diff --git a/net/tipc/port.h b/net/tipc/port.h index 231d9488189c..3f28fd420ff9 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -140,7 +140,7 @@ int tipc_port_mcast_xmit(struct tipc_port *port, unsigned int len); struct sk_buff *tipc_port_get_ports(void); -void tipc_port_proto_rcv(struct sk_buff *buf); +void tipc_port_proto_rcv(struct tipc_port *port, struct sk_buff *buf); void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp); void tipc_port_reinit(void); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index bfe79bbd83a1..d838a4b66d3a 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1416,6 +1416,11 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf) unsigned int limit = rcvbuf_limit(sk, buf); int rc = TIPC_OK; + if (unlikely(msg_user(msg) == CONN_MANAGER)) { + tipc_port_proto_rcv(&tsk->port, buf); + return TIPC_OK; + } + /* Reject message if it is wrong sort of message for socket */ if (msg_type(msg) > TIPC_DIRECT_MSG) return -TIPC_ERR_NO_PORT; -- cgit v1.2.3