mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	tipc: add support for broadcast rcv stats dumping
This commit enables dumping the statistics of a broadcast-receiver link like the traditional 'broadcast-link' one (which is for broadcast- sender). The link dumping can be triggered via netlink (e.g. the iproute2/tipc tool) by the link flag - 'TIPC_NLA_LINK_BROADCAST' as the indicator. The name of a broadcast-receiver link of a specific peer will be in the format: 'broadcast-link:<peer-id>'. For example: Link <broadcast-link:1001002> Window:50 packets RX packets:7841 fragments:2408/440 bundles:0/0 TX packets:0 fragments:0/0 bundles:0/0 RX naks:0 defs:124 dups:0 TX naks:21 acks:0 retrans:0 Congestion link:0 Send queue max:0 avg:0 In addition, the broadcast-receiver link statistics can be reset in the usual way via netlink by specifying that link name in command. Note: the 'tipc_link_name_ext()' is removed because the link name can now be retrieved simply via the 'l->name'. Acked-by: Ying Xue <ying.xue@windriver.com> Acked-by: Jon Maloy <jmaloy@redhat.com> Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									a91d55d162
								
							
						
					
					
						commit
						03b6fefd9b
					
				
					 9 changed files with 103 additions and 58 deletions
				
			
		| 
						 | 
					@ -563,10 +563,8 @@ void tipc_bcast_remove_peer(struct net *net, struct tipc_link *rcv_l)
 | 
				
			||||||
		tipc_sk_rcv(net, inputq);
 | 
							tipc_sk_rcv(net, inputq);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int tipc_bclink_reset_stats(struct net *net)
 | 
					int tipc_bclink_reset_stats(struct net *net, struct tipc_link *l)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tipc_link *l = tipc_bc_sndlink(net);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!l)
 | 
						if (!l)
 | 
				
			||||||
		return -ENOPROTOOPT;
 | 
							return -ENOPROTOOPT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -694,7 +692,7 @@ int tipc_bcast_init(struct net *net)
 | 
				
			||||||
	tn->bcbase = bb;
 | 
						tn->bcbase = bb;
 | 
				
			||||||
	spin_lock_init(&tipc_net(net)->bclock);
 | 
						spin_lock_init(&tipc_net(net)->bclock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!tipc_link_bc_create(net, 0, 0,
 | 
						if (!tipc_link_bc_create(net, 0, 0, NULL,
 | 
				
			||||||
				 FB_MTU,
 | 
									 FB_MTU,
 | 
				
			||||||
				 BCLINK_WIN_DEFAULT,
 | 
									 BCLINK_WIN_DEFAULT,
 | 
				
			||||||
				 BCLINK_WIN_DEFAULT,
 | 
									 BCLINK_WIN_DEFAULT,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,9 +96,10 @@ void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
 | 
				
			||||||
int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
 | 
					int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
 | 
				
			||||||
			struct tipc_msg *hdr,
 | 
								struct tipc_msg *hdr,
 | 
				
			||||||
			struct sk_buff_head *retrq);
 | 
								struct sk_buff_head *retrq);
 | 
				
			||||||
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,
 | 
				
			||||||
 | 
								struct tipc_link *bcl);
 | 
				
			||||||
int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]);
 | 
					int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]);
 | 
				
			||||||
