Commit 83a18b8e authored by David S. Miller's avatar David S. Miller

Merge branch 'mptcp-next'

Mat Martineau says:

====================
mptcp: Miscellaneous changes for 5.18

Patch 1 has some minor cleanup in mptcp_write_options().

Patch 2 moves a rarely-needed branch to optimize mptcp_write_options().

Patch 3 adds a comment explaining which combinations of MPTCP option
headers are expected.

Patch 4 adds a pr_debug() for the MPTCP_RST option.

Patches 5-7 allow setting MPTCP_PM_ADDR_FLAG_FULLMESH with the "set
flags" netlink command. This allows changing the behavior of existing
path manager endpoints. The flag was previously only set at endpoint
creation time. Associated selftests also updated.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 156a532b 6a0653b9
...@@ -336,6 +336,8 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -336,6 +336,8 @@ static void mptcp_parse_option(const struct sk_buff *skb,
flags = *ptr++; flags = *ptr++;
mp_opt->reset_transient = flags & MPTCP_RST_TRANSIENT; mp_opt->reset_transient = flags & MPTCP_RST_TRANSIENT;
mp_opt->reset_reason = *ptr; mp_opt->reset_reason = *ptr;
pr_debug("MP_RST: transient=%u reason=%u",
mp_opt->reset_transient, mp_opt->reset_reason);
break; break;
case MPTCPOPT_MP_FAIL: case MPTCPOPT_MP_FAIL:
...@@ -1264,22 +1266,30 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext) ...@@ -1264,22 +1266,30 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext)
void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
struct mptcp_out_options *opts) struct mptcp_out_options *opts)
{ {
if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions)) { const struct sock *ssk = (const struct sock *)tp;
const struct sock *ssk = (const struct sock *)tp; struct mptcp_subflow_context *subflow;
struct mptcp_subflow_context *subflow;
/* Which options can be used together?
subflow = mptcp_subflow_ctx(ssk); *
subflow->send_mp_fail = 0; * X: mutually exclusive
* O: often used together
*ptr++ = mptcp_option(MPTCPOPT_MP_FAIL, * C: can be used together in some cases
TCPOLEN_MPTCP_FAIL, * P: could be used together but we prefer not to (optimisations)
0, 0); *
put_unaligned_be64(opts->fail_seq, ptr); * Opt: | MPC | MPJ | DSS | ADD | RM | PRIO | FAIL | FC |
ptr += 2; * ------|------|------|------|------|------|------|------|------|
} * MPC |------|------|------|------|------|------|------|------|
* MPJ | X |------|------|------|------|------|------|------|
/* DSS, MPC, MPJ, ADD_ADDR, FASTCLOSE and RST are mutually exclusive, * DSS | X | X |------|------|------|------|------|------|
* see mptcp_established_options*() * ADD | X | X | P |------|------|------|------|------|
* RM | C | C | C | P |------|------|------|------|
* PRIO | X | C | C | C | C |------|------|------|
* FAIL | X | X | C | X | X | X |------|------|
* FC | X | X | X | X | X | X | X |------|
* RST | X | X | X | X | X | X | O | O |
* ------|------|------|------|------|------|------|------|------|
*
* The same applies in mptcp_established_options() function.
*/ */
if (likely(OPTION_MPTCP_DSS & opts->suboptions)) { if (likely(OPTION_MPTCP_DSS & opts->suboptions)) {
struct mptcp_ext *mpext = &opts->ext_copy; struct mptcp_ext *mpext = &opts->ext_copy;
...@@ -1336,6 +1346,10 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, ...@@ -1336,6 +1346,10 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
} }
ptr += 1; ptr += 1;
} }
/* We might need to add MP_FAIL options in rare cases */
if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions))
goto mp_fail;
} else if (OPTIONS_MPTCP_MPC & opts->suboptions) { } else if (OPTIONS_MPTCP_MPC & opts->suboptions) {
u8 len, flag = MPTCP_CAP_HMAC_SHA256; u8 len, flag = MPTCP_CAP_HMAC_SHA256;
...@@ -1476,6 +1490,21 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, ...@@ -1476,6 +1490,21 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
put_unaligned_be64(opts->rcvr_key, ptr); put_unaligned_be64(opts->rcvr_key, ptr);
ptr += 2; ptr += 2;
if (OPTION_MPTCP_RST & opts->suboptions)
goto mp_rst;
return;
} else if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions)) {
mp_fail:
/* MP_FAIL is mutually exclusive with others except RST */
subflow = mptcp_subflow_ctx(ssk);
subflow->send_mp_fail = 0;
*ptr++ = mptcp_option(MPTCPOPT_MP_FAIL,
TCPOLEN_MPTCP_FAIL,
0, 0);
put_unaligned_be64(opts->fail_seq, ptr);
ptr += 2;
if (OPTION_MPTCP_RST & opts->suboptions) if (OPTION_MPTCP_RST & opts->suboptions)
goto mp_rst; goto mp_rst;
return; return;
...@@ -1489,9 +1518,6 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, ...@@ -1489,9 +1518,6 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
} }
if (OPTION_MPTCP_PRIO & opts->suboptions) { if (OPTION_MPTCP_PRIO & opts->suboptions) {
const struct sock *ssk = (const struct sock *)tp;
struct mptcp_subflow_context *subflow;
subflow = mptcp_subflow_ctx(ssk); subflow = mptcp_subflow_ctx(ssk);
subflow->send_mp_prio = 0; subflow->send_mp_prio = 0;
......
...@@ -1728,9 +1728,20 @@ mptcp_nl_cmd_get_limits(struct sk_buff *skb, struct genl_info *info) ...@@ -1728,9 +1728,20 @@ mptcp_nl_cmd_get_limits(struct sk_buff *skb, struct genl_info *info)
return -EMSGSIZE; return -EMSGSIZE;
} }
static int mptcp_nl_addr_backup(struct net *net, static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
struct mptcp_addr_info *addr, struct mptcp_addr_info *addr)
u8 bkup) {
struct mptcp_rm_list list = { .nr = 0 };
list.ids[list.nr++] = addr->id;
mptcp_pm_nl_rm_subflow_received(msk, &list);
mptcp_pm_create_subflow_or_signal_addr(msk);
}
static int mptcp_nl_set_flags(struct net *net,
struct mptcp_addr_info *addr,
u8 bkup, u8 changed)
{ {
long s_slot = 0, s_num = 0; long s_slot = 0, s_num = 0;
struct mptcp_sock *msk; struct mptcp_sock *msk;
...@@ -1744,7 +1755,10 @@ static int mptcp_nl_addr_backup(struct net *net, ...@@ -1744,7 +1755,10 @@ static int mptcp_nl_addr_backup(struct net *net,
lock_sock(sk); lock_sock(sk);
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, bkup); if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, bkup);
if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
mptcp_pm_nl_fullmesh(msk, addr);
spin_unlock_bh(&msk->pm.lock); spin_unlock_bh(&msk->pm.lock);
release_sock(sk); release_sock(sk);
...@@ -1761,6 +1775,8 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) ...@@ -1761,6 +1775,8 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry; struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry;
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR]; struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
struct pm_nl_pernet *pernet = genl_info_pm_nl(info); struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP |
MPTCP_PM_ADDR_FLAG_FULLMESH;
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
u8 bkup = 0, lookup_by_id = 0; u8 bkup = 0, lookup_by_id = 0;
int ret; int ret;
...@@ -1783,15 +1799,18 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) ...@@ -1783,15 +1799,18 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
spin_unlock_bh(&pernet->lock); spin_unlock_bh(&pernet->lock);
return -EINVAL; return -EINVAL;
} }
if ((addr.flags & MPTCP_PM_ADDR_FLAG_FULLMESH) &&
(entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) {
spin_unlock_bh(&pernet->lock);
return -EINVAL;
}
if (bkup) changed = (addr.flags ^ entry->flags) & mask;
entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP; entry->flags = (entry->flags & ~mask) | (addr.flags & mask);
else
entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
addr = *entry; addr = *entry;
spin_unlock_bh(&pernet->lock); spin_unlock_bh(&pernet->lock);
mptcp_nl_addr_backup(net, &addr.addr, bkup); mptcp_nl_set_flags(net, &addr.addr, bkup, changed);
return 0; return 0;
} }
......
...@@ -289,7 +289,7 @@ do_transfer() ...@@ -289,7 +289,7 @@ do_transfer()
addr_nr_ns1="$7" addr_nr_ns1="$7"
addr_nr_ns2="$8" addr_nr_ns2="$8"
speed="$9" speed="$9"
bkup="${10}" sflags="${10}"
port=$((10000+$TEST_COUNT)) port=$((10000+$TEST_COUNT))
TEST_COUNT=$((TEST_COUNT+1)) TEST_COUNT=$((TEST_COUNT+1))
...@@ -461,14 +461,13 @@ do_transfer() ...@@ -461,14 +461,13 @@ do_transfer()
fi fi
fi fi
if [ ! -z $bkup ]; then if [ ! -z $sflags ]; then
sleep 1 sleep 1
for netns in "$ns1" "$ns2"; do for netns in "$ns1" "$ns2"; do
dump=(`ip netns exec $netns ./pm_nl_ctl dump`) dump=(`ip netns exec $netns ./pm_nl_ctl dump`)
if [ ${#dump[@]} -gt 0 ]; then if [ ${#dump[@]} -gt 0 ]; then
addr=${dump[${#dump[@]} - 1]} addr=${dump[${#dump[@]} - 1]}
backup="ip netns exec $netns ./pm_nl_ctl set $addr flags $bkup" ip netns exec $netns ./pm_nl_ctl set $addr flags $sflags
$backup
fi fi
done done
fi fi
...@@ -545,7 +544,7 @@ run_tests() ...@@ -545,7 +544,7 @@ run_tests()
addr_nr_ns1="${5:-0}" addr_nr_ns1="${5:-0}"
addr_nr_ns2="${6:-0}" addr_nr_ns2="${6:-0}"
speed="${7:-fast}" speed="${7:-fast}"
bkup="${8:-""}" sflags="${8:-""}"
lret=0 lret=0
oldin="" oldin=""
...@@ -574,7 +573,7 @@ run_tests() ...@@ -574,7 +573,7 @@ run_tests()
fi fi
do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \ do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \
${test_linkfail} ${addr_nr_ns1} ${addr_nr_ns2} ${speed} ${bkup} ${test_linkfail} ${addr_nr_ns1} ${addr_nr_ns2} ${speed} ${sflags}
lret=$? lret=$?
} }
...@@ -1888,6 +1887,44 @@ fullmesh_tests() ...@@ -1888,6 +1887,44 @@ fullmesh_tests()
run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow
chk_join_nr "fullmesh test 1x2, limited" 4 4 4 chk_join_nr "fullmesh test 1x2, limited" 4 4 4
chk_add_nr 1 1 chk_add_nr 1 1
# set fullmesh flag
reset
ip netns exec $ns1 ./pm_nl_ctl limits 4 4
ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags subflow
ip netns exec $ns2 ./pm_nl_ctl limits 4 4
run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow fullmesh
chk_join_nr "set fullmesh flag test" 2 2 2
chk_rm_nr 0 1
# set nofullmesh flag
reset
ip netns exec $ns1 ./pm_nl_ctl limits 4 4
ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags subflow,fullmesh
ip netns exec $ns2 ./pm_nl_ctl limits 4 4
run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_1 slow nofullmesh
chk_join_nr "set nofullmesh flag test" 2 2 2
chk_rm_nr 0 1
# set backup,fullmesh flags
reset
ip netns exec $ns1 ./pm_nl_ctl limits 4 4
ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags subflow
ip netns exec $ns2 ./pm_nl_ctl limits 4 4
run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow backup,fullmesh
chk_join_nr "set backup,fullmesh flags test" 2 2 2
chk_prio_nr 0 1
chk_rm_nr 0 1
# set nobackup,nofullmesh flags
reset
ip netns exec $ns1 ./pm_nl_ctl limits 4 4
ip netns exec $ns2 ./pm_nl_ctl limits 4 4
ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow,backup,fullmesh
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup,nofullmesh
chk_join_nr "set nobackup,nofullmesh flags test" 2 2 2
chk_prio_nr 0 1
chk_rm_nr 0 1
} }
all_tests() all_tests()
......
...@@ -28,7 +28,7 @@ static void syntax(char *argv[]) ...@@ -28,7 +28,7 @@ static void syntax(char *argv[])
fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n"); fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
fprintf(stderr, "\tdel <id> [<ip>]\n"); fprintf(stderr, "\tdel <id> [<ip>]\n");
fprintf(stderr, "\tget <id>\n"); fprintf(stderr, "\tget <id>\n");
fprintf(stderr, "\tset <ip> [flags backup|nobackup]\n"); fprintf(stderr, "\tset <ip> [flags backup|nobackup|fullmesh|nofullmesh]\n");
fprintf(stderr, "\tflush\n"); fprintf(stderr, "\tflush\n");
fprintf(stderr, "\tdump\n"); fprintf(stderr, "\tdump\n");
fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n"); fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
...@@ -704,12 +704,14 @@ int set_flags(int fd, int pm_family, int argc, char *argv[]) ...@@ -704,12 +704,14 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
if (++arg >= argc) if (++arg >= argc)
error(1, 0, " missing flags value"); error(1, 0, " missing flags value");
/* do not support flag list yet */
for (str = argv[arg]; (tok = strtok(str, ",")); for (str = argv[arg]; (tok = strtok(str, ","));
str = NULL) { str = NULL) {
if (!strcmp(tok, "backup")) if (!strcmp(tok, "backup"))
flags |= MPTCP_PM_ADDR_FLAG_BACKUP; flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
else if (strcmp(tok, "nobackup")) else if (!strcmp(tok, "fullmesh"))
flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
else if (strcmp(tok, "nobackup") &&
strcmp(tok, "nofullmesh"))
error(1, errno, error(1, errno,
"unknown flag %s", argv[arg]); "unknown flag %s", argv[arg]);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment