Skip to content

Commit

Permalink
Merge branch 'mptcp-userspace-pm'
Browse files Browse the repository at this point in the history
Matthieu Baerts says:

====================
mptcp: userspace pm: 'dump addrs' and 'get addr'

This series from Geliang adds two new Netlink commands to the userspace
PM:

- one to dump all addresses of a specific MPTCP connection:
  - feature added in patches 3 to 5
  - test added in patches 7, 8 and 10

- and one to get a specific address for an MPTCP connection:
  - feature added in patches 11 to 13
  - test added in patches 14 and 15

These new Netlink commands can be useful if an MPTCP daemon lost track
of the different connections, e.g. after having been restarted.

The other patches are some clean-ups and small improvements added
while working on the new features.

====================

Signed-off-by: Matthieu Baerts (NGI0) <[email protected]>
  • Loading branch information
davem330 committed Mar 4, 2024
2 parents 86a628b + 4cc5cc7 commit 09fcde5
Show file tree
Hide file tree
Showing 11 changed files with 374 additions and 50 deletions.
3 changes: 2 additions & 1 deletion Documentation/netlink/specs/mptcp_pm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -292,13 +292,14 @@ operations:
-
name: get-addr
doc: Get endpoint information
attribute-set: endpoint
attribute-set: attr
dont-validate: [ strict ]
flags: [ uns-admin-perm ]
do: &get-addr-attrs
request:
attributes:
- addr
- token
reply:
attributes:
- addr
Expand Down
7 changes: 4 additions & 3 deletions net/mptcp/mptcp_pm_gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ const struct nla_policy mptcp_pm_del_addr_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1]
};

/* MPTCP_PM_CMD_GET_ADDR - do */
const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1] = {
[MPTCP_PM_ENDPOINT_ADDR] = NLA_POLICY_NESTED(mptcp_pm_address_nl_policy),
const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ATTR_TOKEN + 1] = {
[MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_address_nl_policy),
[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
};

/* MPTCP_PM_CMD_FLUSH_ADDRS - do */
Expand Down Expand Up @@ -110,7 +111,7 @@ const struct genl_ops mptcp_pm_nl_ops[11] = {
.doit = mptcp_pm_nl_get_addr_doit,
.dumpit = mptcp_pm_nl_get_addr_dumpit,
.policy = mptcp_pm_get_addr_nl_policy,
.maxattr = MPTCP_PM_ENDPOINT_ADDR,
.maxattr = MPTCP_PM_ATTR_TOKEN,
.flags = GENL_UNS_ADMIN_PERM,
},
{
Expand Down
2 changes: 1 addition & 1 deletion net/mptcp/mptcp_pm_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extern const struct nla_policy mptcp_pm_add_addr_nl_policy[MPTCP_PM_ENDPOINT_ADD

extern const struct nla_policy mptcp_pm_del_addr_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1];

extern const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1];
extern const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ATTR_TOKEN + 1];

extern const struct nla_policy mptcp_pm_flush_addrs_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1];

Expand Down
16 changes: 16 additions & 0 deletions net/mptcp/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,22 @@ int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id
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])
return mptcp_userspace_pm_get_addr(skb, info);
return mptcp_pm_nl_get_addr(skb, info);
}

int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb)
{
const struct genl_info *info = genl_info_dump(cb);

if (info->attrs[MPTCP_PM_ATTR_TOKEN])
return mptcp_userspace_pm_dump_addr(msg, cb);
return mptcp_pm_nl_dump_addr(msg, cb);
}

int mptcp_pm_set_flags(struct net *net, struct nlattr *token,
struct mptcp_pm_addr_entry *loc,
struct mptcp_pm_addr_entry *rem, u8 bkup)
Expand Down
30 changes: 19 additions & 11 deletions net/mptcp/pm_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
#include "protocol.h"
#include "mib.h"

/* forward declaration */
static struct genl_family mptcp_genl_family;

static int pm_nl_pernet_id;

struct mptcp_pm_add_entry {
Expand Down Expand Up @@ -1550,8 +1547,8 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
}
}

