mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-03 12:24:37 -04:00
Merge branch 'mptcp-pm-misc-cleanups-part-3'
Matthieu Baerts says: ==================== mptcp: pm: misc cleanups, part 3 These cleanups lead the way to the unification of the path-manager interfaces, and allow future extensions. The following patches are not all linked to each others, but are all related to the path-managers, except the last three. - Patch 1: remove unused returned value in mptcp_nl_set_flags(). - Patch 2: new flag: avoid iterating over all connections if not needed. - Patch 3: add a build check making sure there is enough space in cb-ctx. - Patch 4: new mptcp_pm_genl_fill_addr helper to reduce duplicated code. - Patch 5: simplify userspace_pm_append_new_local_addr helper. - Patch 6: drop unneeded inet6_sk(). - Patch 7: use ipv6_addr_equal() instead of !ipv6_addr_cmp() - Patch 8: scheduler: split an interface in two. - Patch 9: scheduler: save 64 bytes of currently unused data. - Patch 10: small optimisation to exit early in case of retransmissions. ==================== Link: https://patch.msgid.link/20250221-net-next-mptcp-pm-misc-cleanup-3-v1-0-2b70ab1cee79@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -103,13 +103,14 @@ struct mptcp_out_options {
|
||||
#define MPTCP_SUBFLOWS_MAX 8
|
||||
|
||||
struct mptcp_sched_data {
|
||||
bool reinject;
|
||||
u8 subflows;
|
||||
struct mptcp_subflow_context *contexts[MPTCP_SUBFLOWS_MAX];
|
||||
};
|
||||
|
||||
struct mptcp_sched_ops {
|
||||
int (*get_subflow)(struct mptcp_sock *msk,
|
||||
int (*get_send)(struct mptcp_sock *msk,
|
||||
struct mptcp_sched_data *data);
|
||||
int (*get_retrans)(struct mptcp_sock *msk,
|
||||
struct mptcp_sched_data *data);
|
||||
|
||||
char name[MPTCP_SCHED_NAME_MAX];
|
||||
|
||||
@@ -401,26 +401,30 @@ void mptcp_active_enable(struct sock *sk)
|
||||
void mptcp_active_detect_blackhole(struct sock *ssk, bool expired)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
u8 timeouts, to_max;
|
||||
struct net *net;
|
||||
|
||||
if (!sk_is_mptcp(ssk))
|
||||
/* Only check MPTCP SYN ... */
|
||||
if (likely(!sk_is_mptcp(ssk) || ssk->sk_state != TCP_SYN_SENT))
|
||||
return;
|
||||
|
||||
subflow = mptcp_subflow_ctx(ssk);
|
||||
|
||||
if (subflow->request_mptcp && ssk->sk_state == TCP_SYN_SENT) {
|
||||
struct net *net = sock_net(ssk);
|
||||
u8 timeouts, to_max;
|
||||
|
||||
timeouts = inet_csk(ssk)->icsk_retransmits;
|
||||
to_max = mptcp_get_pernet(net)->syn_retrans_before_tcp_fallback;
|
||||
|
||||
if (timeouts == to_max || (timeouts < to_max && expired)) {
|
||||
MPTCP_INC_STATS(net, MPTCP_MIB_MPCAPABLEACTIVEDROP);
|
||||
subflow->mpc_drop = 1;
|
||||
mptcp_subflow_early_fallback(mptcp_sk(subflow->conn), subflow);
|
||||
}
|
||||
} else if (ssk->sk_state == TCP_SYN_SENT) {
|
||||
/* ... + MP_CAPABLE */
|
||||
if (!subflow->request_mptcp) {
|
||||
/* Mark as blackhole iif the 1st non-MPTCP SYN is accepted */
|
||||
subflow->mpc_drop = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
net = sock_net(ssk);
|
||||
timeouts = inet_csk(ssk)->icsk_retransmits;
|
||||
to_max = mptcp_get_pernet(net)->syn_retrans_before_tcp_fallback;
|
||||
|
||||
if (timeouts == to_max || (timeouts < to_max && expired)) {
|
||||
MPTCP_INC_STATS(net, MPTCP_MIB_MPCAPABLEACTIVEDROP);
|
||||
subflow->mpc_drop = 1;
|
||||
mptcp_subflow_early_fallback(mptcp_sk(subflow->conn), subflow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -489,6 +489,27 @@ int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mptcp_pm_genl_fill_addr(struct sk_buff *msg,
|
||||
struct netlink_callback *cb,
|
||||
struct mptcp_pm_addr_entry *entry)
|
||||
{
|
||||
void *hdr;
|
||||
|
||||
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, &mptcp_genl_family,
|
||||
NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
|
||||
if (!hdr)
|
||||
return -EINVAL;
|
||||
|
||||
if (mptcp_nl_fill_addr(msg, entry) < 0) {
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
|
||||
@@ -64,7 +64,7 @@ bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
|
||||
addr_equals = a->addr.s_addr == b->addr.s_addr;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
else
|
||||
addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
|
||||
addr_equals = ipv6_addr_equal(&a->addr6, &b->addr6);
|
||||
} else if (a->family == AF_INET) {
|
||||
if (ipv6_addr_v4mapped(&b->addr6))
|
||||
addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3];
|
||||
@@ -1798,7 +1798,6 @@ int mptcp_pm_nl_dump_addr(struct sk_buff *msg,
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
struct pm_nl_pernet *pernet;
|
||||
int id = cb->args[0];
|
||||
void *hdr;
|
||||
int i;
|
||||
|
||||
pernet = pm_nl_get_pernet(net);
|
||||
@@ -1813,19 +1812,10 @@ int mptcp_pm_nl_dump_addr(struct sk_buff *msg,
|
||||
if (entry->addr.id <= id)
|
||||
continue;
|
||||
|
||||
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, &mptcp_genl_family,
|
||||
NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
|
||||
if (!hdr)
|
||||
if (mptcp_pm_genl_fill_addr(msg, cb, entry) < 0)
|
||||
break;
|
||||
|
||||
if (mptcp_nl_fill_addr(msg, entry) < 0) {
|
||||
genlmsg_cancel(msg, hdr);
|
||||
break;
|
||||
}
|
||||
|
||||
id = entry->addr.id;
|
||||
genlmsg_end(msg, hdr);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@@ -1922,13 +1912,16 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
}
|
||||
|
||||
static int mptcp_nl_set_flags(struct net *net,
|
||||
struct mptcp_addr_info *addr,
|
||||
u8 bkup, u8 changed)
|
||||
static void mptcp_nl_set_flags(struct net *net, struct mptcp_addr_info *addr,
|
||||
u8 flags, u8 changed)
|
||||
{
|
||||
u8 is_subflow = !!(flags & MPTCP_PM_ADDR_FLAG_SUBFLOW);
|
||||
u8 bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP);
|
||||
long s_slot = 0, s_num = 0;
|
||||
struct mptcp_sock *msk;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (changed == MPTCP_PM_ADDR_FLAG_FULLMESH && !is_subflow)
|
||||
return;
|
||||
|
||||
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
@@ -1938,8 +1931,9 @@ static int mptcp_nl_set_flags(struct net *net,
|
||||
|
||||
lock_sock(sk);
|
||||
if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
|
||||
ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
|
||||
if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
|
||||
mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
|
||||
/* Subflows will only be recreated if the SUBFLOW flag is set */
|
||||
if (is_subflow && (changed & MPTCP_PM_ADDR_FLAG_FULLMESH))
|
||||
mptcp_pm_nl_fullmesh(msk, addr);
|
||||
release_sock(sk);
|
||||
|
||||
@@ -1948,7 +1942,7 @@ static int mptcp_nl_set_flags(struct net *net,
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
|
||||
@@ -1961,7 +1955,6 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
struct pm_nl_pernet *pernet;
|
||||
u8 lookup_by_id = 0;
|
||||
u8 bkup = 0;
|
||||
|
||||
pernet = pm_nl_get_pernet(net);
|
||||
|
||||
@@ -1974,9 +1967,6 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
|
||||
}
|
||||
}
|
||||
|
||||
if (local->flags & MPTCP_PM_ADDR_FLAG_BACKUP)
|
||||
bkup = 1;
|
||||
|
||||
spin_lock_bh(&pernet->lock);
|
||||
entry = lookup_by_id ? __lookup_addr_by_id(pernet, local->addr.id) :
|
||||
__lookup_addr(pernet, &local->addr);
|
||||
@@ -1998,7 +1988,7 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
|
||||
*local = *entry;
|
||||
spin_unlock_bh(&pernet->lock);
|
||||
|
||||
mptcp_nl_set_flags(net, &local->addr, bkup, changed);
|
||||
mptcp_nl_set_flags(net, &local->addr, entry->flags, changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2032,9 +2022,7 @@ static int mptcp_event_add_subflow(struct sk_buff *skb, const struct sock *ssk)
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
case AF_INET6: {
|
||||
const struct ipv6_pinfo *np = inet6_sk(ssk);
|
||||
|
||||
if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &np->saddr))
|
||||
if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &issk->pinet6->saddr))
|
||||
return -EMSGSIZE;
|
||||
if (nla_put_in6_addr(skb, MPTCP_ATTR_DADDR6, &ssk->sk_v6_daddr))
|
||||
return -EMSGSIZE;
|
||||
@@ -2261,9 +2249,7 @@ void mptcp_event_pm_listener(const struct sock *ssk,
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
case AF_INET6: {
|
||||
const struct ipv6_pinfo *np = inet6_sk(ssk);
|
||||
|
||||
if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &np->saddr))
|
||||
if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &issk->pinet6->saddr))
|
||||
goto nla_put_failure;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
|
||||
bool needs_id)
|
||||
{
|
||||
DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
|
||||
struct mptcp_pm_addr_entry *match = NULL;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct mptcp_pm_addr_entry *e;
|
||||
bool addr_match = false;
|
||||
@@ -63,16 +62,12 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
|
||||
if (addr_match && entry->addr.id == 0 && needs_id)
|
||||
entry->addr.id = e->addr.id;
|
||||
id_match = (e->addr.id == entry->addr.id);
|
||||
if (addr_match && id_match) {
|
||||
match = e;
|
||||
if (addr_match || id_match)
|
||||
break;
|
||||
} else if (addr_match || id_match) {
|
||||
break;
|
||||
}
|
||||
__set_bit(e->addr.id, id_bitmap);
|
||||
}
|
||||
|
||||
if (!match && !addr_match && !id_match) {
|
||||
if (!addr_match && !id_match) {
|
||||
/* Memory for the entry is allocated from the
|
||||
* sock option buffer.
|
||||
*/
|
||||
@@ -90,7 +85,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
|
||||
list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
|
||||
msk->pm.local_addr_used++;
|
||||
ret = e->addr.id;
|
||||
} else if (match) {
|
||||
} else if (addr_match && id_match) {
|
||||
ret = entry->addr.id;
|
||||
}
|
||||
|
||||
@@ -465,9 +460,7 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
case AF_INET6: {
|
||||
const struct ipv6_pinfo *pinfo = inet6_sk(ssk);
|
||||
|
||||
if (!ipv6_addr_equal(&local->addr6, &pinfo->saddr) ||
|
||||
if (!ipv6_addr_equal(&local->addr6, &issk->pinet6->saddr) ||
|
||||
!ipv6_addr_equal(&remote->addr6, &ssk->sk_v6_daddr))
|
||||
continue;
|
||||
break;
|
||||
@@ -641,7 +634,8 @@ int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
|
||||
struct mptcp_sock *msk;
|
||||
int ret = -EINVAL;
|
||||
struct sock *sk;
|
||||
void *hdr;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct id_bitmap) > sizeof(cb->ctx));
|
||||
|
||||
bitmap = (struct id_bitmap *)cb->ctx;
|
||||
|
||||
@@ -657,19 +651,10 @@ int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
|
||||
if (test_bit(entry->addr.id, bitmap->map))
|
||||
continue;
|
||||
|
||||
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, &mptcp_genl_family,
|
||||
NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
|
||||
if (!hdr)
|
||||
if (mptcp_pm_genl_fill_addr(msg, cb, entry) < 0)
|
||||
break;
|
||||
|
||||
if (mptcp_nl_fill_addr(msg, entry) < 0) {
|
||||
genlmsg_cancel(msg, hdr);
|
||||
break;
|
||||
}
|
||||
|
||||
__set_bit(entry->addr.id, bitmap->map);
|
||||
genlmsg_end(msg, hdr);
|
||||
}
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
release_sock(sk);
|
||||
|
||||
@@ -1057,6 +1057,9 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subf
|
||||
struct request_sock *req);
|
||||
int mptcp_nl_fill_addr(struct sk_buff *skb,
|
||||
struct mptcp_pm_addr_entry *entry);
|
||||
int mptcp_pm_genl_fill_addr(struct sk_buff *msg,
|
||||
struct netlink_callback *cb,
|
||||
struct mptcp_pm_addr_entry *entry);
|
||||
|
||||
static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
|
||||
{
|
||||
|
||||
@@ -16,13 +16,25 @@
|
||||
static DEFINE_SPINLOCK(mptcp_sched_list_lock);
|
||||
static LIST_HEAD(mptcp_sched_list);
|
||||
|
||||
static int mptcp_sched_default_get_subflow(struct mptcp_sock *msk,
|
||||
static int mptcp_sched_default_get_send(struct mptcp_sock *msk,
|
||||
struct mptcp_sched_data *data)
|
||||
{
|
||||
struct sock *ssk;
|
||||
|
||||
ssk = mptcp_subflow_get_send(msk);
|
||||
if (!ssk)
|
||||
return -EINVAL;
|
||||
|
||||
mptcp_subflow_set_scheduled(mptcp_subflow_ctx(ssk), true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mptcp_sched_default_get_retrans(struct mptcp_sock *msk,
|
||||
struct mptcp_sched_data *data)
|
||||
{
|
||||
struct sock *ssk;
|
||||
|
||||
ssk = data->reinject ? mptcp_subflow_get_retrans(msk) :
|
||||
mptcp_subflow_get_send(msk);
|
||||
ssk = mptcp_subflow_get_retrans(msk);
|
||||
if (!ssk)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -31,7 +43,8 @@ static int mptcp_sched_default_get_subflow(struct mptcp_sock *msk,
|
||||
}
|
||||
|
||||
static struct mptcp_sched_ops mptcp_sched_default = {
|
||||
.get_subflow = mptcp_sched_default_get_subflow,
|
||||
.get_send = mptcp_sched_default_get_send,
|
||||
.get_retrans = mptcp_sched_default_get_retrans,
|
||||
.name = "default",
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
@@ -73,7 +86,7 @@ void mptcp_get_available_schedulers(char *buf, size_t maxlen)
|
||||
|
||||
int mptcp_register_scheduler(struct mptcp_sched_ops *sched)
|
||||
{
|
||||
if (!sched->get_subflow)
|
||||
if (!sched->get_send)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&mptcp_sched_list_lock);
|
||||
@@ -144,7 +157,7 @@ void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,
|
||||
int mptcp_sched_get_send(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct mptcp_sched_data data;
|
||||
struct mptcp_sched_data *data = NULL;
|
||||
|
||||
msk_owned_by_me(msk);
|
||||
|
||||
@@ -164,16 +177,15 @@ int mptcp_sched_get_send(struct mptcp_sock *msk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
data.reinject = false;
|
||||
if (msk->sched == &mptcp_sched_default || !msk->sched)
|
||||
return mptcp_sched_default_get_subflow(msk, &data);
|
||||
return msk->sched->get_subflow(msk, &data);
|
||||
return mptcp_sched_default_get_send(msk, data);
|
||||
return msk->sched->get_send(msk, data);
|
||||
}
|
||||
|
||||
int mptcp_sched_get_retrans(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct mptcp_sched_data data;
|
||||
struct mptcp_sched_data *data = NULL;
|
||||
|
||||
msk_owned_by_me(msk);
|
||||
|
||||
@@ -186,8 +198,9 @@ int mptcp_sched_get_retrans(struct mptcp_sock *msk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
data.reinject = true;
|
||||
if (msk->sched == &mptcp_sched_default || !msk->sched)
|
||||
return mptcp_sched_default_get_subflow(msk, &data);
|
||||
return msk->sched->get_subflow(msk, &data);
|
||||
return mptcp_sched_default_get_retrans(msk, data);
|
||||
if (msk->sched->get_retrans)
|
||||
return msk->sched->get_retrans(msk, data);
|
||||
return msk->sched->get_send(msk, data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user