aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-10-22 08:51:38 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-24 09:56:32 -0400
commitc1ab3f1dea3df566ad38caf98baf69c656679090 (patch)
treef62e1118dade62d290f0a5cfc418b355194da013 /net/tipc
parent323019069e8d96d87e9dba51f897060f94999821 (diff)
tipc: make struct tipc_link generic to support broadcast
Realizing that unicast is just a special case of broadcast, we also see that we can go in the other direction, i.e., that modest changes to the current unicast link can make it generic enough to support broadcast. The following changes are introduced here: - A new counter ("ackers") in struct tipc_link, to indicate how many peers need to ack a packet before it can be released. - A corresponding counter in the skb user area, to keep track of how many peers a are left to ack before a buffer can be released. - A new counter ("acked"), to keep persistent track of how far a peer has acked at the moment, i.e., where in the transmission queue to start updating buffers when the next ack arrives. This is to avoid double acknowledgements from a peer, with inadvertent relase of packets as a result. - A more generic tipc_link_retrans() function, where retransmit starts from a given sequence number, instead of the first packet in the transmision queue. This is to minimize the number of retransmitted packets on the broadcast media. When the new functionality is taken into use in the next commits, we expect it to have minimal effect on unicast mode performance. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/link.c38
-rw-r--r--net/tipc/link.h7
-rw-r--r--net/tipc/msg.h1
3 files changed, 34 insertions, 12 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index f0cf768a59f3..dfc738e5cff9 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -221,6 +221,7 @@ bool tipc_link_create(struct tipc_node *n, char *if_name, int bearer_id,
221 l->mtu = mtu; 221 l->mtu = mtu;
222 l->priority = priority; 222 l->priority = priority;
223 tipc_link_set_queue_limits(l, window); 223 tipc_link_set_queue_limits(l, window);
224 l->ackers = 1;
224 l->inputq = inputq; 225 l->inputq = inputq;
225 l->namedq = namedq; 226 l->namedq = namedq;
226 l->state = LINK_RESETTING; 227 l->state = LINK_RESETTING;
@@ -647,6 +648,7 @@ void tipc_link_reset(struct tipc_link *l)
647 l->rcv_unacked = 0; 648 l->rcv_unacked = 0;
648 l->snd_nxt = 1; 649 l->snd_nxt = 1;
649 l->rcv_nxt = 1; 650 l->rcv_nxt = 1;
651 l->acked = 0;
650 l->silent_intv_cnt = 0; 652 l->silent_intv_cnt = 0;
651 l->stats.recv_info = 0; 653 l->stats.recv_info = 0;
652 l->stale_count = 0; 654 l->stale_count = 0;
@@ -769,6 +771,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
769 __skb_dequeue(list); 771 __skb_dequeue(list);
770 __skb_queue_tail(transmq, skb); 772 __skb_queue_tail(transmq, skb);
771 __skb_queue_tail(xmitq, _skb); 773 __skb_queue_tail(xmitq, _skb);
774 TIPC_SKB_CB(skb)->ackers = l->ackers;
772 l->rcv_unacked = 0; 775 l->rcv_unacked = 0;
773 seqno++; 776 seqno++;
774 continue; 777 continue;
@@ -829,6 +832,7 @@ void tipc_link_push_packets(struct tipc_link *link)
829 skb = __skb_dequeue(&link->backlogq); 832 skb = __skb_dequeue(&link->backlogq);
830 if (!skb) 833 if (!skb)
831 break; 834 break;
835 TIPC_SKB_CB(skb)->ackers = link->ackers;
832 msg = buf_msg(skb); 836 msg = buf_msg(skb);
833 link->backlog[msg_importance(msg)].len--; 837 link->backlog[msg_importance(msg)].len--;
834 msg_set_ack(msg, ack); 838 msg_set_ack(msg, ack);
@@ -862,6 +866,7 @@ void tipc_link_advance_backlog(struct tipc_link *l, struct sk_buff_head *xmitq)
862 l->backlog[msg_importance(hdr)].len--; 866 l->backlog[msg_importance(hdr)].len--;
863 __skb_queue_tail(&l->transmq, skb); 867 __skb_queue_tail(&l->transmq, skb);
864 __skb_queue_tail(xmitq, _skb); 868 __skb_queue_tail(xmitq, _skb);
869 TIPC_SKB_CB(skb)->ackers = l->ackers;
865 msg_set_ack(hdr, ack); 870 msg_set_ack(hdr, ack);
866 msg_set_seqno(hdr, seqno); 871 msg_set_seqno(hdr, seqno);
867 msg_set_bcast_ack(hdr, l->owner->bclink.last_in); 872 msg_set_bcast_ack(hdr, l->owner->bclink.last_in);
@@ -947,11 +952,13 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *skb,
947 } 952 }
948} 953}
949 954
950static int tipc_link_retransm(struct tipc_link *l, int retransm, 955int tipc_link_retrans(struct tipc_link *l, u16 from, u16 to,
951 struct sk_buff_head *xmitq) 956 struct sk_buff_head *xmitq)
952{ 957{
953 struct sk_buff *_skb, *skb = skb_peek(&l->transmq); 958 struct sk_buff *_skb, *skb = skb_peek(&l->transmq);
954 struct tipc_msg *hdr; 959 struct tipc_msg *hdr;
960 u16 ack = l->rcv_nxt - 1;
961 u16 bc_ack = l->owner->bclink.last_in;
955 962
956 if (!skb) 963 if (!skb)
957 return 0; 964 return 0;
@@ -964,19 +971,25 @@ static int tipc_link_retransm(struct tipc_link *l, int retransm,
964 link_retransmit_failure(l, skb); 971 link_retransmit_failure(l, skb);
965 return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); 972 return tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
966 } 973 }
974
975 /* Move forward to where retransmission should start */
967 skb_queue_walk(&l->transmq, skb) { 976 skb_queue_walk(&l->transmq, skb) {
968 if (!retransm) 977 if (!less(buf_seqno(skb), from))
969 return 0; 978 break;
979 }
980
981 skb_queue_walk_from(&l->transmq, skb) {
982 if (more(buf_seqno(skb), to))
983 break;
970 hdr = buf_msg(skb); 984 hdr = buf_msg(skb);
971 _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC); 985 _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
972 if (!_skb) 986 if (!_skb)
973 return 0; 987 return 0;
974 hdr = buf_msg(_skb); 988 hdr = buf_msg(_skb);
975 msg_set_ack(hdr, l->rcv_nxt - 1); 989 msg_set_ack(hdr, ack);
976 msg_set_bcast_ack(hdr, l->owner->bclink.last_in); 990 msg_set_bcast_ack(hdr, bc_ack);
977 _skb->priority = TC_PRIO_CONTROL; 991 _skb->priority = TC_PRIO_CONTROL;
978 __skb_queue_tail(xmitq, _skb); 992 __skb_queue_tail(xmitq, _skb);
979 retransm--;
980 l->stats.retransmitted++; 993 l->stats.retransmitted++;
981 } 994 }
982 return 0; 995 return 0;
@@ -1390,7 +1403,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1390{ 1403{
1391 struct tipc_msg *hdr = buf_msg(skb); 1404 struct tipc_msg *hdr = buf_msg(skb);
1392 u16 rcvgap = 0; 1405 u16 rcvgap = 0;
1393 u16 nacked_gap = msg_seq_gap(hdr); 1406 u16 ack = msg_ack(hdr);
1407 u16 gap = msg_seq_gap(hdr);
1394 u16 peers_snd_nxt = msg_next_sent(hdr); 1408 u16 peers_snd_nxt = msg_next_sent(hdr);
1395 u16 peers_tol = msg_link_tolerance(hdr); 1409 u16 peers_tol = msg_link_tolerance(hdr);
1396 u16 peers_prio = msg_linkprio(hdr); 1410 u16 peers_prio = msg_linkprio(hdr);
@@ -1469,11 +1483,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1469 if (rcvgap || (msg_probe(hdr))) 1483 if (rcvgap || (msg_probe(hdr)))
1470 tipc_link_build_proto_msg(l, STATE_MSG, 0, rcvgap, 1484 tipc_link_build_proto_msg(l, STATE_MSG, 0, rcvgap,
1471 0, 0, xmitq); 1485 0, 0, xmitq);
1472 tipc_link_release_pkts(l, msg_ack(hdr)); 1486 tipc_link_release_pkts(l, ack);
1473 1487
1474 /* If NACK, retransmit will now start at right position */ 1488 /* If NACK, retransmit will now start at right position */
1475 if (nacked_gap) { 1489 if (gap) {
1476 rc = tipc_link_retransm(l, nacked_gap, xmitq); 1490 rc = tipc_link_retrans(l, ack + 1, ack + gap, xmitq);
1477 l->stats.recv_nacks++; 1491 l->stats.recv_nacks++;
1478 } 1492 }
1479 1493
@@ -1550,7 +1564,7 @@ static void link_reset_statistics(struct tipc_link *l_ptr)
1550static void link_print(struct tipc_link *l, const char *str) 1564static void link_print(struct tipc_link *l, const char *str)
1551{ 1565{
1552 struct sk_buff *hskb = skb_peek(&l->transmq); 1566 struct sk_buff *hskb = skb_peek(&l->transmq);
1553 u16 head = hskb ? msg_seqno(buf_msg(hskb)) : l->snd_nxt; 1567 u16 head = hskb ? msg_seqno(buf_msg(hskb)) : l->snd_nxt - 1;
1554 u16 tail = l->snd_nxt - 1; 1568 u16 tail = l->snd_nxt - 1;
1555 1569
1556 pr_info("%s Link <%s> state %x\n", str, l->name, l->state); 1570 pr_info("%s Link <%s> state %x\n", str, l->name, l->state);
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 9e4e3673da76..be24d1fd5132 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -134,6 +134,8 @@ struct tipc_stats {
134 * @snt_nxt: next sequence number to use for outbound messages 134 * @snt_nxt: next sequence number to use for outbound messages
135 * @last_retransmitted: sequence number of most recently retransmitted message 135 * @last_retransmitted: sequence number of most recently retransmitted message
136 * @stale_count: # of identical retransmit requests made by peer 136 * @stale_count: # of identical retransmit requests made by peer
137 * @ackers: # of peers that needs to ack each packet before it can be released
138 * @acked: # last packet acked by a certain peer. Used for broadcast.
137 * @rcv_nxt: next sequence number to expect for inbound messages 139 * @rcv_nxt: next sequence number to expect for inbound messages
138 * @deferred_queue: deferred queue saved OOS b'cast message received from node 140 * @deferred_queue: deferred queue saved OOS b'cast message received from node
139 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer 141 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
@@ -143,6 +145,7 @@ struct tipc_stats {
143 * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate 145 * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate
144 * @long_msg_seq_no: next identifier to use for outbound fragmented messages 146 * @long_msg_seq_no: next identifier to use for outbound fragmented messages
145 * @reasm_buf: head of partially reassembled inbound message fragments 147 * @reasm_buf: head of partially reassembled inbound message fragments
148 * @bc_rcvr: marks that this is a broadcast receiver link
146 * @stats: collects statistics regarding link activity 149 * @stats: collects statistics regarding link activity
147 */ 150 */
148struct tipc_link { 151struct tipc_link {
@@ -201,6 +204,10 @@ struct tipc_link {
201 /* Fragmentation/reassembly */ 204 /* Fragmentation/reassembly */
202 struct sk_buff *reasm_buf; 205 struct sk_buff *reasm_buf;
203 206
207 /* Broadcast */
208 u16 ackers;
209 u16 acked;
210
204 /* Statistics */ 211 /* Statistics */
205 struct tipc_stats stats; 212 struct tipc_stats stats;
206}; 213};
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 9f0ef54be612..799782c47f6c 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -112,6 +112,7 @@ struct tipc_skb_cb {
112 bool wakeup_pending; 112 bool wakeup_pending;
113 u16 chain_sz; 113 u16 chain_sz;
114 u16 chain_imp; 114 u16 chain_imp;
115 u16 ackers;
115}; 116};
116 117
117#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) 118#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))