mirror of
https://github.com/torvalds/linux.git
synced 2024-09-20 06:53:04 +00:00
mptcp: pm: reduce entries iterations on connect
__mptcp_subflow_connect() is currently called from the path-managers,
which have all the required information to create subflows. No need to
call the PM again to re-iterate over the list of entries with RCU lock
to get more info.
Instead, it is possible to pass a mptcp_pm_addr_entry structure, instead
of a mptcp_addr_info one. The former contains the ifindex and the flags
that are required when creating the new subflow.
This is a partial revert of commit ee285257a9
("mptcp: drop flags and
ifindex arguments").
While at it, the local ID can also be set if it is known and 0, to avoid
having to set it in the 'rebuild_header' hook, which will cause a new
iteration of the endpoint entries.
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240902-net-next-mptcp-mib-mpjtx-misc-v1-2-d3e0f3773b90@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
7bcf4d8022
commit
b83fbca1b4
|
@ -430,17 +430,6 @@ bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc)
|
|||
return mptcp_pm_nl_is_backup(msk, &skc_local);
|
||||
}
|
||||
|
||||
int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id,
|
||||
u8 *flags, int *ifindex)
|
||||
{
|
||||
*flags = 0;
|
||||
*ifindex = 0;
|
||||
|
||||
if (mptcp_pm_is_userspace(msk))
|
||||
return mptcp_userspace_pm_get_flags_and_ifindex_by_id(msk, id, flags, ifindex);
|
||||
return mptcp_pm_nl_get_flags_and_ifindex_by_id(msk, id, flags, ifindex);
|
||||
}
|
||||
|
||||
int mptcp_pm_get_addr(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
if (info->attrs[MPTCP_PM_ATTR_TOKEN])
|
||||
|
|
|
@ -149,7 +149,7 @@ static bool lookup_subflow_by_daddr(const struct list_head *list,
|
|||
static bool
|
||||
select_local_address(const struct pm_nl_pernet *pernet,
|
||||
const struct mptcp_sock *msk,
|
||||
struct mptcp_pm_addr_entry *new_entry)
|
||||
struct mptcp_pm_local *new_local)
|
||||
{
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
bool found = false;
|
||||
|
@ -164,7 +164,9 @@ select_local_address(const struct pm_nl_pernet *pernet,
|
|||
if (!test_bit(entry->addr.id, msk->pm.id_avail_bitmap))
|
||||
continue;
|
||||
|
||||
*new_entry = *entry;
|
||||
new_local->addr = entry->addr;
|
||||
new_local->flags = entry->flags;
|
||||
new_local->ifindex = entry->ifindex;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -175,7 +177,7 @@ select_local_address(const struct pm_nl_pernet *pernet,
|
|||
|
||||
static bool
|
||||
select_signal_address(struct pm_nl_pernet *pernet, const struct mptcp_sock *msk,
|
||||
struct mptcp_pm_addr_entry *new_entry)
|
||||
struct mptcp_pm_local *new_local)
|
||||
{
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
bool found = false;
|
||||
|
@ -193,7 +195,9 @@ select_signal_address(struct pm_nl_pernet *pernet, const struct mptcp_sock *msk,
|
|||
if (!(entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
|
||||
continue;
|
||||
|
||||
*new_entry = *entry;
|
||||
new_local->addr = entry->addr;
|
||||
new_local->flags = entry->flags;
|
||||
new_local->ifindex = entry->ifindex;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -524,11 +528,11 @@ __lookup_addr(struct pm_nl_pernet *pernet, const struct mptcp_addr_info *info)
|
|||
static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
||||
{
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct mptcp_pm_addr_entry local;
|
||||
unsigned int add_addr_signal_max;
|
||||
bool signal_and_subflow = false;
|
||||
unsigned int local_addr_max;
|
||||
struct pm_nl_pernet *pernet;
|
||||
struct mptcp_pm_local local;
|
||||
unsigned int subflows_max;
|
||||
|
||||
pernet = pm_nl_get_pernet(sock_net(sk));
|
||||
|
@ -629,7 +633,7 @@ subflow:
|
|||
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
for (i = 0; i < nr; i++)
|
||||
__mptcp_subflow_connect(sk, &local.addr, &addrs[i]);
|
||||
__mptcp_subflow_connect(sk, &local, &addrs[i]);
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
}
|
||||
mptcp_pm_nl_check_work_pending(msk);
|
||||
|
@ -650,7 +654,7 @@ static void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk)
|
|||
*/
|
||||
static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk,
|
||||
struct mptcp_addr_info *remote,
|
||||
struct mptcp_addr_info *addrs)
|
||||
struct mptcp_pm_local *locals)
|
||||
{
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
|
@ -673,13 +677,15 @@ static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk,
|
|||
continue;
|
||||
|
||||
if (msk->pm.subflows < subflows_max) {
|
||||
msk->pm.subflows++;
|
||||
addrs[i] = entry->addr;
|
||||
locals[i].addr = entry->addr;
|
||||
locals[i].flags = entry->flags;
|
||||
locals[i].ifindex = entry->ifindex;
|
||||
|
||||
/* Special case for ID0: set the correct ID */
|
||||
if (mptcp_addresses_equal(&entry->addr, &mpc_addr, entry->addr.port))
|
||||
addrs[i].id = 0;
|
||||
if (mptcp_addresses_equal(&locals[i].addr, &mpc_addr, locals[i].addr.port))
|
||||
locals[i].addr.id = 0;
|
||||
|
||||
msk->pm.subflows++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -689,21 +695,19 @@ static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk,
|
|||
* 'IPADDRANY' local address
|
||||
*/
|
||||
if (!i) {
|
||||
struct mptcp_addr_info local;
|
||||
|
||||
memset(&local, 0, sizeof(local));
|
||||
local.family =
|
||||
memset(&locals[i], 0, sizeof(locals[i]));
|
||||
locals[i].addr.family =
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
remote->family == AF_INET6 &&
|
||||
ipv6_addr_v4mapped(&remote->addr6) ? AF_INET :
|
||||
#endif
|
||||
remote->family;
|
||||
|
||||
if (!mptcp_pm_addr_families_match(sk, &local, remote))
|
||||
if (!mptcp_pm_addr_families_match(sk, &locals[i].addr, remote))
|
||||
return 0;
|
||||
|
||||
msk->pm.subflows++;
|
||||
addrs[i++] = local;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
|
@ -711,7 +715,7 @@ static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk,
|
|||
|
||||
static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_addr_info addrs[MPTCP_PM_ADDR_MAX];
|
||||
struct mptcp_pm_local locals[MPTCP_PM_ADDR_MAX];
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
unsigned int add_addr_accept_max;
|
||||
struct mptcp_addr_info remote;
|
||||
|
@ -740,13 +744,13 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
|
|||
/* connect to the specified remote address, using whatever
|
||||
* local address the routing configuration will pick.
|
||||
*/
|
||||
nr = fill_local_addresses_vec(msk, &remote, addrs);
|
||||
nr = fill_local_addresses_vec(msk, &remote, locals);
|
||||
if (nr == 0)
|
||||
return;
|
||||
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
for (i = 0; i < nr; i++)
|
||||
if (__mptcp_subflow_connect(sk, &addrs[i], &remote) == 0)
|
||||
if (__mptcp_subflow_connect(sk, &locals[i], &remote) == 0)
|
||||
sf_created = true;
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
|
@ -1433,28 +1437,6 @@ out_free:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int mptcp_pm_nl_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id,
|
||||
u8 *flags, int *ifindex)
|
||||
{
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct net *net = sock_net(sk);
|
||||
|
||||
/* No entries with ID 0 */
|
||||
if (id == 0)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
entry = __lookup_addr_by_id(pm_nl_get_pernet(net), id);
|
||||
if (entry) {
|
||||
*flags = entry->flags;
|
||||
*ifindex = entry->ifindex;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
|
|
|
@ -119,23 +119,6 @@ mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
|
||||
unsigned int id,
|
||||
u8 *flags, int *ifindex)
|
||||
{
|
||||
struct mptcp_pm_addr_entry *match;
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
match = mptcp_userspace_pm_lookup_addr_by_id(msk, id);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
if (match) {
|
||||
*flags = match->flags;
|
||||
*ifindex = match->ifindex;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
|
||||
struct mptcp_addr_info *skc)
|
||||
{
|
||||
|
@ -352,8 +335,9 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
|
||||
struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
|
||||
struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
|
||||
struct mptcp_pm_addr_entry local = { 0 };
|
||||
struct mptcp_pm_addr_entry entry = { 0 };
|
||||
struct mptcp_addr_info addr_r;
|
||||
struct mptcp_pm_local local;
|
||||
struct mptcp_sock *msk;
|
||||
int err = -EINVAL;
|
||||
struct sock *sk;
|
||||
|
@ -379,18 +363,18 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
goto create_err;
|
||||
}
|
||||
|
||||
err = mptcp_pm_parse_entry(laddr, info, true, &local);
|
||||
err = mptcp_pm_parse_entry(laddr, info, true, &entry);
|
||||
if (err < 0) {
|
||||
NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr");
|
||||
goto create_err;
|
||||
}
|
||||
|
||||
if (local.flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
|
||||
if (entry.flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
|
||||
GENL_SET_ERR_MSG(info, "invalid addr flags");
|
||||
err = -EINVAL;
|
||||
goto create_err;
|
||||
}
|
||||
local.flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
|
||||
entry.flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;
|
||||
|
||||
err = mptcp_pm_parse_addr(raddr, info, &addr_r);
|
||||
if (err < 0) {
|
||||
|
@ -398,27 +382,29 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
goto create_err;
|
||||
}
|
||||
|
||||
if (!mptcp_pm_addr_families_match(sk, &local.addr, &addr_r)) {
|
||||
if (!mptcp_pm_addr_families_match(sk, &entry.addr, &addr_r)) {
|
||||
GENL_SET_ERR_MSG(info, "families mismatch");
|
||||
err = -EINVAL;
|
||||
goto create_err;
|
||||
}
|
||||
|
||||
err = mptcp_userspace_pm_append_new_local_addr(msk, &local, false);
|
||||
err = mptcp_userspace_pm_append_new_local_addr(msk, &entry, false);
|
||||
if (err < 0) {
|
||||
GENL_SET_ERR_MSG(info, "did not match address and id");
|
||||
goto create_err;
|
||||
}
|
||||
|
||||
local.addr = entry.addr;
|
||||
local.flags = entry.flags;
|
||||
local.ifindex = entry.ifindex;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
err = __mptcp_subflow_connect(sk, &local.addr, &addr_r);
|
||||
|
||||
err = __mptcp_subflow_connect(sk, &local, &addr_r);
|
||||
release_sock(sk);
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
if (err)
|
||||
mptcp_userspace_pm_delete_local_addr(msk, &local);
|
||||
mptcp_userspace_pm_delete_local_addr(msk, &entry);
|
||||
else
|
||||
msk->pm.subflows++;
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
|
|
@ -236,6 +236,12 @@ struct mptcp_pm_data {
|
|||
struct mptcp_rm_list rm_list_rx;
|
||||
};
|
||||
|
||||
struct mptcp_pm_local {
|
||||
struct mptcp_addr_info addr;
|
||||
u8 flags;
|
||||
int ifindex;
|
||||
};
|
||||
|
||||
struct mptcp_pm_addr_entry {
|
||||
struct list_head list;
|
||||
struct mptcp_addr_info addr;
|
||||
|
@ -719,7 +725,7 @@ bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
|
|||
void mptcp_local_address(const struct sock_common *skc, struct mptcp_addr_info *addr);
|
||||
|
||||
/* called with sk socket lock held */
|
||||
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
|
||||
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_pm_local *local,
|
||||
const struct mptcp_addr_info *remote);
|
||||
int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
|
||||
struct socket **new_sock);
|
||||
|
@ -1014,14 +1020,6 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,
|
|||
struct mptcp_pm_add_entry *
|
||||
mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr);
|
||||
int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
|
||||
unsigned int id,
|
||||
u8 *flags, int *ifindex);
|
||||
int mptcp_pm_nl_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id,
|
||||
u8 *flags, int *ifindex);
|
||||
int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
|
||||
unsigned int id,
|
||||
u8 *flags, int *ifindex);
|
||||
int mptcp_pm_set_flags(struct sk_buff *skb, struct genl_info *info);
|
||||
int mptcp_pm_nl_set_flags(struct sk_buff *skb, struct genl_info *info);
|
||||
int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info);
|
||||
|
|
|
@ -1565,26 +1565,24 @@ void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
|
|||
#endif
|
||||
}
|
||||
|
||||
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
|
||||
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_pm_local *local,
|
||||
const struct mptcp_addr_info *remote)
|
||||
{
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
struct mptcp_subflow_context *subflow;
|
||||
int local_id = local->addr.id;
|
||||
struct sockaddr_storage addr;
|
||||
int remote_id = remote->id;
|
||||
int local_id = loc->id;
|
||||
int err = -ENOTCONN;
|
||||
struct socket *sf;
|
||||
struct sock *ssk;
|
||||
u32 remote_token;
|
||||
int addrlen;
|
||||
int ifindex;
|
||||
u8 flags;
|
||||
|
||||
if (!mptcp_is_fully_established(sk))
|
||||
goto err_out;
|
||||
|
||||
err = mptcp_subflow_create_socket(sk, loc->family, &sf);
|
||||
err = mptcp_subflow_create_socket(sk, local->addr.family, &sf);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
|
@ -1594,23 +1592,32 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
|
|||
get_random_bytes(&subflow->local_nonce, sizeof(u32));
|
||||
} while (!subflow->local_nonce);
|
||||
|
||||
if (local_id)
|
||||
/* if 'IPADDRANY', the ID will be set later, after the routing */
|
||||
if (local->addr.family == AF_INET) {
|
||||
if (!local->addr.addr.s_addr)
|
||||
local_id = -1;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
} else if (sk->sk_family == AF_INET6) {
|
||||
if (ipv6_addr_any(&local->addr.addr6))
|
||||
local_id = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (local_id >= 0)
|
||||
subflow_set_local_id(subflow, local_id);
|
||||
|
||||
mptcp_pm_get_flags_and_ifindex_by_id(msk, local_id,
|
||||
&flags, &ifindex);
|
||||
subflow->remote_key_valid = 1;
|
||||
subflow->remote_key = READ_ONCE(msk->remote_key);
|
||||
subflow->local_key = READ_ONCE(msk->local_key);
|
||||
subflow->token = msk->token;
|
||||
mptcp_info2sockaddr(loc, &addr, ssk->sk_family);
|
||||
mptcp_info2sockaddr(&local->addr, &addr, ssk->sk_family);
|
||||
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
if (addr.ss_family == AF_INET6)
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
ssk->sk_bound_dev_if = ifindex;
|
||||
ssk->sk_bound_dev_if = local->ifindex;
|
||||
err = kernel_bind(sf, (struct sockaddr *)&addr, addrlen);
|
||||
if (err)
|
||||
goto failed;
|
||||
|
@ -1621,7 +1628,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
|
|||
subflow->remote_token = remote_token;
|
||||
WRITE_ONCE(subflow->remote_id, remote_id);
|
||||
subflow->request_join = 1;
|
||||
subflow->request_bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP);
|
||||
subflow->request_bkup = !!(local->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
|
||||
subflow->subflow_id = msk->subflow_id++;
|
||||
mptcp_info2sockaddr(remote, &addr, ssk->sk_family);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user