Commit 013dc9d5 authored by David S. Miller's avatar David S. Miller

Merge branch 'tipc-tracepoints'

Tuong Lien says:

====================
tipc: tracepoints and trace_events in TIPC

The patch series is the first step of introducing a tracing framework in
TIPC, which will assist in collecting complete & plentiful data for post
analysis, even in the case of a single failure occurrence e.g. when the
failure is unreproducible.

The tracing code in TIPC utilizes the powerful kernel tracepoints, trace
events features along with particular dump functions to trace the TIPC
object data and events (incl. bearer, link, socket, node, etc.).

The tracing code should generate zero-load to TIPC when the trace events
are not enabled.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4a54877e cf5f55f7
...@@ -9,7 +9,9 @@ tipc-y += addr.o bcast.o bearer.o \ ...@@ -9,7 +9,9 @@ tipc-y += addr.o bcast.o bearer.o \
core.o link.o discover.o msg.o \ core.o link.o discover.o msg.o \
name_distr.o subscr.o monitor.o name_table.o net.o \ name_distr.o subscr.o monitor.o name_table.o net.o \
netlink.o netlink_compat.o node.o socket.o eth_media.o \ netlink.o netlink_compat.o node.o socket.o eth_media.o \
topsrv.o socket.o group.o topsrv.o socket.o group.o trace.o
CFLAGS_trace.o += -I$(src)
tipc-$(CONFIG_TIPC_MEDIA_UDP) += udp_media.o tipc-$(CONFIG_TIPC_MEDIA_UDP) += udp_media.o
tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "bcast.h" #include "bcast.h"
#include "netlink.h" #include "netlink.h"
#include "udp_media.h" #include "udp_media.h"
#include "trace.h"
#define MAX_ADDR_STR 60 #define MAX_ADDR_STR 60
...@@ -99,7 +100,7 @@ static struct tipc_media *media_find_id(u8 type) ...@@ -99,7 +100,7 @@ static struct tipc_media *media_find_id(u8 type)
/** /**
* tipc_media_addr_printf - record media address in print buffer * tipc_media_addr_printf - record media address in print buffer
*/ */
void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a) int tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
{ {
char addr_str[MAX_ADDR_STR]; char addr_str[MAX_ADDR_STR];
struct tipc_media *m; struct tipc_media *m;
...@@ -114,9 +115,10 @@ void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a) ...@@ -114,9 +115,10 @@ void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
ret = scnprintf(buf, len, "UNKNOWN(%u)", a->media_id); ret = scnprintf(buf, len, "UNKNOWN(%u)", a->media_id);
for (i = 0; i < sizeof(a->value); i++) for (i = 0; i < sizeof(a->value); i++)
ret += scnprintf(buf - ret, len + ret, ret += scnprintf(buf + ret, len - ret,
"-%02x", a->value[i]); "-%x", a->value[i]);
} }
return ret;
} }
/** /**
...@@ -607,6 +609,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, ...@@ -607,6 +609,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
if (!b) if (!b)
return NOTIFY_DONE; return NOTIFY_DONE;
trace_tipc_l2_device_event(dev, b, evt);
switch (evt) { switch (evt) {
case NETDEV_CHANGE: case NETDEV_CHANGE:
if (netif_carrier_ok(dev) && netif_oper_up(dev)) { if (netif_carrier_ok(dev) && netif_oper_up(dev)) {
......
...@@ -207,7 +207,7 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info); ...@@ -207,7 +207,7 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info);
int tipc_media_set_priority(const char *name, u32 new_value); int tipc_media_set_priority(const char *name, u32 new_value);
int tipc_media_set_window(const char *name, u32 new_value); int tipc_media_set_window(const char *name, u32 new_value);
void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a); int tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
struct nlattr *attrs[]); struct nlattr *attrs[]);
void tipc_disable_l2_media(struct tipc_bearer *b); void tipc_disable_l2_media(struct tipc_bearer *b);
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "discover.h" #include "discover.h"
#include "netlink.h" #include "netlink.h"
#include "monitor.h" #include "monitor.h"
#include "trace.h"
#include <linux/pkt_sched.h> #include <linux/pkt_sched.h>
...@@ -356,9 +357,11 @@ void tipc_link_remove_bc_peer(struct tipc_link *snd_l, ...@@ -356,9 +357,11 @@ void tipc_link_remove_bc_peer(struct tipc_link *snd_l,
rcv_l->bc_peer_is_up = true; rcv_l->bc_peer_is_up = true;
rcv_l->state = LINK_ESTABLISHED; rcv_l->state = LINK_ESTABLISHED;
tipc_link_bc_ack_rcv(rcv_l, ack, xmitq); tipc_link_bc_ack_rcv(rcv_l, ack, xmitq);
trace_tipc_link_reset(rcv_l, TIPC_DUMP_ALL, "bclink removed!");
tipc_link_reset(rcv_l); tipc_link_reset(rcv_l);
rcv_l->state = LINK_RESET; rcv_l->state = LINK_RESET;
if (!snd_l->ackers) { if (!snd_l->ackers) {
trace_tipc_link_reset(snd_l, TIPC_DUMP_ALL, "zero ackers!");
tipc_link_reset(snd_l); tipc_link_reset(snd_l);
snd_l->state = LINK_RESET; snd_l->state = LINK_RESET;
__skb_queue_purge(xmitq); __skb_queue_purge(xmitq);
...@@ -522,6 +525,7 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, ...@@ -522,6 +525,7 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
l = *link; l = *link;
strcpy(l->name, tipc_bclink_name); strcpy(l->name, tipc_bclink_name);
trace_tipc_link_reset(l, TIPC_DUMP_ALL, "bclink created!");
tipc_link_reset(l); tipc_link_reset(l);
l->state = LINK_RESET; l->state = LINK_RESET;
l->ackers = 0; l->ackers = 0;
...@@ -546,6 +550,7 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, ...@@ -546,6 +550,7 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
int tipc_link_fsm_evt(struct tipc_link *l, int evt) int tipc_link_fsm_evt(struct tipc_link *l, int evt)
{ {
int rc = 0; int rc = 0;
int old_state = l->state;
switch (l->state) { switch (l->state) {
case LINK_RESETTING: case LINK_RESETTING:
...@@ -692,10 +697,12 @@ int tipc_link_fsm_evt(struct tipc_link *l, int evt) ...@@ -692,10 +697,12 @@ int tipc_link_fsm_evt(struct tipc_link *l, int evt)
default: default:
pr_err("Unknown FSM state %x in %s\n", l->state, l->name); pr_err("Unknown FSM state %x in %s\n", l->state, l->name);
} }
trace_tipc_link_fsm(l->name, old_state, l->state, evt);
return rc; return rc;
illegal_evt: illegal_evt:
pr_err("Illegal FSM event %x in state %x on link %s\n", pr_err("Illegal FSM event %x in state %x on link %s\n",
evt, l->state, l->name); evt, l->state, l->name);
trace_tipc_link_fsm(l->name, old_state, l->state, evt);
return rc; return rc;
} }
...@@ -740,6 +747,18 @@ static void link_profile_stats(struct tipc_link *l) ...@@ -740,6 +747,18 @@ static void link_profile_stats(struct tipc_link *l)
l->stats.msg_length_profile[6]++; l->stats.msg_length_profile[6]++;
} }
/**
* tipc_link_too_silent - check if link is "too silent"
* @l: tipc link to be checked
*
* Returns true if the link 'silent_intv_cnt' is about to reach the
* 'abort_limit' value, otherwise false
*/
bool tipc_link_too_silent(struct tipc_link *l)
{
return (l->silent_intv_cnt + 2 > l->abort_limit);
}
/* tipc_link_timeout - perform periodic task as instructed from node timeout /* tipc_link_timeout - perform periodic task as instructed from node timeout
*/ */
int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq)
...@@ -753,6 +772,8 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) ...@@ -753,6 +772,8 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq)
u16 bc_acked = l->bc_rcvlink->acked; u16 bc_acked = l->bc_rcvlink->acked;
struct tipc_mon_state *mstate = &l->mon_state; struct tipc_mon_state *mstate = &l->mon_state;
trace_tipc_link_timeout(l, TIPC_DUMP_NONE, " ");
trace_tipc_link_too_silent(l, TIPC_DUMP_ALL, " ");
switch (l->state) { switch (l->state) {
case LINK_ESTABLISHED: case LINK_ESTABLISHED:
case LINK_SYNCHING: case LINK_SYNCHING:
...@@ -815,6 +836,7 @@ static int link_schedule_user(struct tipc_link *l, struct tipc_msg *hdr) ...@@ -815,6 +836,7 @@ static int link_schedule_user(struct tipc_link *l, struct tipc_msg *hdr)
TIPC_SKB_CB(skb)->chain_imp = msg_importance(hdr); TIPC_SKB_CB(skb)->chain_imp = msg_importance(hdr);
skb_queue_tail(&l->wakeupq, skb); skb_queue_tail(&l->wakeupq, skb);
l->stats.link_congs++; l->stats.link_congs++;
trace_tipc_link_conges(l, TIPC_DUMP_ALL, "wakeup scheduled!");
return -ELINKCONG; return -ELINKCONG;
} }
...@@ -1036,6 +1058,7 @@ static int tipc_link_retrans(struct tipc_link *l, struct tipc_link *r, ...@@ -1036,6 +1058,7 @@ static int tipc_link_retrans(struct tipc_link *l, struct tipc_link *r,
if (less(to, from)) if (less(to, from))
return 0; return 0;
trace_tipc_link_retrans(r, from, to, &l->transmq);
/* Detect repeated retransmit failures on same packet */ /* Detect repeated retransmit failures on same packet */
if (r->prev_from != from) { if (r->prev_from != from) {
r->prev_from = from; r->prev_from = from;
...@@ -1043,6 +1066,9 @@ static int tipc_link_retrans(struct tipc_link *l, struct tipc_link *r, ...@@ -1043,6 +1066,9 @@ static int tipc_link_retrans(struct tipc_link *l, struct tipc_link *r,
r->stale_cnt = 0; r->stale_cnt = 0;
} else if (++r->stale_cnt > 99 && time_after(jiffies, r->stale_limit)) { } else if (++r->stale_cnt > 99 && time_after(jiffies, r->stale_limit)) {
link_retransmit_failure(l, skb); link_retransmit_failure(l, skb);
trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
if (link_is_bc_sndlink(l)) if (link_is_bc_sndlink(l))
return TIPC_LINK_DOWN_EVT; return TIPC_LINK_DOWN_EVT;
return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); return tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
...@@ -1402,6 +1428,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, ...@@ -1402,6 +1428,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
l->stats.sent_nacks++; l->stats.sent_nacks++;
skb->priority = TC_PRIO_CONTROL; skb->priority = TC_PRIO_CONTROL;
__skb_queue_tail(xmitq, skb); __skb_queue_tail(xmitq, skb);
trace_tipc_proto_build(skb, false, l->name);
} }
void tipc_link_create_dummy_tnl_msg(struct tipc_link *l, void tipc_link_create_dummy_tnl_msg(struct tipc_link *l,
...@@ -1565,6 +1592,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, ...@@ -1565,6 +1592,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
char *if_name; char *if_name;
int rc = 0; int rc = 0;
trace_tipc_proto_rcv(skb, false, l->name);
if (tipc_link_is_blocked(l) || !xmitq) if (tipc_link_is_blocked(l) || !xmitq)
goto exit; goto exit;
...@@ -1575,8 +1603,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, ...@@ -1575,8 +1603,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
hdr = buf_msg(skb); hdr = buf_msg(skb);
data = msg_data(hdr); data = msg_data(hdr);
if (!tipc_link_validate_msg(l, hdr)) if (!tipc_link_validate_msg(l, hdr)) {
trace_tipc_skb_dump(skb, false, "PROTO invalid (1)!");
trace_tipc_link_dump(l, TIPC_DUMP_NONE, "PROTO invalid (1)!");
goto exit; goto exit;
}
switch (mtyp) { switch (mtyp) {
case RESET_MSG: case RESET_MSG:
...@@ -1819,6 +1850,7 @@ void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked, ...@@ -1819,6 +1850,7 @@ void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
if (!more(acked, l->acked)) if (!more(acked, l->acked))
return; return;
trace_tipc_link_bc_ack(l, l->acked, acked, &snd_l->transmq);
/* Skip over packets peer has already acked */ /* Skip over packets peer has already acked */
skb_queue_walk(&snd_l->transmq, skb) { skb_queue_walk(&snd_l->transmq, skb) {
if (more(buf_seqno(skb), l->acked)) if (more(buf_seqno(skb), l->acked))
...@@ -2222,3 +2254,122 @@ void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit) ...@@ -2222,3 +2254,122 @@ void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit)
{ {
l->abort_limit = limit; l->abort_limit = limit;
} }
char *tipc_link_name_ext(struct tipc_link *l, char *buf)
{
if (!l)
scnprintf(buf, TIPC_MAX_LINK_NAME, "null");
else if (link_is_bc_sndlink(l))
scnprintf(buf, TIPC_MAX_LINK_NAME, "broadcast-sender");
else if (link_is_bc_rcvlink(l))
scnprintf(buf, TIPC_MAX_LINK_NAME,
"broadcast-receiver, peer %x", l->addr);
else
memcpy(buf, l->name, TIPC_MAX_LINK_NAME);
return buf;
}
/**
* tipc_link_dump - dump TIPC link data
* @l: tipc link to be dumped
* @dqueues: bitmask to decide if any link queue to be dumped?
* - TIPC_DUMP_NONE: don't dump link queues
* - TIPC_DUMP_TRANSMQ: dump link transmq queue
* - TIPC_DUMP_BACKLOGQ: dump link backlog queue
* - TIPC_DUMP_DEFERDQ: dump link deferd queue
* - TIPC_DUMP_INPUTQ: dump link input queue
* - TIPC_DUMP_WAKEUP: dump link wakeup queue
* - TIPC_DUMP_ALL: dump all the link queues above
* @buf: returned buffer of dump data in format
*/
int tipc_link_dump(struct tipc_link *l, u16 dqueues, char *buf)
{
int i = 0;
size_t sz = (dqueues) ? LINK_LMAX : LINK_LMIN;
struct sk_buff_head *list;
struct sk_buff *hskb, *tskb;
u32 len;
if (!l) {
i += scnprintf(buf, sz, "link data: (null)\n");
return i;
}
i += scnprintf(buf, sz, "link data: %x", l->addr);
i += scnprintf(buf + i, sz - i, " %x", l->state);
i += scnprintf(buf + i, sz - i, " %u", l->in_session);
i += scnprintf(buf + i, sz - i, " %u", l->session);
i += scnprintf(buf + i, sz - i, " %u", l->peer_session);
i += scnprintf(buf + i, sz - i, " %u", l->snd_nxt);
i += scnprintf(buf + i, sz - i, " %u", l->rcv_nxt);
i += scnprintf(buf + i, sz - i, " %u", l->snd_nxt_state);
i += scnprintf(buf + i, sz - i, " %u", l->rcv_nxt_state);
i += scnprintf(buf + i, sz - i, " %x", l->peer_caps);
i += scnprintf(buf + i, sz - i, " %u", l->silent_intv_cnt);
i += scnprintf(buf + i, sz - i, " %u", l->rst_cnt);
i += scnprintf(buf + i, sz - i, " %u", l->prev_from);
i += scnprintf(buf + i, sz - i, " %u", l->stale_cnt);
i += scnprintf(buf + i, sz - i, " %u", l->acked);
list = &l->transmq;
len = skb_queue_len(list);
hskb = skb_peek(list);
tskb = skb_peek_tail(list);
i += scnprintf(buf + i, sz - i, " | %u %u %u", len,
(hskb) ? msg_seqno(buf_msg(hskb)) : 0,
(tskb) ? msg_seqno(buf_msg(tskb)) : 0);
list = &l->deferdq;
len = skb_queue_len(list);
hskb = skb_peek(list);
tskb = skb_peek_tail(list);
i += scnprintf(buf + i, sz - i, " | %u %u %u", len,
(hskb) ? msg_seqno(buf_msg(hskb)) : 0,
(tskb) ? msg_seqno(buf_msg(tskb)) : 0);
list = &l->backlogq;
len = skb_queue_len(list);
hskb = skb_peek(list);
tskb = skb_peek_tail(list);
i += scnprintf(buf + i, sz - i, " | %u %u %u", len,
(hskb) ? msg_seqno(buf_msg(hskb)) : 0,
(tskb) ? msg_seqno(buf_msg(tskb)) : 0);
list = l->inputq;
len = skb_queue_len(list);
hskb = skb_peek(list);
tskb = skb_peek_tail(list);
i += scnprintf(buf + i, sz - i, " | %u %u %u\n", len,
(hskb) ? msg_seqno(buf_msg(hskb)) : 0,
(tskb) ? msg_seqno(buf_msg(tskb)) : 0);
if (dqueues & TIPC_DUMP_TRANSMQ) {
i += scnprintf(buf + i, sz - i, "transmq: ");
i += tipc_list_dump(&l->transmq, false, buf + i);
}
if (dqueues & TIPC_DUMP_BACKLOGQ) {
i += scnprintf(buf + i, sz - i,
"backlogq: <%u %u %u %u %u>, ",
l->backlog[TIPC_LOW_IMPORTANCE].len,
l->backlog[TIPC_MEDIUM_IMPORTANCE].len,
l->backlog[TIPC_HIGH_IMPORTANCE].len,
l->backlog[TIPC_CRITICAL_IMPORTANCE].len,
l->backlog[TIPC_SYSTEM_IMPORTANCE].len);
i += tipc_list_dump(&l->backlogq, false, buf + i);
}
if (dqueues & TIPC_DUMP_DEFERDQ) {
i += scnprintf(buf + i, sz - i, "deferdq: ");
i += tipc_list_dump(&l->deferdq, false, buf + i);
}
if (dqueues & TIPC_DUMP_INPUTQ) {
i += scnprintf(buf + i, sz - i, "inputq: ");
i += tipc_list_dump(l->inputq, false, buf + i);
}
if (dqueues & TIPC_DUMP_WAKEUP) {
i += scnprintf(buf + i, sz - i, "wakeup: ");
i += tipc_list_dump(&l->wakeupq, false, buf + i);
}
return i;
}
...@@ -109,6 +109,7 @@ u16 tipc_link_rcv_nxt(struct tipc_link *l); ...@@ -109,6 +109,7 @@ u16 tipc_link_rcv_nxt(struct tipc_link *l);
u16 tipc_link_acked(struct tipc_link *l); u16 tipc_link_acked(struct tipc_link *l);
u32 tipc_link_id(struct tipc_link *l); u32 tipc_link_id(struct tipc_link *l);
char *tipc_link_name(struct tipc_link *l); char *tipc_link_name(struct tipc_link *l);
char *tipc_link_name_ext(struct tipc_link *l, char *buf);
u32 tipc_link_state(struct tipc_link *l); u32 tipc_link_state(struct tipc_link *l);
char tipc_link_plane(struct tipc_link *l); char tipc_link_plane(struct tipc_link *l);
int tipc_link_prio(struct tipc_link *l); int tipc_link_prio(struct tipc_link *l);
...@@ -147,4 +148,5 @@ int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr, ...@@ -147,4 +148,5 @@ int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
bool tipc_link_too_silent(struct tipc_link *l);
#endif #endif
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "monitor.h" #include "monitor.h"
#include "discover.h" #include "discover.h"
#include "netlink.h" #include "netlink.h"
#include "trace.h"
#define INVALID_NODE_SIG 0x10000 #define INVALID_NODE_SIG 0x10000
#define NODE_CLEANUP_AFTER 300000 #define NODE_CLEANUP_AFTER 300000
...@@ -432,6 +433,7 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr, ...@@ -432,6 +433,7 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
break; break;
} }
list_add_tail_rcu(&n->list, &temp_node->list); list_add_tail_rcu(&n->list, &temp_node->list);
trace_tipc_node_create(n, true, " ");
exit: exit:
spin_unlock_bh(&tn->node_list_lock); spin_unlock_bh(&tn->node_list_lock);
return n; return n;
...@@ -459,6 +461,7 @@ static void tipc_node_delete_from_list(struct tipc_node *node) ...@@ -459,6 +461,7 @@ static void tipc_node_delete_from_list(struct tipc_node *node)
static void tipc_node_delete(struct tipc_node *node) static void tipc_node_delete(struct tipc_node *node)
{ {
trace_tipc_node_delete(node, true, " ");
tipc_node_delete_from_list(node); tipc_node_delete_from_list(node);
del_timer_sync(&node->timer); del_timer_sync(&node->timer);
...@@ -616,6 +619,7 @@ static void tipc_node_timeout(struct timer_list *t) ...@@ -616,6 +619,7 @@ static void tipc_node_timeout(struct timer_list *t)
int bearer_id; int bearer_id;
int rc = 0; int rc = 0;
trace_tipc_node_timeout(n, false, " ");
if (!node_is_up(n) && tipc_node_cleanup(n)) { if (!node_is_up(n) && tipc_node_cleanup(n)) {
/*Removing the reference of Timer*/ /*Removing the reference of Timer*/
tipc_node_put(n); tipc_node_put(n);
...@@ -681,6 +685,7 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id, ...@@ -681,6 +685,7 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id,
pr_debug("Established link <%s> on network plane %c\n", pr_debug("Established link <%s> on network plane %c\n",
tipc_link_name(nl), tipc_link_plane(nl)); tipc_link_name(nl), tipc_link_plane(nl));
trace_tipc_node_link_up(n, true, " ");
/* Ensure that a STATE message goes first */ /* Ensure that a STATE message goes first */
tipc_link_build_state_msg(nl, xmitq); tipc_link_build_state_msg(nl, xmitq);
...@@ -783,6 +788,7 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, ...@@ -783,6 +788,7 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id,
if (tipc_link_peer_is_down(l)) if (tipc_link_peer_is_down(l))
tipc_node_fsm_evt(n, PEER_LOST_CONTACT_EVT); tipc_node_fsm_evt(n, PEER_LOST_CONTACT_EVT);
tipc_node_fsm_evt(n, SELF_LOST_CONTACT_EVT); tipc_node_fsm_evt(n, SELF_LOST_CONTACT_EVT);
trace_tipc_link_reset(l, TIPC_DUMP_ALL, "link down!");
tipc_link_fsm_evt(l, LINK_RESET_EVT); tipc_link_fsm_evt(l, LINK_RESET_EVT);
tipc_link_reset(l); tipc_link_reset(l);
tipc_link_build_reset_msg(l, xmitq); tipc_link_build_reset_msg(l, xmitq);
...@@ -800,6 +806,7 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id, ...@@ -800,6 +806,7 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id,
tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT);
n->sync_point = tipc_link_rcv_nxt(tnl) + (U16_MAX / 2 - 1); n->sync_point = tipc_link_rcv_nxt(tnl) + (U16_MAX / 2 - 1);
tipc_link_tnl_prepare(l, tnl, FAILOVER_MSG, xmitq); tipc_link_tnl_prepare(l, tnl, FAILOVER_MSG, xmitq);
trace_tipc_link_reset(l, TIPC_DUMP_ALL, "link down -> failover!");
tipc_link_reset(l); tipc_link_reset(l);
tipc_link_fsm_evt(l, LINK_RESET_EVT); tipc_link_fsm_evt(l, LINK_RESET_EVT);
tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT);
...@@ -832,6 +839,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) ...@@ -832,6 +839,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
/* Defuse pending tipc_node_link_up() */ /* Defuse pending tipc_node_link_up() */
tipc_link_fsm_evt(l, LINK_RESET_EVT); tipc_link_fsm_evt(l, LINK_RESET_EVT);
} }
trace_tipc_node_link_down(n, true, "node link down or deleted!");
tipc_node_write_unlock(n); tipc_node_write_unlock(n);
if (delete) if (delete)
tipc_mon_remove_peer(n->net, n->addr, old_bearer_id); tipc_mon_remove_peer(n->net, n->addr, old_bearer_id);
...@@ -1021,6 +1029,7 @@ void tipc_node_check_dest(struct net *net, u32 addr, ...@@ -1021,6 +1029,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
*respond = false; *respond = false;
goto exit; goto exit;
} }
trace_tipc_link_reset(l, TIPC_DUMP_ALL, "link created!");
tipc_link_reset(l); tipc_link_reset(l);
tipc_link_fsm_evt(l, LINK_RESET_EVT); tipc_link_fsm_evt(l, LINK_RESET_EVT);
if (n->state == NODE_FAILINGOVER) if (n->state == NODE_FAILINGOVER)
...@@ -1060,6 +1069,7 @@ static void tipc_node_reset_links(struct tipc_node *n) ...@@ -1060,6 +1069,7 @@ static void tipc_node_reset_links(struct tipc_node *n)
pr_warn("Resetting all links to %x\n", n->addr); pr_warn("Resetting all links to %x\n", n->addr);
trace_tipc_node_reset_links(n, true, " ");
for (i = 0; i < MAX_BEARERS; i++) { for (i = 0; i < MAX_BEARERS; i++) {
tipc_node_link_down(n, i, false); tipc_node_link_down(n, i, false);
} }
...@@ -1235,11 +1245,13 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt) ...@@ -1235,11 +1245,13 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt)
pr_err("Unknown node fsm state %x\n", state); pr_err("Unknown node fsm state %x\n", state);
break; break;
} }
trace_tipc_node_fsm(n->peer_id, n->state, state, evt);
n->state = state; n->state = state;
return; return;
illegal_evt: illegal_evt:
pr_err("Illegal node fsm evt %x in state %x\n", evt, state); pr_err("Illegal node fsm evt %x in state %x\n", evt, state);
trace_tipc_node_fsm(n->peer_id, n->state, state, evt);
} }
static void node_lost_contact(struct tipc_node *n, static void node_lost_contact(struct tipc_node *n,
...@@ -1253,6 +1265,7 @@ static void node_lost_contact(struct tipc_node *n, ...@@ -1253,6 +1265,7 @@ static void node_lost_contact(struct tipc_node *n,
pr_debug("Lost contact with %x\n", n->addr); pr_debug("Lost contact with %x\n", n->addr);
n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER); n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
trace_tipc_node_lost_contact(n, true, " ");
/* Clean up broadcast state */ /* Clean up broadcast state */
tipc_bcast_remove_peer(n->net, n->bc_entry.link); tipc_bcast_remove_peer(n->net, n->bc_entry.link);
...@@ -1581,6 +1594,10 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, ...@@ -1581,6 +1594,10 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
struct tipc_media_addr *maddr; struct tipc_media_addr *maddr;
int pb_id; int pb_id;
if (trace_tipc_node_check_state_enabled()) {
trace_tipc_skb_dump(skb, false, "skb for node state check");
trace_tipc_node_check_state(n, true, " ");
}
l = n->links[bearer_id].link; l = n->links[bearer_id].link;
if (!l) if (!l)
return false; return false;
...@@ -1598,8 +1615,11 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, ...@@ -1598,8 +1615,11 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
} }
} }
if (!tipc_link_validate_msg(l, hdr)) if (!tipc_link_validate_msg(l, hdr)) {
trace_tipc_skb_dump(skb, false, "PROTO invalid (2)!");
trace_tipc_link_dump(l, TIPC_DUMP_NONE, "PROTO invalid (2)!");
return false; return false;
}
/* Check and update node accesibility if applicable */ /* Check and update node accesibility if applicable */
if (state == SELF_UP_PEER_COMING) { if (state == SELF_UP_PEER_COMING) {
...@@ -1629,6 +1649,8 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, ...@@ -1629,6 +1649,8 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
syncpt = oseqno + exp_pkts - 1; syncpt = oseqno + exp_pkts - 1;
if (pl && tipc_link_is_up(pl)) { if (pl && tipc_link_is_up(pl)) {
__tipc_node_link_down(n, &pb_id, xmitq, &maddr); __tipc_node_link_down(n, &pb_id, xmitq, &maddr);
trace_tipc_node_link_down(n, true,
"node link down <- failover!");
tipc_skb_queue_splice_tail_init(tipc_link_inputq(pl), tipc_skb_queue_splice_tail_init(tipc_link_inputq(pl),
tipc_link_inputq(l)); tipc_link_inputq(l));
} }
...@@ -2435,3 +2457,65 @@ int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb, ...@@ -2435,3 +2457,65 @@ int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
return skb->len; return skb->len;
} }
u32 tipc_node_get_addr(struct tipc_node *node)
{
return (node) ? node->addr : 0;
}
/**
* tipc_node_dump - dump TIPC node data
* @n: tipc node to be dumped
* @more: dump more?
* - false: dump only tipc node data
* - true: dump node link data as well
* @buf: returned buffer of dump data in format
*/
int tipc_node_dump(struct tipc_node *n, bool more, char *buf)
{
int i = 0;
size_t sz = (more) ? NODE_LMAX : NODE_LMIN;
if (!n) {
i += scnprintf(buf, sz, "node data: (null)\n");
return i;
}
i += scnprintf(buf, sz, "node data: %x", n->addr);
i += scnprintf(buf + i, sz - i, " %x", n->state);
i += scnprintf(buf + i, sz - i, " %d", n->active_links[0]);
i += scnprintf(buf + i, sz - i, " %d", n->active_links[1]);
i += scnprintf(buf + i, sz - i, " %x", n->action_flags);
i += scnprintf(buf + i, sz - i, " %u", n->failover_sent);
i += scnprintf(buf + i, sz - i, " %u", n->sync_point);
i += scnprintf(buf + i, sz - i, " %d", n->link_cnt);
i += scnprintf(buf + i, sz - i, " %u", n->working_links);
i += scnprintf(buf + i, sz - i, " %x", n->capabilities);
i += scnprintf(buf + i, sz - i, " %lu\n", n->keepalive_intv);
if (!more)
return i;
i += scnprintf(buf + i, sz - i, "link_entry[0]:\n");
i += scnprintf(buf + i, sz - i, " mtu: %u\n", n->links[0].mtu);
i += scnprintf(buf + i, sz - i, " media: ");
i += tipc_media_addr_printf(buf + i, sz - i, &n->links[0].maddr);
i += scnprintf(buf + i, sz - i, "\n");
i += tipc_link_dump(n->links[0].link, TIPC_DUMP_NONE, buf + i);
i += scnprintf(buf + i, sz - i, " inputq: ");
i += tipc_list_dump(&n->links[0].inputq, false, buf + i);
i += scnprintf(buf + i, sz - i, "link_entry[1]:\n");
i += scnprintf(buf + i, sz - i, " mtu: %u\n", n->links[1].mtu);
i += scnprintf(buf + i, sz - i, " media: ");
i += tipc_media_addr_printf(buf + i, sz - i, &n->links[1].maddr);
i += scnprintf(buf + i, sz - i, "\n");
i += tipc_link_dump(n->links[1].link, TIPC_DUMP_NONE, buf + i);
i += scnprintf(buf + i, sz - i, " inputq: ");
i += tipc_list_dump(&n->links[1].inputq, false, buf + i);
i += scnprintf(buf + i, sz - i, "bclink:\n ");
i += tipc_link_dump(n->bc_entry.link, TIPC_DUMP_NONE, buf + i);
return i;
}
...@@ -65,6 +65,7 @@ enum { ...@@ -65,6 +65,7 @@ enum {
void tipc_node_stop(struct net *net); void tipc_node_stop(struct net *net);
bool tipc_node_get_id(struct net *net, u32 addr, u8 *id); bool tipc_node_get_id(struct net *net, u32 addr, u8 *id);
u32 tipc_node_get_addr(struct tipc_node *node);
u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr); u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr);
void tipc_node_check_dest(struct net *net, u32 onode, u8 *peer_id128, void tipc_node_check_dest(struct net *net, u32 onode, u8 *peer_id128,
struct tipc_bearer *bearer, struct tipc_bearer *bearer,
......
This diff is collapsed.
...@@ -71,4 +71,8 @@ int tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb, ...@@ -71,4 +71,8 @@ int tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb,
int tipc_dump_start(struct netlink_callback *cb); int tipc_dump_start(struct netlink_callback *cb);
int __tipc_dump_start(struct netlink_callback *cb, struct net *net); int __tipc_dump_start(struct netlink_callback *cb, struct net *net);
int tipc_dump_done(struct netlink_callback *cb); int tipc_dump_done(struct netlink_callback *cb);
u32 tipc_sock_get_portid(struct sock *sk);
bool tipc_sk_overlimit1(struct sock *sk, struct sk_buff *skb);
bool tipc_sk_overlimit2(struct sock *sk, struct sk_buff *skb);
#endif #endif
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
*/ */
#include "core.h" #include "core.h"
#include "trace.h"
#include <linux/sysctl.h> #include <linux/sysctl.h>
...@@ -54,6 +55,13 @@ static struct ctl_table tipc_table[] = { ...@@ -54,6 +55,13 @@ static struct ctl_table tipc_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{
.procname = "sk_filter",
.data = &sysctl_tipc_sk_filter,
.maxlen = sizeof(sysctl_tipc_sk_filter),
.mode = 0644,
.proc_handler = proc_doulongvec_minmax,
},
{} {}
}; };
......
/*
* net/tipc/trace.c: TIPC tracepoints code
*
* Copyright (c) 2018, Ericsson AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "ASIS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define CREATE_TRACE_POINTS
#include "trace.h"
/**
* socket tuples for filtering in socket traces:
* (portid, sock type, name type, name lower, name upper)
*/
unsigned long sysctl_tipc_sk_filter[5] __read_mostly = {0, };
/**
* tipc_skb_dump - dump TIPC skb data
* @skb: skb to be dumped
* @more: dump more?
* - false: dump only tipc msg data
* - true: dump kernel-related skb data and tipc cb[] array as well
* @buf: returned buffer of dump data in format
*/
int tipc_skb_dump(struct sk_buff *skb, bool more, char *buf)
{
int i = 0;
size_t sz = (more) ? SKB_LMAX : SKB_LMIN;
struct tipc_msg *hdr;
struct tipc_skb_cb *skbcb;
if (!skb) {
i += scnprintf(buf, sz, "msg: (null)\n");
return i;
}
hdr = buf_msg(skb);
skbcb = TIPC_SKB_CB(skb);
/* tipc msg data section */
i += scnprintf(buf, sz, "msg: %u", msg_user(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_type(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_hdr_sz(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_data_sz(hdr));
i += scnprintf(buf + i, sz - i, " %x", msg_orignode(hdr));
i += scnprintf(buf + i, sz - i, " %x", msg_destnode(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_seqno(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_ack(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_bcast_ack(hdr));
switch (msg_user(hdr)) {
case LINK_PROTOCOL:
i += scnprintf(buf + i, sz - i, " %c", msg_net_plane(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_probe(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_peer_stopping(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_session(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_next_sent(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_seq_gap(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_bc_snd_nxt(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_bc_gap(hdr));
break;
case TIPC_LOW_IMPORTANCE:
case TIPC_MEDIUM_IMPORTANCE:
case TIPC_HIGH_IMPORTANCE:
case TIPC_CRITICAL_IMPORTANCE:
case CONN_MANAGER:
case SOCK_WAKEUP:
i += scnprintf(buf + i, sz - i, " | %u", msg_origport(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_destport(hdr));
switch (msg_type(hdr)) {
case TIPC_NAMED_MSG:
i += scnprintf(buf + i, sz - i, " %u",
msg_nametype(hdr));
i += scnprintf(buf + i, sz - i, " %u",
msg_nameinst(hdr));
break;
case TIPC_MCAST_MSG:
i += scnprintf(buf + i, sz - i, " %u",
msg_nametype(hdr));
i += scnprintf(buf + i, sz - i, " %u",
msg_namelower(hdr));
i += scnprintf(buf + i, sz - i, " %u",
msg_nameupper(hdr));
break;
default:
break;
};
i += scnprintf(buf + i, sz - i, " | %u",
msg_src_droppable(hdr));
i += scnprintf(buf + i, sz - i, " %u",
msg_dest_droppable(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_errcode(hdr));
i += scnprintf(buf + i, sz - i, " %u", msg_reroute_cnt(hdr));
break;
default:
/* need more? */
break;
};
i += scnprintf(buf + i, sz - i, "\n");
if (!more)
return i;
/* kernel-related skb data section */
i += scnprintf(buf + i, sz - i, "skb: %s",
(skb->dev) ? skb->dev->name : "n/a");
i += scnprintf(buf + i, sz - i, " %u", skb->len);
i += scnprintf(buf + i, sz - i, " %u", skb->data_len);
i += scnprintf(buf + i, sz - i, " %u", skb->hdr_len);
i += scnprintf(buf + i, sz - i, " %u", skb->truesize);
i += scnprintf(buf + i, sz - i, " %u", skb_cloned(skb));
i += scnprintf(buf + i, sz - i, " %p", skb->sk);
i += scnprintf(buf + i, sz - i, " %u", skb_shinfo(skb)->nr_frags);
i += scnprintf(buf + i, sz - i, " %llx",
ktime_to_ms(skb_get_ktime(skb)));
i += scnprintf(buf + i, sz - i, " %llx\n",
ktime_to_ms(skb_hwtstamps(skb)->hwtstamp));
/* tipc skb cb[] data section */
i += scnprintf(buf + i, sz - i, "cb[]: %u", skbcb->bytes_read);
i += scnprintf(buf + i, sz - i, " %u", skbcb->orig_member);
i += scnprintf(buf + i, sz - i, " %u",
jiffies_to_msecs(skbcb->nxt_retr));
i += scnprintf(buf + i, sz - i, " %u", skbcb->validated);
i += scnprintf(buf + i, sz - i, " %u", skbcb->chain_imp);
i += scnprintf(buf + i, sz - i, " %u\n", skbcb->ackers);
return i;
}
/**
* tipc_list_dump - dump TIPC skb list/queue
* @list: list of skbs to be dumped
* @more: dump more?
* - false: dump only the head & tail skbs
* - true: dump the first & last 5 skbs
* @buf: returned buffer of dump data in format
*/
int tipc_list_dump(struct sk_buff_head *list, bool more, char *buf)
{
int i = 0;
size_t sz = (more) ? LIST_LMAX : LIST_LMIN;
u32 count, len;
struct sk_buff *hskb, *tskb, *skb, *tmp;
if (!list) {
i += scnprintf(buf, sz, "(null)\n");
return i;
}
len = skb_queue_len(list);
i += scnprintf(buf, sz, "len = %d\n", len);
if (!len)
return i;
if (!more) {
hskb = skb_peek(list);
i += scnprintf(buf + i, sz - i, " head ");
i += tipc_skb_dump(hskb, false, buf + i);
if (len > 1) {
tskb = skb_peek_tail(list);
i += scnprintf(buf + i, sz - i, " tail ");
i += tipc_skb_dump(tskb, false, buf + i);
}
} else {
count = 0;
skb_queue_walk_safe(list, skb, tmp) {
count++;
if (count == 6)
i += scnprintf(buf + i, sz - i, " .\n .\n");
if (count > 5 && count <= len - 5)
continue;
i += scnprintf(buf + i, sz - i, " #%d ", count);
i += tipc_skb_dump(skb, false, buf + i);
}
}
return i;
}
This diff is collapsed.
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