diff options
Diffstat (limited to 'net/tipc/link.c')
| -rw-r--r-- | net/tipc/link.c | 106 |
1 files changed, 80 insertions, 26 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 1f2cde0d025f..3cb9f326ee6f 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -151,6 +151,7 @@ struct tipc_link { | |||
| 151 | /* Failover/synch */ | 151 | /* Failover/synch */ |
| 152 | u16 drop_point; | 152 | u16 drop_point; |
| 153 | struct sk_buff *failover_reasm_skb; | 153 | struct sk_buff *failover_reasm_skb; |
| 154 | struct sk_buff_head failover_deferdq; | ||
| 154 | 155 | ||
| 155 | /* Max packet negotiation */ | 156 | /* Max packet negotiation */ |
| 156 | u16 mtu; | 157 | u16 mtu; |
| @@ -498,6 +499,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id, | |||
| 498 | __skb_queue_head_init(&l->transmq); | 499 | __skb_queue_head_init(&l->transmq); |
| 499 | __skb_queue_head_init(&l->backlogq); | 500 | __skb_queue_head_init(&l->backlogq); |
| 500 | __skb_queue_head_init(&l->deferdq); | 501 | __skb_queue_head_init(&l->deferdq); |
| 502 | __skb_queue_head_init(&l->failover_deferdq); | ||
| 501 | skb_queue_head_init(&l->wakeupq); | 503 | skb_queue_head_init(&l->wakeupq); |
| 502 | skb_queue_head_init(l->inputq); | 504 | skb_queue_head_init(l->inputq); |
| 503 | return true; | 505 | return true; |
| @@ -888,6 +890,7 @@ void tipc_link_reset(struct tipc_link *l) | |||
| 888 | __skb_queue_purge(&l->transmq); | 890 | __skb_queue_purge(&l->transmq); |
| 889 | __skb_queue_purge(&l->deferdq); | 891 | __skb_queue_purge(&l->deferdq); |
| 890 | __skb_queue_purge(&l->backlogq); | 892 | __skb_queue_purge(&l->backlogq); |
| 893 | __skb_queue_purge(&l->failover_deferdq); | ||
| 891 | l->backlog[TIPC_LOW_IMPORTANCE].len = 0; | 894 | l->backlog[TIPC_LOW_IMPORTANCE].len = 0; |
| 892 | l->backlog[TIPC_MEDIUM_IMPORTANCE].len = 0; | 895 | l->backlog[TIPC_MEDIUM_IMPORTANCE].len = 0; |
| 893 | l->backlog[TIPC_HIGH_IMPORTANCE].len = 0; | 896 | l->backlog[TIPC_HIGH_IMPORTANCE].len = 0; |
| @@ -1159,34 +1162,14 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb, | |||
| 1159 | * Consumes buffer | 1162 | * Consumes buffer |
| 1160 | */ | 1163 | */ |
| 1161 | static int tipc_link_input(struct tipc_link *l, struct sk_buff *skb, | 1164 | static int tipc_link_input(struct tipc_link *l, struct sk_buff *skb, |
| 1162 | struct sk_buff_head *inputq) | 1165 | struct sk_buff_head *inputq, |
| 1166 | struct sk_buff **reasm_skb) | ||
| 1163 | { | 1167 | { |
| 1164 | struct tipc_msg *hdr = buf_msg(skb); | 1168 | struct tipc_msg *hdr = buf_msg(skb); |
| 1165 | struct sk_buff **reasm_skb = &l->reasm_buf; | ||
| 1166 | struct sk_buff *iskb; | 1169 | struct sk_buff *iskb; |
| 1167 | struct sk_buff_head tmpq; | 1170 | struct sk_buff_head tmpq; |
| 1168 | int usr = msg_user(hdr); | 1171 | int usr = msg_user(hdr); |
| 1169 | int rc = 0; | ||
| 1170 | int pos = 0; | 1172 | int pos = 0; |
| 1171 | int ipos = 0; | ||
| 1172 | |||
| 1173 | if (unlikely(usr == TUNNEL_PROTOCOL)) { | ||
| 1174 | if (msg_type(hdr) == SYNCH_MSG) { | ||
| 1175 | __skb_queue_purge(&l->deferdq); | ||
| 1176 | goto drop; | ||
| 1177 | } | ||
| 1178 | if (!tipc_msg_extract(skb, &iskb, &ipos)) | ||
| 1179 | return rc; | ||
| 1180 | kfree_skb(skb); | ||
| 1181 | skb = iskb; | ||
| 1182 | hdr = buf_msg(skb); | ||
| 1183 | if (less(msg_seqno(hdr), l->drop_point)) | ||
| 1184 | goto drop; | ||
| 1185 | if (tipc_data_input(l, skb, inputq)) | ||
| 1186 | return rc; | ||
| 1187 | usr = msg_user(hdr); | ||
| 1188 | reasm_skb = &l->failover_reasm_skb; | ||
| 1189 | } | ||
| 1190 | 1173 | ||
| 1191 | if (usr == MSG_BUNDLER) { | 1174 | if (usr == MSG_BUNDLER) { |
| 1192 | skb_queue_head_init(&tmpq); | 1175 | skb_queue_head_init(&tmpq); |
| @@ -1211,11 +1194,66 @@ static int tipc_link_input(struct tipc_link *l, struct sk_buff *skb, | |||
| 1211 | tipc_link_bc_init_rcv(l->bc_rcvlink, hdr); | 1194 | tipc_link_bc_init_rcv(l->bc_rcvlink, hdr); |
| 1212 | tipc_bcast_unlock(l->net); | 1195 | tipc_bcast_unlock(l->net); |
| 1213 | } | 1196 | } |
| 1214 | drop: | 1197 | |
| 1215 | kfree_skb(skb); | 1198 | kfree_skb(skb); |
| 1216 | return 0; | 1199 | return 0; |
| 1217 | } | 1200 | } |
| 1218 | 1201 | ||
| 1202 | /* tipc_link_tnl_rcv() - receive TUNNEL_PROTOCOL message, drop or process the | ||
| 1203 | * inner message along with the ones in the old link's | ||
| 1204 | * deferdq | ||
| 1205 | * @l: tunnel link | ||
| 1206 | * @skb: TUNNEL_PROTOCOL message | ||
| 1207 | * @inputq: queue to put messages ready for delivery | ||
| 1208 | */ | ||
| 1209 | static int tipc_link_tnl_rcv(struct tipc_link *l, struct sk_buff *skb, | ||
| 1210 | struct sk_buff_head *inputq) | ||
| 1211 | { | ||
| 1212 | struct sk_buff **reasm_skb = &l->failover_reasm_skb; | ||
| 1213 | struct sk_buff_head *fdefq = &l->failover_deferdq; | ||
| 1214 | struct tipc_msg *hdr = buf_msg(skb); | ||
| 1215 | struct sk_buff *iskb; | ||
| 1216 | int ipos = 0; | ||
| 1217 | int rc = 0; | ||
| 1218 | u16 seqno; | ||
| 1219 | |||
| 1220 | /* SYNCH_MSG */ | ||
| 1221 | if (msg_type(hdr) == SYNCH_MSG) | ||
| 1222 | goto drop; | ||
| 1223 | |||
| 1224 | /* FAILOVER_MSG */ | ||
| 1225 | if (!tipc_msg_extract(skb, &iskb, &ipos)) { | ||
| 1226 | pr_warn_ratelimited("Cannot extract FAILOVER_MSG, defq: %d\n", | ||
| 1227 | skb_queue_len(fdefq)); | ||
| 1228 | return rc; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | do { | ||
| 1232 | seqno = buf_seqno(iskb); | ||
| 1233 | |||
| 1234 | if (unlikely(less(seqno, l->drop_point))) { | ||
| 1235 | kfree_skb(iskb); | ||
| 1236 | continue; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | if (unlikely(seqno != l->drop_point)) { | ||
| 1240 | __tipc_skb_queue_sorted(fdefq, seqno, iskb); | ||
| 1241 | continue; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | l->drop_point++; | ||
| 1245 | |||
| 1246 | if (!tipc_data_input(l, iskb, inputq)) | ||
| 1247 | rc |= tipc_link_input(l, iskb, inputq, reasm_skb); | ||
| 1248 | if (unlikely(rc)) | ||
| 1249 | break; | ||
| 1250 | } while ((iskb = __tipc_skb_dequeue(fdefq, l->drop_point))); | ||
| 1251 | |||
| 1252 | drop: | ||
| 1253 | kfree_skb(skb); | ||
| 1254 | return rc; | ||
| 1255 | } | ||
| 1256 | |||
| 1219 | static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked) | 1257 | static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked) |
| 1220 | { | 1258 | { |
| 1221 | bool released = false; | 1259 | bool released = false; |
| @@ -1457,8 +1495,11 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
| 1457 | /* Deliver packet */ | 1495 | /* Deliver packet */ |
| 1458 | l->rcv_nxt++; | 1496 | l->rcv_nxt++; |
| 1459 | l->stats.recv_pkts++; | 1497 | l->stats.recv_pkts++; |
| 1460 | if (!tipc_data_input(l, skb, l->inputq)) | 1498 | |
| 1461 | rc |= tipc_link_input(l, skb, l->inputq); | 1499 | if (unlikely(msg_user(hdr) == TUNNEL_PROTOCOL)) |
| 1500 | rc |= tipc_link_tnl_rcv(l, skb, l->inputq); | ||
| 1501 | else if (!tipc_data_input(l, skb, l->inputq)) | ||
| 1502 | rc |= tipc_link_input(l, skb, l->inputq, &l->reasm_buf); | ||
| 1462 | if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN)) | 1503 | if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN)) |
| 1463 | rc |= tipc_link_build_state_msg(l, xmitq); | 1504 | rc |= tipc_link_build_state_msg(l, xmitq); |
| 1464 | if (unlikely(rc & ~TIPC_LINK_SND_STATE)) | 1505 | if (unlikely(rc & ~TIPC_LINK_SND_STATE)) |
| @@ -1588,6 +1629,7 @@ void tipc_link_create_dummy_tnl_msg(struct tipc_link *l, | |||
| 1588 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | 1629 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, |
| 1589 | int mtyp, struct sk_buff_head *xmitq) | 1630 | int mtyp, struct sk_buff_head *xmitq) |
| 1590 | { | 1631 | { |
| 1632 | struct sk_buff_head *fdefq = &tnl->failover_deferdq; | ||
| 1591 | struct sk_buff *skb, *tnlskb; | 1633 | struct sk_buff *skb, *tnlskb; |
| 1592 | struct tipc_msg *hdr, tnlhdr; | 1634 | struct tipc_msg *hdr, tnlhdr; |
| 1593 | struct sk_buff_head *queue = &l->transmq; | 1635 | struct sk_buff_head *queue = &l->transmq; |
| @@ -1615,7 +1657,11 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | |||
| 1615 | /* Initialize reusable tunnel packet header */ | 1657 | /* Initialize reusable tunnel packet header */ |
| 1616 | tipc_msg_init(tipc_own_addr(l->net), &tnlhdr, TUNNEL_PROTOCOL, | 1658 | tipc_msg_init(tipc_own_addr(l->net), &tnlhdr, TUNNEL_PROTOCOL, |
| 1617 | mtyp, INT_H_SIZE, l->addr); | 1659 | mtyp, INT_H_SIZE, l->addr); |
| 1618 | pktcnt = skb_queue_len(&l->transmq) + skb_queue_len(&l->backlogq); | 1660 | if (mtyp == SYNCH_MSG) |
| 1661 | pktcnt = l->snd_nxt - buf_seqno(skb_peek(&l->transmq)); | ||
| 1662 | else | ||
| 1663 | pktcnt = skb_queue_len(&l->transmq); | ||
| 1664 | pktcnt += skb_queue_len(&l->backlogq); | ||
| 1619 | msg_set_msgcnt(&tnlhdr, pktcnt); | 1665 | msg_set_msgcnt(&tnlhdr, pktcnt); |
| 1620 | msg_set_bearer_id(&tnlhdr, l->peer_bearer_id); | 1666 | msg_set_bearer_id(&tnlhdr, l->peer_bearer_id); |
| 1621 | tnl: | 1667 | tnl: |
| @@ -1646,6 +1692,14 @@ tnl: | |||
| 1646 | tnl->drop_point = l->rcv_nxt; | 1692 | tnl->drop_point = l->rcv_nxt; |
| 1647 | tnl->failover_reasm_skb = l->reasm_buf; | 1693 | tnl->failover_reasm_skb = l->reasm_buf; |
| 1648 | l->reasm_buf = NULL; | 1694 | l->reasm_buf = NULL; |
| 1695 | |||
| 1696 | /* Failover the link's deferdq */ | ||
| 1697 | if (unlikely(!skb_queue_empty(fdefq))) { | ||
| 1698 | pr_warn("Link failover deferdq not empty: %d!\n", | ||
| 1699 | skb_queue_len(fdefq)); | ||
| 1700 | __skb_queue_purge(fdefq); | ||
| 1701 | } | ||
| 1702 | skb_queue_splice_init(&l->deferdq, fdefq); | ||
| 1649 | } | 1703 | } |
| 1650 | } | 1704 | } |
| 1651 | 1705 | ||
