Skip to content

Commit 1bff1e4

Browse files
Paolo Abenidavem330
Paolo Abeni
authored andcommitted
mptcp: optimize out option generation
Currently we have several protocol constraints on MPTCP options generation (e.g. MPC and MPJ subopt are mutually exclusive) and some additional ones required by our implementation (e.g. almost all ADD_ADDR variant are mutually exclusive with everything else). We can leverage the above to optimize the out option generation: we check DSS/MPC/MPJ presence in a mutually exclusive way, avoiding many unneeded conditionals in the common cases. Additionally extend the existing constraints on ADD_ADDR opt on all subvariants, so that it becomes fully mutually exclusive with the above and we can skip another conditional statement for the common case. This change is also needed by the next patch. Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d484dc2 commit 1bff1e4

File tree

2 files changed

+121
-109
lines changed

2 files changed

+121
-109
lines changed

net/mptcp/options.c

Lines changed: 120 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
592592
dss_size = map_size;
593593
if (skb && snd_data_fin_enable)
594594
mptcp_write_data_fin(subflow, skb, &opts->ext_copy);
595+
opts->suboptions = OPTION_MPTCP_DSS;
595596
ret = true;
596597
}
597598

@@ -615,6 +616,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
615616
opts->ext_copy.ack64 = 0;
616617
}
617618
opts->ext_copy.use_ack = 1;
619+
opts->suboptions = OPTION_MPTCP_DSS;
618620
WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk));
619621

620622
/* Add kind/length/subtype/flag overhead if mapping is not populated */
@@ -686,8 +688,13 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
686688
if (drop_other_suboptions) {
687689
pr_debug("drop other suboptions");
688690
opts->suboptions = 0;
689-
opts->ext_copy.use_ack = 0;
690-
opts->ext_copy.use_map = 0;
691+
692+
/* note that e.g. DSS could have written into the memory
693+
* aliased by ahmac, we must reset the field here
694+
* to avoid appending the hmac even for ADD_ADDR echo
695+
* options
696+
*/
697+
opts->ahmac = 0;
691698
*size -= opt_size;
692699
}
693700
opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
@@ -739,7 +746,12 @@ static bool mptcp_established_options_mp_prio(struct sock *sk,
739746
{
740747
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
741748

742-
if (!subflow->send_mp_prio)
749+
/* can't send MP_PRIO with MPC, as they share the same option space:
750+
* 'backup'. Also it makes no sense at all
751+
*/
752+
if (!subflow->send_mp_prio ||
753+
((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK |
754+
OPTION_MPTCP_MPC_ACK) & opts->suboptions))
743755
return false;
744756

745757
/* account for the trailing 'nop' option */
@@ -1198,8 +1210,74 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext)
11981210
void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
11991211
struct mptcp_out_options *opts)
12001212
{
1201-
if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK |
1202-
OPTION_MPTCP_MPC_ACK) & opts->suboptions) {
1213+
/* RST is mutually exclusive with everything else */
1214+
if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) {
1215+
*ptr++ = mptcp_option(MPTCPOPT_RST,
1216+
TCPOLEN_MPTCP_RST,
1217+
opts->reset_transient,
1218+
opts->reset_reason);
1219+
return;
1220+
}
1221+
1222+
/* DSS, MPC, MPJ and ADD_ADDR are mutually exclusive, see
1223+
* mptcp_established_options*()
1224+
*/
1225+
if (likely(OPTION_MPTCP_DSS & opts->suboptions)) {
1226+
struct mptcp_ext *mpext = &opts->ext_copy;
1227+
u8 len = TCPOLEN_MPTCP_DSS_BASE;
1228+
u8 flags = 0;
1229+
1230+
if (mpext->use_ack) {
1231+
flags = MPTCP_DSS_HAS_ACK;
1232+
if (mpext->ack64) {
1233+
len += TCPOLEN_MPTCP_DSS_ACK64;
1234+
flags |= MPTCP_DSS_ACK64;
1235+
} else {
1236+
len += TCPOLEN_MPTCP_DSS_ACK32;
1237+
}
1238+
}
1239+
1240+
if (mpext->use_map) {
1241+
len += TCPOLEN_MPTCP_DSS_MAP64;
1242+
1243+
/* Use only 64-bit mapping flags for now, add
1244+
* support for optional 32-bit mappings later.
1245+
*/
1246+
flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64;
1247+
if (mpext->data_fin)
1248+
flags |= MPTCP_DSS_DATA_FIN;
1249+
1250+
if (opts->csum_reqd)
1251+
len += TCPOLEN_MPTCP_DSS_CHECKSUM;
1252+
}
1253+
1254+
*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
1255+
1256+
if (mpext->use_ack) {
1257+
if (mpext->ack64) {
1258+
put_unaligned_be64(mpext->data_ack, ptr);
1259+
ptr += 2;
1260+
} else {
1261+
put_unaligned_be32(mpext->data_ack32, ptr);
1262+
ptr += 1;
1263+
}
1264+
}
1265+
1266+
if (mpext->use_map) {
1267+
put_unaligned_be64(mpext->data_seq, ptr);
1268+
ptr += 2;
1269+
put_unaligned_be32(mpext->subflow_seq, ptr);
1270+
ptr += 1;
1271+
if (opts->csum_reqd) {
1272+
put_unaligned_be32(mpext->data_len << 16 |
1273+
mptcp_make_csum(mpext), ptr);
1274+
} else {
1275+
put_unaligned_be32(mpext->data_len << 16 |
1276+
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
1277+
}
1278+
}
1279+
} else if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK |
1280+
OPTION_MPTCP_MPC_ACK) & opts->suboptions) {
12031281
u8 len, flag = MPTCP_CAP_HMAC_SHA256;
12041282

12051283
if (OPTION_MPTCP_MPC_SYN & opts->suboptions) {
@@ -1246,10 +1324,31 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
12461324
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
12471325
}
12481326
ptr += 1;
1249-
}
12501327