int tipc_bclink_reset_stats(struct net *net);
 | 
					int tipc_bclink_reset_stats(struct net *net, struct tipc_link *l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
u32 tipc_bcast_get_broadcast_mode(struct net *net);
 | 
					u32 tipc_bcast_get_broadcast_mode(struct net *net);
 | 
				
			||||||
u32 tipc_bcast_get_broadcast_ratio(struct net *net);
 | 
					u32 tipc_bcast_get_broadcast_ratio(struct net *net);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -539,7 +539,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns true if link was created, otherwise false
 | 
					 * Returns true if link was created, otherwise false
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
 | 
					bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, u8 *peer_id,
 | 
				
			||||||
			 int mtu, u32 min_win, u32 max_win, u16 peer_caps,
 | 
								 int mtu, u32 min_win, u32 max_win, u16 peer_caps,
 | 
				
			||||||
			 struct sk_buff_head *inputq,
 | 
								 struct sk_buff_head *inputq,
 | 
				
			||||||
			 struct sk_buff_head *namedq,
 | 
								 struct sk_buff_head *namedq,
 | 
				
			||||||
| 
						 | 
					@ -554,7 +554,18 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l = *link;
 | 
						l = *link;
 | 
				
			||||||
 | 
						if (peer_id) {
 | 
				
			||||||
 | 
							char peer_str[NODE_ID_STR_LEN] = {0,};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tipc_nodeid2string(peer_str, peer_id);
 | 
				
			||||||
 | 
							if (strlen(peer_str) > 16)
 | 
				
			||||||
 | 
								sprintf(peer_str, "%x", peer);
 | 
				
			||||||
 | 
							/* Broadcast receiver link name: "broadcast-link:<peer>" */
 | 
				
			||||||
 | 
							snprintf(l->name, sizeof(l->name), "%s:%s", tipc_bclink_name,
 | 
				
			||||||
 | 
								 peer_str);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		strcpy(l->name, tipc_bclink_name);
 | 
							strcpy(l->name, tipc_bclink_name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	trace_tipc_link_reset(l, TIPC_DUMP_ALL, "bclink created!");
 | 
						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;
 | 
				
			||||||
| 
						 | 
					@ -1412,11 +1423,8 @@ static u8 __tipc_build_gap_ack_blks(struct tipc_gap_ack_blks *ga,
 | 
				
			||||||
			gacks[n].ack = htons(expect - 1);
 | 
								gacks[n].ack = htons(expect - 1);
 | 
				
			||||||
			gacks[n].gap = htons(seqno - expect);
 | 
								gacks[n].gap = htons(seqno - expect);
 | 
				
			||||||
			if (++n >= MAX_GAP_ACK_BLKS / 2) {
 | 
								if (++n >= MAX_GAP_ACK_BLKS / 2) {
 | 
				
			||||||
				char buf[TIPC_MAX_LINK_NAME];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				pr_info_ratelimited("Gacks on %s: %d, ql: %d!\n",
 | 
									pr_info_ratelimited("Gacks on %s: %d, ql: %d!\n",
 | 
				
			||||||
						    tipc_link_name_ext(l, buf),
 | 
											    l->name, n,
 | 
				
			||||||
						    n,
 | 
					 | 
				
			||||||
						    skb_queue_len(&l->deferdq));
 | 
											    skb_queue_len(&l->deferdq));
 | 
				
			||||||
				return n;
 | 
									return n;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -1587,6 +1595,8 @@ static int tipc_link_advance_transmq(struct tipc_link *l, struct tipc_link *r,
 | 
				
			||||||
			_skb->priority = TC_PRIO_CONTROL;
 | 
								_skb->priority = TC_PRIO_CONTROL;
 | 
				
			||||||
			__skb_queue_tail(xmitq, _skb);
 | 
								__skb_queue_tail(xmitq, _skb);
 | 
				
			||||||
			l->stats.retransmitted++;
 | 
								l->stats.retransmitted++;
 | 
				
			||||||
 | 
								if (!is_uc)
 | 
				
			||||||
 | 
									r->stats.retransmitted++;
 | 
				
			||||||
			*retransmitted = true;
 | 
								*retransmitted = true;
 | 
				
			||||||
			/* Increase actual retrans counter & mark first time */
 | 
								/* Increase actual retrans counter & mark first time */
 | 
				
			||||||
			if (!TIPC_SKB_CB(skb)->retr_cnt++)
 | 
								if (!TIPC_SKB_CB(skb)->retr_cnt++)
 | 
				
			||||||
| 
						 | 
					@ -1753,7 +1763,8 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Defer delivery if sequence gap */
 | 
							/* Defer delivery if sequence gap */
 | 
				
			||||||
		if (unlikely(seqno != rcv_nxt)) {
 | 
							if (unlikely(seqno != rcv_nxt)) {
 | 
				
			||||||
			__tipc_skb_queue_sorted(defq, seqno, skb);
 | 
								if (!__tipc_skb_queue_sorted(defq, seqno, skb))
 | 
				
			||||||
 | 
									l->stats.duplicates++;
 | 
				
			||||||
			rc |= tipc_link_build_nack_msg(l, xmitq);
 | 
								rc |= tipc_link_build_nack_msg(l, xmitq);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1787,15 +1798,15 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
 | 
				
			||||||
				      int tolerance, int priority,
 | 
									      int tolerance, int priority,
 | 
				
			||||||
				      struct sk_buff_head *xmitq)
 | 
									      struct sk_buff_head *xmitq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tipc_link *bcl = l->bc_rcvlink;
 | 
					 | 
				
			||||||
	struct sk_buff *skb;
 | 
					 | 
				
			||||||
	struct tipc_msg *hdr;
 | 
					 | 
				
			||||||
	struct sk_buff_head *dfq = &l->deferdq;
 | 
					 | 
				
			||||||
	bool node_up = link_is_up(bcl);
 | 
					 | 
				
			||||||
	struct tipc_mon_state *mstate = &l->mon_state;
 | 
						struct tipc_mon_state *mstate = &l->mon_state;
 | 
				
			||||||
 | 
						struct sk_buff_head *dfq = &l->deferdq;
 | 
				
			||||||
 | 
						struct tipc_link *bcl = l->bc_rcvlink;
 | 
				
			||||||
 | 
						struct tipc_msg *hdr;
 | 
				
			||||||
 | 
						struct sk_buff *skb;
 | 
				
			||||||
 | 
						bool node_up = link_is_up(bcl);
 | 
				
			||||||
 | 
						u16 glen = 0, bc_rcvgap = 0;
 | 
				
			||||||
	int dlen = 0;
 | 
						int dlen = 0;
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
	u16 glen = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Don't send protocol message during reset or link failover */
 | 
						/* Don't send protocol message during reset or link failover */
 | 
				
			||||||
	if (tipc_link_is_blocked(l))
 | 
						if (tipc_link_is_blocked(l))
 | 
				
			||||||
| 
						 | 
					@ -1833,7 +1844,8 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
 | 
				
			||||||
		if (l->peer_caps & TIPC_LINK_PROTO_SEQNO)
 | 
							if (l->peer_caps & TIPC_LINK_PROTO_SEQNO)
 | 
				
			||||||
			msg_set_seqno(hdr, l->snd_nxt_state++);
 | 
								msg_set_seqno(hdr, l->snd_nxt_state++);
 | 
				
			||||||
		msg_set_seq_gap(hdr, rcvgap);
 | 
							msg_set_seq_gap(hdr, rcvgap);
 | 
				
			||||||
		msg_set_bc_gap(hdr, link_bc_rcv_gap(bcl));
 | 
							bc_rcvgap = link_bc_rcv_gap(bcl);
 | 
				
			||||||
 | 
							msg_set_bc_gap(hdr, bc_rcvgap);
 | 
				
			||||||
		msg_set_probe(hdr, probe);
 | 
							msg_set_probe(hdr, probe);
 | 
				
			||||||
		msg_set_is_keepalive(hdr, probe || probe_reply);
 | 
							msg_set_is_keepalive(hdr, probe || probe_reply);
 | 
				
			||||||
		if (l->peer_caps & TIPC_GAP_ACK_BLOCK)
 | 
							if (l->peer_caps & TIPC_GAP_ACK_BLOCK)
 | 
				
			||||||
| 
						 | 
					@ -1858,6 +1870,8 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
 | 
				
			||||||
		l->stats.sent_probes++;
 | 
							l->stats.sent_probes++;
 | 
				
			||||||
	if (rcvgap)
 | 
						if (rcvgap)
 | 
				
			||||||
		l->stats.sent_nacks++;
 | 
							l->stats.sent_nacks++;
 | 
				
			||||||
 | 
						if (bc_rcvgap)
 | 
				
			||||||
 | 
							bcl->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);
 | 
						trace_tipc_proto_build(skb, false, l->name);
 | 
				
			||||||
| 
						 | 
					@ -2358,8 +2372,6 @@ int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
 | 
				
			||||||
	if (!l->bc_peer_is_up)
 | 
						if (!l->bc_peer_is_up)
 | 
				
			||||||
		return rc;
 | 
							return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l->stats.recv_nacks++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Ignore if peers_snd_nxt goes beyond receive window */
 | 
						/* Ignore if peers_snd_nxt goes beyond receive window */
 | 
				
			||||||
	if (more(peers_snd_nxt, l->rcv_nxt + l->window))
 | 
						if (more(peers_snd_nxt, l->rcv_nxt + l->window))
 | 
				
			||||||
		return rc;
 | 
							return rc;
 | 
				
			||||||
| 
						 | 
					@ -2410,6 +2422,11 @@ int tipc_link_bc_ack_rcv(struct tipc_link *r, u16 acked, u16 gap,
 | 
				
			||||||
	if (!link_is_up(r) || !r->bc_peer_is_up)
 | 
						if (!link_is_up(r) || !r->bc_peer_is_up)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (gap) {
 | 
				
			||||||
 | 
							l->stats.recv_nacks++;
 | 
				
			||||||
 | 
							r->stats.recv_nacks++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (less(acked, r->acked) || (acked == r->acked && !gap && !ga))
 | 
						if (less(acked, r->acked) || (acked == r->acked && !gap && !ga))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2721,16 +2738,15 @@ static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb,
 | 
				
			||||||
	return -EMSGSIZE;
 | 
						return -EMSGSIZE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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,
 | 
				
			||||||
 | 
								struct tipc_link *bcl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
	void *hdr;
 | 
						void *hdr;
 | 
				
			||||||
	struct nlattr *attrs;
 | 
						struct nlattr *attrs;
 | 
				
			||||||
	struct nlattr *prop;
 | 
						struct nlattr *prop;
 | 
				
			||||||
	struct tipc_net *tn = net_generic(net, tipc_net_id);
 | 
					 | 
				
			||||||
	u32 bc_mode = tipc_bcast_get_broadcast_mode(net);
 | 
						u32 bc_mode = tipc_bcast_get_broadcast_mode(net);
 | 
				
			||||||
	u32 bc_ratio = tipc_bcast_get_broadcast_ratio(net);
 | 
						u32 bc_ratio = tipc_bcast_get_broadcast_ratio(net);
 | 
				
			||||||
	struct tipc_link *bcl = tn->bcl;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!bcl)
 | 
						if (!bcl)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -2817,21 +2833,6 @@ 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
 | 
					 * tipc_link_dump - dump TIPC link data
 | 
				
			||||||
 * @l: tipc link to be dumped
 | 
					 * @l: tipc link to be dumped
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
 | 
				
			||||||
		      struct sk_buff_head *inputq,
 | 
							      struct sk_buff_head *inputq,
 | 
				
			||||||
		      struct sk_buff_head *namedq,
 | 
							      struct sk_buff_head *namedq,
 | 
				
			||||||
		      struct tipc_link **link);
 | 
							      struct tipc_link **link);
 | 
				
			||||||
bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer,
 | 
					bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, u8 *peer_id,
 | 
				
			||||||
			 int mtu, u32 min_win, u32 max_win, u16 peer_caps,
 | 
								 int mtu, u32 min_win, u32 max_win, u16 peer_caps,
 | 
				
			||||||
			 struct sk_buff_head *inputq,
 | 
								 struct sk_buff_head *inputq,
 | 
				
			||||||
			 struct sk_buff_head *namedq,
 | 
								 struct sk_buff_head *namedq,
 | 
				
			||||||
| 
						 | 
					@ -111,7 +111,6 @@ 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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -825,19 +825,19 @@ bool tipc_msg_pskb_copy(u32 dst, struct sk_buff_head *msg,
 | 
				
			||||||
 * @seqno: sequence number of buffer to add
 | 
					 * @seqno: sequence number of buffer to add
 | 
				
			||||||
 * @skb: buffer to add
 | 
					 * @skb: buffer to add
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
 | 
					bool __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
 | 
				
			||||||
			     struct sk_buff *skb)
 | 
								     struct sk_buff *skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sk_buff *_skb, *tmp;
 | 
						struct sk_buff *_skb, *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (skb_queue_empty(list) || less(seqno, buf_seqno(skb_peek(list)))) {
 | 
						if (skb_queue_empty(list) || less(seqno, buf_seqno(skb_peek(list)))) {
 | 
				
			||||||
		__skb_queue_head(list, skb);
 | 
							__skb_queue_head(list, skb);
 | 
				
			||||||
		return;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (more(seqno, buf_seqno(skb_peek_tail(list)))) {
 | 
						if (more(seqno, buf_seqno(skb_peek_tail(list)))) {
 | 
				
			||||||
		__skb_queue_tail(list, skb);
 | 
							__skb_queue_tail(list, skb);
 | 
				
			||||||
		return;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb_queue_walk_safe(list, _skb, tmp) {
 | 
						skb_queue_walk_safe(list, _skb, tmp) {
 | 
				
			||||||
| 
						 | 
					@ -846,9 +846,10 @@ void __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
 | 
				
			||||||
		if (seqno == buf_seqno(_skb))
 | 
							if (seqno == buf_seqno(_skb))
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		__skb_queue_before(list, _skb, skb);
 | 
							__skb_queue_before(list, _skb, skb);
 | 
				
			||||||
		return;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	kfree_skb(skb);
 | 
						kfree_skb(skb);
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void tipc_skb_reject(struct net *net, int err, struct sk_buff *skb,
 | 
					void tipc_skb_reject(struct net *net, int err, struct sk_buff *skb,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1145,7 +1145,7 @@ bool tipc_msg_assemble(struct sk_buff_head *list);
 | 
				
			||||||
bool tipc_msg_reassemble(struct sk_buff_head *list, struct sk_buff_head *rcvq);
 | 
					bool tipc_msg_reassemble(struct sk_buff_head *list, struct sk_buff_head *rcvq);
 | 
				
			||||||
bool tipc_msg_pskb_copy(u32 dst, struct sk_buff_head *msg,
 | 
					bool tipc_msg_pskb_copy(u32 dst, struct sk_buff_head *msg,
 | 
				
			||||||
			struct sk_buff_head *cpy);
 | 
								struct sk_buff_head *cpy);
 | 
				
			||||||
void __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
 | 
					bool __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
 | 
				
			||||||
			     struct sk_buff *skb);
 | 
								     struct sk_buff *skb);
 | 
				
			||||||
bool tipc_msg_skb_clone(struct sk_buff_head *msg, struct sk_buff_head *cpy);
 | 
					bool tipc_msg_skb_clone(struct sk_buff_head *msg, struct sk_buff_head *cpy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,7 +188,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		.cmd	= TIPC_NL_LINK_GET,
 | 
							.cmd	= TIPC_NL_LINK_GET,
 | 
				
			||||||
		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 | 
							.validate = GENL_DONT_VALIDATE_STRICT,
 | 
				
			||||||
		.doit   = tipc_nl_node_get_link,
 | 
							.doit   = tipc_nl_node_get_link,
 | 
				
			||||||
		.dumpit	= tipc_nl_node_dump_link,
 | 
							.dumpit	= tipc_nl_node_dump_link,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1138,7 +1138,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
 | 
				
			||||||
	if (unlikely(!n->bc_entry.link)) {
 | 
						if (unlikely(!n->bc_entry.link)) {
 | 
				
			||||||
		snd_l = tipc_bc_sndlink(net);
 | 
							snd_l = tipc_bc_sndlink(net);
 | 
				
			||||||
		if (!tipc_link_bc_create(net, tipc_own_addr(net),
 | 
							if (!tipc_link_bc_create(net, tipc_own_addr(net),
 | 
				
			||||||
					 addr, U16_MAX,
 | 
										 addr, peer_id, U16_MAX,
 | 
				
			||||||
					 tipc_link_min_win(snd_l),
 | 
										 tipc_link_min_win(snd_l),
 | 
				
			||||||
					 tipc_link_max_win(snd_l),
 | 
										 tipc_link_max_win(snd_l),
 | 
				
			||||||
					 n->capabilities,
 | 
										 n->capabilities,
 | 
				
			||||||
| 
						 | 
					@ -2435,7 +2435,7 @@ int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (strcmp(name, tipc_bclink_name) == 0) {
 | 
						if (strcmp(name, tipc_bclink_name) == 0) {
 | 
				
			||||||
		err = tipc_nl_add_bc_link(net, &msg);
 | 
							err = tipc_nl_add_bc_link(net, &msg, tipc_net(net)->bcl);
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			goto err_free;
 | 
								goto err_free;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -2479,6 +2479,7 @@ int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	struct tipc_node *node;
 | 
						struct tipc_node *node;
 | 
				
			||||||
	struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
 | 
						struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
 | 
				
			||||||
	struct net *net = sock_net(skb->sk);
 | 
						struct net *net = sock_net(skb->sk);
 | 
				
			||||||
 | 
						struct tipc_net *tn = tipc_net(net);
 | 
				
			||||||
	struct tipc_link_entry *le;
 | 
						struct tipc_link_entry *le;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!info->attrs[TIPC_NLA_LINK])
 | 
						if (!info->attrs[TIPC_NLA_LINK])
 | 
				
			||||||
| 
						 | 
					@ -2495,11 +2496,26 @@ int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
 | 
						link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (strcmp(link_name, tipc_bclink_name) == 0) {
 | 
						err = -EINVAL;
 | 
				
			||||||
		err = tipc_bclink_reset_stats(net);
 | 
						if (!strcmp(link_name, tipc_bclink_name)) {
 | 
				
			||||||
 | 
							err = tipc_bclink_reset_stats(net, tipc_bc_sndlink(net));
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			return err;
 | 
								return err;
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if (strstr(link_name, tipc_bclink_name)) {
 | 
				
			||||||
 | 
							rcu_read_lock();
 | 
				
			||||||
 | 
							list_for_each_entry_rcu(node, &tn->node_list, list) {
 | 
				
			||||||
 | 
								tipc_node_read_lock(node);
 | 
				
			||||||
 | 
								link = node->bc_entry.link;
 | 
				
			||||||
 | 
								if (link && !strcmp(link_name, tipc_link_name(link))) {
 | 
				
			||||||
 | 
									err = tipc_bclink_reset_stats(net, link);
 | 
				
			||||||
 | 
									tipc_node_read_unlock(node);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								tipc_node_read_unlock(node);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rcu_read_unlock();
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	node = tipc_node_find_by_name(net, link_name, &bearer_id);
 | 
						node = tipc_node_find_by_name(net, link_name, &bearer_id);
 | 
				
			||||||
| 
						 | 
					@ -2523,7 +2539,8 @@ int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Caller should hold node lock  */
 | 
					/* Caller should hold node lock  */
 | 
				
			||||||
static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg,
 | 
					static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg,
 | 
				
			||||||
				    struct tipc_node *node, u32 *prev_link)
 | 
									    struct tipc_node *node, u32 *prev_link,
 | 
				
			||||||
 | 
									    bool bc_link)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 i;
 | 
						u32 i;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
| 
						 | 
					@ -2539,6 +2556,14 @@ static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg,
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			return err;
 | 
								return err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bc_link) {
 | 
				
			||||||
 | 
							*prev_link = i;
 | 
				
			||||||
 | 
							err = tipc_nl_add_bc_link(net, msg, node->bc_entry.link);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*prev_link = 0;
 | 
						*prev_link = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -2547,17 +2572,36 @@ static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg,
 | 
				
			||||||
int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb)
 | 
					int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net *net = sock_net(skb->sk);
 | 
						struct net *net = sock_net(skb->sk);
 | 
				
			||||||
 | 
						struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
 | 
				
			||||||
 | 
						struct nlattr *link[TIPC_NLA_LINK_MAX + 1];
 | 
				
			||||||
	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_nl_msg msg;
 | 
						struct tipc_nl_msg msg;
 | 
				
			||||||
	u32 prev_node = cb->args[0];
 | 
						u32 prev_node = cb->args[0];
 | 
				
			||||||
	u32 prev_link = cb->args[1];
 | 
						u32 prev_link = cb->args[1];
 | 
				
			||||||
	int done = cb->args[2];
 | 
						int done = cb->args[2];
 | 
				
			||||||
 | 
						bool bc_link = cb->args[3];
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (done)
 | 
						if (done)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!prev_node) {
 | 
				
			||||||
 | 
							/* Check if broadcast-receiver links dumping is needed */
 | 
				
			||||||
 | 
							if (attrs && attrs[TIPC_NLA_LINK]) {
 | 
				
			||||||
 | 
								err = nla_parse_nested_deprecated(link,
 | 
				
			||||||
 | 
												  TIPC_NLA_LINK_MAX,
 | 
				
			||||||
 | 
												  attrs[TIPC_NLA_LINK],
 | 
				
			||||||
 | 
												  tipc_nl_link_policy,
 | 
				
			||||||
 | 
												  NULL);
 | 
				
			||||||
 | 
								if (unlikely(err))
 | 
				
			||||||
 | 
									return err;
 | 
				
			||||||
 | 
								if (unlikely(!link[TIPC_NLA_LINK_BROADCAST]))
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
								bc_link = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msg.skb = skb;
 | 
						msg.skb = skb;
 | 
				
			||||||
	msg.portid = NETLINK_CB(cb->skb).portid;
 | 
						msg.portid = NETLINK_CB(cb->skb).portid;
 | 
				
			||||||
	msg.seq = cb->nlh->nlmsg_seq;
 | 
						msg.seq = cb->nlh->nlmsg_seq;
 | 
				
			||||||
| 
						 | 
					@ -2581,7 +2625,7 @@ int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb)
 | 
				
			||||||
						 list) {
 | 
											 list) {
 | 
				
			||||||
			tipc_node_read_lock(node);
 | 
								tipc_node_read_lock(node);
 | 
				
			||||||
			err = __tipc_nl_add_node_links(net, &msg, node,
 | 
								err = __tipc_nl_add_node_links(net, &msg, node,
 | 
				
			||||||
						       &prev_link);
 | 
											       &prev_link, bc_link);
 | 
				
			||||||
			tipc_node_read_unlock(node);
 | 
								tipc_node_read_unlock(node);
 | 
				
			||||||
			if (err)
 | 
								if (err)
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
| 
						 | 
					@ -2589,14 +2633,14 @@ int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb)
 | 
				
			||||||
			prev_node = node->addr;
 | 
								prev_node = node->addr;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		err = tipc_nl_add_bc_link(net, &msg);
 | 
							err = tipc_nl_add_bc_link(net, &msg, tn->bcl);
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		list_for_each_entry_rcu(node, &tn->node_list, list) {
 | 
							list_for_each_entry_rcu(node, &tn->node_list, list) {
 | 
				
			||||||
			tipc_node_read_lock(node);
 | 
								tipc_node_read_lock(node);
 | 
				
			||||||
			err = __tipc_nl_add_node_links(net, &msg, node,
 | 
								err = __tipc_nl_add_node_links(net, &msg, node,
 | 
				
			||||||
						       &prev_link);
 | 
											       &prev_link, bc_link);
 | 
				
			||||||
			tipc_node_read_unlock(node);
 | 
								tipc_node_read_unlock(node);
 | 
				
			||||||
			if (err)
 | 
								if (err)
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
| 
						 | 
					@ -2611,6 +2655,7 @@ int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb)
 | 
				
			||||||
	cb->args[0] = prev_node;
 | 
						cb->args[0] = prev_node;
 | 
				
			||||||
	cb->args[1] = prev_link;
 | 
						cb->args[1] = prev_link;
 | 
				
			||||||
	cb->args[2] = done;
 | 
						cb->args[2] = done;
 | 
				
			||||||
 | 
						cb->args[3] = bc_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return skb->len;
 | 
						return skb->len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,7 +255,7 @@ DECLARE_EVENT_CLASS(tipc_link_class,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TP_fast_assign(
 | 
						TP_fast_assign(
 | 
				
			||||||
		__assign_str(header, header);
 | 
							__assign_str(header, header);
 | 
				
			||||||
		tipc_link_name_ext(l, __entry->name);
 | 
							memcpy(__entry->name, tipc_link_name(l), TIPC_MAX_LINK_NAME);
 | 
				
			||||||
		tipc_link_dump(l, dqueues, __get_str(buf));
 | 
							tipc_link_dump(l, dqueues, __get_str(buf));
 | 
				
			||||||
	),
 | 
						),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -295,7 +295,7 @@ DECLARE_EVENT_CLASS(tipc_link_transmq_class,
 | 
				
			||||||
	),
 | 
						),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TP_fast_assign(
 | 
						TP_fast_assign(
 | 
				
			||||||
		tipc_link_name_ext(r, __entry->name);
 | 
							memcpy(__entry->name, tipc_link_name(r), TIPC_MAX_LINK_NAME);
 | 
				
			||||||
		__entry->from = f;
 | 
							__entry->from = f;
 | 
				
			||||||
		__entry->to = t;
 | 
							__entry->to = t;
 | 
				
			||||||
		__entry->len = skb_queue_len(tq);
 | 
							__entry->len = skb_queue_len(tq);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue