Skip to content

Commit 8a1577c

Browse files
Jon Paul Maloydavem330
authored andcommitted
tipc: move link supervision timer to node level
In our effort to move control of the links to the link aggregation layer, we move the perodic link supervision timer to struct tipc_node. The new timer is shared between all links belonging to the node, thus saving resources, while still kicking the FSM on both its pertaining links at each expiration. The current link timer and corresponding functions are removed. Reviewed-by: Ying Xue <[email protected]> Signed-off-by: Jon Maloy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 333ef69 commit 8a1577c

File tree

4 files changed

+68
-80
lines changed

4 files changed

+68
-80
lines changed

net/tipc/link.c

Lines changed: 4 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ static void link_handle_out_of_seq_msg(struct tipc_link *link,
127127
struct sk_buff *skb);
128128
static void tipc_link_proto_rcv(struct tipc_link *link,
129129
struct sk_buff *skb);
130-
static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tol);
131130
static void link_state_event(struct tipc_link *l_ptr, u32 event);
132131
static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
133132
u16 rcvgap, int tolerance, int priority,
@@ -139,7 +138,6 @@ static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf);
139138
static void tipc_link_input(struct tipc_link *l, struct sk_buff *skb);
140139
static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb);
141140
static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb);
142-
static void link_set_timer(struct tipc_link *link, unsigned long time);
143141
static void link_activate(struct tipc_link *link);
144142

145143
/*
@@ -150,21 +148,6 @@ static unsigned int align(unsigned int i)
150148
return (i + 3) & ~3u;
151149
}
152150

153-
static void tipc_link_release(struct kref *kref)
154-
{
155-
kfree(container_of(kref, struct tipc_link, ref));
156-
}
157-
158-
static void tipc_link_get(struct tipc_link *l_ptr)
159-
{
160-
kref_get(&l_ptr->ref);
161-
}
162-
163-
static void tipc_link_put(struct tipc_link *l_ptr)
164-
{
165-
kref_put(&l_ptr->ref, tipc_link_release);
166-
}
167-
168151
static struct tipc_link *tipc_parallel_link(struct tipc_link *l)
169152
{
170153
struct tipc_node *n = l->owner;
@@ -191,40 +174,6 @@ int tipc_link_is_active(struct tipc_link *l)
191174
return (node_active_link(n, 0) == l) || (node_active_link(n, 1) == l);
192175
}
193176

194-
/**
195-
* link_timeout - handle expiration of link timer
196-
*/
197-
static void link_timeout(unsigned long data)
198-
{
199-
struct tipc_link *l = (struct tipc_link *)data;
200-
struct sk_buff_head xmitq;
201-
struct sk_buff *skb;
202-
int rc;
203-
204-
__skb_queue_head_init(&xmitq);
205-
206-
tipc_node_lock(l->owner);
207-
208-
rc = tipc_link_timeout(l, &xmitq);
209-
210-
if (rc & TIPC_LINK_DOWN_EVT)
211-
tipc_link_reset(l);
212-
213-
skb = __skb_dequeue(&xmitq);
214-
if (skb)
215-
tipc_bearer_send(l->owner->net, l->bearer_id,
216-
skb, &l->media_addr);
217-
link_set_timer(l, l->keepalive_intv);
218-
tipc_node_unlock(l->owner);
219-
tipc_link_put(l);
220-
}
221-
222-
static void link_set_timer(struct tipc_link *link, unsigned long time)
223-
{
224-
if (!mod_timer(&link->timer, jiffies + time))
225-
tipc_link_get(link);
226-
}
227-
228177
/**
229178
* tipc_link_create - create a new link
230179
* @n_ptr: pointer to associated node
@@ -265,7 +214,6 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
265214
pr_warn("Link creation failed, no memory\n");
266215
return NULL;
267216
}
268-
kref_init(&l_ptr->ref);
269217
l_ptr->addr = peer;
270218
if_name = strchr(b_ptr->name, ':') + 1;
271219
sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown",
@@ -278,7 +226,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
278226
l_ptr->owner = n_ptr;
279227
l_ptr->peer_session = WILDCARD_SESSION;
280228
l_ptr->bearer_id = b_ptr->identity;
281-
link_set_supervision_props(l_ptr, b_ptr->tolerance);
229+
l_ptr->tolerance = b_ptr->tolerance;
282230
l_ptr->state = TIPC_LINK_RESETTING;
283231

284232
l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;
@@ -304,8 +252,6 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
304252
skb_queue_head_init(l_ptr->inputq);
305253
link_reset_statistics(l_ptr);
306254
tipc_node_attach_link(n_ptr, l_ptr);
307-
setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr);
308-
link_set_timer(l_ptr, l_ptr->keepalive_intv);
309255
return l_ptr;
310256
}
311257

@@ -316,12 +262,8 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
316262
void tipc_link_delete(struct tipc_link *l)
317263
{
318264
tipc_link_reset(l);
319-
if (del_timer(&l->timer))
320-
tipc_link_put(l);
321-
/* Delete link now, or when timer is finished: */
322265
tipc_link_reset_fragments(l);
323266
tipc_node_detach_link(l->owner, l);
324-
tipc_link_put(l);
325267
}
326268

327269
void tipc_link_delete_list(struct net *net, unsigned int bearer_id)
@@ -1447,7 +1389,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
14471389

14481390
msg_tol = msg_link_tolerance(msg);
14491391
if (msg_tol > l_ptr->tolerance)
1450-
link_set_supervision_props(l_ptr, msg_tol);
1392+
l_ptr->tolerance = msg_tol;
14511393

14521394
if (msg_linkprio(msg) > l_ptr->priority)
14531395
l_ptr->priority = msg_linkprio(msg);
@@ -1473,7 +1415,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
14731415

14741416
msg_tol = msg_link_tolerance(msg);
14751417
if (msg_tol)
1476-
link_set_supervision_props(l_ptr, msg_tol);
1418+
l_ptr->tolerance = msg_tol;
14771419

14781420
if (msg_linkprio(msg) &&
14791421
(msg_linkprio(msg) != l_ptr->priority)) {
@@ -1796,18 +1738,6 @@ static bool tipc_link_failover_rcv(struct tipc_link *link,
17961738
return *skb;
17971739
}
17981740

1799-
static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tol)
1800-
{
1801-
unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4;
1802-
1803-
if ((tol < TIPC_MIN_LINK_TOL) || (tol > TIPC_MAX_LINK_TOL))
1804-
return;
1805-
1806-
l_ptr->tolerance = tol;
1807-
l_ptr->keepalive_intv = msecs_to_jiffies(intv);
1808-
l_ptr->abort_limit = tol / (jiffies_to_msecs(l_ptr->keepalive_intv));
1809-
}
1810-
18111741
void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
18121742
{
18131743
int max_bulk = TIPC_MAX_PUBLICATIONS / (l->mtu / ITEM_SIZE);
@@ -1984,7 +1914,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info)
19841914
u32 tol;
19851915