1251-
mp_capable_done:
1252-
if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) {
1328+
/* MPC is additionally mutually exclusive with MP_PRIO */
1329+
goto mp_capable_done;
1330+
} else if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
1331+
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
1332+
TCPOLEN_MPTCP_MPJ_SYN,
1333+
opts->backup, opts->join_id);
1334+
put_unaligned_be32(opts->token, ptr);
1335+
ptr += 1;
1336+
put_unaligned_be32(opts->nonce, ptr);
1337+
ptr += 1;
1338+
} else if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
1339+
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
1340+
TCPOLEN_MPTCP_MPJ_SYNACK,
1341+
opts->backup, opts->join_id);
1342+
put_unaligned_be64(opts->thmac, ptr);
1343+
ptr += 2;
1344+
put_unaligned_be32(opts->nonce, ptr);
1345+
ptr += 1;
1346+
} else if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) {
1347+
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
1348+
TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
1349+
memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
1350+
ptr += 5;
1351+
} else if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) {
12531352
u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE;
12541353
u8 echo = MPTCP_ADDR_ECHO;
12551354

@@ -1307,6 +1406,19 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
13071406
}
13081407
}
13091408

1409+
if (OPTION_MPTCP_PRIO & opts->suboptions) {
1410+
const struct sock *ssk = (const struct sock *)tp;
1411+
struct mptcp_subflow_context *subflow;
1412+
1413+
subflow = mptcp_subflow_ctx(ssk);
1414+
subflow->send_mp_prio = 0;
1415+
1416+
*ptr++ = mptcp_option(MPTCPOPT_MP_PRIO,
1417+
TCPOLEN_MPTCP_PRIO,
1418+
opts->backup, TCPOPT_NOP);
1419+
}
1420+
1421+
mp_capable_done:
13101422
if (OPTION_MPTCP_RM_ADDR & opts->suboptions) {
13111423
u8 i = 1;
13121424

@@ -1327,107 +1439,6 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
13271439
}
13281440
}
13291441

