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.

ipvlan: remove ipvlan_ht_addr_lookup()

ipvlan_ht_addr_lookup() is called four times and not inlined.

Split it to ipvlan_ht_addr_lookup6() and ipvlan_ht_addr_lookup4()
and rework ipvlan_addr_lookup() to call these helpers once,
so that they are (auto)inlined.

After this change, ipvlan_addr_lookup() is faster, and we save
350 bytes of text on x86_64.

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/2 grow/shrink: 1/0 up/down: 123/-473 (-350)
Function old new delta
ipvlan_addr_lookup 467 590 +123
__pfx_ipvlan_ht_addr_lookup 16 - -16
ipvlan_ht_addr_lookup 457 - -457
Total: Before=22571833, After=22571483, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Mahesh Bandewar <maheshb@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260122165049.2366985-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
05413022 37b0ea8f

+34 -21
+34 -21
drivers/net/ipvlan/ipvlan_core.c
··· 48 48 } 49 49 #endif 50 50 51 - static u8 ipvlan_get_v4_hash(const void *iaddr) 51 + static u8 ipvlan_get_v4_hash(__be32 addr) 52 52 { 53 - const struct in_addr *ip4_addr = iaddr; 54 - 55 - return jhash_1word((__force u32)ip4_addr->s_addr, ipvlan_jhash_secret) & 53 + return jhash_1word((__force u32)addr, ipvlan_jhash_secret) & 56 54 IPVLAN_HASH_MASK; 57 55 } 58 56 ··· 71 73 return false; 72 74 } 73 75 74 - static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, 75 - const void *iaddr, bool is_v6) 76 + #if IS_ENABLED(CONFIG_IPV6) 77 + static struct ipvl_addr *ipvlan_ht_addr_lookup6(const struct ipvl_port *port, 78 + const void *iaddr) 76 79 { 77 80 struct ipvl_addr *addr; 78 81 u8 hash; 79 82 80 - hash = is_v6 ? ipvlan_get_v6_hash(iaddr) : 81 - ipvlan_get_v4_hash(iaddr); 83 + hash = ipvlan_get_v6_hash(iaddr); 82 84 hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode) 83 - if (addr_equal(is_v6, addr, iaddr)) 85 + if (addr_equal(true, addr, iaddr)) 86 + return addr; 87 + return NULL; 88 + } 89 + #endif 90 + 91 + static struct ipvl_addr *ipvlan_ht_addr_lookup4(const struct ipvl_port *port, 92 + __be32 addr4) 93 + { 94 + struct ipvl_addr *addr; 95 + u8 hash; 96 + 97 + hash = ipvlan_get_v4_hash(addr4); 98 + hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode) 99 + if (addr->atype == IPVL_IPV4 && addr->ip4addr.s_addr == addr4) 84 100 return addr; 85 101 return NULL; 86 102 } ··· 106 94 107 95 hash = (addr->atype == IPVL_IPV6) ? 108 96 ipvlan_get_v6_hash(&addr->ip6addr) : 109 - ipvlan_get_v4_hash(&addr->ip4addr); 97 + ipvlan_get_v4_hash(addr->ip4addr.s_addr); 110 98 if (hlist_unhashed(&addr->hlnode)) 111 99 hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); 112 100 } ··· 367 355 int addr_type, bool use_dest) 368 356 { 369 357 struct ipvl_addr *addr = NULL; 358 + #if IS_ENABLED(CONFIG_IPV6) 359 + struct in6_addr *i6addr; 360 + #endif 361 + __be32 addr4; 370 362 371 363 switch (addr_type) { 372 364 #if IS_ENABLED(CONFIG_IPV6) 373 365 case IPVL_IPV6: { 374 366 struct ipv6hdr *ip6h; 375 - struct in6_addr *i6addr; 376 367 377 368 ip6h = (struct ipv6hdr *)lyr3h; 378 369 i6addr = use_dest ? &ip6h->daddr : &ip6h->saddr; 379 - addr = ipvlan_ht_addr_lookup(port, i6addr, true); 370 + lookup6: 371 + addr = ipvlan_ht_addr_lookup6(port, i6addr); 380 372 break; 381 373 } 382 374 case IPVL_ICMPV6: { 383 375 struct nd_msg *ndmh; 384 - struct in6_addr *i6addr; 385 376 386 377 /* Make sure that the NeighborSolicitation ICMPv6 packets 387 378 * are handled to avoid DAD issue. ··· 392 377 ndmh = (struct nd_msg *)lyr3h; 393 378 if (ndmh->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { 394 379 i6addr = &ndmh->target; 395 - addr = ipvlan_ht_addr_lookup(port, i6addr, true); 380 + goto lookup6; 396 381 } 397 382 break; 398 383 } 399 384 #endif 400 385 case IPVL_IPV4: { 401 386 struct iphdr *ip4h; 402 - __be32 *i4addr; 403 387 404 388 ip4h = (struct iphdr *)lyr3h; 405 - i4addr = use_dest ? &ip4h->daddr : &ip4h->saddr; 406 - addr = ipvlan_ht_addr_lookup(port, i4addr, false); 389 + addr4 = use_dest ? ip4h->daddr : ip4h->saddr; 390 + lookup4: 391 + addr = ipvlan_ht_addr_lookup4(port, addr4); 407 392 break; 408 393 } 409 394 case IPVL_ARP: { 410 395 struct arphdr *arph; 411 396 unsigned char *arp_ptr; 412 - __be32 dip; 413 397 414 398 arph = (struct arphdr *)lyr3h; 415 399 arp_ptr = (unsigned char *)(arph + 1); ··· 417 403 else 418 404 arp_ptr += port->dev->addr_len; 419 405 420 - memcpy(&dip, arp_ptr, 4); 421 - addr = ipvlan_ht_addr_lookup(port, &dip, false); 422 - break; 406 + addr4 = get_unaligned((__be32 *)arp_ptr); 407 + goto lookup4; 423 408 } 424 409 } 425 410