route.c (320424c7d44f54c18df9812fd7c45f6963524002) route.c (6126891c6d4f6f4ef50323d2020635ee255a796e)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Linux INET6 implementation
4 * FIB front-end.
5 *
6 * Authors:
7 * Pedro Roque <roque@di.fc.ul.pt>
8 */

--- 2312 unchanged lines hidden (view full) ---

2321 } else {
2322 keys->addrs.v6addrs.src = key_iph->saddr;
2323 keys->addrs.v6addrs.dst = key_iph->daddr;
2324 keys->tags.flow_label = ip6_flowlabel(key_iph);
2325 keys->basic.ip_proto = key_iph->nexthdr;
2326 }
2327}
2328
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Linux INET6 implementation
4 * FIB front-end.
5 *
6 * Authors:
7 * Pedro Roque <roque@di.fc.ul.pt>
8 */

--- 2312 unchanged lines hidden (view full) ---

2321 } else {
2322 keys->addrs.v6addrs.src = key_iph->saddr;
2323 keys->addrs.v6addrs.dst = key_iph->daddr;
2324 keys->tags.flow_label = ip6_flowlabel(key_iph);
2325 keys->basic.ip_proto = key_iph->nexthdr;
2326 }
2327}
2328
2329static u32 rt6_multipath_custom_hash_outer(const struct net *net,
2330 const struct sk_buff *skb,
2331 bool *p_has_inner)
2332{
2333 u32 hash_fields = ip6_multipath_hash_fields(net);
2334 struct flow_keys keys, hash_keys;
2335
2336 if (!(hash_fields & FIB_MULTIPATH_HASH_FIELD_OUTER_MASK))
2337 return 0;
2338
2339 memset(&hash_keys, 0, sizeof(hash_keys));
2340 skb_flow_dissect_flow_keys(skb, &keys, FLOW_DISSECTOR_F_STOP_AT_ENCAP);
2341
2342 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2343 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP)
2344 hash_keys.addrs.v6addrs.src = keys.addrs.v6addrs.src;
2345 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP)
2346 hash_keys.addrs.v6addrs.dst = keys.addrs.v6addrs.dst;
2347 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
2348 hash_keys.basic.ip_proto = keys.basic.ip_proto;
2349 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_FLOWLABEL)
2350 hash_keys.tags.flow_label = keys.tags.flow_label;
2351 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
2352 hash_keys.ports.src = keys.ports.src;
2353 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
2354 hash_keys.ports.dst = keys.ports.dst;
2355
2356 *p_has_inner = !!(keys.control.flags & FLOW_DIS_ENCAPSULATION);
2357 return flow_hash_from_keys(&hash_keys);
2358}
2359
2360static u32 rt6_multipath_custom_hash_inner(const struct net *net,
2361 const struct sk_buff *skb,
2362 bool has_inner)
2363{
2364 u32 hash_fields = ip6_multipath_hash_fields(net);
2365 struct flow_keys keys, hash_keys;
2366
2367 /* We assume the packet carries an encapsulation, but if none was
2368 * encountered during dissection of the outer flow, then there is no
2369 * point in calling the flow dissector again.
2370 */
2371 if (!has_inner)
2372 return 0;
2373
2374 if (!(hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_MASK))
2375 return 0;
2376
2377 memset(&hash_keys, 0, sizeof(hash_keys));
2378 skb_flow_dissect_flow_keys(skb, &keys, 0);
2379
2380 if (!(keys.control.flags & FLOW_DIS_ENCAPSULATION))
2381 return 0;
2382
2383 if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
2384 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
2385 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP)
2386 hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src;
2387 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP)
2388 hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst;
2389 } else if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
2390 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2391 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP)
2392 hash_keys.addrs.v6addrs.src = keys.addrs.v6addrs.src;
2393 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP)
2394 hash_keys.addrs.v6addrs.dst = keys.addrs.v6addrs.dst;
2395 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL)
2396 hash_keys.tags.flow_label = keys.tags.flow_label;
2397 }
2398
2399 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO)
2400 hash_keys.basic.ip_proto = keys.basic.ip_proto;
2401 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT)
2402 hash_keys.ports.src = keys.ports.src;
2403 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT)
2404 hash_keys.ports.dst = keys.ports.dst;
2405
2406 return flow_hash_from_keys(&hash_keys);
2407}
2408
2409static u32 rt6_multipath_custom_hash_skb(const struct net *net,
2410 const struct sk_buff *skb)
2411{
2412 u32 mhash, mhash_inner;
2413 bool has_inner = true;
2414
2415 mhash = rt6_multipath_custom_hash_outer(net, skb, &has_inner);
2416 mhash_inner = rt6_multipath_custom_hash_inner(net, skb, has_inner);
2417
2418 return jhash_2words(mhash, mhash_inner, 0);
2419}
2420
2421static u32 rt6_multipath_custom_hash_fl6(const struct net *net,
2422 const struct flowi6 *fl6)
2423{
2424 u32 hash_fields = ip6_multipath_hash_fields(net);
2425 struct flow_keys hash_keys;
2426
2427 if (!(hash_fields & FIB_MULTIPATH_HASH_FIELD_OUTER_MASK))
2428 return 0;
2429
2430 memset(&hash_keys, 0, sizeof(hash_keys));
2431 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2432 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP)
2433 hash_keys.addrs.v6addrs.src = fl6->saddr;
2434 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP)
2435 hash_keys.addrs.v6addrs.dst = fl6->daddr;
2436 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
2437 hash_keys.basic.ip_proto = fl6->flowi6_proto;
2438 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_FLOWLABEL)
2439 hash_keys.tags.flow_label = (__force u32)flowi6_get_flowlabel(fl6);
2440 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
2441 hash_keys.ports.src = fl6->fl6_sport;
2442 if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
2443 hash_keys.ports.dst = fl6->fl6_dport;
2444
2445 return flow_hash_from_keys(&hash_keys);
2446}
2447
2329/* if skb is set it will be used and fl6 can be NULL */
2330u32 rt6_multipath_hash(const struct net *net, const struct flowi6 *fl6,
2331 const struct sk_buff *skb, struct flow_keys *flkeys)
2332{
2333 struct flow_keys hash_keys;
2448/* if skb is set it will be used and fl6 can be NULL */
2449u32 rt6_multipath_hash(const struct net *net, const struct flowi6 *fl6,
2450 const struct sk_buff *skb, struct flow_keys *flkeys)
2451{
2452 struct flow_keys hash_keys;
2334 u32 mhash;
2453 u32 mhash = 0;
2335
2336 switch (ip6_multipath_hash_policy(net)) {
2337 case 0:
2338 memset(&hash_keys, 0, sizeof(hash_keys));
2339 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2340 if (skb) {
2341 ip6_multipath_l3_keys(skb, &hash_keys, flkeys);
2342 } else {
2343 hash_keys.addrs.v6addrs.src = fl6->saddr;
2344 hash_keys.addrs.v6addrs.dst = fl6->daddr;
2345 hash_keys.tags.flow_label = (__force u32)flowi6_get_flowlabel(fl6);
2346 hash_keys.basic.ip_proto = fl6->flowi6_proto;
2347 }
2454
2455 switch (ip6_multipath_hash_policy(net)) {
2456 case 0:
2457 memset(&hash_keys, 0, sizeof(hash_keys));
2458 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2459 if (skb) {
2460 ip6_multipath_l3_keys(skb, &hash_keys, flkeys);
2461 } else {
2462 hash_keys.addrs.v6addrs.src = fl6->saddr;
2463 hash_keys.addrs.v6addrs.dst = fl6->daddr;
2464 hash_keys.tags.flow_label = (__force u32)flowi6_get_flowlabel(fl6);
2465 hash_keys.basic.ip_proto = fl6->flowi6_proto;
2466 }
2467 mhash = flow_hash_from_keys(&hash_keys);
2348 break;
2349 case 1:
2350 if (skb) {
2351 unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
2352 struct flow_keys keys;
2353
2354 /* short-circuit if we already have L4 hash present */
2355 if (skb->l4_hash)

--- 15 unchanged lines hidden (view full) ---

2371 memset(&hash_keys, 0, sizeof(hash_keys));
2372 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2373 hash_keys.addrs.v6addrs.src = fl6->saddr;
2374 hash_keys.addrs.v6addrs.dst = fl6->daddr;
2375 hash_keys.ports.src = fl6->fl6_sport;
2376 hash_keys.ports.dst = fl6->fl6_dport;
2377 hash_keys.basic.ip_proto = fl6->flowi6_proto;
2378 }
2468 break;
2469 case 1:
2470 if (skb) {
2471 unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
2472 struct flow_keys keys;
2473
2474 /* short-circuit if we already have L4 hash present */
2475 if (skb->l4_hash)

--- 15 unchanged lines hidden (view full) ---

2491 memset(&hash_keys, 0, sizeof(hash_keys));
2492 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2493 hash_keys.addrs.v6addrs.src = fl6->saddr;
2494 hash_keys.addrs.v6addrs.dst = fl6->daddr;
2495 hash_keys.ports.src = fl6->fl6_sport;
2496 hash_keys.ports.dst = fl6->fl6_dport;
2497 hash_keys.basic.ip_proto = fl6->flowi6_proto;
2498 }
2499 mhash = flow_hash_from_keys(&hash_keys);
2379 break;
2380 case 2:
2381 memset(&hash_keys, 0, sizeof(hash_keys));
2382 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2383 if (skb) {
2384 struct flow_keys keys;
2385
2386 if (!flkeys) {

--- 20 unchanged lines hidden (view full) ---

2407 } else {
2408 /* Same as case 0 */
2409 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2410 hash_keys.addrs.v6addrs.src = fl6->saddr;
2411 hash_keys.addrs.v6addrs.dst = fl6->daddr;
2412 hash_keys.tags.flow_label = (__force u32)flowi6_get_flowlabel(fl6);
2413 hash_keys.basic.ip_proto = fl6->flowi6_proto;
2414 }
2500 break;
2501 case 2:
2502 memset(&hash_keys, 0, sizeof(hash_keys));
2503 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2504 if (skb) {
2505 struct flow_keys keys;
2506
2507 if (!flkeys) {

--- 20 unchanged lines hidden (view full) ---

2528 } else {
2529 /* Same as case 0 */
2530 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
2531 hash_keys.addrs.v6addrs.src = fl6->saddr;
2532 hash_keys.addrs.v6addrs.dst = fl6->daddr;
2533 hash_keys.tags.flow_label = (__force u32)flowi6_get_flowlabel(fl6);
2534 hash_keys.basic.ip_proto = fl6->flowi6_proto;
2535 }
2536 mhash = flow_hash_from_keys(&hash_keys);
2415 break;
2537 break;
2538 case 3:
2539 if (skb)
2540 mhash = rt6_multipath_custom_hash_skb(net, skb);
2541 else
2542 mhash = rt6_multipath_custom_hash_fl6(net, fl6);
2543 break;
2416 }
2544 }
2417 mhash = flow_hash_from_keys(&hash_keys);
2418
2419 return mhash >> 1;
2420}
2421
2422/* Called with rcu held */
2423void ip6_route_input(struct sk_buff *skb)
2424{
2425 const struct ipv6hdr *iph = ipv6_hdr(skb);

--- 4080 unchanged lines hidden (view full) ---

6506int __init ip6_route_init(void)
6507{
6508 int ret;
6509 int cpu;
6510
6511 ret = -ENOMEM;
6512 ip6_dst_ops_template.kmem_cachep =
6513 kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
2545
2546 return mhash >> 1;
2547}
2548
2549/* Called with rcu held */
2550void ip6_route_input(struct sk_buff *skb)
2551{
2552 const struct ipv6hdr *iph = ipv6_hdr(skb);

--- 4080 unchanged lines hidden (view full) ---

6633int __init ip6_route_init(void)
6634{
6635 int ret;
6636 int cpu;
6637
6638 ret = -ENOMEM;
6639 ip6_dst_ops_template.kmem_cachep =
6640 kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
6514 SLAB_HWCACHE_ALIGN, NULL);
6641 SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, NULL);
6515 if (!ip6_dst_ops_template.kmem_cachep)
6516 goto out;
6517
6518 ret = dst_entries_init(&ip6_dst_blackhole_ops);
6519 if (ret)
6520 goto out_kmem_cache;
6521
6522 ret = register_pernet_subsys(&ipv6_inetpeer_ops);

--- 100 unchanged lines hidden ---
6642 if (!ip6_dst_ops_template.kmem_cachep)
6643 goto out;
6644
6645 ret = dst_entries_init(&ip6_dst_blackhole_ops);
6646 if (ret)
6647 goto out_kmem_cache;
6648
6649 ret = register_pernet_subsys(&ipv6_inetpeer_ops);

--- 100 unchanged lines hidden ---