1330-
if (OPTION_MPTCP_PRIO & opts->suboptions) {
1331-
const struct sock *ssk = (const struct sock *)tp;
1332-
struct mptcp_subflow_context *subflow;
1333-
1334-
subflow = mptcp_subflow_ctx(ssk);
1335-
subflow->send_mp_prio = 0;
1336-
1337-
*ptr++ = mptcp_option(MPTCPOPT_MP_PRIO,
1338-
TCPOLEN_MPTCP_PRIO,
1339-
opts->backup, TCPOPT_NOP);
1340-
}
1341-
1342-
if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
1343-
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
1344-
TCPOLEN_MPTCP_MPJ_SYN,
1345-
opts->backup, opts->join_id);
1346-
put_unaligned_be32(opts->token, ptr);
1347-
ptr += 1;
1348-
put_unaligned_be32(opts->nonce, ptr);
1349-
ptr += 1;
1350-
}
1351-
1352-
if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
1353-
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
1354-
TCPOLEN_MPTCP_MPJ_SYNACK,
1355-
opts->backup, opts->join_id);
1356-
put_unaligned_be64(opts->thmac, ptr);
1357-
ptr += 2;
1358-
put_unaligned_be32(opts->nonce, ptr);
1359-
ptr += 1;
1360-
}
1361-
1362-
if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) {
1363-
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
1364-
TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
1365-
memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
1366-
ptr += 5;
1367-
}
1368-
1369-
if (OPTION_MPTCP_RST & opts->suboptions)
1370-
*ptr++ = mptcp_option(MPTCPOPT_RST,
1371-
TCPOLEN_MPTCP_RST,
1372-
opts->reset_transient,
1373-
opts->reset_reason);
1374-
1375-
if (opts->ext_copy.use_ack || opts->ext_copy.use_map) {
1376-
struct mptcp_ext *mpext = &opts->ext_copy;
1377-
u8 len = TCPOLEN_MPTCP_DSS_BASE;
1378-
u8 flags = 0;
1379-
1380-
if (mpext->use_ack) {
1381-
flags = MPTCP_DSS_HAS_ACK;
1382-
if (mpext->ack64) {
1383-
len += TCPOLEN_MPTCP_DSS_ACK64;
1384-
flags |= MPTCP_DSS_ACK64;
1385-
} else {
1386-
len += TCPOLEN_MPTCP_DSS_ACK32;
1387-
}
1388-
}
1389-
1390-
if (mpext->use_map) {
1391-
len += TCPOLEN_MPTCP_DSS_MAP64;
1392-
1393-
/* Use only 64-bit mapping flags for now, add
1394-
* support for optional 32-bit mappings later.
1395-
*/
1396-
flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64;
1397-
if (mpext->data_fin)
1398-
flags |= MPTCP_DSS_DATA_FIN;
1399-
1400-
if (opts->csum_reqd)
1401-
len += TCPOLEN_MPTCP_DSS_CHECKSUM;
1402-
}
1403-
1404-
*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
1405-
1406-
if (mpext->use_ack) {
1407-
if (mpext->ack64) {
1408-
put_unaligned_be64(mpext->data_ack, ptr);
1409-
ptr += 2;
1410-
} else {
1411-
put_unaligned_be32(mpext->data_ack32, ptr);
1412-
ptr += 1;
1413-
}
1414-
}
1415-
1416-
if (mpext->use_map) {
1417-
put_unaligned_be64(mpext->data_seq, ptr);
1418-
ptr += 2;
1419-
put_unaligned_be32(mpext->subflow_seq, ptr);
1420-
ptr += 1;
1421-
if (opts->csum_reqd) {
1422-
put_unaligned_be32(mpext->data_len << 16 |
1423-
mptcp_make_csum(mpext), ptr);
1424-
} else {
1425-
put_unaligned_be32(mpext->data_len << 16 |
1426-
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
1427-
}
1428-
}
1429-
}
1430-
14311442
if (tp)
14321443
mptcp_set_rwin(tp);
14331444
}

net/mptcp/protocol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define OPTION_MPTCP_FASTCLOSE BIT(8)
2727
#define OPTION_MPTCP_PRIO BIT(9)
2828
#define OPTION_MPTCP_RST BIT(10)
29+
#define OPTION_MPTCP_DSS BIT(11)
2930

3031
/* MPTCP option subtypes */
3132
#define MPTCPOPT_MP_CAPABLE 0

0 commit comments

Comments
 (0)