summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2018-07-09 19:07:36 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-12 02:06:14 -0400
commit7ea817f4e8322fa27fb860d15025bf72f68b179f (patch)
tree906e6081a486ba6f244a8c0bb6d7c51c6343423d
parent9012de5089560136b849b920ad038b96160ed8f6 (diff)
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>
-rw-r--r--net/tipc/link.c68
-rw-r--r--net/tipc/link.h1
-rw-r--r--net/tipc/node.c5
3 files changed, 52 insertions, 22 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 065e9e67da5d..df763be38541 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -128,8 +128,8 @@ struct tipc_link {
128 struct net *net; 128 struct net *net;
129 129
130 /* Management and link supervision data */ 130 /* Management and link supervision data */
131 u32 peer_session; 131 u16 peer_session;
132 u32 session; 132 u16 session;
133 u16 snd_nxt_state; 133 u16 snd_nxt_state;
134 u16 rcv_nxt_state; 134 u16 rcv_nxt_state;
135 u32 peer_bearer_id; 135 u32 peer_bearer_id;
@@ -138,6 +138,7 @@ struct tipc_link {
138 u32 abort_limit; 138 u32 abort_limit;
139 u32 state; 139 u32 state;
140 u16 peer_caps; 140 u16 peer_caps;
141 bool in_session;
141 bool active; 142 bool active;
142 u32 silent_intv_cnt; 143 u32 silent_intv_cnt;
143 char if_name[TIPC_MAX_IF_NAME]; 144 char if_name[TIPC_MAX_IF_NAME];
@@ -216,11 +217,6 @@ enum {
216 */ 217 */
217#define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2) 218#define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2)
218 219
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
224/* Link FSM states: 220/* Link FSM states:
225 */ 221 */
226enum { 222enum {
@@ -478,7 +474,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
478 l->addr = peer; 474 l->addr = peer;
479 l->peer_caps = peer_caps; 475 l->peer_caps = peer_caps;
480 l->net = net; 476 l->net = net;
481 l->peer_session = ANY_SESSION; 477 l->in_session = false;
482 l->bearer_id = bearer_id; 478 l->bearer_id = bearer_id;
483 l->tolerance = tolerance; 479 l->tolerance = tolerance;
484 l->net_plane = net_plane; 480 l->net_plane = net_plane;
@@ -847,7 +843,7 @@ void link_prepare_wakeup(struct tipc_link *l)
847 843
848void tipc_link_reset(struct tipc_link *l) 844void tipc_link_reset(struct tipc_link *l)
849{ 845{
850 l->peer_session = ANY_SESSION; 846 l->in_session = false;
851 l->session++; 847 l->session++;
852 l->mtu = l->advertised_mtu; 848 l->mtu = l->advertised_mtu;
853 __skb_queue_purge(&l->transmq); 849 __skb_queue_purge(&l->transmq);
@@ -1455,6 +1451,44 @@ tnl:
1455 } 1451 }
1456} 1452}
1457 1453
1454/* tipc_link_validate_msg(): validate message against current link state
1455 * Returns true if message should be accepted, otherwise false
1456 */
1457bool 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
1458/* tipc_link_proto_rcv(): receive link level protocol message : 1492/* tipc_link_proto_rcv(): receive link level protocol message :
1459 * Note that network plane id propagates through the network, and may 1493 * Note that network plane id propagates through the network, and may
1460 * change at any time. The node with lowest numerical id determines 1494 * 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,
1488 hdr = buf_msg(skb); 1522 hdr = buf_msg(skb);
1489 data = msg_data(hdr); 1523 data = msg_data(hdr);
1490 1524
1525 if (!tipc_link_validate_msg(l, hdr))
1526 goto exit;
1527
1491 switch (mtyp) { 1528 switch (mtyp) {
1492 case RESET_MSG: 1529 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
1500 case ACTIVATE_MSG: 1530 case ACTIVATE_MSG:
1501
1502 /* Complete own link name with peer's interface name */ 1531 /* Complete own link name with peer's interface name */
1503 if_name = strrchr(l->name, ':') + 1; 1532 if_name = strrchr(l->name, ':') + 1;
1504 if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME) 1533 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,
1526 rc = TIPC_LINK_UP_EVT; 1555 rc = TIPC_LINK_UP_EVT;
1527 1556
1528 l->peer_session = msg_session(hdr); 1557 l->peer_session = msg_session(hdr);
1558 l->in_session = true;
1529 l->peer_bearer_id = msg_bearer_id(hdr); 1559 l->peer_bearer_id = msg_bearer_id(hdr);
1530 if (l->mtu > msg_max_pkt(hdr)) 1560 if (l->mtu > msg_max_pkt(hdr))
1531 l->mtu = msg_max_pkt(hdr); 1561 l->mtu = msg_max_pkt(hdr);
1532 break; 1562 break;
1533 1563
1534 case STATE_MSG: 1564 case STATE_MSG:
1535
1536 if (l->peer_caps & TIPC_LINK_PROTO_SEQNO &&
1537 less(msg_seqno(hdr), l->rcv_nxt_state))
1538 break;
1539 l->rcv_nxt_state = msg_seqno(hdr) + 1; 1565 l->rcv_nxt_state = msg_seqno(hdr) + 1;
1540 1566
1541 /* Update own tolerance if peer indicates a non-zero value */ 1567 /* Update own tolerance if peer indicates a non-zero value */
diff --git a/net/tipc/link.h b/net/tipc/link.h
index d56f9c9e5000..7bc494a33fdf 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -111,6 +111,7 @@ char tipc_link_plane(struct tipc_link *l);
111int tipc_link_prio(struct tipc_link *l); 111int tipc_link_prio(struct tipc_link *l);
112int tipc_link_window(struct tipc_link *l); 112int tipc_link_window(struct tipc_link *l);
113void tipc_link_update_caps(struct tipc_link *l, u16 capabilities); 113void tipc_link_update_caps(struct tipc_link *l, u16 capabilities);
114bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr);
114unsigned long tipc_link_tolerance(struct tipc_link *l); 115unsigned long tipc_link_tolerance(struct tipc_link *l);
115void tipc_link_set_tolerance(struct tipc_link *l, u32 tol, 116void tipc_link_set_tolerance(struct tipc_link *l, u32 tol,
116 struct sk_buff_head *xmitq); 117 struct sk_buff_head *xmitq);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 1cdb176798f7..52fd80b0e728 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1540,7 +1540,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id
1540 * tipc_node_check_state - check and if necessary update node state 1540 * tipc_node_check_state - check and if necessary update node state
1541 * @skb: TIPC packet 1541 * @skb: TIPC packet
1542 * @bearer_id: identity of bearer delivering the packet 1542 * @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
1544 */ 1544 */
1545static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, 1545static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
1546 int bearer_id, struct sk_buff_head *xmitq) 1546 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,
1574 } 1574 }
1575 } 1575 }
1576 1576
1577 if (!tipc_link_validate_msg(l, hdr))
1578 return false;
1579
1577 /* Check and update node accesibility if applicable */ 1580 /* Check and update node accesibility if applicable */
1578 if (state == SELF_UP_PEER_COMING) { 1581 if (state == SELF_UP_PEER_COMING) {
1579 if (!tipc_link_is_up(l)) 1582 if (!tipc_link_is_up(l))