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 | 1584 | *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, |
| 1585 | 1585 | TCPOLEN_MPTCP_PRIO, |
| 1586 | 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 | 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, | |
| 721 | − struct mptcp_addr_info *addr, | |
| 722 | − u8 bkup) | |
| 720 | +int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, | |
| 721 | + struct mptcp_addr_info *addr, | |
| 722 | + struct mptcp_addr_info *rem, | |
| 723 | + u8 bkup) | |
| 723 | 724 | { |
| 724 | 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 | 729 | mptcp_for_each_subflow(msk, subflow) { |
| 729 | 730 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 730 | − struct sock *sk = (struct sock *)msk; | |
| 731 | − struct mptcp_addr_info local; | |
| 731 | + struct mptcp_addr_info local, remote; | |
| 732 | + bool slow; | |
| 732 | 733 | |
| 733 | 734 | local_address((struct sock_common *)ssk, &local); |
| 734 | 735 | if (!mptcp_addresses_equal(&local, addr, addr->port)) |
| 735 | 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 | 745 | if (subflow->backup != bkup) |
| 738 | 746 | msk->last_snd = NULL; |
| 739 | 747 | subflow->backup = bkup; |
| 740 | 748 | subflow->send_mp_prio = 1; |
| 741 | 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 | 751 | pr_debug("send ack for mp_prio"); |
| 746 | − mptcp_subflow_send_ack(ssk); | |
| 747 | − spin_lock_bh(&msk->pm.lock); | |
| 752 | + __mptcp_subflow_send_ack(ssk); | |
| 753 | + unlock_sock_fast(ssk, slow); | |
| 748 | 754 | |
| 749 | 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 | 807 | removed = true; |
| 802 | 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 | 812 | if (!removed) |
| 806 | 813 | continue; |
| 807 | 814 | |
| @@ -1816,8 +1823,10 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk, · 1008 unmodified lines | ||
| 1816 | 1823 | |
| 1817 | 1824 | list.ids[list.nr++] = addr->id; |
| 1818 | 1825 | |
| 1826 | + spin_lock_bh(&msk->pm.lock); | |
| 1819 | 1827 | mptcp_pm_nl_rm_subflow_received(msk, &list); |
| 1820 | 1828 | mptcp_pm_create_subflow_or_signal_addr(msk); |
| 1829 | + spin_unlock_bh(&msk->pm.lock); | |
| 1821 | 1830 | } |
| 1822 | 1831 | |
| 1823 | 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 | 1844 | goto next; |
| 1836 | 1845 | |
| 1837 | 1846 | lock_sock(sk); |
| 1838 | − spin_lock_bh(&msk->pm.lock); | |
| 1839 | 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 | 1849 | if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH) |
| 1842 | 1850 | mptcp_pm_nl_fullmesh(msk, addr); |
| 1843 | − spin_unlock_bh(&msk->pm.lock); | |
| 1844 | 1851 | release_sock(sk); |
| 1845 | 1852 | |
| 1846 | 1853 | next: |
| @@ -1854,6 +1861,9 @@ next: · 7 unmodified lines | ||
| 1854 | 1861 | static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) |
| 1855 | 1862 | { |
| 1856 | 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 | 1867 | struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR]; |
| 1858 | 1868 | struct pm_nl_pernet *pernet = genl_info_pm_nl(info); |
| 1859 | 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 | 1876 | if (ret < 0) |
| 1867 | 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 | 1885 | if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP) |
| 1870 | 1886 | bkup = 1; |
| 1871 | 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 | 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 | 1897 | spin_lock_bh(&pernet->lock); |
| 1878 | 1898 | entry = __lookup_addr(pernet, &addr.addr, lookup_by_id); |
| 1879 | 1899 | if (!entry) { |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | #include "protocol.h" |
| 8 | +#include "mib.h" | |
| 8 | 9 | |
| 9 | 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 | 307 | const struct mptcp_addr_info *local, |
| 307 | 308 | const struct mptcp_addr_info *remote) |
| 308 | 309 | { |
| 309 | − struct sock *sk = &msk->sk.icsk_inet.sk; | |
| 310 | 310 | struct mptcp_subflow_context *subflow; |
| 311 | − struct sock *found = NULL; | |
| 312 | 311 | |
| 313 | 312 | if (local->family != remote->family) |
| 314 | 313 | return NULL; |
| 315 | 314 | |
| 316 | − lock_sock(sk); | |
| 317 | − | |
| 318 | 315 | mptcp_for_each_subflow(msk, subflow) { |
| 319 | 316 | const struct inet_sock *issk; |
| 320 | 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 | 346 | if (issk->inet_sport == local->port && |
| 350 | − issk->inet_dport == remote->port) { | |
| 351 | − found = ssk; | |
| 352 | − goto found; | |
| 353 | − } | |
| 347 | + issk->inet_dport == remote->port) | |
| 348 | + return ssk; | |
| 354 | 349 | } |
| 355 | 350 | |
| 356 | −found: | |
| 357 | − release_sock(sk); | |
| 358 | − | |
| 359 | − return found; | |
| 351 | + return NULL; | |
| 360 | 352 | } |
| 361 | 353 | |
| 362 | 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 | 406 | sk = &msk->sk.icsk_inet.sk; |
| 407 | + lock_sock(sk); | |
| 415 | 408 | ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r); |
| 416 | 409 | if (ssk) { |
| 417 | 410 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 418 | 411 | |
| 419 | 412 | mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN); |
| 420 | 413 | mptcp_close_ssk(sk, ssk, subflow); |
| 414 | + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW); | |
| 421 | 415 | err = 0; |
| 422 | 416 | } else { |
| 423 | 417 | err = -ESRCH; |
| 424 | 418 | } |
| 419 | + release_sock(sk); | |
| 425 | 420 | |
| 426 | − destroy_err: | |
| 421 | +destroy_err: | |
| 427 | 422 | sock_put((struct sock *)msk); |
| 428 | 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 | 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 | 515 | void mptcp_subflow_send_ack(struct sock *ssk) |
| 510 | 516 | { |
| 511 | 517 | bool slow; |
| 512 | 518 | |
| 513 | 519 | slow = lock_sock_fast(ssk); |
| 514 | − if (tcp_can_send_ack(ssk)) | |
| 515 | − tcp_send_ack(ssk); | |
| 520 | + __mptcp_subflow_send_ack(ssk); | |
| 516 | 521 | unlock_sock_fast(ssk, slow); |
| 517 | 522 | } |
| 518 | 523 | |
| @@ -607,6 +607,7 @@ void __init mptcp_subflow_init(void); · 606 unmodified lines | ||
| 607 | 607 | void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how); |
| 608 | 608 | void mptcp_close_ssk(struct sock *sk, struct sock *ssk, |
| 609 | 609 | struct mptcp_subflow_context *subflow); |
| 610 | +void __mptcp_subflow_send_ack(struct sock *ssk); | |
| 610 | 611 | void mptcp_subflow_send_ack(struct sock *ssk); |
| 611 | 612 | void mptcp_subflow_reset(struct sock *ssk); |
| 612 | 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 | 772 | const struct mptcp_rm_list *rm_list); |
| 772 | 773 | void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup); |
| 773 | 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 | 779 | bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk, |
| 775 | 780 | const struct mptcp_pm_addr_entry *entry); |
| 776 | 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 | 792 | int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, |
| 788 | 793 | unsigned int id, |
| 789 | 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 | 798 | int mptcp_pm_announce_addr(struct mptcp_sock *msk, |
| 792 | 799 | const struct mptcp_addr_info *addr, |
| 793 | 800 | bool echo); |
| @@ -39,7 +39,7 @@ static void syntax(char *argv[]) · 38 unmodified lines | ||
| 39 | 39 | fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n"); |
| 40 | 40 | fprintf(stderr, "\tdel <id> [<ip>]\n"); |
| 41 | 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 | 43 | fprintf(stderr, "\tflush\n"); |
| 44 | 44 | fprintf(stderr, "\tdump\n"); |
| 45 | 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 | 1279 | struct rtattr *rta, *nest; |
| 1280 | 1280 | struct nlmsghdr *nh; |
| 1281 | 1281 | u_int32_t flags = 0; |
| 1282 | + u_int32_t token = 0; | |
| 1283 | + u_int16_t rport = 0; | |
| 1282 | 1284 | u_int16_t family; |
| 1285 | + void *rip = NULL; | |
| 1283 | 1286 | int nest_start; |
| 1284 | 1287 | int use_id = 0; |
| 1285 | 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 | 1342 | error(1, 0, " missing flags keyword"); |
| 1340 | 1343 | |
| 1341 | 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 | 1352 | char *tok, *str; |
| 1344 | 1353 | |
| 1345 | 1354 | /* flags */ |
| @@ -1378,12 +1387,72 @@ int set_flags(int fd, int pm_family, int argc, char *argv[]) · 32 unmodified lines | ||
| 1378 | 1387 | rta->rta_len = RTA_LENGTH(2); |
| 1379 | 1388 | memcpy(RTA_DATA(rta), &port, 2); |
| 1380 | 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 | 1400 | } else { |
| 1382 | 1401 | error(1, 0, "unknown keyword %s", argv[arg]); |
| 1383 | 1402 | } |
| 1384 | 1403 | } |
| 1385 | 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 | 1456 | do_nl_req(fd, nh, off, 0); |
| 1388 | 1457 | return 0; |
| 1389 | 1458 | } |
| @@ -770,10 +770,42 @@ test_subflows() · 769 unmodified lines | ||
| 770 | 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 | 804 | make_connection |
| 774 | 805 | make_connection "v6" |
| 775 | 806 | test_announce |
| 776 | 807 | test_remove |
| 777 | 808 | test_subflows |
| 809 | +test_prio | |
| 778 | 810 | |
| 779 | 811 | exit 0 |