Commit e4bf4f76 authored by Jon Paul Maloy's avatar Jon Paul Maloy Committed by David S. Miller

tipc: simplify packet sequence number handling

Although the sequence number in the TIPC protocol is 16 bits, we have
until now stored it internally as an unsigned 32 bits integer.
We got around this by always doing explicit modulo-65535 operations
whenever we need to access a sequence number.

We now make the incoming and outgoing sequence numbers to unsigned
16-bit integers, and remove the modulo operations where applicable.

We also move the arithmetic inline functions for 16 bit integers
to core.h, and the function buf_seqno() to msg.h, so they can easily
be accessed from anywhere in the code.
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a6bf70f7
...@@ -109,6 +109,26 @@ struct tipc_net { ...@@ -109,6 +109,26 @@ struct tipc_net {
atomic_t subscription_count; atomic_t subscription_count;
}; };
static inline u16 mod(u16 x)
{
return x & 0xffffu;
}
static inline int less_eq(u16 left, u16 right)
{
return mod(right - left) < 32768u;
}
static inline int more(u16 left, u16 right)
{
return !less_eq(left, right);
}
static inline int less(u16 left, u16 right)
{
return less_eq(left, right) && (mod(right) != mod(left));
}
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
int tipc_register_sysctl(void); int tipc_register_sysctl(void);
void tipc_unregister_sysctl(void); void tipc_unregister_sysctl(void);
......
...@@ -685,9 +685,9 @@ int __tipc_link_xmit(struct net *net, struct tipc_link *link, ...@@ -685,9 +685,9 @@ int __tipc_link_xmit(struct net *net, struct tipc_link *link,
unsigned int maxwin = link->window; unsigned int maxwin = link->window;
unsigned int imp = msg_importance(msg); unsigned int imp = msg_importance(msg);
uint mtu = link->mtu; uint mtu = link->mtu;
uint ack = mod(link->next_in_no - 1); u16 ack = mod(link->next_in_no - 1);
uint seqno = link->next_out_no; u16 seqno = link->next_out_no;
uint bc_last_in = link->owner->bclink.last_in; u16 bc_last_in = link->owner->bclink.last_in;
struct tipc_media_addr *addr = &link->media_addr; struct tipc_media_addr *addr = &link->media_addr;
struct sk_buff_head *transmq = &link->transmq; struct sk_buff_head *transmq = &link->transmq;
struct sk_buff_head *backlogq = &link->backlogq; struct sk_buff_head *backlogq = &link->backlogq;
...@@ -859,7 +859,7 @@ void tipc_link_push_packets(struct tipc_link *link) ...@@ -859,7 +859,7 @@ void tipc_link_push_packets(struct tipc_link *link)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct tipc_msg *msg; struct tipc_msg *msg;
unsigned int ack = mod(link->next_in_no - 1); u16 ack = mod(link->next_in_no - 1);
while (skb_queue_len(&link->transmq) < link->window) { while (skb_queue_len(&link->transmq) < link->window) {
skb = __skb_dequeue(&link->backlogq); skb = __skb_dequeue(&link->backlogq);
...@@ -998,13 +998,13 @@ static bool link_synch(struct tipc_link *l) ...@@ -998,13 +998,13 @@ static bool link_synch(struct tipc_link *l)
static void link_retrieve_defq(struct tipc_link *link, static void link_retrieve_defq(struct tipc_link *link,
struct sk_buff_head *list) struct sk_buff_head *list)
{ {
u32 seq_no; u16 seq_no;
if (skb_queue_empty(&link->deferdq)) if (skb_queue_empty(&link->deferdq))
return; return;
seq_no = buf_seqno(skb_peek(&link->deferdq)); seq_no = buf_seqno(skb_peek(&link->deferdq));
if (seq_no == mod(link->next_in_no)) if (seq_no == link->next_in_no)
skb_queue_splice_tail_init(&link->deferdq, list); skb_queue_splice_tail_init(&link->deferdq, list);
} }
...@@ -1025,8 +1025,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) ...@@ -1025,8 +1025,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
struct tipc_link *l_ptr; struct tipc_link *l_ptr;
struct sk_buff *skb1, *tmp; struct sk_buff *skb1, *tmp;
struct tipc_msg *msg; struct tipc_msg *msg;
u32 seq_no; u16 seq_no;
u32 ackd; u16 ackd;
u32 released; u32 released;
skb2list(skb, &head); skb2list(skb, &head);
...@@ -1119,7 +1119,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) ...@@ -1119,7 +1119,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
} }
/* Link is now in state WORKING_WORKING */ /* Link is now in state WORKING_WORKING */
if (unlikely(seq_no != mod(l_ptr->next_in_no))) { if (unlikely(seq_no != l_ptr->next_in_no)) {
link_handle_out_of_seq_msg(l_ptr, skb); link_handle_out_of_seq_msg(l_ptr, skb);
link_retrieve_defq(l_ptr, &head); link_retrieve_defq(l_ptr, &head);
skb = NULL; skb = NULL;
...@@ -1250,7 +1250,7 @@ static void tipc_link_input(struct tipc_link *link, struct sk_buff *skb) ...@@ -1250,7 +1250,7 @@ static void tipc_link_input(struct tipc_link *link, struct sk_buff *skb)
u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb) u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb)
{ {
struct sk_buff *skb1; struct sk_buff *skb1;
u32 seq_no = buf_seqno(skb); u16 seq_no = buf_seqno(skb);
/* Empty queue ? */ /* Empty queue ? */
if (skb_queue_empty(list)) { if (skb_queue_empty(list)) {
...@@ -1266,7 +1266,7 @@ u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb) ...@@ -1266,7 +1266,7 @@ u32 tipc_link_defer_pkt(struct sk_buff_head *list, struct sk_buff *skb)
/* Locate insertion point in queue, then insert; discard if duplicate */ /* Locate insertion point in queue, then insert; discard if duplicate */
skb_queue_walk(list, skb1) { skb_queue_walk(list, skb1) {
u32 curr_seqno = buf_seqno(skb1); u16 curr_seqno = buf_seqno(skb1);
if (seq_no == curr_seqno) { if (seq_no == curr_seqno) {
kfree_skb(skb); kfree_skb(skb);
...@@ -1301,7 +1301,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, ...@@ -1301,7 +1301,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
* Discard packet if a duplicate; otherwise add it to deferred queue * Discard packet if a duplicate; otherwise add it to deferred queue
* and notify peer of gap as per protocol specification * and notify peer of gap as per protocol specification
*/ */
if (less(seq_no, mod(l_ptr->next_in_no))) { if (less(seq_no, l_ptr->next_in_no)) {
l_ptr->stats.duplicates++; l_ptr->stats.duplicates++;
kfree_skb(buf); kfree_skb(buf);
return; return;
...@@ -1326,6 +1326,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, ...@@ -1326,6 +1326,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
struct tipc_msg *msg = l_ptr->pmsg; struct tipc_msg *msg = l_ptr->pmsg;
u32 msg_size = sizeof(l_ptr->proto_msg); u32 msg_size = sizeof(l_ptr->proto_msg);
int r_flag; int r_flag;
u16 last_rcv;
/* Don't send protocol message during link failover */ /* Don't send protocol message during link failover */
if (l_ptr->flags & LINK_FAILINGOVER) if (l_ptr->flags & LINK_FAILINGOVER)
...@@ -1342,7 +1343,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, ...@@ -1342,7 +1343,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
msg_set_last_bcast(msg, tipc_bclink_get_last_sent(l_ptr->owner->net)); msg_set_last_bcast(msg, tipc_bclink_get_last_sent(l_ptr->owner->net));
if (msg_typ == STATE_MSG) { if (msg_typ == STATE_MSG) {
u32 next_sent = mod(l_ptr->next_out_no); u16 next_sent = l_ptr->next_out_no;
if (!tipc_link_is_up(l_ptr)) if (!tipc_link_is_up(l_ptr))
return; return;
...@@ -1350,8 +1351,8 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, ...@@ -1350,8 +1351,8 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
next_sent = buf_seqno(skb_peek(&l_ptr->backlogq)); next_sent = buf_seqno(skb_peek(&l_ptr->backlogq));
msg_set_next_sent(msg, next_sent); msg_set_next_sent(msg, next_sent);
if (!skb_queue_empty(&l_ptr->deferdq)) { if (!skb_queue_empty(&l_ptr->deferdq)) {
u32 rec = buf_seqno(skb_peek(&l_ptr->deferdq)); last_rcv = buf_seqno(skb_peek(&l_ptr->deferdq));
gap = mod(rec - mod(l_ptr->next_in_no)); gap = mod(last_rcv - l_ptr->next_in_no);
} }
msg_set_seq_gap(msg, gap); msg_set_seq_gap(msg, gap);
if (gap) if (gap)
...@@ -1485,10 +1486,8 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, ...@@ -1485,10 +1486,8 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
if (link_reset_unknown(l_ptr)) if (link_reset_unknown(l_ptr))
break; break;
if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) { if (less_eq(l_ptr->next_in_no, msg_next_sent(msg)))
rec_gap = mod(msg_next_sent(msg) - rec_gap = mod(msg_next_sent(msg) - l_ptr->next_in_no);
mod(l_ptr->next_in_no));
}
if (msg_probe(msg)) if (msg_probe(msg))
l_ptr->stats.recv_probes++; l_ptr->stats.recv_probes++;
......
...@@ -151,7 +151,7 @@ struct tipc_link { ...@@ -151,7 +151,7 @@ struct tipc_link {
/* Management and link supervision data */ /* Management and link supervision data */
unsigned int flags; unsigned int flags;
u32 checkpoint; u16 checkpoint;
u32 peer_session; u32 peer_session;
u32 peer_bearer_id; u32 peer_bearer_id;
u32 bearer_id; u32 bearer_id;
...@@ -185,13 +185,13 @@ struct tipc_link { ...@@ -185,13 +185,13 @@ struct tipc_link {
u16 len; u16 len;
u16 limit; u16 limit;
} backlog[5]; } backlog[5];
u32 next_out_no; u16 next_out_no;
u16 last_retransmitted;
u32 window; u32 window;
u32 last_retransmitted;
u32 stale_count; u32 stale_count;
/* Reception */ /* Reception */
u32 next_in_no; u16 next_in_no;
u32 rcv_unacked; u32 rcv_unacked;
struct sk_buff_head deferdq; struct sk_buff_head deferdq;
struct sk_buff_head inputq; struct sk_buff_head inputq;
...@@ -245,39 +245,6 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info); ...@@ -245,39 +245,6 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info);
int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]); int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
void link_prepare_wakeup(struct tipc_link *l); void link_prepare_wakeup(struct tipc_link *l);
/*
* Link sequence number manipulation routines (uses modulo 2**16 arithmetic)
*/
static inline u32 buf_seqno(struct sk_buff *buf)
{
return msg_seqno(buf_msg(buf));
}
static inline u32 mod(u32 x)
{
return x & 0xffffu;
}
static inline int less_eq(u32 left, u32 right)
{
return mod(right - left) < 32768u;
}
static inline int more(u32 left, u32 right)
{
return !less_eq(left, right);
}
static inline int less(u32 left, u32 right)
{
return less_eq(left, right) && (mod(right) != mod(left));
}
static inline u32 lesser(u32 left, u32 right)
{
return less_eq(left, right) ? left : right;
}
static inline u32 link_own_addr(struct tipc_link *l) static inline u32 link_own_addr(struct tipc_link *l)
{ {
return msg_prevnode(l->pmsg); return msg_prevnode(l->pmsg);
......
...@@ -313,12 +313,12 @@ static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) ...@@ -313,12 +313,12 @@ static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
msg_set_bits(m, 1, 19, 0x3, n); msg_set_bits(m, 1, 19, 0x3, n);
} }
static inline u32 msg_bcast_ack(struct tipc_msg *m) static inline u16 msg_bcast_ack(struct tipc_msg *m)
{ {
return msg_bits(m, 1, 0, 0xffff); return msg_bits(m, 1, 0, 0xffff);
} }
static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) static inline void msg_set_bcast_ack(struct tipc_msg *m, u16 n)
{ {
msg_set_bits(m, 1, 0, 0xffff, n); msg_set_bits(m, 1, 0, 0xffff, n);
} }
...@@ -327,22 +327,22 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) ...@@ -327,22 +327,22 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n)
/* /*
* Word 2 * Word 2
*/ */
static inline u32 msg_ack(struct tipc_msg *m) static inline u16 msg_ack(struct tipc_msg *m)
{ {
return msg_bits(m, 2, 16, 0xffff); return msg_bits(m, 2, 16, 0xffff);
} }
static inline void msg_set_ack(struct tipc_msg *m, u32 n) static inline void msg_set_ack(struct tipc_msg *m, u16 n)
{ {
msg_set_bits(m, 2, 16, 0xffff, n); msg_set_bits(m, 2, 16, 0xffff, n);
} }
static inline u32 msg_seqno(struct tipc_msg *m) static inline u16 msg_seqno(struct tipc_msg *m)
{ {
return msg_bits(m, 2, 0, 0xffff); return msg_bits(m, 2, 0, 0xffff);
} }
static inline void msg_set_seqno(struct tipc_msg *m, u32 n) static inline void msg_set_seqno(struct tipc_msg *m, u16 n)
{ {
msg_set_bits(m, 2, 0, 0xffff, n); msg_set_bits(m, 2, 0, 0xffff, n);
} }
...@@ -782,6 +782,11 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode, ...@@ -782,6 +782,11 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode,
int *err); int *err);
struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list);
static inline u16 buf_seqno(struct sk_buff *skb)
{
return msg_seqno(buf_msg(skb));
}
/* tipc_skb_peek(): peek and reserve first buffer in list /* tipc_skb_peek(): peek and reserve first buffer in list
* @list: list to be peeked in * @list: list to be peeked in
* Returns pointer to first buffer in list, if any * Returns pointer to first buffer in list, if any
......
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