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

mptcp: pm: in-kernel: refactor fill_local_addresses_vec

Before this modification, this function was quite long with many levels
of indentations.

Each case can be split in a dedicated function: fullmesh, C flag, any.

No functional changes intended.

Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250925-net-next-mptcp-c-flag-laminar-v1-3-ad126cc47c6b@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Matthieu Baerts (NGI0) and committed by
Jakub Kicinski
8dc63ade 008385ef

+116 -83
+116 -83
net/mptcp/pm_kernel.c
··· 377 377 mptcp_pm_create_subflow_or_signal_addr(msk); 378 378 } 379 379 380 - /* Fill all the local addresses into the array addrs[], 381 - * and return the array size. 382 - */ 383 - static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk, 384 - struct mptcp_addr_info *remote, 385 - struct mptcp_pm_local *locals) 380 + static unsigned int 381 + fill_local_addresses_vec_fullmesh(struct mptcp_sock *msk, 382 + struct mptcp_addr_info *remote, 383 + struct mptcp_pm_local *locals, 384 + bool c_flag_case) 386 385 { 386 + struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk); 387 + unsigned int subflows_max = mptcp_pm_get_subflows_max(msk); 387 388 struct sock *sk = (struct sock *)msk; 388 389 struct mptcp_pm_addr_entry *entry; 389 390 struct mptcp_addr_info mpc_addr; 390 - struct pm_nl_pernet *pernet; 391 - unsigned int subflows_max; 392 - bool c_flag_case; 391 + struct mptcp_pm_local *local; 393 392 int i = 0; 394 - 395 - pernet = pm_nl_get_pernet_from_msk(msk); 396 - subflows_max = mptcp_pm_get_subflows_max(msk); 397 - c_flag_case = remote->id && mptcp_pm_add_addr_c_flag_case(msk); 398 393 399 394 mptcp_local_address((struct sock_common *)msk, &mpc_addr); 400 395 401 396 rcu_read_lock(); 402 397 list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) { 398 + bool is_id0; 399 + 403 400 if (!(entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH)) 404 401 continue; 405 402 406 403 if (!mptcp_pm_addr_families_match(sk, &entry->addr, remote)) 407 404 continue; 408 405 409 - if (msk->pm.subflows < subflows_max) { 410 - bool is_id0; 406 + local = &locals[i]; 407 + local->addr = entry->addr; 408 + local->flags = entry->flags; 409 + local->ifindex = entry->ifindex; 411 410 412 - locals[i].addr = entry->addr; 413 - locals[i].flags = entry->flags; 414 - locals[i].ifindex = entry->ifindex; 411 + is_id0 = mptcp_addresses_equal(&local->addr, &mpc_addr, 412 + local->addr.port); 415 413 416 - is_id0 = mptcp_addresses_equal(&locals[i].addr, 417 - &mpc_addr, 418 - locals[i].addr.port); 414 + if (c_flag_case && 415 + (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW)) { 416 + __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); 419 417 420 - if (c_flag_case && 421 - (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW)) { 422 - __clear_bit(locals[i].addr.id, 423 - msk->pm.id_avail_bitmap); 424 - 425 - if (!is_id0) 426 - msk->pm.local_addr_used++; 427 - } 428 - 429 - /* Special case for ID0: set the correct ID */ 430 - if (is_id0) 431 - locals[i].addr.id = 0; 432 - 433 - msk->pm.subflows++; 434 - i++; 418 + if (!is_id0) 419 + msk->pm.local_addr_used++; 435 420 } 421 + 422 + /* Special case for ID0: set the correct ID */ 423 + if (is_id0) 424 + local->addr.id = 0; 425 + 426 + msk->pm.subflows++; 427 + i++; 428 + 429 + if (msk->pm.subflows >= subflows_max) 430 + break; 436 431 } 437 432 rcu_read_unlock(); 433 + 434 + return i; 435 + } 436 + 437 + static unsigned int 438 + fill_local_addresses_vec_c_flag(struct mptcp_sock *msk, 439 + struct mptcp_addr_info *remote, 440 + struct mptcp_pm_local *locals) 441 + { 442 + unsigned int local_addr_max = mptcp_pm_get_local_addr_max(msk); 443 + struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk); 444 + unsigned int subflows_max = mptcp_pm_get_subflows_max(msk); 445 + struct sock *sk = (struct sock *)msk; 446 + struct mptcp_addr_info mpc_addr; 447 + struct mptcp_pm_local *local; 448 + int i = 0; 449 + 450 + mptcp_local_address((struct sock_common *)msk, &mpc_addr); 451 + 452 + while (msk->pm.local_addr_used < local_addr_max) { 453 + local = &locals[i]; 454 + 455 + if (!select_local_address(pernet, msk, local)) 456 + break; 457 + 458 + __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); 459 + 460 + if (!mptcp_pm_addr_families_match(sk, &local->addr, remote)) 461 + continue; 462 + 463 + if (mptcp_addresses_equal(&local->addr, &mpc_addr, 464 + local->addr.port)) 465 + continue; 466 + 467 + msk->pm.local_addr_used++; 468 + msk->pm.subflows++; 469 + i++; 470 + 471 + if (msk->pm.subflows >= subflows_max) 472 + break; 473 + } 474 + 475 + return i; 476 + } 477 + 478 + static unsigned int 479 + fill_local_address_any(struct mptcp_sock *msk, struct mptcp_addr_info *remote, 480 + struct mptcp_pm_local *local) 481 + { 482 + struct sock *sk = (struct sock *)msk; 483 + 484 + memset(local, 0, sizeof(*local)); 485 + local->addr.family = 486 + #if IS_ENABLED(CONFIG_MPTCP_IPV6) 487 + remote->family == AF_INET6 && 488 + ipv6_addr_v4mapped(&remote->addr6) ? AF_INET : 489 + #endif 490 + remote->family; 491 + 492 + if (!mptcp_pm_addr_families_match(sk, &local->addr, remote)) 493 + return 0; 494 + 495 + msk->pm.subflows++; 496 + 497 + return 1; 498 + } 499 + 500 + /* Fill all the local addresses into the array addrs[], 501 + * and return the array size. 502 + */ 503 + static unsigned int 504 + fill_local_addresses_vec(struct mptcp_sock *msk, struct mptcp_addr_info *remote, 505 + struct mptcp_pm_local *locals) 506 + { 507 + bool c_flag_case = remote->id && mptcp_pm_add_addr_c_flag_case(msk); 508 + int i; 509 + 510 + /* If there is at least one MPTCP endpoint with a fullmesh flag */ 511 + i = fill_local_addresses_vec_fullmesh(msk, remote, locals, c_flag_case); 512 + if (i) 513 + return i; 438 514 439 515 /* Special case: peer sets the C flag, accept one ADD_ADDR if default 440 516 * limits are used -- accepting no ADD_ADDR -- and use subflow endpoints 441 517 */ 442 - if (!i && c_flag_case) { 443 - unsigned int local_addr_max = mptcp_pm_get_local_addr_max(msk); 518 + if (c_flag_case) 519 + return fill_local_addresses_vec_c_flag(msk, remote, locals); 444 520 445 - while (msk->pm.local_addr_used < local_addr_max && 446 - msk->pm.subflows < subflows_max) { 447 - struct mptcp_pm_local *local = &locals[i]; 448 - 449 - if (!select_local_address(pernet, msk, local)) 450 - break; 451 - 452 - __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); 453 - 454 - if (!mptcp_pm_addr_families_match(sk, &local->addr, 455 - remote)) 456 - continue; 457 - 458 - if (mptcp_addresses_equal(&local->addr, &mpc_addr, 459 - local->addr.port)) 460 - continue; 461 - 462 - msk->pm.local_addr_used++; 463 - msk->pm.subflows++; 464 - i++; 465 - } 466 - 467 - return i; 468 - } 469 - 470 - /* If the array is empty, fill in the single 471 - * 'IPADDRANY' local address 472 - */ 473 - if (!i) { 474 - memset(&locals[i], 0, sizeof(locals[i])); 475 - locals[i].addr.family = 476 - #if IS_ENABLED(CONFIG_MPTCP_IPV6) 477 - remote->family == AF_INET6 && 478 - ipv6_addr_v4mapped(&remote->addr6) ? AF_INET : 479 - #endif 480 - remote->family; 481 - 482 - if (!mptcp_pm_addr_families_match(sk, &locals[i].addr, remote)) 483 - return 0; 484 - 485 - msk->pm.subflows++; 486 - i++; 487 - } 488 - 489 - return i; 521 + /* No special case: fill in the single 'IPADDRANY' local address */ 522 + return fill_local_address_any(msk, remote, &locals[0]); 490 523 } 491 524 492 525 static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)