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

Merge branch 'mptcp-add-mp_prio-support-and-rework-local-address-ids'

Mat Martineau says:

====================
MPTCP: Add MP_PRIO support and rework local address IDs

Patches 1 and 2 rework the assignment of local address IDs to allow them
to be assigned by a userspace path manager, and add corresponding self
tests.

Patches 2-8 add the ability to change subflow priority after a subflow
has been established. Each subflow in a MPTCP connection has a priority
level: "regular" or "backup". Data should only be sent on backup
subflows if no regular subflows are available. The priority level can be
set when the subflow connection is established (as was already
implemented), or during the life of the connection by sending MP_PRIO in
the TCP options (as added here). Self tests are included.
====================

Link: https://lore.kernel.org/r/20210109004802.341602-1-mathew.j.martineau@linux.intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+429 -21
+1
include/uapi/linux/mptcp.h
··· 82 82 MPTCP_PM_CMD_FLUSH_ADDRS, 83 83 MPTCP_PM_CMD_SET_LIMITS, 84 84 MPTCP_PM_CMD_GET_LIMITS, 85 + MPTCP_PM_CMD_SET_FLAGS, 85 86 86 87 __MPTCP_PM_CMD_AFTER_LAST 87 88 };
+2
net/mptcp/mib.c
··· 31 31 SNMP_MIB_ITEM("EchoAdd", MPTCP_MIB_ECHOADD), 32 32 SNMP_MIB_ITEM("RmAddr", MPTCP_MIB_RMADDR), 33 33 SNMP_MIB_ITEM("RmSubflow", MPTCP_MIB_RMSUBFLOW), 34 + SNMP_MIB_ITEM("MPPrioTx", MPTCP_MIB_MPPRIOTX), 35 + SNMP_MIB_ITEM("MPPrioRx", MPTCP_MIB_MPPRIORX), 34 36 SNMP_MIB_SENTINEL 35 37 }; 36 38
+2
net/mptcp/mib.h
··· 24 24 MPTCP_MIB_ECHOADD, /* Received ADD_ADDR with echo-flag=1 */ 25 25 MPTCP_MIB_RMADDR, /* Received RM_ADDR */ 26 26 MPTCP_MIB_RMSUBFLOW, /* Remove a subflow */ 27 + MPTCP_MIB_MPPRIOTX, /* Transmit a MP_PRIO */ 28 + MPTCP_MIB_MPPRIORX, /* Received a MP_PRIO */ 27 29 __MPTCP_MIB_MAX 28 30 }; 29 31
+56
net/mptcp/options.c
··· 282 282 pr_debug("RM_ADDR: id=%d", mp_opt->rm_id); 283 283 break; 284 284 285 + case MPTCPOPT_MP_PRIO: 286 + if (opsize != TCPOLEN_MPTCP_PRIO) 287 + break; 288 + 289 + mp_opt->mp_prio = 1; 290 + mp_opt->backup = *ptr++ & MPTCP_PRIO_BKUP; 291 + pr_debug("MP_PRIO: prio=%d", mp_opt->backup); 292 + break; 293 + 285 294 case MPTCPOPT_MP_FASTCLOSE: 286 295 if (opsize != TCPOLEN_MPTCP_FASTCLOSE) 287 296 break; ··· 322 313 mp_opt->port = 0; 323 314 mp_opt->rm_addr = 0; 324 315 mp_opt->dss = 0; 316 + mp_opt->mp_prio = 0; 325 317 326 318 length = (th->doff * 4) - sizeof(struct tcphdr); 327 319 ptr = (const unsigned char *)(th + 1); ··· 689 679 return true; 690 680 } 691 681 682 + static bool mptcp_established_options_mp_prio(struct sock *sk, 683 + unsigned int *size, 684 + unsigned int remaining, 685 + struct mptcp_out_options *opts) 686 + { 687 + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 688 + 689 + if (!subflow->send_mp_prio) 690 + return false; 691 + 692 + if (remaining < TCPOLEN_MPTCP_PRIO) 693 + return false; 694 + 695 + *size = TCPOLEN_MPTCP_PRIO; 696 + opts->suboptions |= OPTION_MPTCP_PRIO; 697 + opts->backup = subflow->request_bkup; 698 + 699 + pr_debug("prio=%d", opts->backup); 700 + 701 + return true; 702 + } 703 + 692 704 bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, 693 705 unsigned int *size, unsigned int remaining, 694 706 struct mptcp_out_options *opts) ··· 748 716 remaining -= opt_size; 749 717 ret = true; 750 718 } else if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) { 719 + *size += opt_size; 720 + remaining -= opt_size; 721 + ret = true; 722 + } 723 + 724 + if (mptcp_established_options_mp_prio(sk, &opt_size, remaining, opts)) { 751 725 *size += opt_size; 752 726 remaining -= opt_size; 753 727 ret = true; ··· 1032 994 mp_opt.rm_addr = 0; 1033 995 } 1034 996 997 + if (mp_opt.mp_prio) { 998 + mptcp_pm_mp_prio_received(sk, mp_opt.backup); 999 + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIORX); 1000 + mp_opt.mp_prio = 0; 1001 + } 1002 + 1035 1003 if (!mp_opt.dss) 1036 1004 return; 1037 1005 ··· 1210 1166 *ptr++ = mptcp_option(MPTCPOPT_RM_ADDR, 1211 1167 TCPOLEN_MPTCP_RM_ADDR_BASE, 1212 1168 0, opts->rm_id); 1169 + } 1170 + 1171 + if (OPTION_MPTCP_PRIO & opts->suboptions) { 1172 + const struct sock *ssk = (const struct sock *)tp; 1173 + struct mptcp_subflow_context *subflow; 1174 + 1175 + subflow = mptcp_subflow_ctx(ssk); 1176 + subflow->send_mp_prio = 0; 1177 + 1178 + *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, 1179 + TCPOLEN_MPTCP_PRIO, 1180 + opts->backup, TCPOPT_NOP); 1213 1181 } 1214 1182 1215 1183 if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
+8
net/mptcp/pm.c
··· 207 207 spin_unlock_bh(&pm->lock); 208 208 } 209 209 210 + void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup) 211 + { 212 + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 213 + 214 + pr_debug("subflow->backup=%d, bkup=%d\n", subflow->backup, bkup); 215 + subflow->backup = bkup; 216 + } 217 + 210 218 /* path manager helpers */ 211 219 212 220 bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
+153 -17
net/mptcp/pm_netlink.c
··· 36 36 u8 retrans_times; 37 37 }; 38 38 39 + #define MAX_ADDR_ID 255 40 + #define BITMAP_SZ DIV_ROUND_UP(MAX_ADDR_ID + 1, BITS_PER_LONG) 41 + 39 42 struct pm_nl_pernet { 40 43 /* protects pernet updates */ 41 44 spinlock_t lock; ··· 49 46 unsigned int local_addr_max; 50 47 unsigned int subflows_max; 51 48 unsigned int next_id; 49 + unsigned long id_bitmap[BITMAP_SZ]; 52 50 }; 53 51 54 52 #define MPTCP_PM_ADDR_MAX 8 ··· 442 438 } 443 439 } 444 440 441 + int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, 442 + struct mptcp_addr_info *addr, 443 + u8 bkup) 444 + { 445 + struct mptcp_subflow_context *subflow; 446 + 447 + pr_debug("bkup=%d", bkup); 448 + 449 + mptcp_for_each_subflow(msk, subflow) { 450 + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); 451 + struct sock *sk = (struct sock *)msk; 452 + struct mptcp_addr_info local; 453 + 454 + local_address((struct sock_common *)ssk, &local); 455 + if (!addresses_equal(&local, addr, addr->port)) 456 + continue; 457 + 458 + subflow->backup = bkup; 459 + subflow->send_mp_prio = 1; 460 + subflow->request_bkup = bkup; 461 + __MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIOTX); 462 + 463 + spin_unlock_bh(&msk->pm.lock); 464 + pr_debug("send ack for mp_prio"); 465 + lock_sock(ssk); 466 + tcp_send_ack(ssk); 467 + release_sock(ssk); 468 + spin_lock_bh(&msk->pm.lock); 469 + 470 + return 0; 471 + } 472 + 473 + return -EINVAL; 474 + } 475 + 445 476 void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk) 446 477 { 447 478 struct mptcp_subflow_context *subflow, *tmp; ··· 563 524 /* to keep the code simple, don't do IDR-like allocation for address ID, 564 525 * just bail when we exceed limits 565 526 */ 566 - if (pernet->next_id > 255) 567 - goto out; 527 + if (pernet->next_id == MAX_ADDR_ID) 528 + pernet->next_id = 1; 568 529 if (pernet->addrs >= MPTCP_PM_ADDR_MAX) 530 + goto out; 531 + if (test_bit(entry->addr.id, pernet->id_bitmap)) 569 532 goto out; 570 533 571 534 /* do not insert duplicate address, differentiate on port only ··· 580 539 goto out; 581 540 } 582 541 542 + if (!entry->addr.id) { 543 + find_next: 544 + entry->addr.id = find_next_zero_bit(pernet->id_bitmap, 545 + MAX_ADDR_ID + 1, 546 + pernet->next_id); 547 + if ((!entry->addr.id || entry->addr.id > MAX_ADDR_ID) && 548 + pernet->next_id != 1) { 549 + pernet->next_id = 1; 550 + goto find_next; 551 + } 552 + } 553 + 554 + if (!entry->addr.id || entry->addr.id > MAX_ADDR_ID) 555 + goto out; 556 + 557 + __set_bit(entry->addr.id, pernet->id_bitmap); 558 + if (entry->addr.id > pernet->next_id) 559 + pernet->next_id = entry->addr.id; 560 + 583 561 if (entry->addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL) 584 562 pernet->add_addr_signal_max++; 585 563 if (entry->addr.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) 586 564 pernet->local_addr_max++; 587 565 588 - entry->addr.id = pernet->next_id++; 589 566 pernet->addrs++; 590 567 list_add_tail_rcu(&entry->list, &pernet->local_addr_list); 591 568 ret = entry->addr.id; ··· 656 597 entry->addr = skc_local; 657 598 entry->addr.ifindex = 0; 658 599 entry->addr.flags = 0; 600 + entry->addr.id = 0; 659 601 ret = mptcp_pm_nl_append_new_local_addr(pernet, entry); 660 602 if (ret < 0) 661 603 kfree(entry); ··· 917 857 918 858 pernet->addrs--; 919 859 list_del_rcu(&entry->list); 860 + __clear_bit(entry->addr.id, pernet->id_bitmap); 920 861 spin_unlock_bh(&pernet->lock); 921 862 922 863 mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr); ··· 955 894 spin_lock_bh(&pernet->lock); 956 895 list_splice_init(&pernet->local_addr_list, &free_list); 957 896 __reset_counters(pernet); 897 + pernet->next_id = 1; 898 + bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1); 958 899 spin_unlock_bh(&pernet->lock); 959 900 __flush_addrs(sock_net(skb->sk), &free_list); 960 901 return 0; ··· 1057 994 struct pm_nl_pernet *pernet; 1058 995 int id = cb->args[0]; 1059 996 void *hdr; 997 + int i; 1060 998 1061 999 pernet = net_generic(net, pm_nl_pernet_id); 1062 1000 1063 1001 spin_lock_bh(&pernet->lock); 1064 - list_for_each_entry(entry, &pernet->local_addr_list, list) { 1065 - if (entry->addr.id <= id) 1066 - continue; 1002 + for (i = id; i < MAX_ADDR_ID + 1; i++) { 1003 + if (test_bit(i, pernet->id_bitmap)) { 1004 + entry = __lookup_addr_by_id(pernet, i); 1005 + if (!entry) 1006 + break; 1067 1007 1068 - hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid, 1069 - cb->nlh->nlmsg_seq, &mptcp_genl_family, 1070 - NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR); 1071 - if (!hdr) 1072 - break; 1008 + if (entry->addr.id <= id) 1009 + continue; 1073 1010 1074 - if (mptcp_nl_fill_addr(msg, entry) < 0) { 1075 - genlmsg_cancel(msg, hdr); 1076 - break; 1011 + hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid, 1012 + cb->nlh->nlmsg_seq, &mptcp_genl_family, 1013 + NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR); 1014 + if (!hdr) 1015 + break; 1016 + 1017 + if (mptcp_nl_fill_addr(msg, entry) < 0) { 1018 + genlmsg_cancel(msg, hdr); 1019 + break; 1020 + } 1021 + 1022 + id = entry->addr.id; 1023 + genlmsg_end(msg, hdr); 1077 1024 } 1078 - 1079 - id = entry->addr.id; 1080 - genlmsg_end(msg, hdr); 1081 1025 } 1082 1026 spin_unlock_bh(&pernet->lock); 1083 1027 ··· 1166 1096 return -EMSGSIZE; 1167 1097 } 1168 1098 1099 + static int mptcp_nl_addr_backup(struct net *net, 1100 + struct mptcp_addr_info *addr, 1101 + u8 bkup) 1102 + { 1103 + long s_slot = 0, s_num = 0; 1104 + struct mptcp_sock *msk; 1105 + int ret = -EINVAL; 1106 + 1107 + while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) { 1108 + struct sock *sk = (struct sock *)msk; 1109 + 1110 + if (list_empty(&msk->conn_list)) 1111 + goto next; 1112 + 1113 + lock_sock(sk); 1114 + spin_lock_bh(&msk->pm.lock); 1115 + ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, bkup); 1116 + spin_unlock_bh(&msk->pm.lock); 1117 + release_sock(sk); 1118 + 1119 + next: 1120 + sock_put(sk); 1121 + cond_resched(); 1122 + } 1123 + 1124 + return ret; 1125 + } 1126 + 1127 + static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) 1128 + { 1129 + struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR]; 1130 + struct pm_nl_pernet *pernet = genl_info_pm_nl(info); 1131 + struct mptcp_pm_addr_entry addr, *entry; 1132 + struct net *net = sock_net(skb->sk); 1133 + u8 bkup = 0; 1134 + int ret; 1135 + 1136 + ret = mptcp_pm_parse_addr(attr, info, true, &addr); 1137 + if (ret < 0) 1138 + return ret; 1139 + 1140 + if (addr.addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP) 1141 + bkup = 1; 1142 + 1143 + list_for_each_entry(entry, &pernet->local_addr_list, list) { 1144 + if (addresses_equal(&entry->addr, &addr.addr, true)) { 1145 + ret = mptcp_nl_addr_backup(net, &entry->addr, bkup); 1146 + if (ret) 1147 + return ret; 1148 + 1149 + if (bkup) 1150 + entry->addr.flags |= MPTCP_PM_ADDR_FLAG_BACKUP; 1151 + else 1152 + entry->addr.flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP; 1153 + } 1154 + } 1155 + 1156 + return 0; 1157 + } 1158 + 1169 1159 static const struct genl_small_ops mptcp_pm_ops[] = { 1170 1160 { 1171 1161 .cmd = MPTCP_PM_CMD_ADD_ADDR, ··· 1256 1126 .cmd = MPTCP_PM_CMD_GET_LIMITS, 1257 1127 .doit = mptcp_nl_cmd_get_limits, 1258 1128 }, 1129 + { 1130 + .cmd = MPTCP_PM_CMD_SET_FLAGS, 1131 + .doit = mptcp_nl_cmd_set_flags, 1132 + .flags = GENL_ADMIN_PERM, 1133 + }, 1259 1134 }; 1260 1135 1261 1136 static struct genl_family mptcp_genl_family __ro_after_init = { ··· 1283 1148 INIT_LIST_HEAD_RCU(&pernet->local_addr_list); 1284 1149 __reset_counters(pernet); 1285 1150 pernet->next_id = 1; 1151 + bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1); 1286 1152 spin_lock_init(&pernet->lock); 1287 1153 return 0; 1288 1154 }
+11
net/mptcp/protocol.h
··· 24 24 #define OPTION_MPTCP_ADD_ADDR6 BIT(7) 25 25 #define OPTION_MPTCP_RM_ADDR BIT(8) 26 26 #define OPTION_MPTCP_FASTCLOSE BIT(9) 27 + #define OPTION_MPTCP_PRIO BIT(10) 27 28 28 29 /* MPTCP option subtypes */ 29 30 #define MPTCPOPT_MP_CAPABLE 0 ··· 60 59 #define TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT 24 61 60 #define TCPOLEN_MPTCP_PORT_LEN 4 62 61 #define TCPOLEN_MPTCP_RM_ADDR_BASE 4 62 + #define TCPOLEN_MPTCP_PRIO 4 63 63 #define TCPOLEN_MPTCP_FASTCLOSE 12 64 64 65 65 /* MPTCP MP_JOIN flags */ ··· 87 85 #define MPTCP_ADDR_ECHO BIT(0) 88 86 #define MPTCP_ADDR_IPVERSION_4 4 89 87 #define MPTCP_ADDR_IPVERSION_6 6 88 + 89 + /* MPTCP MP_PRIO flags */ 90 + #define MPTCP_PRIO_BKUP BIT(0) 90 91 91 92 /* MPTCP socket flags */ 92 93 #define MPTCP_DATA_READY 0 ··· 121 116 dss : 1, 122 117 add_addr : 1, 123 118 rm_addr : 1, 119 + mp_prio : 1, 124 120 family : 4, 125 121 echo : 1, 126 122 backup : 1; ··· 402 396 map_valid : 1, 403 397 mpc_map : 1, 404 398 backup : 1, 399 + send_mp_prio : 1, 405 400 rx_eof : 1, 406 401 can_ack : 1, /* only after processing the remote a key */ 407 402 disposable : 1; /* ctx can be free at ulp release time */ ··· 557 550 const struct mptcp_addr_info *addr); 558 551 void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk); 559 552 void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id); 553 + void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup); 554 + int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, 555 + struct mptcp_addr_info *addr, 556 + u8 bkup); 560 557 void mptcp_pm_free_anno_list(struct mptcp_sock *msk); 561 558 struct mptcp_pm_add_entry * 562 559 mptcp_pm_del_add_timer(struct mptcp_sock *msk,
+71 -1
tools/testing/selftests/net/mptcp/mptcp_join.sh
··· 212 212 rm_nr_ns1="$7" 213 213 rm_nr_ns2="$8" 214 214 speed="$9" 215 + bkup="${10}" 215 216 216 217 port=$((10000+$TEST_COUNT)) 217 218 TEST_COUNT=$((TEST_COUNT+1)) ··· 298 297 fi 299 298 fi 300 299 300 + if [ ! -z $bkup ]; then 301 + sleep 1 302 + for netns in "$ns1" "$ns2"; do 303 + dump=(`ip netns exec $netns ./pm_nl_ctl dump`) 304 + if [ ${#dump[@]} -gt 0 ]; then 305 + addr=${dump[${#dump[@]} - 1]} 306 + backup="ip netns exec $netns ./pm_nl_ctl set $addr flags $bkup" 307 + $backup 308 + fi 309 + done 310 + fi 311 + 301 312 wait $cpid 302 313 retc=$? 303 314 wait $spid ··· 371 358 rm_nr_ns1="${5:-0}" 372 359 rm_nr_ns2="${6:-0}" 373 360 speed="${7:-fast}" 361 + bkup="${8:-""}" 374 362 lret=0 375 363 oldin="" 376 364 ··· 386 372 fi 387 373 388 374 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \ 389 - ${test_linkfail} ${rm_nr_ns1} ${rm_nr_ns2} ${speed} 375 + ${test_linkfail} ${rm_nr_ns1} ${rm_nr_ns2} ${speed} ${bkup} 390 376 lret=$? 391 377 392 378 if [ "$test_linkfail" -eq 1 ];then ··· 509 495 [ -z "$count" ] && count=0 510 496 if [ "$count" != "$rm_subflow_nr" ]; then 511 497 echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr" 498 + ret=1 499 + dump_stats=1 500 + else 501 + echo "[ ok ]" 502 + fi 503 + 504 + if [ "${dump_stats}" = 1 ]; then 505 + echo Server ns stats 506 + ip netns exec $ns1 nstat -as | grep MPTcp 507 + echo Client ns stats 508 + ip netns exec $ns2 nstat -as | grep MPTcp 509 + fi 510 + } 511 + 512 + chk_prio_nr() 513 + { 514 + local mp_prio_nr_tx=$1 515 + local mp_prio_nr_rx=$2 516 + local count 517 + local dump_stats 518 + 519 + printf "%-39s %s" " " "ptx" 520 + count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}'` 521 + [ -z "$count" ] && count=0 522 + if [ "$count" != "$mp_prio_nr_tx" ]; then 523 + echo "[fail] got $count MP_PRIO[s] TX expected $mp_prio_nr_tx" 524 + ret=1 525 + dump_stats=1 526 + else 527 + echo -n "[ ok ]" 528 + fi 529 + 530 + echo -n " - prx " 531 + count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}'` 532 + [ -z "$count" ] && count=0 533 + if [ "$count" != "$mp_prio_nr_rx" ]; then 534 + echo "[fail] got $count MP_PRIO[s] RX expected $mp_prio_nr_rx" 512 535 ret=1 513 536 dump_stats=1 514 537 else ··· 789 738 chk_join_nr "remove subflow and signal IPv6" 2 2 2 790 739 chk_add_nr 1 1 791 740 chk_rm_nr 1 1 741 + 742 + # single subflow, backup 743 + reset 744 + ip netns exec $ns1 ./pm_nl_ctl limits 0 1 745 + ip netns exec $ns2 ./pm_nl_ctl limits 0 1 746 + ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow,backup 747 + run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup 748 + chk_join_nr "single subflow, backup" 1 1 1 749 + chk_prio_nr 0 1 750 + 751 + # single address, backup 752 + reset 753 + ip netns exec $ns1 ./pm_nl_ctl limits 0 1 754 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 755 + ip netns exec $ns2 ./pm_nl_ctl limits 1 1 756 + run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup 757 + chk_join_nr "single address, backup" 1 1 1 758 + chk_add_nr 1 1 759 + chk_prio_nr 1 0 792 760 793 761 # single subflow, syncookies 794 762 reset_with_cookies
+39 -2
tools/testing/selftests/net/mptcp/pm_netlink.sh
··· 91 91 ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.3 92 92 check "ip netns exec $ns1 ./pm_nl_ctl get 4" "" "duplicate addr" 93 93 94 - ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.4 id 10 flags signal 94 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.4 flags signal 95 95 check "ip netns exec $ns1 ./pm_nl_ctl get 4" "id 4 flags signal 10.0.1.4" "id addr increment" 96 96 97 97 for i in `seq 5 9`; do ··· 102 102 103 103 for i in `seq 9 256`; do 104 104 ip netns exec $ns1 ./pm_nl_ctl del $i 105 - ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.9 105 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.9 id $((i+1)) 106 106 done 107 107 check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.1.1 108 + id 2 flags 10.0.0.9 108 109 id 3 flags signal,backup 10.0.1.3 109 110 id 4 flags signal 10.0.1.4 110 111 id 5 flags signal 10.0.1.5 ··· 127 126 ip netns exec $ns1 ./pm_nl_ctl limits 8 8 128 127 check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 8 129 128 subflows 8" "set limits" 129 + 130 + ip netns exec $ns1 ./pm_nl_ctl flush 131 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 132 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.2 133 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.3 id 100 134 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.4 135 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.5 id 254 136 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.6 137 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.7 138 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.8 139 + check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.1.1 140 + id 2 flags 10.0.1.2 141 + id 3 flags 10.0.1.7 142 + id 4 flags 10.0.1.8 143 + id 100 flags 10.0.1.3 144 + id 101 flags 10.0.1.4 145 + id 254 flags 10.0.1.5 146 + id 255 flags 10.0.1.6" "set ids" 147 + 148 + ip netns exec $ns1 ./pm_nl_ctl flush 149 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.1 150 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.2 id 254 151 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.3 152 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.4 153 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.5 id 253 154 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.6 155 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.7 156 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.8 157 + check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.0.1 158 + id 2 flags 10.0.0.4 159 + id 3 flags 10.0.0.6 160 + id 4 flags 10.0.0.7 161 + id 5 flags 10.0.0.8 162 + id 253 flags 10.0.0.5 163 + id 254 flags 10.0.0.2 164 + id 255 flags 10.0.0.3" "wrap-around ids" 130 165 131 166 exit $ret
+86 -1
tools/testing/selftests/net/mptcp/pm_nl_ctl.c
··· 24 24 25 25 static void syntax(char *argv[]) 26 26 { 27 - fprintf(stderr, "%s add|get|del|flush|dump|accept [<args>]\n", argv[0]); 27 + fprintf(stderr, "%s add|get|set|del|flush|dump|accept [<args>]\n", argv[0]); 28 28 fprintf(stderr, "\tadd [flags signal|subflow|backup] [id <nr>] [dev <name>] <ip>\n"); 29 29 fprintf(stderr, "\tdel <id>\n"); 30 30 fprintf(stderr, "\tget <id>\n"); 31 + fprintf(stderr, "\tset <ip> [flags backup|nobackup]\n"); 31 32 fprintf(stderr, "\tflush\n"); 32 33 fprintf(stderr, "\tdump\n"); 33 34 fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n"); ··· 585 584 return 0; 586 585 } 587 586 587 + int set_flags(int fd, int pm_family, int argc, char *argv[]) 588 + { 589 + char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 590 + NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 591 + 1024]; 592 + struct rtattr *rta, *nest; 593 + struct nlmsghdr *nh; 594 + u_int32_t flags = 0; 595 + u_int16_t family; 596 + int nest_start; 597 + int off = 0; 598 + int arg; 599 + 600 + memset(data, 0, sizeof(data)); 601 + nh = (void *)data; 602 + off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS, 603 + MPTCP_PM_VER); 604 + 605 + if (argc < 3) 606 + syntax(argv); 607 + 608 + nest_start = off; 609 + nest = (void *)(data + off); 610 + nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR; 611 + nest->rta_len = RTA_LENGTH(0); 612 + off += NLMSG_ALIGN(nest->rta_len); 613 + 614 + /* addr data */ 615 + rta = (void *)(data + off); 616 + if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) { 617 + family = AF_INET; 618 + rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4; 619 + rta->rta_len = RTA_LENGTH(4); 620 + } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) { 621 + family = AF_INET6; 622 + rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6; 623 + rta->rta_len = RTA_LENGTH(16); 624 + } else { 625 + error(1, errno, "can't parse ip %s", argv[2]); 626 + } 627 + off += NLMSG_ALIGN(rta->rta_len); 628 + 629 + /* family */ 630 + rta = (void *)(data + off); 631 + rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY; 632 + rta->rta_len = RTA_LENGTH(2); 633 + memcpy(RTA_DATA(rta), &family, 2); 634 + off += NLMSG_ALIGN(rta->rta_len); 635 + 636 + for (arg = 3; arg < argc; arg++) { 637 + if (!strcmp(argv[arg], "flags")) { 638 + char *tok, *str; 639 + 640 + /* flags */ 641 + if (++arg >= argc) 642 + error(1, 0, " missing flags value"); 643 + 644 + /* do not support flag list yet */ 645 + for (str = argv[arg]; (tok = strtok(str, ",")); 646 + str = NULL) { 647 + if (!strcmp(tok, "backup")) 648 + flags |= MPTCP_PM_ADDR_FLAG_BACKUP; 649 + else if (strcmp(tok, "nobackup")) 650 + error(1, errno, 651 + "unknown flag %s", argv[arg]); 652 + } 653 + 654 + rta = (void *)(data + off); 655 + rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS; 656 + rta->rta_len = RTA_LENGTH(4); 657 + memcpy(RTA_DATA(rta), &flags, 4); 658 + off += NLMSG_ALIGN(rta->rta_len); 659 + } else { 660 + error(1, 0, "unknown keyword %s", argv[arg]); 661 + } 662 + } 663 + nest->rta_len = off - nest_start; 664 + 665 + do_nl_req(fd, nh, off, 0); 666 + return 0; 667 + } 668 + 588 669 int main(int argc, char *argv[]) 589 670 { 590 671 int fd, pm_family; ··· 692 609 return dump_addrs(fd, pm_family, argc, argv); 693 610 else if (!strcmp(argv[1], "limits")) 694 611 return get_set_limits(fd, pm_family, argc, argv); 612 + else if (!strcmp(argv[1], "set")) 613 + return set_flags(fd, pm_family, argc, argv); 695 614 696 615 fprintf(stderr, "unknown sub-command: %s", argv[1]); 697 616 syntax(argv);