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

xfrm: remove extract_output indirection from xfrm_state_afinfo

Move this to xfrm_output.c. This avoids the state->extract_output
indirection.

This patch also removes the duplicated __xfrm6_extract_header helper
added in an earlier patch, we can now use the one from xfrm_inout.h .

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

authored by

Florian Westphal and committed by
Steffen Klassert
f3075f48 ede64dd2

+59 -70
-3
include/net/xfrm.h
··· 362 362 363 363 int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); 364 364 int (*output_finish)(struct sock *sk, struct sk_buff *skb); 365 - int (*extract_output)(struct xfrm_state *x, 366 - struct sk_buff *skb); 367 365 int (*transport_finish)(struct sk_buff *skb, 368 366 int async); 369 367 void (*local_error)(struct sk_buff *skb, u32 mtu); ··· 1599 1601 int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); 1600 1602 __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr); 1601 1603 __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr); 1602 - int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); 1603 1604 int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb); 1604 1605 int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb); 1605 1606 int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
-58
net/ipv6/xfrm6_output.c
··· 47 47 ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); 48 48 } 49 49 50 - static int xfrm6_tunnel_check_size(struct sk_buff *skb) 51 - { 52 - int mtu, ret = 0; 53 - struct dst_entry *dst = skb_dst(skb); 54 - 55 - if (skb->ignore_df) 56 - goto out; 57 - 58 - mtu = dst_mtu(dst); 59 - if (mtu < IPV6_MIN_MTU) 60 - mtu = IPV6_MIN_MTU; 61 - 62 - if ((!skb_is_gso(skb) && skb->len > mtu) || 63 - (skb_is_gso(skb) && 64 - !skb_gso_validate_network_len(skb, ip6_skb_dst_mtu(skb)))) { 65 - skb->dev = dst->dev; 66 - skb->protocol = htons(ETH_P_IPV6); 67 - 68 - if (xfrm6_local_dontfrag(skb->sk)) 69 - xfrm6_local_rxpmtu(skb, mtu); 70 - else if (skb->sk) 71 - xfrm_local_error(skb, mtu); 72 - else 73 - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 74 - ret = -EMSGSIZE; 75 - } 76 - out: 77 - return ret; 78 - } 79 - 80 - static void __xfrm6_extract_header(struct sk_buff *skb) 81 - { 82 - struct ipv6hdr *iph = ipv6_hdr(skb); 83 - 84 - XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); 85 - XFRM_MODE_SKB_CB(skb)->id = 0; 86 - XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); 87 - XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); 88 - XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; 89 - XFRM_MODE_SKB_CB(skb)->optlen = 0; 90 - memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, 91 - sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); 92 - } 93 - 94 - int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb) 95 - { 96 - int err; 97 - 98 - err = xfrm6_tunnel_check_size(skb); 99 - if (err) 100 - return err; 101 - 102 - XFRM_MODE_SKB_CB(skb)->protocol = ipv6_hdr(skb)->nexthdr; 103 - 104 - __xfrm6_extract_header(skb); 105 - return 0; 106 - } 107 - 108 50 int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb) 109 51 { 110 52 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
-1
net/ipv6/xfrm6_state.c
··· 19 19 .proto = IPPROTO_IPV6, 20 20 .output = xfrm6_output, 21 21 .output_finish = xfrm6_output_finish, 22 - .extract_output = xfrm6_extract_output, 23 22 .transport_finish = xfrm6_transport_finish, 24 23 .local_error = xfrm6_local_error, 25 24 };
+59 -8
net/xfrm/xfrm_output.c
··· 17 17 #include <net/inet_ecn.h> 18 18 #include <net/xfrm.h> 19 19 20 + #if IS_ENABLED(CONFIG_IPV6) 21 + #include <net/ip6_route.h> 22 + #include <net/ipv6_stubs.h> 23 + #endif 24 + 20 25 #include "xfrm_inout.h" 21 26 22 27 static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb); ··· 656 651 return 0; 657 652 } 658 653 654 + #if IS_ENABLED(CONFIG_IPV6) 655 + static int xfrm6_tunnel_check_size(struct sk_buff *skb) 656 + { 657 + int mtu, ret = 0; 658 + struct dst_entry *dst = skb_dst(skb); 659 + 660 + if (skb->ignore_df) 661 + goto out; 662 + 663 + mtu = dst_mtu(dst); 664 + if (mtu < IPV6_MIN_MTU) 665 + mtu = IPV6_MIN_MTU; 666 + 667 + if ((!skb_is_gso(skb) && skb->len > mtu) || 668 + (skb_is_gso(skb) && 669 + !skb_gso_validate_network_len(skb, ip6_skb_dst_mtu(skb)))) { 670 + skb->dev = dst->dev; 671 + skb->protocol = htons(ETH_P_IPV6); 672 + 673 + if (xfrm6_local_dontfrag(skb->sk)) 674 + ipv6_stub->xfrm6_local_rxpmtu(skb, mtu); 675 + else if (skb->sk) 676 + xfrm_local_error(skb, mtu); 677 + else 678 + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 679 + ret = -EMSGSIZE; 680 + } 681 + out: 682 + return ret; 683 + } 684 + #endif 685 + 686 + static int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb) 687 + { 688 + #if IS_ENABLED(CONFIG_IPV6) 689 + int err; 690 + 691 + err = xfrm6_tunnel_check_size(skb); 692 + if (err) 693 + return err; 694 + 695 + XFRM_MODE_SKB_CB(skb)->protocol = ipv6_hdr(skb)->nexthdr; 696 + 697 + xfrm6_extract_header(skb); 698 + return 0; 699 + #else 700 + WARN_ON_ONCE(1); 701 + return -EAFNOSUPPORT; 702 + #endif 703 + } 704 + 659 705 static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb) 660 706 { 661 - const struct xfrm_state_afinfo *afinfo; 662 707 const struct xfrm_mode *inner_mode; 663 - int err = -EAFNOSUPPORT; 664 708 665 709 if (x->sel.family == AF_UNSPEC) 666 710 inner_mode = xfrm_ip2inner_mode(x, ··· 723 669 switch (inner_mode->family) { 724 670 case AF_INET: 725 671 return xfrm4_extract_output(x, skb); 672 + case AF_INET6: 673 + return xfrm6_extract_output(x, skb); 726 674 } 727 - rcu_read_lock(); 728 - afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family); 729 - if (likely(afinfo)) 730 - err = afinfo->extract_output(x, skb); 731 - rcu_read_unlock(); 732 675 733 - return err; 676 + return -EAFNOSUPPORT; 734 677 } 735 678 736 679 void xfrm_local_error(struct sk_buff *skb, int mtu)