Commit 9012de50 authored by Jon Maloy's avatar Jon Maloy Committed by David S. Miller

tipc: add sequence number check for link STATE messages

Some switch infrastructures produce huge amounts of packet duplicates.
This becomes a problem if those messages are STATE/NACK protocol
messages, causing unnecessary retransmissions of already accepted
packets.

We now introduce a unique sequence number per STATE protocol message
so that duplicates can be identified and ignored. This will also be
useful when tracing such cases, and to avert replay attacks when TIPC
is encrypted.

For compatibility reasons we have to introduce a new capability flag
TIPC_LINK_PROTO_SEQNO to handle this new feature.
Signed-off-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e32f55f3
...@@ -130,6 +130,8 @@ struct tipc_link { ...@@ -130,6 +130,8 @@ struct tipc_link {
/* Management and link supervision data */ /* Management and link supervision data */
u32 peer_session; u32 peer_session;
u32 session; u32 session;
u16 snd_nxt_state;
u16 rcv_nxt_state;
u32 peer_bearer_id; u32 peer_bearer_id;
u32 bearer_id; u32 bearer_id;
u32 tolerance; u32 tolerance;
...@@ -339,6 +341,11 @@ char tipc_link_plane(struct tipc_link *l) ...@@ -339,6 +341,11 @@ char tipc_link_plane(struct tipc_link *l)
return l->net_plane; return l->net_plane;
} }
void tipc_link_update_caps(struct tipc_link *l, u16 capabilities)
{
l->peer_caps = capabilities;
}
void tipc_link_add_bc_peer(struct tipc_link *snd_l, void tipc_link_add_bc_peer(struct tipc_link *snd_l,
struct tipc_link *uc_l, struct tipc_link *uc_l,
struct sk_buff_head *xmitq) struct sk_buff_head *xmitq)
...@@ -859,6 +866,8 @@ void tipc_link_reset(struct tipc_link *l) ...@@ -859,6 +866,8 @@ void tipc_link_reset(struct tipc_link *l)
l->rcv_unacked = 0; l->rcv_unacked = 0;
l->snd_nxt = 1; l->snd_nxt = 1;
l->rcv_nxt = 1; l->rcv_nxt = 1;
l->snd_nxt_state = 1;
l->rcv_nxt_state = 1;
l->acked = 0; l->acked = 0;
l->silent_intv_cnt = 0; l->silent_intv_cnt = 0;
l->rst_cnt = 0; l->rst_cnt = 0;
...@@ -1353,6 +1362,8 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, ...@@ -1353,6 +1362,8 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
msg_set_seqno(hdr, l->snd_nxt + U16_MAX / 2); msg_set_seqno(hdr, l->snd_nxt + U16_MAX / 2);
if (mtyp == STATE_MSG) { if (mtyp == STATE_MSG) {
if (l->peer_caps & TIPC_LINK_PROTO_SEQNO)
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)); msg_set_bc_gap(hdr, link_bc_rcv_gap(bcl));
msg_set_probe(hdr, probe); msg_set_probe(hdr, probe);
...@@ -1522,6 +1533,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, ...@@ -1522,6 +1533,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
case STATE_MSG: case STATE_MSG:
if (l->peer_caps & TIPC_LINK_PROTO_SEQNO &&
less(msg_seqno(hdr), l->rcv_nxt_state))
break;
l->rcv_nxt_state = msg_seqno(hdr) + 1;
/* Update own tolerance if peer indicates a non-zero value */ /* Update own tolerance if peer indicates a non-zero value */
if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL))
l->tolerance = peers_tol; l->tolerance = peers_tol;
......
...@@ -110,6 +110,7 @@ char *tipc_link_name(struct tipc_link *l); ...@@ -110,6 +110,7 @@ char *tipc_link_name(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);
int tipc_link_window(struct tipc_link *l); int tipc_link_window(struct tipc_link *l);
void tipc_link_update_caps(struct tipc_link *l, u16 capabilities);
unsigned long tipc_link_tolerance(struct tipc_link *l); unsigned long tipc_link_tolerance(struct tipc_link *l);
void tipc_link_set_tolerance(struct tipc_link *l, u32 tol, void tipc_link_set_tolerance(struct tipc_link *l, u32 tol,
struct sk_buff_head *xmitq); struct sk_buff_head *xmitq);
......
...@@ -363,6 +363,8 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr, ...@@ -363,6 +363,8 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
{ {
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_node *n, *temp_node; struct tipc_node *n, *temp_node;
struct tipc_link *l;
int bearer_id;
int i; int i;
spin_lock_bh(&tn->node_list_lock); spin_lock_bh(&tn->node_list_lock);
...@@ -370,6 +372,11 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr, ...@@ -370,6 +372,11 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
if (n) { if (n) {
/* Same node may come back with new capabilities */ /* Same node may come back with new capabilities */
n->capabilities = capabilities; n->capabilities = capabilities;
for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
l = n->links[bearer_id].link;
if (l)
tipc_link_update_caps(l, capabilities);
}
goto exit; goto exit;
} }
n = kzalloc(sizeof(*n), GFP_ATOMIC); n = kzalloc(sizeof(*n), GFP_ATOMIC);
......
...@@ -49,14 +49,16 @@ enum { ...@@ -49,14 +49,16 @@ enum {
TIPC_BCAST_STATE_NACK = (1 << 2), TIPC_BCAST_STATE_NACK = (1 << 2),
TIPC_BLOCK_FLOWCTL = (1 << 3), TIPC_BLOCK_FLOWCTL = (1 << 3),
TIPC_BCAST_RCAST = (1 << 4), TIPC_BCAST_RCAST = (1 << 4),
TIPC_NODE_ID128 = (1 << 5) TIPC_NODE_ID128 = (1 << 5),
TIPC_LINK_PROTO_SEQNO = (1 << 6)
}; };
#define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | \ #define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | \
TIPC_BCAST_STATE_NACK | \ TIPC_BCAST_STATE_NACK | \
TIPC_BCAST_RCAST | \ TIPC_BCAST_RCAST | \
TIPC_BLOCK_FLOWCTL | \ TIPC_BLOCK_FLOWCTL | \
TIPC_NODE_ID128) TIPC_NODE_ID128 | \
TIPC_LINK_PROTO_SEQNO)
#define INVALID_BEARER_ID -1 #define INVALID_BEARER_ID -1
void tipc_node_stop(struct net *net); void tipc_node_stop(struct net *net);
......
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