mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-15 15:04:27 +08:00
Merge branch 'mptcp-userspace-pm'
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) <matttbe@kernel.org>
This commit is contained in:
commit
09fcde5477
@ -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
|
||||
|
@ -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 */
|
||||
@ -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,
|
||||
},
|
||||
{
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -1675,7 +1672,7 @@ nla_put_failure:
|
||||
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);
|
||||
@ -1725,8 +1722,13 @@ fail:
|
||||
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;
|
||||
@ -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];
|
||||
@ -2281,7 +2289,7 @@ nla_put_failure:
|
||||
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,
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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;
|
||||
@ -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");
|
||||
@ -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);
|
||||
|
||||
@ -572,3 +578,137 @@ set_flags_err:
|
||||
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;
|
||||
}
|
||||
|
@ -343,6 +343,8 @@ struct mptcp_sock {
|
||||
#define mptcp_for_each_subflow_safe(__msk, __subflow, __tmp) \
|
||||
list_for_each_entry_safe(__subflow, __tmp, &((__msk)->conn_list), node)
|
||||
|
||||
extern struct genl_family mptcp_genl_family;
|
||||
|
||||
static inline void msk_owned_by_me(const struct mptcp_sock *msk)
|
||||
{
|
||||
sock_owned_by_me((const struct sock *)msk);
|
||||
@ -981,8 +983,6 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
|
||||
int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);
|
||||
int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);
|
||||
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);
|
||||
|
||||
void mptcp_free_local_addr_list(struct mptcp_sock *msk);
|
||||
|
||||
@ -998,6 +998,8 @@ void __mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflo
|
||||
const struct mptcp_options_received *mp_opt);
|
||||
void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow,
|
||||
struct request_sock *req);
|
||||
int mptcp_nl_fill_addr(struct sk_buff *skb,
|
||||
struct mptcp_pm_addr_entry *entry);
|
||||
|
||||
static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk)
|
||||
{
|
||||
@ -1062,6 +1064,15 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
||||
int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
|
||||
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
|
||||
int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
|
||||
int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb);
|
||||
int mptcp_pm_nl_dump_addr(struct sk_buff *msg,
|
||||
struct netlink_callback *cb);
|
||||
int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
|
||||
struct netlink_callback *cb);
|
||||
int mptcp_pm_get_addr(struct sk_buff *skb, struct genl_info *info);
|
||||
int mptcp_pm_nl_get_addr(struct sk_buff *skb, struct genl_info *info);
|
||||
int mptcp_userspace_pm_get_addr(struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
|
||||
static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflow)
|
||||
{
|
||||
|
@ -21,6 +21,7 @@ cinfail=""
|
||||
cinsent=""
|
||||
tmpfile=""
|
||||
cout=""
|
||||
err=""
|
||||
capout=""
|
||||
ns1=""
|
||||
ns2=""
|
||||
@ -189,6 +190,7 @@ init() {
|
||||
cin=$(mktemp)
|
||||
cinsent=$(mktemp)
|
||||
cout=$(mktemp)
|
||||
err=$(mktemp)
|
||||
evts_ns1=$(mktemp)
|
||||
evts_ns2=$(mktemp)
|
||||
|
||||
@ -204,6 +206,7 @@ cleanup()
|
||||
rm -f "$sin" "$sout" "$cinsent" "$cinfail"
|
||||
rm -f "$tmpfile"
|
||||
rm -rf $evts_ns1 $evts_ns2
|
||||
rm -f "$err"
|
||||
cleanup_partial
|
||||
}
|
||||
|
||||
@ -3356,6 +3359,77 @@ userspace_pm_rm_sf()
|
||||
wait_rm_sf $1 "${cnt}"
|
||||
}
|
||||
|
||||
check_output()
|
||||
{
|
||||
local cmd="$1"
|
||||
local expected="$2"
|
||||
local msg="$3"
|
||||
local rc=0
|
||||
|
||||
mptcp_lib_check_output "${err}" "${cmd}" "${expected}" || rc=${?}
|
||||
if [ ${rc} -eq 2 ]; then
|
||||
fail_test "fail to check output # error ${rc}"
|
||||
elif [ ${rc} -eq 0 ]; then
|
||||
print_ok
|
||||
elif [ ${rc} -eq 1 ]; then
|
||||
fail_test "fail to check output # different output"
|
||||
fi
|
||||
}
|
||||
|
||||
# $1: ns
|
||||
userspace_pm_dump()
|
||||
{
|
||||
local evts=$evts_ns1
|
||||
local tk
|
||||
|
||||
[ "$1" == "$ns2" ] && evts=$evts_ns2
|
||||
tk=$(mptcp_lib_evts_get_info token "$evts")
|
||||
|
||||
ip netns exec $1 ./pm_nl_ctl dump token $tk
|
||||
}
|
||||
|
||||
# $1: ns ; $2: id
|
||||
userspace_pm_get_addr()
|
||||
{
|
||||
local evts=$evts_ns1
|
||||
local tk
|
||||
|
||||
[ "$1" == "$ns2" ] && evts=$evts_ns2
|
||||
tk=$(mptcp_lib_evts_get_info token "$evts")
|
||||
|
||||
ip netns exec $1 ./pm_nl_ctl get $2 token $tk
|
||||
}
|
||||
|
||||
userspace_pm_chk_dump_addr()
|
||||
{
|
||||
local ns="${1}"
|
||||
local exp="${2}"
|
||||
local check="${3}"
|
||||
|
||||
print_check "dump addrs ${check}"
|
||||
|
||||
if mptcp_lib_kallsyms_has "mptcp_userspace_pm_dump_addr$"; then
|
||||
check_output "userspace_pm_dump ${ns}" "${exp}"
|
||||
else
|
||||
print_skip
|
||||
fi
|
||||
}
|
||||
|
||||
userspace_pm_chk_get_addr()
|
||||
{
|
||||
local ns="${1}"
|
||||
local id="${2}"
|
||||
local exp="${3}"
|
||||
|
||||
print_check "get id ${id} addr"
|
||||
|
||||
if mptcp_lib_kallsyms_has "mptcp_userspace_pm_get_addr$"; then
|
||||
check_output "userspace_pm_get_addr ${ns} ${id}" "${exp}"
|
||||
else
|
||||
print_skip
|
||||
fi
|
||||
}
|
||||
|
||||
userspace_tests()
|
||||
{
|
||||
# userspace pm type prevents add_addr
|
||||
@ -3447,10 +3521,18 @@ userspace_tests()
|
||||
chk_mptcp_info subflows 2 subflows 2
|
||||
chk_subflows_total 3 3
|
||||
chk_mptcp_info add_addr_signal 2 add_addr_accepted 2
|
||||
userspace_pm_chk_dump_addr "${ns1}" \
|
||||
$'id 10 flags signal 10.0.2.1\nid 20 flags signal 10.0.3.1' \
|
||||
"signal"
|
||||
userspace_pm_chk_get_addr "${ns1}" "10" "id 10 flags signal 10.0.2.1"
|
||||
userspace_pm_chk_get_addr "${ns1}" "20" "id 20 flags signal 10.0.3.1"
|
||||
userspace_pm_rm_addr $ns1 10
|
||||
userspace_pm_rm_sf $ns1 "::ffff:10.0.2.1" $SUB_ESTABLISHED
|
||||
userspace_pm_chk_dump_addr "${ns1}" \
|
||||
"id 20 flags signal 10.0.3.1" "after rm_addr 10"
|
||||
userspace_pm_rm_addr $ns1 20
|
||||
userspace_pm_rm_sf $ns1 10.0.3.1 $SUB_ESTABLISHED
|
||||
userspace_pm_chk_dump_addr "${ns1}" "" "after rm_addr 20"
|
||||
chk_rm_nr 2 2 invert
|
||||
chk_mptcp_info subflows 0 subflows 0
|
||||
chk_subflows_total 1 1
|
||||
@ -3471,8 +3553,15 @@ userspace_tests()
|
||||
chk_join_nr 1 1 1
|
||||
chk_mptcp_info subflows 1 subflows 1
|
||||
chk_subflows_total 2 2
|
||||
userspace_pm_chk_dump_addr "${ns2}" \
|
||||
"id 20 flags subflow 10.0.3.2" \
|
||||
"subflow"
|
||||
userspace_pm_chk_get_addr "${ns2}" "20" "id 20 flags subflow 10.0.3.2"
|
||||
userspace_pm_rm_addr $ns2 20
|
||||
userspace_pm_rm_sf $ns2 10.0.3.2 $SUB_ESTABLISHED
|
||||
userspace_pm_chk_dump_addr "${ns2}" \
|
||||
"" \
|
||||
"after rm_addr 20"
|
||||
chk_rm_nr 1 1
|
||||
chk_mptcp_info subflows 0 subflows 0
|
||||
chk_subflows_total 1 1
|
||||
@ -3492,6 +3581,8 @@ userspace_tests()
|
||||
chk_mptcp_info subflows 0 subflows 0
|
||||
chk_subflows_total 1 1
|
||||
userspace_pm_add_sf $ns2 10.0.3.2 0
|
||||
userspace_pm_chk_dump_addr "${ns2}" \
|
||||
"id 0 flags subflow 10.0.3.2" "id 0 subflow"
|
||||
chk_join_nr 1 1 1
|
||||
chk_mptcp_info subflows 1 subflows 1
|
||||
chk_subflows_total 2 2
|
||||
|
@ -319,3 +319,26 @@ mptcp_lib_wait_local_port_listen() {
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
|
||||
mptcp_lib_check_output() {
|
||||
local err="${1}"
|
||||
local cmd="${2}"
|
||||
local expected="${3}"
|
||||
local cmd_ret=0
|
||||
local out
|
||||
|
||||
if ! out=$(${cmd} 2>"${err}"); then
|
||||
cmd_ret=${?}
|
||||
fi
|
||||
|
||||
if [ ${cmd_ret} -ne 0 ]; then
|
||||
mptcp_lib_print_err "[FAIL] command execution '${cmd}' stderr"
|
||||
cat "${err}"
|
||||
return 2
|
||||
elif [ "${out}" = "${expected}" ]; then
|
||||
return 0
|
||||
else
|
||||
mptcp_lib_print_err "[FAIL] expected '${expected}' got '${out}'"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
@ -54,21 +54,17 @@ check()
|
||||
local cmd="$1"
|
||||
local expected="$2"
|
||||
local msg="$3"
|
||||
local out=`$cmd 2>$err`
|
||||
local cmd_ret=$?
|
||||
local rc=0
|
||||
|
||||
printf "%-50s" "$msg"
|
||||
if [ $cmd_ret -ne 0 ]; then
|
||||
echo "[FAIL] command execution '$cmd' stderr "
|
||||
cat $err
|
||||
mptcp_lib_result_fail "${msg} # error ${cmd_ret}"
|
||||
mptcp_lib_check_output "${err}" "${cmd}" "${expected}" || rc=${?}
|
||||
if [ ${rc} -eq 2 ]; then
|
||||
mptcp_lib_result_fail "${msg} # error ${rc}"
|
||||
ret=1
|
||||
elif [ "$out" = "$expected" ]; then
|
||||
echo "[ OK ]"
|
||||
elif [ ${rc} -eq 0 ]; then
|
||||
mptcp_lib_print_ok "[ OK ]"
|
||||
mptcp_lib_result_pass "${msg}"
|
||||
else
|
||||
echo -n "[FAIL] "
|
||||
echo "expected '$expected' got '$out'"
|
||||
elif [ ${rc} -eq 1 ]; then
|
||||
mptcp_lib_result_fail "${msg} # different output"
|
||||
ret=1
|
||||
fi
|
||||
|
@ -453,6 +453,7 @@ int csf(int fd, int pm_family, int argc, char *argv[])
|
||||
char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
|
||||
NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
|
||||
1024];
|
||||
u_int32_t flags = MPTCP_PM_ADDR_FLAG_SUBFLOW;
|
||||
const char *params[5];
|
||||
struct nlmsghdr *nh;
|
||||
struct rtattr *addr;
|
||||
@ -558,6 +559,13 @@ int csf(int fd, int pm_family, int argc, char *argv[])
|
||||
off += NLMSG_ALIGN(rta->rta_len);
|
||||
}
|
||||
|
||||
/* addr flags */
|
||||
rta = (void *)(data + off);
|
||||
rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &flags, 4);
|
||||
off += NLMSG_ALIGN(rta->rta_len);
|
||||
|
||||
addr->rta_len = off - addr_start;
|
||||
}
|
||||
|
||||
@ -1079,6 +1087,7 @@ int get_addr(int fd, int pm_family, int argc, char *argv[])
|
||||
1024];
|
||||
struct rtattr *rta, *nest;
|
||||
struct nlmsghdr *nh;
|
||||
u_int32_t token = 0;
|
||||
int nest_start;
|
||||
u_int8_t id;
|
||||
int off = 0;
|
||||
@ -1089,10 +1098,12 @@ int get_addr(int fd, int pm_family, int argc, char *argv[])
|
||||
MPTCP_PM_VER);
|
||||
|
||||
/* the only argument is the address id */
|
||||
if (argc != 3)
|
||||
if (argc != 3 && argc != 5)
|
||||
syntax(argv);
|
||||
|
||||
id = atoi(argv[2]);
|
||||
if (argc == 5 && !strcmp(argv[3], "token"))
|
||||
token = strtoul(argv[4], NULL, 10);
|
||||
|
||||
nest_start = off;
|
||||
nest = (void *)(data + off);
|
||||
@ -1108,6 +1119,15 @@ int get_addr(int fd, int pm_family, int argc, char *argv[])
|
||||
off += NLMSG_ALIGN(rta->rta_len);
|
||||
nest->rta_len = off - nest_start;
|
||||
|
||||
/* token */
|
||||
if (token) {
|
||||
rta = (void *)(data + off);
|
||||
rta->rta_type = MPTCP_PM_ATTR_TOKEN;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &token, 4);
|
||||
off += NLMSG_ALIGN(rta->rta_len);
|
||||
}
|
||||
|
||||
print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
|
||||
return 0;
|
||||
}
|
||||
@ -1119,8 +1139,16 @@ int dump_addrs(int fd, int pm_family, int argc, char *argv[])
|
||||
1024];
|
||||
pid_t pid = getpid();
|
||||
struct nlmsghdr *nh;
|
||||
u_int32_t token = 0;
|
||||
struct rtattr *rta;
|
||||
int off = 0;
|
||||
|
||||
if (argc != 2 && argc != 4)
|
||||
syntax(argv);
|
||||
|
||||
if (argc == 4 && !strcmp(argv[2], "token"))
|
||||
token = strtoul(argv[3], NULL, 10);
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
nh = (void *)data;
|
||||
off = init_genl_req(data, pm_family, MPTCP_PM_CMD_GET_ADDR,
|
||||
@ -1130,6 +1158,15 @@ int dump_addrs(int fd, int pm_family, int argc, char *argv[])
|
||||
nh->nlmsg_pid = pid;
|
||||
nh->nlmsg_len = off;
|
||||
|
||||
/* token */
|
||||
if (token) {
|
||||
rta = (void *)(data + off);
|
||||
rta->rta_type = MPTCP_PM_ATTR_TOKEN;
|
||||
rta->rta_len = RTA_LENGTH(4);
|
||||
memcpy(RTA_DATA(rta), &token, 4);
|
||||
off += NLMSG_ALIGN(rta->rta_len);
|
||||
}
|
||||
|
||||
print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data)));
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user