void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
struct list_head *rm_list)
static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
struct list_head *rm_list)
{
struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 };
struct mptcp_pm_addr_entry *entry;
Expand Down Expand Up @@ -1636,8 +1633,8 @@ int mptcp_pm_nl_flush_addrs_doit(struct sk_buff *skb, struct genl_info *info)
return 0;
}

static int mptcp_nl_fill_addr(struct sk_buff *skb,
struct mptcp_pm_addr_entry *entry)
int mptcp_nl_fill_addr(struct sk_buff *skb,
struct mptcp_pm_addr_entry *entry)
{
struct mptcp_addr_info *addr = &entry->addr;
struct nlattr *attr;
Expand Down Expand Up @@ -1675,7 +1672,7 @@ static int mptcp_nl_fill_addr(struct sk_buff *skb,
return -EMSGSIZE;
}

int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
int mptcp_pm_nl_get_addr(struct sk_buff *skb, struct genl_info *info)
{
struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR];
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
Expand Down Expand Up @@ -1725,8 +1722,13 @@ int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
return ret;
}

int mptcp_pm_nl_get_addr_dumpit(struct sk_buff *msg,
struct netlink_callback *cb)
int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
{
return mptcp_pm_get_addr(skb, info);
}

int mptcp_pm_nl_dump_addr(struct sk_buff *msg,
struct netlink_callback *cb)
{
struct net *net = sock_net(msg->sk);
struct mptcp_pm_addr_entry *entry;
Expand Down Expand Up @@ -1768,6 +1770,12 @@ int mptcp_pm_nl_get_addr_dumpit(struct sk_buff *msg,
return msg->len;
}

int mptcp_pm_nl_get_addr_dumpit(struct sk_buff *msg,
struct netlink_callback *cb)
{
return mptcp_pm_dump_addr(msg, cb);
}

static int parse_limit(struct genl_info *info, int id, unsigned int *limit)
{
struct nlattr *attr = info->attrs[id];
Expand Down Expand Up @@ -2281,7 +2289,7 @@ void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
nlmsg_free(skb);
}

static struct genl_family mptcp_genl_family __ro_after_init = {
struct genl_family mptcp_genl_family __ro_after_init = {
.name = MPTCP_PM_NAME,
.version = MPTCP_PM_VER,
.netnsok = true,
Expand Down
180 changes: 160 additions & 20 deletions net/mptcp/pm_userspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,26 @@ static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
return -EINVAL;
}

static struct mptcp_pm_addr_entry *
mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id)
{
struct mptcp_pm_addr_entry *entry;

list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
if (entry->addr.id == id)
return entry;
}
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 *entry, *match = NULL;
struct mptcp_pm_addr_entry *match;

spin_lock_bh(&msk->pm.lock);
list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
if (id == entry->addr.id) {
match = entry;
break;
}
}
match = mptcp_userspace_pm_lookup_addr_by_id(msk, id);
spin_unlock_bh(&msk->pm.lock);
if (match) {
*flags = match->flags;
Expand Down Expand Up @@ -261,7 +268,7 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
{
struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
struct nlattr *id = info->attrs[MPTCP_PM_ATTR_LOC_ID];
struct mptcp_pm_addr_entry *match = NULL;
struct mptcp_pm_addr_entry *match;
struct mptcp_pm_addr_entry *entry;
struct mptcp_sock *msk;
LIST_HEAD(free_list);
Expand Down Expand Up @@ -298,13 +305,7 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)

lock_sock(sk);

list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
if (entry->addr.id == id_val) {
match = entry;
break;
}
}

match = mptcp_userspace_pm_lookup_addr_by_id(msk, id_val);
if (!match) {
GENL_SET_ERR_MSG(info, "address with specified id not found");
release_sock(sk);
Expand Down Expand Up @@ -334,7 +335,6 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
struct mptcp_pm_addr_entry local = { 0 };
struct mptcp_addr_info addr_r;
struct mptcp_addr_info addr_l;
struct mptcp_sock *msk;
int err = -EINVAL;
struct sock *sk;
Expand All @@ -360,25 +360,31 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
goto create_err;
}

