Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfrm: iptfs: handle reordering of received packets

Handle the receipt of the outer tunnel packets out-of-order. Pointers to
the out-of-order packets are saved in a window (array) awaiting needed
prior packets. When the required prior packets are received the now
in-order packets are then passed on to the regular packet receive code.
A timer is used to consider missing earlier packet as lost so the
algorithm will advance.

Signed-off-by: Christian Hopps <chopps@labn.net>
Tested-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

authored by

Christian Hopps and committed by
Steffen Klassert
6be02e3e 5f2b6a90

+484 -13
+484 -13
net/xfrm/xfrm_iptfs.c
··· 39 39 */ 40 40 #define IPTFS_DEFAULT_DROP_TIME_USECS 1000000 41 41 42 + /** 43 + * define IPTFS_DEFAULT_REORDER_WINDOW - default reorder window size 44 + * 45 + * The default IPTFS reorder window size. The reorder window size dictates the 46 + * maximum number of IPTFS tunnel packets in a sequence that may arrive out of 47 + * order. 48 + * 49 + * Default 3. (tcp folks suggested) 50 + */ 51 + #define IPTFS_DEFAULT_REORDER_WINDOW 3 52 + 42 53 /* ------------------------------------------------ */ 43 54 /* IPTFS default SA values (tunnel ingress/dir-out) */ 44 55 /* ------------------------------------------------ */ ··· 106 95 * @max_queue_size: The maximum number of octets allowed to be queued to be sent 107 96 * over the IPTFS SA. The queue size is measured as the size of all the 108 97 * packets enqueued. 98 + * @reorder_win_size: the number slots in the reorder window, thus the number of 99 + * packets that may arrive out of order. 109 100 * @dont_frag: true to inhibit fragmenting across IPTFS outer packets. 110 101 */ 111 102 struct xfrm_iptfs_config { 112 103 u32 pkt_size; /* outer_packet_size or 0 */ 113 104 u32 max_queue_size; /* octets */ 105 + u16 reorder_win_size; 114 106 u8 dont_frag : 1; 107 + }; 108 + 109 + struct skb_wseq { 110 + struct sk_buff *skb; 111 + u64 drop_time; 115 112 }; 116 113 117 114 /** ··· 132 113 * @init_delay_ns: nanoseconds to wait to send initial IPTFS packet. 133 114 * @iptfs_timer: output timer. 134 115 * @payload_mtu: max payload size. 116 + * @w_seq_set: true after first seq received. 117 + * @w_wantseq: waiting for this seq number as next to process (in order). 118 + * @w_saved: the saved buf array (reorder window). 119 + * @w_savedlen: the saved len (not size). 135 120 * @drop_lock: lock to protect reorder queue. 136 121 * @drop_timer: timer for considering next packet lost. 137 122 * @drop_time_ns: timer intervan in nanoseconds. ··· 157 134 struct hrtimer iptfs_timer; /* output timer */ 158 135 u32 payload_mtu; /* max payload size */ 159 136 160 - /* Tunnel egress */ 137 + /* Tunnel input reordering */ 138 + bool w_seq_set; /* true after first seq received */ 139 + u64 w_wantseq; /* expected next sequence */ 140 + struct skb_wseq *w_saved; /* the saved buf array */ 141 + u32 w_savedlen; /* the saved len (not size) */ 161 142 spinlock_t drop_lock; 162 143 struct hrtimer drop_timer; 163 144 u64 drop_time_ns; 164 145 165 - /* Tunnel egress reassembly */ 146 + /* Tunnel input reassembly */ 166 147 struct sk_buff *ra_newskb; /* new pkt being reassembled */ 167 148 u64 ra_wantseq; /* expected next sequence */ 168 149 u8 ra_runt[6]; /* last pkt bytes from last skb */ ··· 1150 1123 } 1151 1124 1152 1125 /** 1153 - * iptfs_input() - handle receipt of iptfs payload 1126 + * iptfs_input_ordered() - handle next in order IPTFS payload. 1154 1127 * @x: xfrm state 1155 - * @skb: the packet 1128 + * @skb: current packet 1156 1129 * 1157 1130 * Process the IPTFS payload in `skb` and consume it afterwards. 1158 - * 1159 - * Returns 0. 1160 1131 */ 1161 - static int iptfs_input(struct xfrm_state *x, struct sk_buff *skb) 1132 + static void iptfs_input_ordered(struct xfrm_state *x, struct sk_buff *skb) 1162 1133 { 1163 1134 struct ip_iptfs_cc_hdr iptcch; 1164 1135 struct skb_seq_state skbseq; ··· 1231 1206 skb_abort_seq_read(&skbseq); 1232 1207 kfree_skb(skb); 1233 1208 } 1209 + } 1234 1210 1235 - /* We always have dealt with the input SKB, either we are re-using it, 1236 - * or we have freed it. Return EINPROGRESS so that xfrm_input stops 1237 - * processing it. 1211 + /* ------------------------------- */ 1212 + /* Input (Egress) Re-ordering Code */ 1213 + /* ------------------------------- */ 1214 + 1215 + static void __vec_shift(struct xfrm_iptfs_data *xtfs, u32 shift) 1216 + { 1217 + u32 savedlen = xtfs->w_savedlen; 1218 + 1219 + if (shift > savedlen) 1220 + shift = savedlen; 1221 + if (shift != savedlen) 1222 + memcpy(xtfs->w_saved, xtfs->w_saved + shift, 1223 + (savedlen - shift) * sizeof(*xtfs->w_saved)); 1224 + memset(xtfs->w_saved + savedlen - shift, 0, 1225 + shift * sizeof(*xtfs->w_saved)); 1226 + xtfs->w_savedlen -= shift; 1227 + } 1228 + 1229 + static void __reorder_past(struct xfrm_iptfs_data *xtfs, struct sk_buff *inskb, 1230 + struct list_head *freelist) 1231 + { 1232 + list_add_tail(&inskb->list, freelist); 1233 + } 1234 + 1235 + static u32 __reorder_drop(struct xfrm_iptfs_data *xtfs, struct list_head *list) 1236 + 1237 + { 1238 + struct skb_wseq *s, *se; 1239 + const u32 savedlen = xtfs->w_savedlen; 1240 + time64_t now = ktime_get_raw_fast_ns(); 1241 + u32 count = 0; 1242 + u32 scount = 0; 1243 + 1244 + if (xtfs->w_saved[0].drop_time > now) 1245 + goto set_timer; 1246 + 1247 + ++xtfs->w_wantseq; 1248 + 1249 + /* Keep flushing packets until we reach a drop time greater than now. */ 1250 + s = xtfs->w_saved; 1251 + se = s + savedlen; 1252 + do { 1253 + /* Walking past empty slots until we reach a packet */ 1254 + for (; s < se && !s->skb; s++) { 1255 + if (s->drop_time > now) 1256 + goto outerdone; 1257 + } 1258 + /* Sending packets until we hit another empty slot. */ 1259 + for (; s < se && s->skb; scount++, s++) 1260 + list_add_tail(&s->skb->list, list); 1261 + } while (s < se); 1262 + outerdone: 1263 + 1264 + count = s - xtfs->w_saved; 1265 + if (count) { 1266 + xtfs->w_wantseq += count; 1267 + 1268 + /* Shift handled slots plus final empty slot into slot 0. */ 1269 + __vec_shift(xtfs, count); 1270 + } 1271 + 1272 + if (xtfs->w_savedlen) { 1273 + set_timer: 1274 + /* Drifting is OK */ 1275 + hrtimer_start(&xtfs->drop_timer, 1276 + xtfs->w_saved[0].drop_time - now, 1277 + IPTFS_HRTIMER_MODE); 1278 + } 1279 + return scount; 1280 + } 1281 + 1282 + static void __reorder_this(struct xfrm_iptfs_data *xtfs, struct sk_buff *inskb, 1283 + struct list_head *list) 1284 + { 1285 + struct skb_wseq *s, *se; 1286 + const u32 savedlen = xtfs->w_savedlen; 1287 + u32 count = 0; 1288 + 1289 + /* Got what we wanted. */ 1290 + list_add_tail(&inskb->list, list); 1291 + ++xtfs->w_wantseq; 1292 + if (!savedlen) 1293 + return; 1294 + 1295 + /* Flush remaining consecutive packets. */ 1296 + 1297 + /* Keep sending until we hit another missed pkt. */ 1298 + for (s = xtfs->w_saved, se = s + savedlen; s < se && s->skb; s++) 1299 + list_add_tail(&s->skb->list, list); 1300 + count = s - xtfs->w_saved; 1301 + if (count) 1302 + xtfs->w_wantseq += count; 1303 + 1304 + /* Shift handled slots plus final empty slot into slot 0. */ 1305 + __vec_shift(xtfs, count + 1); 1306 + } 1307 + 1308 + /* Set the slot's drop time and all the empty slots below it until reaching a 1309 + * filled slot which will already be set. 1310 + */ 1311 + static void iptfs_set_window_drop_times(struct xfrm_iptfs_data *xtfs, int index) 1312 + { 1313 + const u32 savedlen = xtfs->w_savedlen; 1314 + struct skb_wseq *s = xtfs->w_saved; 1315 + time64_t drop_time; 1316 + 1317 + assert_spin_locked(&xtfs->drop_lock); 1318 + 1319 + if (savedlen > index + 1) { 1320 + /* we are below another, our drop time and the timer are already set */ 1321 + return; 1322 + } 1323 + /* we are the most future so get a new drop time. */ 1324 + drop_time = ktime_get_raw_fast_ns(); 1325 + drop_time += xtfs->drop_time_ns; 1326 + 1327 + /* Walk back through the array setting drop times as we go */ 1328 + s[index].drop_time = drop_time; 1329 + while (index-- > 0 && !s[index].skb) 1330 + s[index].drop_time = drop_time; 1331 + 1332 + /* If we walked all the way back, schedule the drop timer if needed */ 1333 + if (index == -1 && !hrtimer_is_queued(&xtfs->drop_timer)) 1334 + hrtimer_start(&xtfs->drop_timer, xtfs->drop_time_ns, 1335 + IPTFS_HRTIMER_MODE); 1336 + } 1337 + 1338 + static void __reorder_future_fits(struct xfrm_iptfs_data *xtfs, 1339 + struct sk_buff *inskb, 1340 + struct list_head *freelist) 1341 + { 1342 + const u64 inseq = __esp_seq(inskb); 1343 + const u64 wantseq = xtfs->w_wantseq; 1344 + const u64 distance = inseq - wantseq; 1345 + const u32 savedlen = xtfs->w_savedlen; 1346 + const u32 index = distance - 1; 1347 + 1348 + /* Handle future sequence number received which fits in the window. 1349 + * 1350 + * We know we don't have the seq we want so we won't be able to flush 1351 + * anything. 1238 1352 */ 1239 - return -EINPROGRESS; 1353 + 1354 + /* slot count is 4, saved size is 3 savedlen is 2 1355 + * 1356 + * "window boundary" is based on the fixed window size 1357 + * distance is also slot number 1358 + * index is an array index (i.e., - 1 of slot) 1359 + * : : - implicit NULL after array len 1360 + * 1361 + * +--------- used length (savedlen == 2) 1362 + * | +----- array size (nslots - 1 == 3) 1363 + * | | + window boundary (nslots == 4) 1364 + * V V | V 1365 + * | 1366 + * 0 1 2 3 | slot number 1367 + * --- 0 1 2 | array index 1368 + * [-] [b] : :| array 1369 + * 1370 + * "2" "3" "4" *5*| seq numbers 1371 + * 1372 + * We receive seq number 5 1373 + * distance == 3 [inseq(5) - w_wantseq(2)] 1374 + * index == 2 [distance(6) - 1] 1375 + */ 1376 + 1377 + if (xtfs->w_saved[index].skb) { 1378 + /* a dup of a future */ 1379 + list_add_tail(&inskb->list, freelist); 1380 + return; 1381 + } 1382 + 1383 + xtfs->w_saved[index].skb = inskb; 1384 + xtfs->w_savedlen = max(savedlen, index + 1); 1385 + iptfs_set_window_drop_times(xtfs, index); 1386 + } 1387 + 1388 + static void __reorder_future_shifts(struct xfrm_iptfs_data *xtfs, 1389 + struct sk_buff *inskb, 1390 + struct list_head *list) 1391 + { 1392 + const u32 nslots = xtfs->cfg.reorder_win_size + 1; 1393 + const u64 inseq = __esp_seq(inskb); 1394 + u32 savedlen = xtfs->w_savedlen; 1395 + u64 wantseq = xtfs->w_wantseq; 1396 + struct skb_wseq *wnext; 1397 + struct sk_buff *slot0; 1398 + u32 beyond, shifting, slot; 1399 + u64 distance; 1400 + 1401 + /* Handle future sequence number received. 1402 + * 1403 + * IMPORTANT: we are at least advancing w_wantseq (i.e., wantseq) by 1 1404 + * b/c we are beyond the window boundary. 1405 + * 1406 + * We know we don't have the wantseq so that counts as a drop. 1407 + */ 1408 + 1409 + /* example: slot count is 4, array size is 3 savedlen is 2, slot 0 is 1410 + * the missing sequence number. 1411 + * 1412 + * the final slot at savedlen (index savedlen - 1) is always occupied. 1413 + * 1414 + * beyond is "beyond array size" not savedlen. 1415 + * 1416 + * +--------- array length (savedlen == 2) 1417 + * | +----- array size (nslots - 1 == 3) 1418 + * | | +- window boundary (nslots == 4) 1419 + * V V | 1420 + * | 1421 + * 0 1 2 3 | slot number 1422 + * --- 0 1 2 | array index 1423 + * [b] [c] : :| array 1424 + * | 1425 + * "2" "3" "4" "5"|*6* seq numbers 1426 + * 1427 + * We receive seq number 6 1428 + * distance == 4 [inseq(6) - w_wantseq(2)] 1429 + * newslot == distance 1430 + * index == 3 [distance(4) - 1] 1431 + * beyond == 1 [newslot(4) - lastslot((nslots(4) - 1))] 1432 + * shifting == 1 [min(savedlen(2), beyond(1)] 1433 + * slot0_skb == [b], and should match w_wantseq 1434 + * 1435 + * +--- window boundary (nslots == 4) 1436 + * 0 1 2 3 | 4 slot number 1437 + * --- 0 1 2 | 3 array index 1438 + * [b] : : : :| array 1439 + * "2" "3" "4" "5" *6* seq numbers 1440 + * 1441 + * We receive seq number 6 1442 + * distance == 4 [inseq(6) - w_wantseq(2)] 1443 + * newslot == distance 1444 + * index == 3 [distance(4) - 1] 1445 + * beyond == 1 [newslot(4) - lastslot((nslots(4) - 1))] 1446 + * shifting == 1 [min(savedlen(1), beyond(1)] 1447 + * slot0_skb == [b] and should match w_wantseq 1448 + * 1449 + * +-- window boundary (nslots == 4) 1450 + * 0 1 2 3 | 4 5 6 slot number 1451 + * --- 0 1 2 | 3 4 5 array index 1452 + * [-] [c] : :| array 1453 + * "2" "3" "4" "5" "6" "7" *8* seq numbers 1454 + * 1455 + * savedlen = 2, beyond = 3 1456 + * iter 1: slot0 == NULL, missed++, lastdrop = 2 (2+1-1), slot0 = [-] 1457 + * iter 2: slot0 == NULL, missed++, lastdrop = 3 (2+2-1), slot0 = [c] 1458 + * 2 < 3, extra = 1 (3-2), missed += extra, lastdrop = 4 (2+2+1-1) 1459 + * 1460 + * We receive seq number 8 1461 + * distance == 6 [inseq(8) - w_wantseq(2)] 1462 + * newslot == distance 1463 + * index == 5 [distance(6) - 1] 1464 + * beyond == 3 [newslot(6) - lastslot((nslots(4) - 1))] 1465 + * shifting == 2 [min(savedlen(2), beyond(3)] 1466 + * 1467 + * slot0_skb == NULL changed from [b] when "savedlen < beyond" is true. 1468 + */ 1469 + 1470 + /* Now send any packets that are being shifted out of saved, and account 1471 + * for missing packets that are exiting the window as we shift it. 1472 + */ 1473 + 1474 + distance = inseq - wantseq; 1475 + beyond = distance - (nslots - 1); 1476 + 1477 + /* If savedlen > beyond we are shifting some, else all. */ 1478 + shifting = min(savedlen, beyond); 1479 + 1480 + /* slot0 is the buf that just shifted out and into slot0 */ 1481 + slot0 = NULL; 1482 + wnext = xtfs->w_saved; 1483 + for (slot = 1; slot <= shifting; slot++, wnext++) { 1484 + /* handle what was in slot0 before we occupy it */ 1485 + if (slot0) 1486 + list_add_tail(&slot0->list, list); 1487 + slot0 = wnext->skb; 1488 + wnext->skb = NULL; 1489 + } 1490 + 1491 + /* slot0 is now either NULL (in which case it's what we now are waiting 1492 + * for, or a buf in which case we need to handle it like we received it; 1493 + * however, we may be advancing past that buffer as well.. 1494 + */ 1495 + 1496 + /* Handle case where we need to shift more than we had saved, slot0 will 1497 + * be NULL iff savedlen is 0, otherwise slot0 will always be 1498 + * non-NULL b/c we shifted the final element, which is always set if 1499 + * there is any saved, into slot0. 1500 + */ 1501 + if (savedlen < beyond) { 1502 + if (savedlen != 0) 1503 + list_add_tail(&slot0->list, list); 1504 + slot0 = NULL; 1505 + /* slot0 has had an empty slot pushed into it */ 1506 + } 1507 + 1508 + /* Remove the entries */ 1509 + __vec_shift(xtfs, beyond); 1510 + 1511 + /* Advance want seq */ 1512 + xtfs->w_wantseq += beyond; 1513 + 1514 + /* Process drops here when implementing congestion control */ 1515 + 1516 + /* We've shifted. plug the packet in at the end. */ 1517 + xtfs->w_savedlen = nslots - 1; 1518 + xtfs->w_saved[xtfs->w_savedlen - 1].skb = inskb; 1519 + iptfs_set_window_drop_times(xtfs, xtfs->w_savedlen - 1); 1520 + 1521 + /* if we don't have a slot0 then we must wait for it */ 1522 + if (!slot0) 1523 + return; 1524 + 1525 + /* If slot0, seq must match new want seq */ 1526 + 1527 + /* slot0 is valid, treat like we received expected. */ 1528 + __reorder_this(xtfs, slot0, list); 1529 + } 1530 + 1531 + /* Receive a new packet into the reorder window. Return a list of ordered 1532 + * packets from the window. 1533 + */ 1534 + static void iptfs_input_reorder(struct xfrm_iptfs_data *xtfs, 1535 + struct sk_buff *inskb, struct list_head *list, 1536 + struct list_head *freelist) 1537 + { 1538 + const u32 nslots = xtfs->cfg.reorder_win_size + 1; 1539 + u64 inseq = __esp_seq(inskb); 1540 + u64 wantseq; 1541 + 1542 + assert_spin_locked(&xtfs->drop_lock); 1543 + 1544 + if (unlikely(!xtfs->w_seq_set)) { 1545 + xtfs->w_seq_set = true; 1546 + xtfs->w_wantseq = inseq; 1547 + } 1548 + wantseq = xtfs->w_wantseq; 1549 + 1550 + if (likely(inseq == wantseq)) 1551 + __reorder_this(xtfs, inskb, list); 1552 + else if (inseq < wantseq) 1553 + __reorder_past(xtfs, inskb, freelist); 1554 + else if ((inseq - wantseq) < nslots) 1555 + __reorder_future_fits(xtfs, inskb, freelist); 1556 + else 1557 + __reorder_future_shifts(xtfs, inskb, list); 1240 1558 } 1241 1559 1242 1560 /** ··· 1606 1238 */ 1607 1239 static enum hrtimer_restart iptfs_drop_timer(struct hrtimer *me) 1608 1240 { 1241 + struct sk_buff *skb, *next; 1242 + struct list_head list; 1609 1243 struct xfrm_iptfs_data *xtfs; 1610 - struct sk_buff *skb; 1244 + struct xfrm_state *x; 1245 + u32 count; 1611 1246 1612 1247 xtfs = container_of(me, typeof(*xtfs), drop_timer); 1248 + x = xtfs->x; 1249 + 1250 + INIT_LIST_HEAD(&list); 1251 + 1252 + spin_lock(&xtfs->drop_lock); 1613 1253 1614 1254 /* Drop any in progress packet */ 1615 - spin_lock(&xtfs->drop_lock); 1616 1255 skb = xtfs->ra_newskb; 1617 1256 xtfs->ra_newskb = NULL; 1257 + 1258 + /* Now drop as many packets as we should from the reordering window 1259 + * saved array 1260 + */ 1261 + count = xtfs->w_savedlen ? __reorder_drop(xtfs, &list) : 0; 1262 + 1618 1263 spin_unlock(&xtfs->drop_lock); 1619 1264 1620 1265 if (skb) 1621 1266 kfree_skb_reason(skb, SKB_DROP_REASON_FRAG_REASM_TIMEOUT); 1622 1267 1268 + if (count) { 1269 + list_for_each_entry_safe(skb, next, &list, list) { 1270 + skb_list_del_init(skb); 1271 + iptfs_input_ordered(x, skb); 1272 + } 1273 + } 1274 + 1623 1275 return HRTIMER_NORESTART; 1276 + } 1277 + 1278 + /** 1279 + * iptfs_input() - handle receipt of iptfs payload 1280 + * @x: xfrm state 1281 + * @skb: the packet 1282 + * 1283 + * We have an IPTFS payload order it if needed, then process newly in order 1284 + * packets. 1285 + * 1286 + * Return: -EINPROGRESS to inform xfrm_input to stop processing the skb. 1287 + */ 1288 + static int iptfs_input(struct xfrm_state *x, struct sk_buff *skb) 1289 + { 1290 + struct list_head freelist, list; 1291 + struct xfrm_iptfs_data *xtfs = x->mode_data; 1292 + struct sk_buff *next; 1293 + 1294 + /* Fast path for no reorder window. */ 1295 + if (xtfs->cfg.reorder_win_size == 0) { 1296 + iptfs_input_ordered(x, skb); 1297 + goto done; 1298 + } 1299 + 1300 + /* Fetch list of in-order packets from the reordering window as well as 1301 + * a list of buffers we need to now free. 1302 + */ 1303 + INIT_LIST_HEAD(&list); 1304 + INIT_LIST_HEAD(&freelist); 1305 + 1306 + spin_lock(&xtfs->drop_lock); 1307 + iptfs_input_reorder(xtfs, skb, &list, &freelist); 1308 + spin_unlock(&xtfs->drop_lock); 1309 + 1310 + list_for_each_entry_safe(skb, next, &list, list) { 1311 + skb_list_del_init(skb); 1312 + iptfs_input_ordered(x, skb); 1313 + } 1314 + 1315 + list_for_each_entry_safe(skb, next, &freelist, list) { 1316 + skb_list_del_init(skb); 1317 + kfree_skb(skb); 1318 + } 1319 + done: 1320 + /* We always have dealt with the input SKB, either we are re-using it, 1321 + * or we have freed it. Return EINPROGRESS so that xfrm_input stops 1322 + * processing it. 1323 + */ 1324 + return -EINPROGRESS; 1624 1325 } 1625 1326 1626 1327 /* ================================= */ ··· 2446 2009 2447 2010 xc = &xtfs->cfg; 2448 2011 xc->max_queue_size = IPTFS_DEFAULT_MAX_QUEUE_SIZE; 2012 + xc->reorder_win_size = IPTFS_DEFAULT_REORDER_WINDOW; 2449 2013 xtfs->drop_time_ns = IPTFS_DEFAULT_DROP_TIME_USECS * NSECS_IN_USEC; 2450 2014 xtfs->init_delay_ns = IPTFS_DEFAULT_INIT_DELAY_USECS * NSECS_IN_USEC; 2451 2015 2452 2016 if (attrs[XFRMA_IPTFS_DONT_FRAG]) 2453 2017 xc->dont_frag = true; 2018 + if (attrs[XFRMA_IPTFS_REORDER_WINDOW]) 2019 + xc->reorder_win_size = 2020 + nla_get_u16(attrs[XFRMA_IPTFS_REORDER_WINDOW]); 2021 + /* saved array is for saving 1..N seq nums from wantseq */ 2022 + if (xc->reorder_win_size) { 2023 + xtfs->w_saved = kcalloc(xc->reorder_win_size, 2024 + sizeof(*xtfs->w_saved), GFP_KERNEL); 2025 + if (!xtfs->w_saved) { 2026 + NL_SET_ERR_MSG(extack, "Cannot alloc reorder window"); 2027 + return -ENOMEM; 2028 + } 2029 + } 2454 2030 if (attrs[XFRMA_IPTFS_PKT_SIZE]) { 2455 2031 xc->pkt_size = nla_get_u32(attrs[XFRMA_IPTFS_PKT_SIZE]); 2456 2032 if (!xc->pkt_size) { ··· 2501 2051 2502 2052 if (x->dir == XFRM_SA_DIR_IN) { 2503 2053 l += nla_total_size(sizeof(u32)); /* drop time usec */ 2054 + l += nla_total_size(sizeof(xc->reorder_win_size)); 2504 2055 } else { 2505 2056 if (xc->dont_frag) 2506 2057 l += nla_total_size(0); /* dont-frag flag */ ··· 2524 2073 q = xtfs->drop_time_ns; 2525 2074 do_div(q, NSECS_IN_USEC); 2526 2075 ret = nla_put_u32(skb, XFRMA_IPTFS_DROP_TIME, q); 2076 + if (ret) 2077 + return ret; 2078 + 2079 + ret = nla_put_u16(skb, XFRMA_IPTFS_REORDER_WINDOW, 2080 + xc->reorder_win_size); 2527 2081 } else { 2528 2082 if (xc->dont_frag) { 2529 2083 ret = nla_put_flag(skb, XFRMA_IPTFS_DONT_FRAG); ··· 2590 2134 xtfs->x = x; 2591 2135 2592 2136 xtfs->ra_newskb = NULL; 2137 + if (xtfs->cfg.reorder_win_size) { 2138 + xtfs->w_saved = kcalloc(xtfs->cfg.reorder_win_size, 2139 + sizeof(*xtfs->w_saved), GFP_KERNEL); 2140 + if (!xtfs->w_saved) { 2141 + kfree_sensitive(xtfs); 2142 + return -ENOMEM; 2143 + } 2144 + } 2593 2145 2594 2146 return 0; 2595 2147 } ··· 2624 2160 { 2625 2161 struct xfrm_iptfs_data *xtfs = x->mode_data; 2626 2162 struct sk_buff_head list; 2163 + struct skb_wseq *s, *se; 2627 2164 struct sk_buff *skb; 2628 2165 2629 2166 if (!xtfs) ··· 2646 2181 if (xtfs->ra_newskb) 2647 2182 kfree_skb(xtfs->ra_newskb); 2648 2183 2184 + for (s = xtfs->w_saved, se = s + xtfs->w_savedlen; s < se; s++) { 2185 + if (s->skb) 2186 + kfree_skb(s->skb); 2187 + } 2188 + 2189 + kfree_sensitive(xtfs->w_saved); 2649 2190 kfree_sensitive(xtfs); 2650 2191 2651 2192 module_put(x->mode_cbs->owner);