Skip to content

Commit 7ea817f

Browse files
Jon Maloydavem330
authored andcommitted
tipc: check session number before accepting link protocol messages
In some virtual environments we observe a significant higher number of packet reordering and delays than we have been used to traditionally. This makes it necessary with stricter checks on incoming link protocol messages' session number, which until now only has been validated for RESET messages. Since the other two message types, ACTIVATE and STATE messages also carry this number, it is easy to extend the validation check to those messages. We also introduce a flag indicating if a link has a valid peer session number or not. This eliminates the mixing of 32- and 16-bit arithmethics we are currently using to achieve this. Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9012de5 commit 7ea817f

File tree

3 files changed

+52
-22
lines changed

3 files changed

+52
-22
lines changed

net/tipc/link.c

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ struct tipc_link {
128128
struct net *net;
129129

130130
/* Management and link supervision data */
131-
u32 peer_session;
132-
u32 session;
131+
u16 peer_session;
132+
u16 session;
133133
u16 snd_nxt_state;
134134
u16 rcv_nxt_state;
135135
u32 peer_bearer_id;
@@ -138,6 +138,7 @@ struct tipc_link {
138138
u32 abort_limit;
139139
u32 state;
140140
u16 peer_caps;
141+
bool in_session;
141142
bool active;
142143
u32 silent_intv_cnt;
143144
char if_name[TIPC_MAX_IF_NAME];
@@ -216,11 +217,6 @@ enum {
216217
*/
217218
#define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2)
218219

219-
/* Wildcard value for link session numbers. When it is known that
220-
* peer endpoint is down, any session number must be accepted.
221-
*/
222-
#define ANY_SESSION 0x10000
223-
224220
/* Link FSM states:
225221
*/
226222
enum {
@@ -478,7 +474,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
478474
l->addr = peer;
479475
l->peer_caps = peer_caps;
480476
l->net = net;
481-
l->peer_session = ANY_SESSION;
477+
l->in_session = false;
482478
l->bearer_id = bearer_id;
483479
l->tolerance = tolerance;
484480
l->net_plane = net_plane;
@@ -847,7 +843,7 @@ void link_prepare_wakeup(struct tipc_link *l)
847843

848844
void tipc_link_reset(struct tipc_link *l)
849845
{
850-
l->peer_session = ANY_SESSION;
846+
l->in_session = false;
851847
l->session++;
852848
l->mtu = l->advertised_mtu;
853849
__skb_queue_purge(&l->transmq);
@@ -1455,6 +1451,44 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl,
14551451
}
14561452
}
14571453

1454+
/* tipc_link_validate_msg(): validate message against current link state
1455+
* Returns true if message should be accepted, otherwise false
1456+
*/
1457+
bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr)
1458+
{
1459+
u16 curr_session = l->peer_session;
1460+
u16 session = msg_session(hdr);
1461+
int mtyp = msg_type(hdr);
1462+
1463+
if (msg_user(hdr) != LINK_PROTOCOL)
1464+
return true;
1465+
1466+
switch (mtyp) {
1467+
case RESET_MSG:
1468+
if (!l->in_session)
1469+
return true;
1470+
/* Accept only RESET with new session number */
1471+
return more(session, curr_session);
1472+
case ACTIVATE_MSG:
1473+
if (!l->in_session)
1474+
return true;
1475+
/* Accept only ACTIVATE with new or current session number */
1476+
return !less(session, curr_session);
1477+
case STATE_MSG:
1478+
/* Accept only STATE with current session number */
1479+
if (!l->in_session)
1480+
return false;
1481+
if (session != curr_session)
1482+
return false;
1483+
if (!(l->peer_caps & TIPC_LINK_PROTO_SEQNO))
1484+
return true;
1485+
/* Accept only STATE with new sequence number */
1486+
return !less(msg_seqno(hdr), l->rcv_nxt_state);
1487+
default:
1488+
return false;
1489+
}
1490+
}
1491+
14581492
/* tipc_link_proto_rcv(): receive link level protocol message :
14591493
* Note that network plane id propagates through the network, and may
14601494
* change at any time. The node with lowest numerical id determines
@@ -1488,17 +1522,12 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
14881522
hdr = buf_msg(skb);
14891523
data = msg_data(hdr);
14901524

1525+
if (!tipc_link_validate_msg(l, hdr))
1526+
goto exit;
1527+
14911528
switch (mtyp) {
14921529
case RESET_MSG:
1493-
1494-
/* Ignore duplicate RESET with old session number */
1495-
if ((less_eq(msg_session(hdr), l->peer_session)) &&
1496-
(l->peer_session != ANY_SESSION))
1497-
break;
1498-
/* fall thru' */
1499-
15001530
case ACTIVATE_MSG:
1501-
15021531
/* Complete own link name with peer's interface name */
15031532
if_name = strrchr(l->name, ':') + 1;
15041533
if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME)
@@ -1526,16 +1555,13 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
15261555
rc = TIPC_LINK_UP_EVT;
15271556

15281557
l->peer_session = msg_session(hdr);
1558+
l->in_session = true;
15291559
l->peer_bearer_id = msg_bearer_id(hdr);
15301560
if (l->mtu > msg_max_pkt(hdr))
15311561
l->mtu = msg_max_pkt(hdr);
15321562
break;
15331563

15341564
case STATE_MSG:
1535-
1536-
if (l->peer_caps & TIPC_LINK_PROTO_SEQNO &&
1537-
less(msg_seqno(hdr), l->rcv_nxt_state))
1538-
break;
15391565
l->rcv_nxt_state = msg_seqno(hdr) + 1;
15401566

15411567
/* Update own tolerance if peer indicates a non-zero value */

net/tipc/link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ char tipc_link_plane(struct tipc_link *l);
111111
int tipc_link_prio(struct tipc_link *l);
112112
int tipc_link_window(struct tipc_link *l);
113113
void tipc_link_update_caps(struct tipc_link *l, u16 capabilities);
114+
bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr);
114115
unsigned long tipc_link_tolerance(struct tipc_link *l);
115116
void tipc_link_set_tolerance(struct tipc_link *l, u32 tol,
116117
struct sk_buff_head *xmitq);

net/tipc/node.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id
15401540
* tipc_node_check_state - check and if necessary update node state
15411541
* @skb: TIPC packet
15421542
* @bearer_id: identity of bearer delivering the packet
1543-
* Returns true if state is ok, otherwise consumes buffer and returns false
1543+
* Returns true if state and msg are ok, otherwise false
15441544
*/
15451545
static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
15461546
int bearer_id, struct sk_buff_head *xmitq)
@@ -1574,6 +1574,9 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
15741574
}
15751575
}
15761576

1577+
if (!tipc_link_validate_msg(l, hdr))
1578+
return false;
1579+
15771580
/* Check and update node accesibility if applicable */
15781581
if (state == SELF_UP_PEER_COMING) {
15791582
if (!tipc_link_is_up(l))

0 commit comments

Comments
 (0)