err = mptcp_pm_parse_addr(laddr, info, &addr_l);
err = mptcp_pm_parse_entry(laddr, info, true, &local);
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) {
GENL_SET_ERR_MSG(info, "invalid addr flags");
err = -EINVAL;
goto create_err;
}
local.flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW;

err = mptcp_pm_parse_addr(raddr, info, &addr_r);
if (err < 0) {
NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr");
goto create_err;
}

if (!mptcp_pm_addr_families_match(sk, &addr_l, &addr_r)) {
if (!mptcp_pm_addr_families_match(sk, &local.addr, &addr_r)) {
GENL_SET_ERR_MSG(info, "families mismatch");
err = -EINVAL;
goto create_err;
}

local.addr = addr_l;
err = mptcp_userspace_pm_append_new_local_addr(msk, &local, false);
if (err < 0) {
GENL_SET_ERR_MSG(info, "did not match address and id");
Expand All @@ -387,7 +393,7 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)

lock_sock(sk);

err = __mptcp_subflow_connect(sk, &addr_l, &addr_r);
err = __mptcp_subflow_connect(sk, &local.addr, &addr_r);

release_sock(sk);

Expand Down Expand Up @@ -572,3 +578,137 @@ int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
sock_put(sk);
return ret;
}

int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
struct netlink_callback *cb)
{
struct id_bitmap {
DECLARE_BITMAP(map, MPTCP_PM_MAX_ADDR_ID + 1);
} *bitmap;
const struct genl_info *info = genl_info_dump(cb);
struct net *net = sock_net(msg->sk);
struct mptcp_pm_addr_entry *entry;
struct mptcp_sock *msk;
struct nlattr *token;
int ret = -EINVAL;
struct sock *sk;
void *hdr;

bitmap = (struct id_bitmap *)cb->ctx;
token = info->attrs[MPTCP_PM_ATTR_TOKEN];

msk = mptcp_token_get_sock(net, nla_get_u32(token));
if (!msk) {
NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
return ret;
}

sk = (struct sock *)msk;

if (!mptcp_pm_is_userspace(msk)) {
GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
goto out;
}

lock_sock(sk);
spin_lock_bh(&msk->pm.lock);
list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
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)
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);
ret = msg->len;

out:
sock_put(sk);
return ret;
}

int mptcp_userspace_pm_get_addr(struct sk_buff *skb,
struct genl_info *info)
{
struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR];
struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
struct mptcp_pm_addr_entry addr, *entry;
struct net *net = sock_net(skb->sk);
struct mptcp_sock *msk;
struct sk_buff *msg;
int ret = -EINVAL;
struct sock *sk;
void *reply;

msk = mptcp_token_get_sock(net, nla_get_u32(token));
if (!msk) {
NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
return ret;
}

sk = (struct sock *)msk;

if (!mptcp_pm_is_userspace(msk)) {
GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
goto out;
}

ret = mptcp_pm_parse_entry(attr, info, false, &addr);
if (ret < 0)
goto out;

msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg) {
ret = -ENOMEM;
goto out;
}

reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0,
info->genlhdr->cmd);
if (!reply) {
GENL_SET_ERR_MSG(info, "not enough space in Netlink message");
ret = -EMSGSIZE;
goto fail;
}

lock_sock(sk);
spin_lock_bh(&msk->pm.lock);
entry = mptcp_userspace_pm_lookup_addr_by_id(msk, addr.addr.id);
if (!entry) {
GENL_SET_ERR_MSG(info, "address not found");
ret = -EINVAL;
goto unlock_fail;
}

ret = mptcp_nl_fill_addr(msg, entry);
if (ret)
goto unlock_fail;

genlmsg_end(msg, reply);
ret = genlmsg_reply(msg, info);
spin_unlock_bh(&msk->pm.lock);
release_sock(sk);
sock_put(sk);
return ret;

unlock_fail:
spin_unlock_bh(&msk->pm.lock);
release_sock(sk);
fail:
nlmsg_free(msg);
out:
sock_put(sk);
return ret;
}
Loading

0 comments on commit 09fcde5

Please sign in to comment.