19861916
tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1987-
link_set_supervision_props(link, tol);
1917+
link->tolerance = tol;
19881918
tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0);
19891919
}
19901920
if (props[TIPC_NLA_PROP_PRIO]) {

net/tipc/link.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,7 @@ struct tipc_link {
146146
u32 addr;
147147
char name[TIPC_MAX_LINK_NAME];
148148
struct tipc_media_addr media_addr;
149-
struct timer_list timer;
150149
struct tipc_node *owner;
151-
struct kref ref;
152150

153151
/* Management and link supervision data */
154152
u32 peer_session;

net/tipc/node.c

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
static void node_lost_contact(struct tipc_node *n_ptr);
4545
static void node_established_contact(struct tipc_node *n_ptr);
4646
static void tipc_node_delete(struct tipc_node *node);
47+
static void tipc_node_timeout(unsigned long data);
4748

4849
struct tipc_sock_conn {
4950
u32 port;
@@ -145,11 +146,27 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
145146
n_ptr->active_links[0] = INVALID_BEARER_ID;
146147
n_ptr->active_links[1] = INVALID_BEARER_ID;
147148
tipc_node_get(n_ptr);
149+
setup_timer(&n_ptr->timer, tipc_node_timeout, (unsigned long)n_ptr);
150+
n_ptr->keepalive_intv = U32_MAX;
148151
exit:
149152
spin_unlock_bh(&tn->node_list_lock);
150153
return n_ptr;
151154
}
152155

156+
static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l)
157+
{
158+
unsigned long tol = l->tolerance;
159+
unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4;
160+
unsigned long keepalive_intv = msecs_to_jiffies(intv);
161+
162+
/* Link with lowest tolerance determines timer interval */
163+
if (keepalive_intv < n->keepalive_intv)
164+
n->keepalive_intv = keepalive_intv;
165+
166+
/* Ensure link's abort limit corresponds to current interval */
167+
l->abort_limit = l->tolerance / jiffies_to_msecs(n->keepalive_intv);
168+
}
169+
153170
static void tipc_node_delete(struct tipc_node *node)
154171
{
155172
list_del_rcu(&node->list);
@@ -163,8 +180,11 @@ void tipc_node_stop(struct net *net)
163180
struct tipc_node *node, *t_node;
164181

165182
spin_lock_bh(&tn->node_list_lock);
166-
list_for_each_entry_safe(node, t_node, &tn->node_list, list)
183+
list_for_each_entry_safe(node, t_node, &tn->node_list, list) {
184+
if (del_timer(&node->timer))
185+
tipc_node_put(node);
167186
tipc_node_put(node);
187+
}
168188
spin_unlock_bh(&tn->node_list_lock);
169189
}
170190

@@ -222,6 +242,38 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
222242
tipc_node_put(node);
223243
}
224244

245+
/* tipc_node_timeout - handle expiration of node timer
246+
*/
247+
static void tipc_node_timeout(unsigned long data)
248+
{
249+
struct tipc_node *n = (struct tipc_node *)data;
250+
struct sk_buff_head xmitq;
251+
struct tipc_link *l;
252+
struct tipc_media_addr *maddr;
253+
int bearer_id;
254+
int rc = 0;
255+
256+
__skb_queue_head_init(&xmitq);
257+
258+
for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
259+
tipc_node_lock(n);
260+
l = n->links[bearer_id].link;
261+
if (l) {
262+
/* Link tolerance may change asynchronously: */
263+
tipc_node_calculate_timer(n, l);
264+
rc = tipc_link_timeout(l, &xmitq);
265+
if (rc & TIPC_LINK_DOWN_EVT)
266+
tipc_link_reset(l);
267+
}
268+
tipc_node_unlock(n);
269+
maddr = &n->links[bearer_id].maddr;
270+
tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
271+
}
272+
if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
273+
tipc_node_get(n);
274+
tipc_node_put(n);
275+
}
276+
225277
/**
226278
* tipc_node_link_up - handle addition of link
227279
*
@@ -335,10 +387,16 @@ bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *b,
335387
struct tipc_media_addr *curr = &n->links[b->identity].maddr;
336388
struct sk_buff_head *inputq = &n->links[b->identity].inputq;
337389

338-
if (!l)
390+
if (!l) {
339391
l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq);
340-
if (!l)
341-
return false;
392+
if (!l)
393+
return false;
394+
tipc_node_calculate_timer(n, l);
395+
if (n->link_cnt == 1) {
396+
if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
397+
tipc_node_get(n);
398+
}
399+
}
342400
memcpy(&l->media_addr, maddr, sizeof(*maddr));
343401
memcpy(curr, maddr, sizeof(*maddr));
344402
tipc_link_reset(l);

net/tipc/node.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ struct tipc_node {
140140
u32 link_id;
141141
struct list_head publ_list;
142142
struct list_head conn_sks;
143+
unsigned long keepalive_intv;
144+
struct timer_list timer;
143145
struct rcu_head rcu;
144146
};
145147

0 commit comments

Comments
 (0)