Commit 7781e5d1 authored by David S. Miller's avatar David S. Miller

Merge branch 'tipc-separate-link-and-aggregation'

Jon Maloy says:

====================
tipc: separate link and link aggregation layer

This is the first batch of a longer series that has two main objectives:

o Finer lock granularity during message sending and reception,
  especially regarding usage of the node spinlock.

o Better separation between the link layer implementation and the link
  aggregation layer, represented by node.c::struct tipc_node.

Hopefully these changes also make this part of code somewhat easier
to comprehend and maintain.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6acc2326 d999297c
...@@ -316,6 +316,29 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr, ...@@ -316,6 +316,29 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr,
} }
} }
void tipc_bclink_sync_state(struct tipc_node *n, struct tipc_msg *hdr)
{
u16 last = msg_last_bcast(hdr);
int mtyp = msg_type(hdr);
if (unlikely(msg_user(hdr) != LINK_PROTOCOL))
return;
if (mtyp == STATE_MSG) {
tipc_bclink_update_link_state(n, last);
return;
}
/* Compatibility: older nodes don't know BCAST_PROTOCOL synchronization,
* and transfer synch info in LINK_PROTOCOL messages.
*/
if (tipc_node_is_up(n))
return;
if ((mtyp != RESET_MSG) && (mtyp != ACTIVATE_MSG))
return;
n->bclink.last_sent = last;
n->bclink.last_in = last;
n->bclink.oos_state = 0;
}
/** /**
* bclink_peek_nack - monitor retransmission requests sent by other nodes * bclink_peek_nack - monitor retransmission requests sent by other nodes
* *
...@@ -358,10 +381,9 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list) ...@@ -358,10 +381,9 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list)
/* Prepare clone of message for local node */ /* Prepare clone of message for local node */
skb = tipc_msg_reassemble(list); skb = tipc_msg_reassemble(list);
if (unlikely(!skb)) { if (unlikely(!skb))
__skb_queue_purge(list);
return -EHOSTUNREACH; return -EHOSTUNREACH;
}
/* Broadcast to all nodes */ /* Broadcast to all nodes */
if (likely(bclink)) { if (likely(bclink)) {
tipc_bclink_lock(net); tipc_bclink_lock(net);
...@@ -413,7 +435,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) ...@@ -413,7 +435,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno)
* all nodes in the cluster don't ACK at the same time * all nodes in the cluster don't ACK at the same time
*/ */
if (((seqno - tn->own_addr) % TIPC_MIN_LINK_WIN) == 0) { if (((seqno - tn->own_addr) % TIPC_MIN_LINK_WIN) == 0) {
tipc_link_proto_xmit(node->active_links[node->addr & 1], tipc_link_proto_xmit(node_active_link(node, node->addr),
STATE_MSG, 0, 0, 0, 0); STATE_MSG, 0, 0, 0, 0);
tn->bcl->stats.sent_acks++; tn->bcl->stats.sent_acks++;
} }
...@@ -925,7 +947,6 @@ int tipc_bclink_init(struct net *net) ...@@ -925,7 +947,6 @@ int tipc_bclink_init(struct net *net)
tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
bcl->bearer_id = MAX_BEARERS; bcl->bearer_id = MAX_BEARERS;
rcu_assign_pointer(tn->bearer_list[MAX_BEARERS], &bcbearer->bearer); rcu_assign_pointer(tn->bearer_list[MAX_BEARERS], &bcbearer->bearer);
bcl->state = WORKING_WORKING;
bcl->pmsg = (struct tipc_msg *)&bcl->proto_msg; bcl->pmsg = (struct tipc_msg *)&bcl->proto_msg;
msg_set_prevnode(bcl->pmsg, tn->own_addr); msg_set_prevnode(bcl->pmsg, tn->own_addr);
strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME);
......
...@@ -133,5 +133,6 @@ void tipc_bclink_wakeup_users(struct net *net); ...@@ -133,5 +133,6 @@ void tipc_bclink_wakeup_users(struct net *net);
int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg); int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg);
int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]); int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]);
void tipc_bclink_input(struct net *net); void tipc_bclink_input(struct net *net);
void tipc_bclink_sync_state(struct tipc_node *n, struct tipc_msg *msg);
#endif #endif
...@@ -470,6 +470,32 @@ void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, ...@@ -470,6 +470,32 @@ void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf,
rcu_read_unlock(); rcu_read_unlock();
} }
/* tipc_bearer_xmit() -send buffer to destination over bearer
*/
void tipc_bearer_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq,
struct tipc_media_addr *dst)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_bearer *b;
struct sk_buff *skb, *tmp;
if (skb_queue_empty(xmitq))
return;
rcu_read_lock();
b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
if (likely(b)) {
skb_queue_walk_safe(xmitq, skb, tmp) {
__skb_dequeue(xmitq);
b->media->send_msg(net, skb, b, dst);
/* Until we remove cloning in tipc_l2_send_msg(): */
kfree_skb(skb);
}
}
rcu_read_unlock();
}
/** /**
* tipc_l2_rcv_msg - handle incoming TIPC message from an interface * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
* @buf: the received packet * @buf: the received packet
......
...@@ -217,5 +217,8 @@ void tipc_bearer_cleanup(void); ...@@ -217,5 +217,8 @@ void tipc_bearer_cleanup(void);
void tipc_bearer_stop(struct net *net); void tipc_bearer_stop(struct net *net);
void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf,
struct tipc_media_addr *dest); struct tipc_media_addr *dest);
void tipc_bearer_xmit(struct net *net, u32 bearer_id,
struct sk_buff_head *xmitq,
struct tipc_media_addr *dst);
#endif /* _TIPC_BEARER_H */ #endif /* _TIPC_BEARER_H */
...@@ -129,6 +129,11 @@ static inline int less(u16 left, u16 right) ...@@ -129,6 +129,11 @@ static inline int less(u16 left, u16 right)
return less_eq(left, right) && (mod(right) != mod(left)); return less_eq(left, right) && (mod(right) != mod(left));
} }
static inline int in_range(u16 val, u16 min, u16 max)
{
return !less(val, min) && !more(val, max);
}
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
int tipc_register_sysctl(void); int tipc_register_sysctl(void);
void tipc_unregister_sysctl(void); void tipc_unregister_sysctl(void);
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
*/ */
#include "core.h" #include "core.h"
#include "link.h" #include "node.h"
#include "discover.h" #include "discover.h"
/* min delay during bearer start up */ /* min delay during bearer start up */
...@@ -125,7 +125,6 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf, ...@@ -125,7 +125,6 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
{ {
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_node *node; struct tipc_node *node;
struct tipc_link *link;
struct tipc_media_addr maddr; struct tipc_media_addr maddr;
struct sk_buff *rbuf; struct sk_buff *rbuf;
struct tipc_msg *msg = buf_msg(buf); struct tipc_msg *msg = buf_msg(buf);
...@@ -170,13 +169,10 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf, ...@@ -170,13 +169,10 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
return; return;
tipc_node_lock(node); tipc_node_lock(node);
node->capabilities = caps; node->capabilities = caps;
link = node->links[bearer->identity];
/* Prepare to validate requesting node's signature and media address */ /* Prepare to validate requesting node's signature and media address */
sign_match = (signature == node->signature); sign_match = (signature == node->signature);
addr_match = link && !memcmp(&link->media_addr, &maddr, sizeof(maddr)); tipc_node_check_dest(node, bearer, &link_up, &addr_match, &maddr);
link_up = link && tipc_link_is_up(link);
/* These three flags give us eight permutations: */ /* These three flags give us eight permutations: */
...@@ -239,16 +235,8 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf, ...@@ -239,16 +235,8 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
if (accept_sign) if (accept_sign)
node->signature = signature; node->signature = signature;
if (accept_addr) { if (accept_addr && !tipc_node_update_dest(node, bearer, &maddr))
if (!link) respond = false;
link = tipc_link_create(node, bearer, &maddr);
if (link) {
memcpy(&link->media_addr, &maddr, sizeof(maddr));
tipc_link_reset(link);
} else {
respond = false;
}
}
/* Send response, if necessary */ /* Send response, if necessary */
if (respond && (mtyp == DSC_REQ_MSG)) { if (respond && (mtyp == DSC_REQ_MSG)) {
......
This diff is collapsed.
...@@ -49,19 +49,21 @@ ...@@ -49,19 +49,21 @@
*/ */
#define INVALID_LINK_SEQ 0x10000 #define INVALID_LINK_SEQ 0x10000
/* Link working states
/* Link endpoint receive states
*/ */
#define WORKING_WORKING 560810u enum {
#define WORKING_UNKNOWN 560811u TIPC_LINK_OPEN,
#define RESET_UNKNOWN 560812u TIPC_LINK_BLOCKED,
#define RESET_RESET 560813u TIPC_LINK_TUNNEL
};
/* Link endpoint execution states /* Events returned from link at packet reception or at timeout
*/ */
#define LINK_STARTED 0x0001 enum {
#define LINK_STOPPED 0x0002 TIPC_LINK_UP_EVT = 1,
#define LINK_SYNCHING 0x0004 TIPC_LINK_DOWN_EVT = (1 << 1)
#define LINK_FAILINGOVER 0x0008 };
/* Starting value for maximum packet size negotiation on unicast links /* Starting value for maximum packet size negotiation on unicast links
* (unless bearer MTU is less) * (unless bearer MTU is less)
...@@ -106,7 +108,6 @@ struct tipc_stats { ...@@ -106,7 +108,6 @@ struct tipc_stats {
* @timer: link timer * @timer: link timer
* @owner: pointer to peer node * @owner: pointer to peer node
* @refcnt: reference counter for permanent references (owner node & timer) * @refcnt: reference counter for permanent references (owner node & timer)
* @flags: execution state flags for link endpoint instance
* @peer_session: link session # being used by peer end of link * @peer_session: link session # being used by peer end of link
* @peer_bearer_id: bearer id used by link's peer endpoint * @peer_bearer_id: bearer id used by link's peer endpoint
* @bearer_id: local bearer id used by link * @bearer_id: local bearer id used by link
...@@ -119,6 +120,7 @@ struct tipc_stats { ...@@ -119,6 +120,7 @@ struct tipc_stats {
* @pmsg: convenience pointer to "proto_msg" field * @pmsg: convenience pointer to "proto_msg" field
* @priority: current link priority * @priority: current link priority
* @net_plane: current link network plane ('A' through 'H') * @net_plane: current link network plane ('A' through 'H')
* @exec_mode: transmit/receive mode for link endpoint instance
* @backlog_limit: backlog queue congestion thresholds (indexed by importance) * @backlog_limit: backlog queue congestion thresholds (indexed by importance)
* @exp_msg_count: # of tunnelled messages expected during link changeover * @exp_msg_count: # of tunnelled messages expected during link changeover
* @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset
...@@ -144,12 +146,9 @@ struct tipc_link { ...@@ -144,12 +146,9 @@ struct tipc_link {
u32 addr; u32 addr;
char name[TIPC_MAX_LINK_NAME]; char name[TIPC_MAX_LINK_NAME];
struct tipc_media_addr media_addr; struct tipc_media_addr media_addr;
struct timer_list timer;
struct tipc_node *owner; struct tipc_node *owner;
struct kref ref;
/* Management and link supervision data */ /* Management and link supervision data */
unsigned int flags;
u32 peer_session; u32 peer_session;
u32 peer_bearer_id; u32 peer_bearer_id;
u32 bearer_id; u32 bearer_id;
...@@ -165,6 +164,7 @@ struct tipc_link { ...@@ -165,6 +164,7 @@ struct tipc_link {
struct tipc_msg *pmsg; struct tipc_msg *pmsg;
u32 priority; u32 priority;
char net_plane; char net_plane;
u8 exec_mode;
u16 synch_point; u16 synch_point;
/* Failover */ /* Failover */
...@@ -192,8 +192,8 @@ struct tipc_link { ...@@ -192,8 +192,8 @@ struct tipc_link {
u16 rcv_nxt; u16 rcv_nxt;
u32 rcv_unacked; u32 rcv_unacked;
struct sk_buff_head deferdq; struct sk_buff_head deferdq;
struct sk_buff_head inputq; struct sk_buff_head *inputq;
struct sk_buff_head namedq; struct sk_buff_head *namedq;
/* Congestion handling */ /* Congestion handling */
struct sk_buff_head wakeupq; struct sk_buff_head wakeupq;
...@@ -207,9 +207,11 @@ struct tipc_link { ...@@ -207,9 +207,11 @@ struct tipc_link {
struct tipc_port; struct tipc_port;
struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, struct tipc_link *tipc_link_create(struct tipc_node *n,
struct tipc_bearer *b_ptr, struct tipc_bearer *b,
const struct tipc_media_addr *media_addr); const struct tipc_media_addr *maddr,
struct sk_buff_head *inputq,
struct sk_buff_head *namedq);
void tipc_link_delete(struct tipc_link *link); void tipc_link_delete(struct tipc_link *link);
void tipc_link_delete_list(struct net *net, unsigned int bearer_id); void tipc_link_delete_list(struct net *net, unsigned int bearer_id);
void tipc_link_failover_send_queue(struct tipc_link *l_ptr); void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
...@@ -221,12 +223,11 @@ void tipc_link_purge_queues(struct tipc_link *l_ptr); ...@@ -221,12 +223,11 @@ void tipc_link_purge_queues(struct tipc_link *l_ptr);
void tipc_link_purge_backlog(struct tipc_link *l); void tipc_link_purge_backlog(struct tipc_link *l);
void tipc_link_reset_all(struct tipc_node *node); void tipc_link_reset_all(struct tipc_node *node);
void tipc_link_reset(struct tipc_link *l_ptr); void tipc_link_reset(struct tipc_link *l_ptr);
int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest, void tipc_link_activate(struct tipc_link *link);
u32 selector);
int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dest,
u32 selector);
int __tipc_link_xmit(struct net *net, struct tipc_link *link, int __tipc_link_xmit(struct net *net, struct tipc_link *link,
struct sk_buff_head *list); struct sk_buff_head *list);
int tipc_link_xmit(struct tipc_link *link, struct sk_buff_head *list,
struct sk_buff_head *xmitq);
void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob, void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob,
u32 gap, u32 tolerance, u32 priority); u32 gap, u32 tolerance, u32 priority);
void tipc_link_push_packets(struct tipc_link *l_ptr); void tipc_link_push_packets(struct tipc_link *l_ptr);
...@@ -243,33 +244,12 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info); ...@@ -243,33 +244,12 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info);
int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info); int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info);
int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
void link_prepare_wakeup(struct tipc_link *l); void link_prepare_wakeup(struct tipc_link *l);
int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq);
int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
struct sk_buff_head *xmitq);
static inline u32 link_own_addr(struct tipc_link *l) static inline u32 link_own_addr(struct tipc_link *l)
{ {
return msg_prevnode(l->pmsg); return msg_prevnode(l->pmsg);
} }
/*
* Link status checking routines
*/
static inline int link_working_working(struct tipc_link *l_ptr)
{
return l_ptr->state == WORKING_WORKING;
}
static inline int link_working_unknown(struct tipc_link *l_ptr)
{
return l_ptr->state == WORKING_UNKNOWN;
}
static inline int link_reset_unknown(struct tipc_link *l_ptr)
{
return l_ptr->state == RESET_UNKNOWN;
}
static inline int link_reset_reset(struct tipc_link *l_ptr)
{
return l_ptr->state == RESET_RESET;
}
#endif #endif
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#define _TIPC_MSG_H #define _TIPC_MSG_H
#include <linux/tipc.h> #include <linux/tipc.h>
#include "core.h"
/* /*
* Constants and routines used to read and write TIPC payload message headers * Constants and routines used to read and write TIPC payload message headers
...@@ -658,12 +659,12 @@ static inline void msg_set_link_selector(struct tipc_msg *m, u32 n) ...@@ -658,12 +659,12 @@ static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
/* /*
* Word 5 * Word 5
*/ */
static inline u32 msg_session(struct tipc_msg *m) static inline u16 msg_session(struct tipc_msg *m)
{ {
return msg_bits(m, 5, 16, 0xffff); return msg_bits(m, 5, 16, 0xffff);
} }
static inline void msg_set_session(struct tipc_msg *m, u32 n) static inline void msg_set_session(struct tipc_msg *m, u16 n)
{ {
msg_set_bits(m, 5, 16, 0xffff, n); msg_set_bits(m, 5, 16, 0xffff, n);
} }
...@@ -766,6 +767,22 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) ...@@ -766,6 +767,22 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
msg_set_bits(m, 9, 0, 0xffff, n); msg_set_bits(m, 9, 0, 0xffff, n);
} }
static inline bool msg_is_traffic(struct tipc_msg *m)
{
if (likely(msg_user(m) != LINK_PROTOCOL))
return true;
if ((msg_type(m) == RESET_MSG) || (msg_type(m) == ACTIVATE_MSG))
return false;
return true;
}
static inline bool msg_peer_is_up(struct tipc_msg *m)
{
if (likely(msg_is_traffic(m)))
return false;
return msg_redundant_link(m);
}
struct sk_buff *tipc_buf_acquire(u32 size); struct sk_buff *tipc_buf_acquire(u32 size);
bool tipc_msg_validate(struct sk_buff *skb); bool tipc_msg_validate(struct sk_buff *skb);
bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode,
...@@ -879,4 +896,36 @@ static inline bool tipc_skb_queue_tail(struct sk_buff_head *list, ...@@ -879,4 +896,36 @@ static inline bool tipc_skb_queue_tail(struct sk_buff_head *list,
return rv; return rv;
} }
/* tipc_skb_queue_sorted(); sort pkt into list according to sequence number
* @list: list to be appended to
* @skb: buffer to add
* Returns true if queue should treated further, otherwise false
*/
static inline bool __tipc_skb_queue_sorted(struct sk_buff_head *list,
struct sk_buff *skb)
{
struct sk_buff *_skb, *tmp;
struct tipc_msg *hdr = buf_msg(skb);
u16 seqno = msg_seqno(hdr);
if (skb_queue_empty(list) || (msg_user(hdr) == LINK_PROTOCOL)) {
__skb_queue_head(list, skb);
return true;
}
if (likely(less(seqno, buf_seqno(skb_peek(list))))) {
__skb_queue_head(list, skb);
return true;
}
if (!more(seqno, buf_seqno(skb_peek_tail(list)))) {
skb_queue_walk_safe(list, _skb, tmp) {
if (likely(less(seqno, buf_seqno(_skb)))) {
__skb_queue_before(list, _skb, skb);
return true;
}
}
}
__skb_queue_tail(list, skb);
return false;
}
#endif #endif
...@@ -96,13 +96,13 @@ void named_cluster_distribute(struct net *net, struct sk_buff *skb) ...@@ -96,13 +96,13 @@ void named_cluster_distribute(struct net *net, struct sk_buff *skb)
dnode = node->addr; dnode = node->addr;
if (in_own_node(net, dnode)) if (in_own_node(net, dnode))
continue; continue;
if (!tipc_node_active_links(node)) if (!tipc_node_is_up(node))
continue; continue;
oskb = pskb_copy(skb, GFP_ATOMIC); oskb = pskb_copy(skb, GFP_ATOMIC);
if (!oskb) if (!oskb)
break; break;
msg_set_destnode(buf_msg(oskb), dnode); msg_set_destnode(buf_msg(oskb), dnode);
tipc_link_xmit_skb(net, oskb, dnode, dnode); tipc_node_xmit_skb(net, oskb, dnode, dnode);
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -223,7 +223,7 @@ void tipc_named_node_up(struct net *net, u32 dnode) ...@@ -223,7 +223,7 @@ void tipc_named_node_up(struct net *net, u32 dnode)
&tn->nametbl->publ_list[TIPC_ZONE_SCOPE]); &tn->nametbl->publ_list[TIPC_ZONE_SCOPE]);
rcu_read_unlock(); rcu_read_unlock();
tipc_link_xmit(net, &head, dnode, dnode); tipc_node_xmit(net, &head, dnode, dnode);
} }
static void tipc_publ_subscribe(struct net *net, struct publication *publ, static void tipc_publ_subscribe(struct net *net, struct publication *publ,
......
This diff is collapsed.
...@@ -45,6 +45,26 @@ ...@@ -45,6 +45,26 @@
/* Out-of-range value for node signature */ /* Out-of-range value for node signature */
#define INVALID_NODE_SIG 0x10000 #define INVALID_NODE_SIG 0x10000
#define INVALID_BEARER_ID -1
/* Node FSM states and events:
*/
enum {
SELF_DOWN_PEER_DOWN = 0xdd,
SELF_UP_PEER_UP = 0xaa,
SELF_DOWN_PEER_LEAVING = 0xd1,
SELF_UP_PEER_COMING = 0xac,
SELF_COMING_PEER_UP = 0xca,
SELF_LEAVING_PEER_DOWN = 0x1d,
};
enum {
SELF_ESTABL_CONTACT_EVT = 0xec,
SELF_LOST_CONTACT_EVT = 0x1c,
PEER_ESTABL_CONTACT_EVT = 0xfec,
PEER_LOST_CONTACT_EVT = 0xf1c
};
/* Flags used to take different actions according to flag type /* Flags used to take different actions according to flag type
* TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down * TIPC_WAIT_PEER_LINKS_DOWN: wait to see that peer's links are down
* TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down
...@@ -54,8 +74,6 @@ ...@@ -54,8 +74,6 @@
*/ */
enum { enum {
TIPC_MSG_EVT = 1, TIPC_MSG_EVT = 1,
TIPC_WAIT_PEER_LINKS_DOWN = (1 << 1),
TIPC_WAIT_OWN_LINKS_DOWN = (1 << 2),
TIPC_NOTIFY_NODE_DOWN = (1 << 3), TIPC_NOTIFY_NODE_DOWN = (1 << 3),
TIPC_NOTIFY_NODE_UP = (1 << 4), TIPC_NOTIFY_NODE_UP = (1 << 4),
TIPC_WAKEUP_BCAST_USERS = (1 << 5), TIPC_WAKEUP_BCAST_USERS = (1 << 5),
...@@ -85,10 +103,17 @@ struct tipc_node_bclink { ...@@ -85,10 +103,17 @@ struct tipc_node_bclink {
u32 deferred_size; u32 deferred_size;
struct sk_buff_head deferdq; struct sk_buff_head deferdq;
struct sk_buff *reasm_buf; struct sk_buff *reasm_buf;
int inputq_map; struct sk_buff_head namedq;
bool recv_permitted; bool recv_permitted;
}; };
struct tipc_link_entry {
struct tipc_link *link;
u32 mtu;
struct sk_buff_head inputq;
struct tipc_media_addr maddr;
};
/** /**
* struct tipc_node - TIPC node structure * struct tipc_node - TIPC node structure
* @addr: network address of node * @addr: network address of node
...@@ -98,9 +123,8 @@ struct tipc_node_bclink { ...@@ -98,9 +123,8 @@ struct tipc_node_bclink {
* @hash: links to adjacent nodes in unsorted hash chain * @hash: links to adjacent nodes in unsorted hash chain
* @inputq: pointer to input queue containing messages for msg event * @inputq: pointer to input queue containing messages for msg event
* @namedq: pointer to name table input queue with name table messages * @namedq: pointer to name table input queue with name table messages
* @curr_link: the link holding the node lock, if any * @active_links: bearer ids of active links, used as index into links[] array
* @active_links: pointers to active links to node * @links: array containing references to all links to node
* @links: pointers to all links to node
* @action_flags: bit mask of different types of node actions * @action_flags: bit mask of different types of node actions
* @bclink: broadcast-related info * @bclink: broadcast-related info
* @list: links to adjacent nodes in sorted list of cluster's nodes * @list: links to adjacent nodes in sorted list of cluster's nodes
...@@ -120,12 +144,12 @@ struct tipc_node { ...@@ -120,12 +144,12 @@ struct tipc_node {
struct hlist_node hash; struct hlist_node hash;
struct sk_buff_head *inputq; struct sk_buff_head *inputq;
struct sk_buff_head *namedq; struct sk_buff_head *namedq;
struct tipc_link *active_links[2]; int active_links[2];
u32 act_mtus[2]; struct tipc_link_entry links[MAX_BEARERS];
struct tipc_link *links[MAX_BEARERS];
int action_flags; int action_flags;
struct tipc_node_bclink bclink; struct tipc_node_bclink bclink;
struct list_head list; struct list_head list;
int state;
int link_cnt; int link_cnt;
u16 working_links; u16 working_links;
u16 capabilities; u16 capabilities;
...@@ -133,6 +157,8 @@ struct tipc_node { ...@@ -133,6 +157,8 @@ struct tipc_node {
u32 link_id; u32 link_id;
struct list_head publ_list; struct list_head publ_list;
struct list_head conn_sks; struct list_head conn_sks;
unsigned long keepalive_intv;
struct timer_list timer;
struct rcu_head rcu; struct rcu_head rcu;
}; };
...@@ -140,18 +166,25 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr); ...@@ -140,18 +166,25 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr);
void tipc_node_put(struct tipc_node *node); void tipc_node_put(struct tipc_node *node);
struct tipc_node *tipc_node_create(struct net *net, u32 addr); struct tipc_node *tipc_node_create(struct net *net, u32 addr);
void tipc_node_stop(struct net *net); void tipc_node_stop(struct net *net);
void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *bearer,
bool *link_up, bool *addr_match,
struct tipc_media_addr *maddr);
bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *bearer,
struct tipc_media_addr *maddr);
void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_link_down(struct tipc_node *n_ptr, int bearer_id);
void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr); void tipc_node_link_up(struct tipc_node *n_ptr, int bearer_id);
int tipc_node_active_links(struct tipc_node *n_ptr); bool tipc_node_is_up(struct tipc_node *n);
int tipc_node_is_up(struct tipc_node *n_ptr);
int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node,
char *linkname, size_t len); char *linkname, size_t len);
void tipc_node_unlock(struct tipc_node *node); void tipc_node_unlock(struct tipc_node *node);
int tipc_node_xmit(struct net *net, struct sk_buff_head *list, u32 dnode,
int selector);
int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dest,
u32 selector);
int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port); int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port);
void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port); void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port);
int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb); int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb);
static inline void tipc_node_lock(struct tipc_node *node) static inline void tipc_node_lock(struct tipc_node *node)
...@@ -159,26 +192,30 @@ static inline void tipc_node_lock(struct tipc_node *node) ...@@ -159,26 +192,30 @@ static inline void tipc_node_lock(struct tipc_node *node)
spin_lock_bh(&node->lock); spin_lock_bh(&node->lock);
} }
static inline bool tipc_node_blocked(struct tipc_node *node) static inline struct tipc_link *node_active_link(struct tipc_node *n, int sel)
{ {
return (node->action_flags & (TIPC_WAIT_PEER_LINKS_DOWN | int bearer_id = n->active_links[sel & 1];
TIPC_NOTIFY_NODE_DOWN | TIPC_WAIT_OWN_LINKS_DOWN));
if (unlikely(bearer_id == INVALID_BEARER_ID))
return NULL;
return n->links[bearer_id].link;
} }
static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector) static inline unsigned int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel)
{ {
struct tipc_node *node; struct tipc_node *n;
u32 mtu; int bearer_id;
unsigned int mtu = MAX_MSG_SIZE;
node = tipc_node_find(net, addr);
if (likely(node)) { n = tipc_node_find(net, addr);
mtu = node->act_mtus[selector & 1]; if (unlikely(!n))
tipc_node_put(node); return mtu;
} else {
mtu = MAX_MSG_SIZE;
}
bearer_id = n->active_links[sel & 1];
if (likely(bearer_id != INVALID_BEARER_ID))
mtu = n->links[bearer_id].mtu;
tipc_node_put(n);
return mtu; return mtu;
} }
......
...@@ -261,7 +261,7 @@ static void tsk_rej_rx_queue(struct sock *sk) ...@@ -261,7 +261,7 @@ static void tsk_rej_rx_queue(struct sock *sk)
while ((skb = __skb_dequeue(&sk->sk_receive_queue))) { while ((skb = __skb_dequeue(&sk->sk_receive_queue))) {
if (tipc_msg_reverse(own_node, skb, &dnode, TIPC_ERR_NO_PORT)) if (tipc_msg_reverse(own_node, skb, &dnode, TIPC_ERR_NO_PORT))
tipc_link_xmit_skb(sock_net(sk), skb, dnode, 0); tipc_node_xmit_skb(sock_net(sk), skb, dnode, 0);
} }
} }
...@@ -443,7 +443,7 @@ static int tipc_release(struct socket *sock) ...@@ -443,7 +443,7 @@ static int tipc_release(struct socket *sock)
} }
if (tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode, if (tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode,
TIPC_ERR_NO_PORT)) TIPC_ERR_NO_PORT))
tipc_link_xmit_skb(net, skb, dnode, 0); tipc_node_xmit_skb(net, skb, dnode, 0);
} }
} }
...@@ -456,7 +456,7 @@ static int tipc_release(struct socket *sock) ...@@ -456,7 +456,7 @@ static int tipc_release(struct socket *sock)
tsk_own_node(tsk), tsk_peer_port(tsk), tsk_own_node(tsk), tsk_peer_port(tsk),
tsk->portid, TIPC_ERR_NO_PORT); tsk->portid, TIPC_ERR_NO_PORT);
if (skb) if (skb)
tipc_link_xmit_skb(net, skb, dnode, tsk->portid); tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
tipc_node_remove_conn(net, dnode, tsk->portid); tipc_node_remove_conn(net, dnode, tsk->portid);
} }
...@@ -686,21 +686,22 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, ...@@ -686,21 +686,22 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
do { do {
rc = tipc_bclink_xmit(net, pktchain); rc = tipc_bclink_xmit(net, pktchain);
if (likely(rc >= 0)) { if (likely(!rc))
rc = dsz; return dsz;
break;
if (rc == -ELINKCONG) {
tsk->link_cong = 1;
rc = tipc_wait_for_sndmsg(sock, &timeo);
if (!rc)
continue;
} }
__skb_queue_purge(pktchain);
if (rc == -EMSGSIZE) { if (rc == -EMSGSIZE) {
msg->msg_iter = save; msg->msg_iter = save;
goto new_mtu; goto new_mtu;
} }
if (rc != -ELINKCONG) break;
break; } while (1);
tipc_sk(sk)->link_cong = 1;
rc = tipc_wait_for_sndmsg(sock, &timeo);
if (rc)
__skb_queue_purge(pktchain);
} while (!rc);
return rc; return rc;
} }
...@@ -924,24 +925,25 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz) ...@@ -924,24 +925,25 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
do { do {
skb = skb_peek(pktchain); skb = skb_peek(pktchain);
TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong; TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
rc = tipc_link_xmit(net, pktchain, dnode, tsk->portid); rc = tipc_node_xmit(net, pktchain, dnode, tsk->portid);
if (likely(rc >= 0)) { if (likely(!rc)) {
if (sock->state != SS_READY) if (sock->state != SS_READY)
sock->state = SS_CONNECTING; sock->state = SS_CONNECTING;
rc = dsz; return dsz;
break;
} }
if (rc == -ELINKCONG) {
tsk->link_cong = 1;
rc = tipc_wait_for_sndmsg(sock, &timeo);
if (!rc)
continue;
}
__skb_queue_purge(pktchain);
if (rc == -EMSGSIZE) { if (rc == -EMSGSIZE) {
m->msg_iter = save; m->msg_iter = save;
goto new_mtu; goto new_mtu;
} }
if (rc != -ELINKCONG) break;
break; } while (1);
tsk->link_cong = 1;
rc = tipc_wait_for_sndmsg(sock, &timeo);
if (rc)
__skb_queue_purge(pktchain);
} while (!rc);
return rc; return rc;
} }
...@@ -1043,15 +1045,16 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz) ...@@ -1043,15 +1045,16 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
return rc; return rc;
do { do {
if (likely(!tsk_conn_cong(tsk))) { if (likely(!tsk_conn_cong(tsk))) {
rc = tipc_link_xmit(net, pktchain, dnode, portid); rc = tipc_node_xmit(net, pktchain, dnode, portid);
if (likely(!rc)) { if (likely(!rc)) {
tsk->sent_unacked++; tsk->sent_unacked++;
sent += send; sent += send;
if (sent == dsz) if (sent == dsz)
break; return dsz;
goto next; goto next;
} }
if (rc == -EMSGSIZE) { if (rc == -EMSGSIZE) {
__skb_queue_purge(pktchain);
tsk->max_pkt = tipc_node_get_mtu(net, dnode, tsk->max_pkt = tipc_node_get_mtu(net, dnode,
portid); portid);
m->msg_iter = save; m->msg_iter = save;
...@@ -1059,13 +1062,13 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz) ...@@ -1059,13 +1062,13 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
} }
if (rc != -ELINKCONG) if (rc != -ELINKCONG)
break; break;
tsk->link_cong = 1; tsk->link_cong = 1;
} }
rc = tipc_wait_for_sndpkt(sock, &timeo); rc = tipc_wait_for_sndpkt(sock, &timeo);
if (rc)
__skb_queue_purge(pktchain);
} while (!rc); } while (!rc);
__skb_queue_purge(pktchain);
return sent ? sent : rc; return sent ? sent : rc;
} }
...@@ -1221,7 +1224,7 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk, uint ack) ...@@ -1221,7 +1224,7 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk, uint ack)
return; return;
msg = buf_msg(skb); msg = buf_msg(skb);
msg_set_msgcnt(msg, ack); msg_set_msgcnt(msg, ack);
tipc_link_xmit_skb(net, skb, dnode, msg_link_selector(msg)); tipc_node_xmit_skb(net, skb, dnode, msg_link_selector(msg));
} }
static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
...@@ -1700,7 +1703,7 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -1700,7 +1703,7 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
return 0; return 0;
} }
if (!err || tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode, -err)) if (!err || tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode, -err))
tipc_link_xmit_skb(net, skb, dnode, tsk->portid); tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
return 0; return 0;
} }
...@@ -1796,7 +1799,7 @@ int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq) ...@@ -1796,7 +1799,7 @@ int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
if (!tipc_msg_reverse(tn->own_addr, skb, &dnode, -err)) if (!tipc_msg_reverse(tn->own_addr, skb, &dnode, -err))
continue; continue;
xmit: xmit:
tipc_link_xmit_skb(net, skb, dnode, dport); tipc_node_xmit_skb(net, skb, dnode, dport);
} }
return err ? -EHOSTUNREACH : 0; return err ? -EHOSTUNREACH : 0;
} }
...@@ -2089,7 +2092,7 @@ static int tipc_shutdown(struct socket *sock, int how) ...@@ -2089,7 +2092,7 @@ static int tipc_shutdown(struct socket *sock, int how)
} }
if (tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode, if (tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode,
TIPC_CONN_SHUTDOWN)) TIPC_CONN_SHUTDOWN))
tipc_link_xmit_skb(net, skb, dnode, tipc_node_xmit_skb(net, skb, dnode,
tsk->portid); tsk->portid);
} else { } else {
dnode = tsk_peer_node(tsk); dnode = tsk_peer_node(tsk);
...@@ -2099,7 +2102,7 @@ static int tipc_shutdown(struct socket *sock, int how) ...@@ -2099,7 +2102,7 @@ static int tipc_shutdown(struct socket *sock, int how)
0, dnode, tsk_own_node(tsk), 0, dnode, tsk_own_node(tsk),
tsk_peer_port(tsk), tsk_peer_port(tsk),
tsk->portid, TIPC_CONN_SHUTDOWN); tsk->portid, TIPC_CONN_SHUTDOWN);
tipc_link_xmit_skb(net, skb, dnode, tsk->portid); tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
} }
tsk->connected = 0; tsk->connected = 0;
sock->state = SS_DISCONNECTING; sock->state = SS_DISCONNECTING;
...@@ -2161,7 +2164,7 @@ static void tipc_sk_timeout(unsigned long data) ...@@ -2161,7 +2164,7 @@ static void tipc_sk_timeout(unsigned long data)
} }
bh_unlock_sock(sk); bh_unlock_sock(sk);
if (skb) if (skb)
tipc_link_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid); tipc_node_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid);
exit: exit:
sock_put(sk); sock_put(sk);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment