Mat Martineau says: ==================== mptcp: Path manager fixes for 5.19 The MPTCP userspace path manager is new in 5.19, and these patches fix some issues in that new code. Patches 1-3 fix path manager locking issues. Patches 4 and 5 allow userspace path managers to change priority of established subflows using the existing MPTCP_PM_CMD_SET_FLAGS generic netlink command. Includes corresponding self test update. Patches 6 and 7 fix accounting of available endpoint IDs and the MPTCP_MIB_RMSUBFLOW counter. ====================
Unified · Split
| @@ -1584,6 +1584,9 @@ mp_rst: · 1583 unmodified lines | |||
| 1584 | *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, | 1584 | *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, |
| 1585 | TCPOLEN_MPTCP_PRIO, | 1585 | TCPOLEN_MPTCP_PRIO, |
| 1586 | opts->backup, TCPOPT_NOP); | 1586 | opts->backup, TCPOPT_NOP); |
| 1587 | |||
| 1588 | MPTCP_INC_STATS(sock_net((const struct sock *)tp), | ||
| 1589 | MPTCP_MIB_MPPRIOTX); | ||
| 1587 | } | 1590 | } |
| 1588 | 1591 | ||
| 1589 | mp_capable_done: | 1592 | mp_capable_done: |
| @@ -717,9 +717,10 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk) · 716 unmodified lines | |||
| 717 | } | 717 | } |
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, | 720 | int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, |
| 721 | struct mptcp_addr_info *addr, | 721 | struct mptcp_addr_info *addr, |
| 722 | u8 bkup) | 722 | struct mptcp_addr_info *rem, |
| 723 | u8 bkup) | ||
| 723 | { | 724 | { |
| 724 | struct mptcp_subflow_context *subflow; | 725 | struct mptcp_subflow_context *subflow; |
| 725 | 726 | ||
| @@ -727,24 +728,29 @@ static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, · 1 unmodified line | |||
| 727 | 728 | ||
| 728 | mptcp_for_each_subflow(msk, subflow) { | 729 | mptcp_for_each_subflow(msk, subflow) { |
| 729 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | 730 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 730 | struct sock *sk = (struct sock *)msk; | 731 | struct mptcp_addr_info local, remote; |
| 731 | struct mptcp_addr_info local; | 732 | bool slow; |
| 732 | 733 | ||
| 733 | local_address((struct sock_common *)ssk, &local); | 734 | local_address((struct sock_common *)ssk, &local); |
| 734 | if (!mptcp_addresses_equal(&local, addr, addr->port)) | 735 | if (!mptcp_addresses_equal(&local, addr, addr->port)) |
| 735 | continue; | 736 | continue; |
| 736 | 737 | ||
| 738 | if (rem && rem->family != AF_UNSPEC) { | ||
| 739 | remote_address((struct sock_common *)ssk, &remote); | ||
| 740 | if (!mptcp_addresses_equal(&remote, rem, rem->port)) | ||
| 741 | continue; | ||
| 742 | } | ||
| 743 | |||
| 744 | slow = lock_sock_fast(ssk); | ||
| 737 | if (subflow->backup != bkup) | 745 | if (subflow->backup != bkup) |
| 738 | msk->last_snd = NULL; | 746 | msk->last_snd = NULL; |
| 739 | subflow->backup = bkup; | 747 | subflow->backup = bkup; |
| 740 | subflow->send_mp_prio = 1; | 748 | subflow->send_mp_prio = 1; |
| 741 | subflow->request_bkup = bkup; | 749 | subflow->request_bkup = bkup; |
| 742 | __MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIOTX); | ||
| 743 | 750 | ||
| 744 | spin_unlock_bh(&msk->pm.lock); | ||
| 745 | pr_debug("send ack for mp_prio"); | 751 | pr_debug("send ack for mp_prio"); |
| 746 | mptcp_subflow_send_ack(ssk); | 752 | __mptcp_subflow_send_ack(ssk); |
| 747 | spin_lock_bh(&msk->pm.lock); | 753 | unlock_sock_fast(ssk, slow); |
| 748 | 754 | ||
| 749 | return 0; | 755 | return 0; |
| 750 | } | 756 | } |
| @@ -801,7 +807,8 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, · 50 unmodified lines | |||
| 801 | removed = true; | 807 | removed = true; |
| 802 | __MPTCP_INC_STATS(sock_net(sk), rm_type); | 808 | __MPTCP_INC_STATS(sock_net(sk), rm_type); |
| 803 | } | 809 | } |
| 804 | __set_bit(rm_list->ids[i], msk->pm.id_avail_bitmap); | 810 | if (rm_type == MPTCP_MIB_RMSUBFLOW) |
| 811 | __set_bit(rm_list->ids[i], msk->pm.id_avail_bitmap); | ||
| 805 | if (!removed) | 812 | if (!removed) |
| 806 | continue; | 813 | continue; |
| 807 | 814 | ||
| @@ -1816,8 +1823,10 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk, · 1008 unmodified lines | |||
| 1816 | 1823 | ||
| 1817 | list.ids[list.nr++] = addr->id; | 1824 | list.ids[list.nr++] = addr->id; |
| 1818 | 1825 | ||
| 1826 | spin_lock_bh(&msk->pm.lock); | ||
| 1819 | mptcp_pm_nl_rm_subflow_received(msk, &list); | 1827 | mptcp_pm_nl_rm_subflow_received(msk, &list); |
| 1820 | mptcp_pm_create_subflow_or_signal_addr(msk); | 1828 | mptcp_pm_create_subflow_or_signal_addr(msk); |
| 1829 | spin_unlock_bh(&msk->pm.lock); | ||
| 1821 | } | 1830 | } |
| 1822 | 1831 | ||
| 1823 | static int mptcp_nl_set_flags(struct net *net, | 1832 | static int mptcp_nl_set_flags(struct net *net, |
| @@ -1835,12 +1844,10 @@ static int mptcp_nl_set_flags(struct net *net, · 11 unmodified lines | |||
| 1835 | goto next; | 1844 | goto next; |
| 1836 | 1845 | ||
| 1837 | lock_sock(sk); | 1846 | lock_sock(sk); |
| 1838 | spin_lock_bh(&msk->pm.lock); | ||
| 1839 | if (changed & MPTCP_PM_ADDR_FLAG_BACKUP) | 1847 | if (changed & MPTCP_PM_ADDR_FLAG_BACKUP) |
| 1840 | ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, bkup); | 1848 | ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup); |
| 1841 | if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH) | 1849 | if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH) |
| 1842 | mptcp_pm_nl_fullmesh(msk, addr); | 1850 | mptcp_pm_nl_fullmesh(msk, addr); |
| 1843 | spin_unlock_bh(&msk->pm.lock); | ||
| 1844 | release_sock(sk); | 1851 | release_sock(sk); |
| 1845 | 1852 | ||
| 1846 | next: | 1853 | next: |
| @@ -1854,6 +1861,9 @@ next: · 7 unmodified lines | |||
| 1854 | static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) | 1861 | static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) |
| 1855 | { | 1862 | { |
| 1856 | struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry; | 1863 | struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry; |
| 1864 | struct mptcp_pm_addr_entry remote = { .addr = { .family = AF_UNSPEC }, }; | ||
| 1865 | struct nlattr *attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE]; | ||
| 1866 | struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; | ||
| 1857 | struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR]; | 1867 | struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR]; |
| 1858 | struct pm_nl_pernet *pernet = genl_info_pm_nl(info); | 1868 | struct pm_nl_pernet *pernet = genl_info_pm_nl(info); |
| 1859 | u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP | | 1869 | u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP | |
| @@ -1866,6 +1876,12 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) · 6 unmodified lines | |||
| 1866 | if (ret < 0) | 1876 | if (ret < 0) |
| 1867 | return ret; | 1877 | return ret; |
| 1868 | 1878 | ||
| 1879 | if (attr_rem) { | ||
| 1880 | ret = mptcp_pm_parse_entry(attr_rem, info, false, &remote); | ||
| 1881 | if (ret < 0) | ||
| 1882 | return ret; | ||
| 1883 | } | ||
| 1884 | |||
| 1869 | if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP) | 1885 | if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP) |
| 1870 | bkup = 1; | 1886 | bkup = 1; |
| 1871 | if (addr.addr.family == AF_UNSPEC) { | 1887 | if (addr.addr.family == AF_UNSPEC) { |
| @@ -1874,6 +1890,10 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) · 2 unmodified lines | |||
| 1874 | return -EOPNOTSUPP; | 1890 | return -EOPNOTSUPP; |
| 1875 | } | 1891 | } |
| 1876 | 1892 | ||
| 1893 | if (token) | ||
| 1894 | return mptcp_userspace_pm_set_flags(sock_net(skb->sk), | ||
| 1895 | token, &addr, &remote, bkup); | ||
| 1896 | |||
| 1877 | spin_lock_bh(&pernet->lock); | 1897 | spin_lock_bh(&pernet->lock); |
| 1878 | entry = __lookup_addr(pernet, &addr.addr, lookup_by_id); | 1898 | entry = __lookup_addr(pernet, &addr.addr, lookup_by_id); |
| 1879 | if (!entry) { | 1899 | if (!entry) { |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include "protocol.h" | 7 | #include "protocol.h" |
| 8 | #include "mib.h" | ||
| 8 | 9 | ||
| 9 | void mptcp_free_local_addr_list(struct mptcp_sock *msk) | 10 | void mptcp_free_local_addr_list(struct mptcp_sock *msk) |
| 10 | { | 11 | { |
| @@ -306,15 +307,11 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk, · 295 unmodified lines | |||
| 306 | const struct mptcp_addr_info *local, | 307 | const struct mptcp_addr_info *local, |
| 307 | const struct mptcp_addr_info *remote) | 308 | const struct mptcp_addr_info *remote) |
| 308 | { | 309 | { |
| 309 | struct sock *sk = &msk->sk.icsk_inet.sk; | ||
| 310 | struct mptcp_subflow_context *subflow; | 310 | struct mptcp_subflow_context *subflow; |
| 311 | struct sock *found = NULL; | ||
| 312 | 311 | ||
| 313 | if (local->family != remote->family) | 312 | if (local->family != remote->family) |
| 314 | return NULL; | 313 | return NULL; |
| 315 | 314 | ||
| 316 | lock_sock(sk); | ||
| 317 | |||
| 318 | mptcp_for_each_subflow(msk, subflow) { | 315 | mptcp_for_each_subflow(msk, subflow) { |
| 319 | const struct inet_sock *issk; | 316 | const struct inet_sock *issk; |
| 320 | struct sock *ssk; | 317 | struct sock *ssk; |
| @@ -347,16 +344,11 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk, · 26 unmodified lines | |||
| 347 | } | 344 | } |
| 348 | 345 | ||
| 349 | if (issk->inet_sport == local->port && | 346 | if (issk->inet_sport == local->port && |
| 350 | issk->inet_dport == remote->port) { | 347 | issk->inet_dport == remote->port) |
| 351 | found = ssk; | 348 | return ssk; |
| 352 | goto found; | ||
| 353 | } | ||
| 354 | } | 349 | } |
| 355 | 350 | ||
| 356 | found: | 351 | return NULL; |
| 357 | release_sock(sk); | ||
| 358 | |||
| 359 | return found; | ||
| 360 | } | 352 | } |
| 361 | 353 | ||
| 362 | int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info) | 354 | int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info) |
| @@ -412,18 +404,51 @@ int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info) · 49 unmodified lines | |||
| 412 | } | 404 | } |
| 413 | 405 | ||
| 414 | sk = &msk->sk.icsk_inet.sk; | 406 | sk = &msk->sk.icsk_inet.sk; |
| 407 | lock_sock(sk); | ||
| 415 | ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r); | 408 | ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r); |
| 416 | if (ssk) { | 409 | if (ssk) { |
| 417 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | 410 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 418 | 411 | ||
| 419 | mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN); | 412 | mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN); |
| 420 | mptcp_close_ssk(sk, ssk, subflow); | 413 | mptcp_close_ssk(sk, ssk, subflow); |
| 414 | MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW); | ||
| 421 | err = 0; | 415 | err = 0; |
| 422 | } else { | 416 | } else { |
| 423 | err = -ESRCH; | 417 | err = -ESRCH; |
| 424 | } | 418 | } |
| 419 | release_sock(sk); | ||
| 425 | 420 | ||
| 426 | destroy_err: | 421 | destroy_err: |
| 427 | sock_put((struct sock *)msk); | 422 | sock_put((struct sock *)msk); |
| 428 | return err; | 423 | return err; |
| 429 | } | 424 | } |
| 425 | |||
| 426 | int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token, | ||
| 427 | struct mptcp_pm_addr_entry *loc, | ||
| 428 | struct mptcp_pm_addr_entry *rem, u8 bkup) | ||
| 429 | { | ||
| 430 | struct mptcp_sock *msk; | ||
| 431 | int ret = -EINVAL; | ||
| 432 | u32 token_val; | ||
| 433 | |||
| 434 | token_val = nla_get_u32(token); | ||
| 435 | |||
| 436 | msk = mptcp_token_get_sock(net, token_val); | ||
| 437 | if (!msk) | ||
| 438 | return ret; | ||
| 439 | |||
| 440 | if (!mptcp_pm_is_userspace(msk)) | ||
| 441 | goto set_flags_err; | ||
| 442 | |||
| 443 | if (loc->addr.family == AF_UNSPEC || | ||
| 444 | rem->addr.family == AF_UNSPEC) | ||
| 445 | goto set_flags_err; | ||
| 446 | |||
| 447 | lock_sock((struct sock *)msk); | ||
| 448 | ret = mptcp_pm_nl_mp_prio_send_ack(msk, &loc->addr, &rem->addr, bkup); | ||
| 449 | release_sock((struct sock *)msk); | ||
| 450 | |||
| 451 | set_flags_err: | ||
| 452 | sock_put((struct sock *)msk); | ||
| 453 | return ret; | ||
| 454 | } | ||
| @@ -506,13 +506,18 @@ static inline bool tcp_can_send_ack(const struct sock *ssk) · 505 unmodified lines | |||
| 506 | (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN)); | 506 | (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN)); |
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | void __mptcp_subflow_send_ack(struct sock *ssk) | ||
| 510 | { | ||
| 511 | if (tcp_can_send_ack(ssk)) | ||
| 512 | tcp_send_ack(ssk); | ||
| 513 | } | ||
| 514 | |||
| 509 | void mptcp_subflow_send_ack(struct sock *ssk) | 515 | void mptcp_subflow_send_ack(struct sock *ssk) |
| 510 | { | 516 | { |
| 511 | bool slow; | 517 | bool slow; |
| 512 | 518 | ||
| 513 | slow = lock_sock_fast(ssk); | 519 | slow = lock_sock_fast(ssk); |
| 514 | if (tcp_can_send_ack(ssk)) | 520 | __mptcp_subflow_send_ack(ssk); |
| 515 | tcp_send_ack(ssk); | ||
| 516 | unlock_sock_fast(ssk, slow); | 521 | unlock_sock_fast(ssk, slow); |
| 517 | } | 522 | } |
| 518 | 523 | ||
| @@ -607,6 +607,7 @@ void __init mptcp_subflow_init(void); · 606 unmodified lines | |||
| 607 | void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how); | 607 | void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how); |
| 608 | void mptcp_close_ssk(struct sock *sk, struct sock *ssk, | 608 | void mptcp_close_ssk(struct sock *sk, struct sock *ssk, |
| 609 | struct mptcp_subflow_context *subflow); | 609 | struct mptcp_subflow_context *subflow); |
| 610 | void __mptcp_subflow_send_ack(struct sock *ssk); | ||
| 610 | void mptcp_subflow_send_ack(struct sock *ssk); | 611 | void mptcp_subflow_send_ack(struct sock *ssk); |
| 611 | void mptcp_subflow_reset(struct sock *ssk); | 612 | void mptcp_subflow_reset(struct sock *ssk); |
| 612 | void mptcp_subflow_queue_clean(struct sock *ssk); | 613 | void mptcp_subflow_queue_clean(struct sock *ssk); |
| @@ -771,6 +772,10 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, · 158 unmodified lines | |||
| 771 | const struct mptcp_rm_list *rm_list); | 772 | const struct mptcp_rm_list *rm_list); |
| 772 | void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup); | 773 | void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup); |
| 773 | void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq); | 774 | void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq); |
| 775 | int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, | ||
| 776 | struct mptcp_addr_info *addr, | ||
| 777 | struct mptcp_addr_info *rem, | ||
| 778 | u8 bkup); | ||
| 774 | bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk, | 779 | bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk, |
| 775 | const struct mptcp_pm_addr_entry *entry); | 780 | const struct mptcp_pm_addr_entry *entry); |
| 776 | void mptcp_pm_free_anno_list(struct mptcp_sock *msk); | 781 | void mptcp_pm_free_anno_list(struct mptcp_sock *msk); |
| @@ -787,7 +792,9 @@ int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, · 10 unmodified lines | |||
| 787 | int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, | 792 | int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, |
| 788 | unsigned int id, | 793 | unsigned int id, |
| 789 | u8 *flags, int *ifindex); | 794 | u8 *flags, int *ifindex); |
| 790 | 795 | int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token, | |
| 796 | struct mptcp_pm_addr_entry *loc, | ||
| 797 | struct mptcp_pm_addr_entry *rem, u8 bkup); | ||
| 791 | int mptcp_pm_announce_addr(struct mptcp_sock *msk, | 798 | int mptcp_pm_announce_addr(struct mptcp_sock *msk, |
| 792 | const struct mptcp_addr_info *addr, | 799 | const struct mptcp_addr_info *addr, |
| 793 | bool echo); | 800 | bool echo); |
| @@ -39,7 +39,7 @@ static void syntax(char *argv[]) · 38 unmodified lines | |||
| 39 | fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n"); | 39 | fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n"); |
| 40 | fprintf(stderr, "\tdel <id> [<ip>]\n"); | 40 | fprintf(stderr, "\tdel <id> [<ip>]\n"); |
| 41 | fprintf(stderr, "\tget <id>\n"); | 41 | fprintf(stderr, "\tget <id>\n"); |
| 42 | fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>]\n"); | 42 | fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n"); |
| 43 | fprintf(stderr, "\tflush\n"); | 43 | fprintf(stderr, "\tflush\n"); |
| 44 | fprintf(stderr, "\tdump\n"); | 44 | fprintf(stderr, "\tdump\n"); |
| 45 | fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n"); | 45 | fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n"); |
| @@ -1279,7 +1279,10 @@ int set_flags(int fd, int pm_family, int argc, char *argv[]) · 1233 unmodified lines | |||
| 1279 | struct rtattr *rta, *nest; | 1279 | struct rtattr *rta, *nest; |
| 1280 | struct nlmsghdr *nh; | 1280 | struct nlmsghdr *nh; |
| 1281 | u_int32_t flags = 0; | 1281 | u_int32_t flags = 0; |
| 1282 | u_int32_t token = 0; | ||
| 1283 | u_int16_t rport = 0; | ||
| 1282 | u_int16_t family; | 1284 | u_int16_t family; |
| 1285 | void *rip = NULL; | ||
| 1283 | int nest_start; | 1286 | int nest_start; |
| 1284 | int use_id = 0; | 1287 | int use_id = 0; |
| 1285 | u_int8_t id; | 1288 | u_int8_t id; |
| @@ -1339,7 +1342,13 @@ int set_flags(int fd, int pm_family, int argc, char *argv[]) · 53 unmodified lines | |||
| 1339 | error(1, 0, " missing flags keyword"); | 1342 | error(1, 0, " missing flags keyword"); |
| 1340 | 1343 | ||
| 1341 | for (; arg < argc; arg++) { | 1344 | for (; arg < argc; arg++) { |
| 1342 | if (!strcmp(argv[arg], "flags")) { | 1345 | if (!strcmp(argv[arg], "token")) { |
| 1346 | if (++arg >= argc) | ||
| 1347 | error(1, 0, " missing token value"); | ||
| 1348 | |||
| 1349 | /* token */ | ||
| 1350 | token = atoi(argv[arg]); | ||
| 1351 | } else if (!strcmp(argv[arg], "flags")) { | ||
| 1343 | char *tok, *str; | 1352 | char *tok, *str; |
| 1344 | 1353 | ||
| 1345 | /* flags */ | 1354 | /* flags */ |
| @@ -1378,12 +1387,72 @@ int set_flags(int fd, int pm_family, int argc, char *argv[]) · 32 unmodified lines | |||
| 1378 | rta->rta_len = RTA_LENGTH(2); | 1387 | rta->rta_len = RTA_LENGTH(2); |
| 1379 | memcpy(RTA_DATA(rta), &port, 2); | 1388 | memcpy(RTA_DATA(rta), &port, 2); |
| 1380 | off += NLMSG_ALIGN(rta->rta_len); | 1389 | off += NLMSG_ALIGN(rta->rta_len); |
| 1390 | } else if (!strcmp(argv[arg], "rport")) { | ||
| 1391 | if (++arg >= argc) | ||
| 1392 | error(1, 0, " missing remote port"); | ||
| 1393 | |||
| 1394 | rport = atoi(argv[arg]); | ||
| 1395 | } else if (!strcmp(argv[arg], "rip")) { | ||
| 1396 | if (++arg >= argc) | ||
| 1397 | error(1, 0, " missing remote ip"); | ||
| 1398 | |||
| 1399 | rip = argv[arg]; | ||
| 1381 | } else { | 1400 | } else { |
| 1382 | error(1, 0, "unknown keyword %s", argv[arg]); | 1401 | error(1, 0, "unknown keyword %s", argv[arg]); |
| 1383 | } | 1402 | } |
| 1384 | } | 1403 | } |
| 1385 | nest->rta_len = off - nest_start; | 1404 | nest->rta_len = off - nest_start; |
| 1386 | 1405 | ||
| 1406 | /* token */ | ||
| 1407 | if (token) { | ||
| 1408 | rta = (void *)(data + off); | ||
| 1409 | rta->rta_type = MPTCP_PM_ATTR_TOKEN; | ||
| 1410 | rta->rta_len = RTA_LENGTH(4); | ||
| 1411 | memcpy(RTA_DATA(rta), &token, 4); | ||
| 1412 | off += NLMSG_ALIGN(rta->rta_len); | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | /* remote addr/port */ | ||
| 1416 | if (rip) { | ||
| 1417 | nest_start = off; | ||
| 1418 | nest = (void *)(data + off); | ||
| 1419 | nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE; | ||
| 1420 | nest->rta_len = RTA_LENGTH(0); | ||
| 1421 | off += NLMSG_ALIGN(nest->rta_len); | ||
| 1422 | |||
| 1423 | /* addr data */ | ||
| 1424 | rta = (void *)(data + off); | ||
| 1425 | if (inet_pton(AF_INET, rip, RTA_DATA(rta))) { | ||
| 1426 | family = AF_INET; | ||
| 1427 | rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4; | ||
| 1428 | rta->rta_len = RTA_LENGTH(4); | ||
| 1429 | } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) { | ||
| 1430 | family = AF_INET6; | ||
| 1431 | rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6; | ||
| 1432 | rta->rta_len = RTA_LENGTH(16); | ||
| 1433 | } else { | ||
| 1434 | error(1, errno, "can't parse ip %s", (char *)rip); | ||
| 1435 | } | ||
| 1436 | off += NLMSG_ALIGN(rta->rta_len); | ||
| 1437 | |||
| 1438 | /* family */ | ||
| 1439 | rta = (void *)(data + off); | ||
| 1440 | rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY; | ||
| 1441 | rta->rta_len = RTA_LENGTH(2); | ||
| 1442 | memcpy(RTA_DATA(rta), &family, 2); | ||
| 1443 | off += NLMSG_ALIGN(rta->rta_len); | ||
| 1444 | |||
| 1445 | if (rport) { | ||
| 1446 | rta = (void *)(data + off); | ||
| 1447 | rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT; | ||
| 1448 | rta->rta_len = RTA_LENGTH(2); | ||
| 1449 | memcpy(RTA_DATA(rta), &rport, 2); | ||
| 1450 | off += NLMSG_ALIGN(rta->rta_len); | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | nest->rta_len = off - nest_start; | ||
| 1454 | } | ||
| 1455 | |||
| 1387 | do_nl_req(fd, nh, off, 0); | 1456 | do_nl_req(fd, nh, off, 0); |
| 1388 | return 0; | 1457 | return 0; |
| 1389 | } | 1458 | } |
| @@ -770,10 +770,42 @@ test_subflows() · 769 unmodified lines | |||
| 770 | rm -f "$evts" | 770 | rm -f "$evts" |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | test_prio() | ||
| 774 | { | ||
| 775 | local count | ||
| 776 | |||
| 777 | # Send MP_PRIO signal from client to server machine | ||
| 778 | ip netns exec "$ns2" ./pm_nl_ctl set 10.0.1.2 port "$client4_port" flags backup token "$client4_token" rip 10.0.1.1 rport "$server4_port" | ||
| 779 | sleep 0.5 | ||
| 780 | |||
| 781 | # Check TX | ||
| 782 | stdbuf -o0 -e0 printf "MP_PRIO TX \t" | ||
| 783 | count=$(ip netns exec "$ns2" nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}') | ||
| 784 | [ -z "$count" ] && count=0 | ||
| 785 | if [ $count != 1 ]; then | ||
| 786 | stdbuf -o0 -e0 printf "[FAIL]\n" | ||
| 787 | exit 1 | ||
| 788 | else | ||
| 789 | stdbuf -o0 -e0 printf "[OK]\n" | ||
| 790 | fi | ||
| 791 | |||
| 792 | # Check RX | ||
| 793 | stdbuf -o0 -e0 printf "MP_PRIO RX \t" | ||
| 794 | count=$(ip netns exec "$ns1" nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}') | ||
| 795 | [ -z "$count" ] && count=0 | ||
| 796 | if [ $count != 1 ]; then | ||
| 797 | stdbuf -o0 -e0 printf "[FAIL]\n" | ||
| 798 | exit 1 | ||
| 799 | else | ||
| 800 | stdbuf -o0 -e0 printf "[OK]\n" | ||
| 801 | fi | ||
| 802 | } | ||
| 803 | |||
| 773 | make_connection | 804 | make_connection |
| 774 | make_connection "v6" | 805 | make_connection "v6" |
| 775 | test_announce | 806 | test_announce |
| 776 | test_remove | 807 | test_remove |
| 777 | test_subflows | 808 | test_subflows |
| 809 | test_prio | ||
| 778 | 810 | ||
| 779 | exit 0 | 811 | exit 0 |