Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+374 -50
+2 -1
Documentation/netlink/specs/mptcp_pm.yaml
··· 292 292 - 293 293 name: get-addr 294 294 doc: Get endpoint information 295 - attribute-set: endpoint 295 + attribute-set: attr 296 296 dont-validate: [ strict ] 297 297 flags: [ uns-admin-perm ] 298 298 do: &get-addr-attrs 299 299 request: 300 300 attributes: 301 301 - addr 302 + - token 302 303 reply: 303 304 attributes: 304 305 - addr
+4 -3
net/mptcp/mptcp_pm_gen.c
··· 32 32 }; 33 33 34 34 /* MPTCP_PM_CMD_GET_ADDR - do */ 35 - const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1] = { 36 - [MPTCP_PM_ENDPOINT_ADDR] = NLA_POLICY_NESTED(mptcp_pm_address_nl_policy), 35 + const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ATTR_TOKEN + 1] = { 36 + [MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_address_nl_policy), 37 + [MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, }, 37 38 }; 38 39 39 40 /* MPTCP_PM_CMD_FLUSH_ADDRS - do */ ··· 111 110 .doit = mptcp_pm_nl_get_addr_doit, 112 111 .dumpit = mptcp_pm_nl_get_addr_dumpit, 113 112 .policy = mptcp_pm_get_addr_nl_policy, 114 - .maxattr = MPTCP_PM_ENDPOINT_ADDR, 113 + .maxattr = MPTCP_PM_ATTR_TOKEN, 115 114 .flags = GENL_UNS_ADMIN_PERM, 116 115 }, 117 116 {
+1 -1
net/mptcp/mptcp_pm_gen.h
··· 18 18 19 19 extern const struct nla_policy mptcp_pm_del_addr_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1]; 20 20 21 - extern const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1]; 21 + extern const struct nla_policy mptcp_pm_get_addr_nl_policy[MPTCP_PM_ATTR_TOKEN + 1]; 22 22 23 23 extern const struct nla_policy mptcp_pm_flush_addrs_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1]; 24 24
+16
net/mptcp/pm.c
··· 441 441 return mptcp_pm_nl_get_flags_and_ifindex_by_id(msk, id, flags, ifindex); 442 442 } 443 443 444 + int mptcp_pm_get_addr(struct sk_buff *skb, struct genl_info *info) 445 + { 446 + if (info->attrs[MPTCP_PM_ATTR_TOKEN]) 447 + return mptcp_userspace_pm_get_addr(skb, info); 448 + return mptcp_pm_nl_get_addr(skb, info); 449 + } 450 + 451 + int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb) 452 + { 453 + const struct genl_info *info = genl_info_dump(cb); 454 + 455 + if (info->attrs[MPTCP_PM_ATTR_TOKEN]) 456 + return mptcp_userspace_pm_dump_addr(msg, cb); 457 + return mptcp_pm_nl_dump_addr(msg, cb); 458 + } 459 + 444 460 int mptcp_pm_set_flags(struct net *net, struct nlattr *token, 445 461 struct mptcp_pm_addr_entry *loc, 446 462 struct mptcp_pm_addr_entry *rem, u8 bkup)
+19 -11
net/mptcp/pm_netlink.c
··· 18 18 #include "protocol.h" 19 19 #include "mib.h" 20 20 21 - /* forward declaration */ 22 - static struct genl_family mptcp_genl_family; 23 - 24 21 static int pm_nl_pernet_id; 25 22 26 23 struct mptcp_pm_add_entry { ··· 1547 1550 } 1548 1551 } 1549 1552 1550 - void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, 1551 - struct list_head *rm_list) 1553 + static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, 1554 + struct list_head *rm_list) 1552 1555 { 1553 1556 struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 }; 1554 1557 struct mptcp_pm_addr_entry *entry; ··· 1633 1636 return 0; 1634 1637 } 1635 1638 1636 - static int mptcp_nl_fill_addr(struct sk_buff *skb, 1637 - struct mptcp_pm_addr_entry *entry) 1639 + int mptcp_nl_fill_addr(struct sk_buff *skb, 1640 + struct mptcp_pm_addr_entry *entry) 1638 1641 { 1639 1642 struct mptcp_addr_info *addr = &entry->addr; 1640 1643 struct nlattr *attr; ··· 1672 1675 return -EMSGSIZE; 1673 1676 } 1674 1677 1675 - int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info) 1678 + int mptcp_pm_nl_get_addr(struct sk_buff *skb, struct genl_info *info) 1676 1679 { 1677 1680 struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR]; 1678 1681 struct pm_nl_pernet *pernet = genl_info_pm_nl(info); ··· 1722 1725 return ret; 1723 1726 } 1724 1727 1725 - int mptcp_pm_nl_get_addr_dumpit(struct sk_buff *msg, 1726 - struct netlink_callback *cb) 1728 + int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info) 1729 + { 1730 + return mptcp_pm_get_addr(skb, info); 1731 + } 1732 + 1733 + int mptcp_pm_nl_dump_addr(struct sk_buff *msg, 1734 + struct netlink_callback *cb) 1727 1735 { 1728 1736 struct net *net = sock_net(msg->sk); 1729 1737 struct mptcp_pm_addr_entry *entry; ··· 1768 1766 1769 1767 cb->args[0] = id; 1770 1768 return msg->len; 1769 + } 1770 + 1771 + int mptcp_pm_nl_get_addr_dumpit(struct sk_buff *msg, 1772 + struct netlink_callback *cb) 1773 + { 1774 + return mptcp_pm_dump_addr(msg, cb); 1771 1775 } 1772 1776 1773 1777 static int parse_limit(struct genl_info *info, int id, unsigned int *limit) ··· 2289 2281 nlmsg_free(skb); 2290 2282 } 2291 2283 2292 - static struct genl_family mptcp_genl_family __ro_after_init = { 2284 + struct genl_family mptcp_genl_family __ro_after_init = { 2293 2285 .name = MPTCP_PM_NAME, 2294 2286 .version = MPTCP_PM_VER, 2295 2287 .netnsok = true,
+160 -20
net/mptcp/pm_userspace.c
··· 106 106 return -EINVAL; 107 107 } 108 108 109 + static struct mptcp_pm_addr_entry * 110 + mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id) 111 + { 112 + struct mptcp_pm_addr_entry *entry; 113 + 114 + list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { 115 + if (entry->addr.id == id) 116 + return entry; 117 + } 118 + return NULL; 119 + } 120 + 109 121 int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, 110 122 unsigned int id, 111 123 u8 *flags, int *ifindex) 112 124 { 113 - struct mptcp_pm_addr_entry *entry, *match = NULL; 125 + struct mptcp_pm_addr_entry *match; 114 126 115 127 spin_lock_bh(&msk->pm.lock); 116 - list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { 117 - if (id == entry->addr.id) { 118 - match = entry; 119 - break; 120 - } 121 - } 128 + match = mptcp_userspace_pm_lookup_addr_by_id(msk, id); 122 129 spin_unlock_bh(&msk->pm.lock); 123 130 if (match) { 124 131 *flags = match->flags; ··· 268 261 { 269 262 struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 270 263 struct nlattr *id = info->attrs[MPTCP_PM_ATTR_LOC_ID]; 271 - struct mptcp_pm_addr_entry *match = NULL; 264 + struct mptcp_pm_addr_entry *match; 272 265 struct mptcp_pm_addr_entry *entry; 273 266 struct mptcp_sock *msk; 274 267 LIST_HEAD(free_list); ··· 305 298 306 299 lock_sock(sk); 307 300 308 - list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { 309 - if (entry->addr.id == id_val) { 310 - match = entry; 311 - break; 312 - } 313 - } 314 - 301 + match = mptcp_userspace_pm_lookup_addr_by_id(msk, id_val); 315 302 if (!match) { 316 303 GENL_SET_ERR_MSG(info, "address with specified id not found"); 317 304 release_sock(sk); ··· 335 334 struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR]; 336 335 struct mptcp_pm_addr_entry local = { 0 }; 337 336 struct mptcp_addr_info addr_r; 338 - struct mptcp_addr_info addr_l; 339 337 struct mptcp_sock *msk; 340 338 int err = -EINVAL; 341 339 struct sock *sk; ··· 360 360 goto create_err; 361 361 } 362 362 363 - err = mptcp_pm_parse_addr(laddr, info, &addr_l); 363 + err = mptcp_pm_parse_entry(laddr, info, true, &local); 364 364 if (err < 0) { 365 365 NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr"); 366 366 goto create_err; 367 367 } 368 + 369 + if (local.flags & MPTCP_PM_ADDR_FLAG_SIGNAL) { 370 + GENL_SET_ERR_MSG(info, "invalid addr flags"); 371 + err = -EINVAL; 372 + goto create_err; 373 + } 374 + local.flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW; 368 375 369 376 err = mptcp_pm_parse_addr(raddr, info, &addr_r); 370 377 if (err < 0) { ··· 379 372 goto create_err; 380 373 } 381 374 382 - if (!mptcp_pm_addr_families_match(sk, &addr_l, &addr_r)) { 375 + if (!mptcp_pm_addr_families_match(sk, &local.addr, &addr_r)) { 383 376 GENL_SET_ERR_MSG(info, "families mismatch"); 384 377 err = -EINVAL; 385 378 goto create_err; 386 379 } 387 380 388 - local.addr = addr_l; 389 381 err = mptcp_userspace_pm_append_new_local_addr(msk, &local, false); 390 382 if (err < 0) { 391 383 GENL_SET_ERR_MSG(info, "did not match address and id"); ··· 393 387 394 388 lock_sock(sk); 395 389 396 - err = __mptcp_subflow_connect(sk, &addr_l, &addr_r); 390 + err = __mptcp_subflow_connect(sk, &local.addr, &addr_r); 397 391 398 392 release_sock(sk); 399 393 ··· 575 569 release_sock(sk); 576 570 577 571 set_flags_err: 572 + sock_put(sk); 573 + return ret; 574 + } 575 + 576 + int mptcp_userspace_pm_dump_addr(struct sk_buff *msg, 577 + struct netlink_callback *cb) 578 + { 579 + struct id_bitmap { 580 + DECLARE_BITMAP(map, MPTCP_PM_MAX_ADDR_ID + 1); 581 + } *bitmap; 582 + const struct genl_info *info = genl_info_dump(cb); 583 + struct net *net = sock_net(msg->sk); 584 + struct mptcp_pm_addr_entry *entry; 585 + struct mptcp_sock *msk; 586 + struct nlattr *token; 587 + int ret = -EINVAL; 588 + struct sock *sk; 589 + void *hdr; 590 + 591 + bitmap = (struct id_bitmap *)cb->ctx; 592 + token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 593 + 594 + msk = mptcp_token_get_sock(net, nla_get_u32(token)); 595 + if (!msk) { 596 + NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 597 + return ret; 598 + } 599 + 600 + sk = (struct sock *)msk; 601 + 602 + if (!mptcp_pm_is_userspace(msk)) { 603 + GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 604 + goto out; 605 + } 606 + 607 + lock_sock(sk); 608 + spin_lock_bh(&msk->pm.lock); 609 + list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { 610 + if (test_bit(entry->addr.id, bitmap->map)) 611 + continue; 612 + 613 + hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid, 614 + cb->nlh->nlmsg_seq, &mptcp_genl_family, 615 + NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR); 616 + if (!hdr) 617 + break; 618 + 619 + if (mptcp_nl_fill_addr(msg, entry) < 0) { 620 + genlmsg_cancel(msg, hdr); 621 + break; 622 + } 623 + 624 + __set_bit(entry->addr.id, bitmap->map); 625 + genlmsg_end(msg, hdr); 626 + } 627 + spin_unlock_bh(&msk->pm.lock); 628 + release_sock(sk); 629 + ret = msg->len; 630 + 631 + out: 632 + sock_put(sk); 633 + return ret; 634 + } 635 + 636 + int mptcp_userspace_pm_get_addr(struct sk_buff *skb, 637 + struct genl_info *info) 638 + { 639 + struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR]; 640 + struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 641 + struct mptcp_pm_addr_entry addr, *entry; 642 + struct net *net = sock_net(skb->sk); 643 + struct mptcp_sock *msk; 644 + struct sk_buff *msg; 645 + int ret = -EINVAL; 646 + struct sock *sk; 647 + void *reply; 648 + 649 + msk = mptcp_token_get_sock(net, nla_get_u32(token)); 650 + if (!msk) { 651 + NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 652 + return ret; 653 + } 654 + 655 + sk = (struct sock *)msk; 656 + 657 + if (!mptcp_pm_is_userspace(msk)) { 658 + GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 659 + goto out; 660 + } 661 + 662 + ret = mptcp_pm_parse_entry(attr, info, false, &addr); 663 + if (ret < 0) 664 + goto out; 665 + 666 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 667 + if (!msg) { 668 + ret = -ENOMEM; 669 + goto out; 670 + } 671 + 672 + reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0, 673 + info->genlhdr->cmd); 674 + if (!reply) { 675 + GENL_SET_ERR_MSG(info, "not enough space in Netlink message"); 676 + ret = -EMSGSIZE; 677 + goto fail; 678 + } 679 + 680 + lock_sock(sk); 681 + spin_lock_bh(&msk->pm.lock); 682 + entry = mptcp_userspace_pm_lookup_addr_by_id(msk, addr.addr.id); 683 + if (!entry) { 684 + GENL_SET_ERR_MSG(info, "address not found"); 685 + ret = -EINVAL; 686 + goto unlock_fail; 687 + } 688 + 689 + ret = mptcp_nl_fill_addr(msg, entry); 690 + if (ret) 691 + goto unlock_fail; 692 + 693 + genlmsg_end(msg, reply); 694 + ret = genlmsg_reply(msg, info); 695 + spin_unlock_bh(&msk->pm.lock); 696 + release_sock(sk); 697 + sock_put(sk); 698 + return ret; 699 + 700 + unlock_fail: 701 + spin_unlock_bh(&msk->pm.lock); 702 + release_sock(sk); 703 + fail: 704 + nlmsg_free(msg); 705 + out: 578 706 sock_put(sk); 579 707 return ret; 580 708 }
+13 -2
net/mptcp/protocol.h
··· 343 343 #define mptcp_for_each_subflow_safe(__msk, __subflow, __tmp) \ 344 344 list_for_each_entry_safe(__subflow, __tmp, &((__msk)->conn_list), node) 345 345 346 + extern struct genl_family mptcp_genl_family; 347 + 346 348 static inline void msk_owned_by_me(const struct mptcp_sock *msk) 347 349 { 348 350 sock_owned_by_me((const struct sock *)msk); ··· 983 981 int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); 984 982 int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); 985 983 void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list); 986 - void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, 987 - struct list_head *rm_list); 988 984 989 985 void mptcp_free_local_addr_list(struct mptcp_sock *msk); 990 986 ··· 998 998 const struct mptcp_options_received *mp_opt); 999 999 void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow, 1000 1000 struct request_sock *req); 1001 + int mptcp_nl_fill_addr(struct sk_buff *skb, 1002 + struct mptcp_pm_addr_entry *entry); 1001 1003 1002 1004 static inline bool mptcp_pm_should_add_signal(struct mptcp_sock *msk) 1003 1005 { ··· 1064 1062 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); 1065 1063 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); 1066 1064 int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); 1065 + int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb); 1066 + int mptcp_pm_nl_dump_addr(struct sk_buff *msg, 1067 + struct netlink_callback *cb); 1068 + int mptcp_userspace_pm_dump_addr(struct sk_buff *msg, 1069 + struct netlink_callback *cb); 1070 + int mptcp_pm_get_addr(struct sk_buff *skb, struct genl_info *info); 1071 + int mptcp_pm_nl_get_addr(struct sk_buff *skb, struct genl_info *info); 1072 + int mptcp_userspace_pm_get_addr(struct sk_buff *skb, 1073 + struct genl_info *info); 1067 1074 1068 1075 static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflow) 1069 1076 {
+91
tools/testing/selftests/net/mptcp/mptcp_join.sh
··· 21 21 cinsent="" 22 22 tmpfile="" 23 23 cout="" 24 + err="" 24 25 capout="" 25 26 ns1="" 26 27 ns2="" ··· 190 189 cin=$(mktemp) 191 190 cinsent=$(mktemp) 192 191 cout=$(mktemp) 192 + err=$(mktemp) 193 193 evts_ns1=$(mktemp) 194 194 evts_ns2=$(mktemp) 195 195 ··· 206 204 rm -f "$sin" "$sout" "$cinsent" "$cinfail" 207 205 rm -f "$tmpfile" 208 206 rm -rf $evts_ns1 $evts_ns2 207 + rm -f "$err" 209 208 cleanup_partial 210 209 } 211 210 ··· 3359 3356 wait_rm_sf $1 "${cnt}" 3360 3357 } 3361 3358 3359 + check_output() 3360 + { 3361 + local cmd="$1" 3362 + local expected="$2" 3363 + local msg="$3" 3364 + local rc=0 3365 + 3366 + mptcp_lib_check_output "${err}" "${cmd}" "${expected}" || rc=${?} 3367 + if [ ${rc} -eq 2 ]; then 3368 + fail_test "fail to check output # error ${rc}" 3369 + elif [ ${rc} -eq 0 ]; then 3370 + print_ok 3371 + elif [ ${rc} -eq 1 ]; then 3372 + fail_test "fail to check output # different output" 3373 + fi 3374 + } 3375 + 3376 + # $1: ns 3377 + userspace_pm_dump() 3378 + { 3379 + local evts=$evts_ns1 3380 + local tk 3381 + 3382 + [ "$1" == "$ns2" ] && evts=$evts_ns2 3383 + tk=$(mptcp_lib_evts_get_info token "$evts") 3384 + 3385 + ip netns exec $1 ./pm_nl_ctl dump token $tk 3386 + } 3387 + 3388 + # $1: ns ; $2: id 3389 + userspace_pm_get_addr() 3390 + { 3391 + local evts=$evts_ns1 3392 + local tk 3393 + 3394 + [ "$1" == "$ns2" ] && evts=$evts_ns2 3395 + tk=$(mptcp_lib_evts_get_info token "$evts") 3396 + 3397 + ip netns exec $1 ./pm_nl_ctl get $2 token $tk 3398 + } 3399 + 3400 + userspace_pm_chk_dump_addr() 3401 + { 3402 + local ns="${1}" 3403 + local exp="${2}" 3404 + local check="${3}" 3405 + 3406 + print_check "dump addrs ${check}" 3407 + 3408 + if mptcp_lib_kallsyms_has "mptcp_userspace_pm_dump_addr$"; then 3409 + check_output "userspace_pm_dump ${ns}" "${exp}" 3410 + else 3411 + print_skip 3412 + fi 3413 + } 3414 + 3415 + userspace_pm_chk_get_addr() 3416 + { 3417 + local ns="${1}" 3418 + local id="${2}" 3419 + local exp="${3}" 3420 + 3421 + print_check "get id ${id} addr" 3422 + 3423 + if mptcp_lib_kallsyms_has "mptcp_userspace_pm_get_addr$"; then 3424 + check_output "userspace_pm_get_addr ${ns} ${id}" "${exp}" 3425 + else 3426 + print_skip 3427 + fi 3428 + } 3429 + 3362 3430 userspace_tests() 3363 3431 { 3364 3432 # userspace pm type prevents add_addr ··· 3521 3447 chk_mptcp_info subflows 2 subflows 2 3522 3448 chk_subflows_total 3 3 3523 3449 chk_mptcp_info add_addr_signal 2 add_addr_accepted 2 3450 + userspace_pm_chk_dump_addr "${ns1}" \ 3451 + $'id 10 flags signal 10.0.2.1\nid 20 flags signal 10.0.3.1' \ 3452 + "signal" 3453 + userspace_pm_chk_get_addr "${ns1}" "10" "id 10 flags signal 10.0.2.1" 3454 + userspace_pm_chk_get_addr "${ns1}" "20" "id 20 flags signal 10.0.3.1" 3524 3455 userspace_pm_rm_addr $ns1 10 3525 3456 userspace_pm_rm_sf $ns1 "::ffff:10.0.2.1" $SUB_ESTABLISHED 3457 + userspace_pm_chk_dump_addr "${ns1}" \ 3458 + "id 20 flags signal 10.0.3.1" "after rm_addr 10" 3526 3459 userspace_pm_rm_addr $ns1 20 3527 3460 userspace_pm_rm_sf $ns1 10.0.3.1 $SUB_ESTABLISHED 3461 + userspace_pm_chk_dump_addr "${ns1}" "" "after rm_addr 20" 3528 3462 chk_rm_nr 2 2 invert 3529 3463 chk_mptcp_info subflows 0 subflows 0 3530 3464 chk_subflows_total 1 1 ··· 3553 3471 chk_join_nr 1 1 1 3554 3472 chk_mptcp_info subflows 1 subflows 1 3555 3473 chk_subflows_total 2 2 3474 + userspace_pm_chk_dump_addr "${ns2}" \ 3475 + "id 20 flags subflow 10.0.3.2" \ 3476 + "subflow" 3477 + userspace_pm_chk_get_addr "${ns2}" "20" "id 20 flags subflow 10.0.3.2" 3556 3478 userspace_pm_rm_addr $ns2 20 3557 3479 userspace_pm_rm_sf $ns2 10.0.3.2 $SUB_ESTABLISHED 3480 + userspace_pm_chk_dump_addr "${ns2}" \ 3481 + "" \ 3482 + "after rm_addr 20" 3558 3483 chk_rm_nr 1 1 3559 3484 chk_mptcp_info subflows 0 subflows 0 3560 3485 chk_subflows_total 1 1 ··· 3581 3492 chk_mptcp_info subflows 0 subflows 0 3582 3493 chk_subflows_total 1 1 3583 3494 userspace_pm_add_sf $ns2 10.0.3.2 0 3495 + userspace_pm_chk_dump_addr "${ns2}" \ 3496 + "id 0 flags subflow 10.0.3.2" "id 0 subflow" 3584 3497 chk_join_nr 1 1 1 3585 3498 chk_mptcp_info subflows 1 subflows 1 3586 3499 chk_subflows_total 2 2
+23
tools/testing/selftests/net/mptcp/mptcp_lib.sh
··· 319 319 sleep 0.1 320 320 done 321 321 } 322 + 323 + mptcp_lib_check_output() { 324 + local err="${1}" 325 + local cmd="${2}" 326 + local expected="${3}" 327 + local cmd_ret=0 328 + local out 329 + 330 + if ! out=$(${cmd} 2>"${err}"); then 331 + cmd_ret=${?} 332 + fi 333 + 334 + if [ ${cmd_ret} -ne 0 ]; then 335 + mptcp_lib_print_err "[FAIL] command execution '${cmd}' stderr" 336 + cat "${err}" 337 + return 2 338 + elif [ "${out}" = "${expected}" ]; then 339 + return 0 340 + else 341 + mptcp_lib_print_err "[FAIL] expected '${expected}' got '${out}'" 342 + return 1 343 + fi 344 + }
+7 -11
tools/testing/selftests/net/mptcp/pm_netlink.sh
··· 54 54 local cmd="$1" 55 55 local expected="$2" 56 56 local msg="$3" 57 - local out=`$cmd 2>$err` 58 - local cmd_ret=$? 57 + local rc=0 59 58 60 59 printf "%-50s" "$msg" 61 - if [ $cmd_ret -ne 0 ]; then 62 - echo "[FAIL] command execution '$cmd' stderr " 63 - cat $err 64 - mptcp_lib_result_fail "${msg} # error ${cmd_ret}" 60 + mptcp_lib_check_output "${err}" "${cmd}" "${expected}" || rc=${?} 61 + if [ ${rc} -eq 2 ]; then 62 + mptcp_lib_result_fail "${msg} # error ${rc}" 65 63 ret=1 66 - elif [ "$out" = "$expected" ]; then 67 - echo "[ OK ]" 64 + elif [ ${rc} -eq 0 ]; then 65 + mptcp_lib_print_ok "[ OK ]" 68 66 mptcp_lib_result_pass "${msg}" 69 - else 70 - echo -n "[FAIL] " 71 - echo "expected '$expected' got '$out'" 67 + elif [ ${rc} -eq 1 ]; then 72 68 mptcp_lib_result_fail "${msg} # different output" 73 69 ret=1 74 70 fi
+38 -1
tools/testing/selftests/net/mptcp/pm_nl_ctl.c
··· 453 453 char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 454 454 NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 455 455 1024]; 456 + u_int32_t flags = MPTCP_PM_ADDR_FLAG_SUBFLOW; 456 457 const char *params[5]; 457 458 struct nlmsghdr *nh; 458 459 struct rtattr *addr; ··· 558 557 memcpy(RTA_DATA(rta), &id, 1); 559 558 off += NLMSG_ALIGN(rta->rta_len); 560 559 } 560 + 561 + /* addr flags */ 562 + rta = (void *)(data + off); 563 + rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS; 564 + rta->rta_len = RTA_LENGTH(4); 565 + memcpy(RTA_DATA(rta), &flags, 4); 566 + off += NLMSG_ALIGN(rta->rta_len); 561 567 562 568 addr->rta_len = off - addr_start; 563 569 } ··· 1087 1079 1024]; 1088 1080 struct rtattr *rta, *nest; 1089 1081 struct nlmsghdr *nh; 1082 + u_int32_t token = 0; 1090 1083 int nest_start; 1091 1084 u_int8_t id; 1092 1085 int off = 0; ··· 1098 1089 MPTCP_PM_VER); 1099 1090 1100 1091 /* the only argument is the address id */ 1101 - if (argc != 3) 1092 + if (argc != 3 && argc != 5) 1102 1093 syntax(argv); 1103 1094 1104 1095 id = atoi(argv[2]); 1096 + if (argc == 5 && !strcmp(argv[3], "token")) 1097 + token = strtoul(argv[4], NULL, 10); 1105 1098 1106 1099 nest_start = off; 1107 1100 nest = (void *)(data + off); ··· 1119 1108 off += NLMSG_ALIGN(rta->rta_len); 1120 1109 nest->rta_len = off - nest_start; 1121 1110 1111 + /* token */ 1112 + if (token) { 1113 + rta = (void *)(data + off); 1114 + rta->rta_type = MPTCP_PM_ATTR_TOKEN; 1115 + rta->rta_len = RTA_LENGTH(4); 1116 + memcpy(RTA_DATA(rta), &token, 4); 1117 + off += NLMSG_ALIGN(rta->rta_len); 1118 + } 1119 + 1122 1120 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data))); 1123 1121 return 0; 1124 1122 } ··· 1139 1119 1024]; 1140 1120 pid_t pid = getpid(); 1141 1121 struct nlmsghdr *nh; 1122 + u_int32_t token = 0; 1123 + struct rtattr *rta; 1142 1124 int off = 0; 1125 + 1126 + if (argc != 2 && argc != 4) 1127 + syntax(argv); 1128 + 1129 + if (argc == 4 && !strcmp(argv[2], "token")) 1130 + token = strtoul(argv[3], NULL, 10); 1143 1131 1144 1132 memset(data, 0, sizeof(data)); 1145 1133 nh = (void *)data; ··· 1157 1129 nh->nlmsg_seq = 1; 1158 1130 nh->nlmsg_pid = pid; 1159 1131 nh->nlmsg_len = off; 1132 + 1133 + /* token */ 1134 + if (token) { 1135 + rta = (void *)(data + off); 1136 + rta->rta_type = MPTCP_PM_ATTR_TOKEN; 1137 + rta->rta_len = RTA_LENGTH(4); 1138 + memcpy(RTA_DATA(rta), &token, 4); 1139 + off += NLMSG_ALIGN(rta->rta_len); 1140 + } 1160 1141 1161 1142 print_addrs(nh, pm_family, do_nl_req(fd, nh, off, sizeof(data))); 1162 1143 return 0;