xfrm: remove output indirection from xfrm_mode
Same is input indirection. Only exception: we need to export
xfrm_outer_mode_output for pktgen.
Increases size of vmlinux by about 163 byte:
Before:
text data bss dec filename
15730208 6936948 4046908 26714064 vmlinux
After:
15730311 6937008
4046908 26714227 vmlinux
xfrm_inner_extract_output has no more external callers, make it static.
v2: add IS_ENABLED(IPV6) guard in xfrm6_prepare_output
add two missing breaks in xfrm_outer_mode_output (Sabrina Dubroca)
add WARN_ON_ONCE for 'call AF_INET6 related output function, but
CONFIG_IPV6=n' case.
make xfrm_inner_extract_output static
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
Родитель
c2d305e510
Коммит
0c620e97b3
|
@ -449,17 +449,6 @@ struct xfrm_mode {
|
|||
*/
|
||||
int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
|
||||
|
||||
/*
|
||||
* This is the actual output entry point.
|
||||
*
|
||||
* For transport mode and equivalent this would be identical to
|
||||
* output2 (which does not need to be set). While tunnel mode
|
||||
* and equivalent would set this to a tunnel encapsulation function
|
||||
* (xfrm4_prepare_output or xfrm6_prepare_output) that would in turn
|
||||
* call output2.
|
||||
*/
|
||||
int (*output)(struct xfrm_state *x, struct sk_buff *skb);
|
||||
|
||||
/*
|
||||
* Adjust pointers into the packet and do GSO segmentation.
|
||||
*/
|
||||
|
@ -1603,7 +1592,11 @@ int xfrm_trans_queue(struct sk_buff *skb,
|
|||
struct sk_buff *));
|
||||
int xfrm_output_resume(struct sk_buff *skb, int err);
|
||||
int xfrm_output(struct sock *sk, struct sk_buff *skb);
|
||||
int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_PKTGEN)
|
||||
int pktgen_xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
#endif
|
||||
|
||||
void xfrm_local_error(struct sk_buff *skb, int mtu);
|
||||
int xfrm4_extract_header(struct sk_buff *skb);
|
||||
int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
|
||||
|
@ -1622,7 +1615,6 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
|
|||
}
|
||||
|
||||
int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb);
|
||||
int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
|
||||
|
@ -1649,7 +1641,6 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family)
|
|||
__be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
|
||||
__be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
|
||||
int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb);
|
||||
int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
|
||||
|
|
|
@ -2521,7 +2521,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
|
|||
skb->_skb_refdst = (unsigned long)&pkt_dev->xdst.u.dst | SKB_DST_NOREF;
|
||||
|
||||
rcu_read_lock_bh();
|
||||
err = x->outer_mode->output(x, skb);
|
||||
err = pktgen_xfrm_outer_mode_output(x, skb);
|
||||
rcu_read_unlock_bh();
|
||||
if (err) {
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
|
||||
|
|
|
@ -129,7 +129,6 @@ out:
|
|||
static struct xfrm_mode xfrm4_beet_mode = {
|
||||
.input2 = xfrm4_beet_input,
|
||||
.output2 = xfrm4_beet_output,
|
||||
.output = xfrm4_prepare_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_BEET,
|
||||
.flags = XFRM_MODE_FLAG_TUNNEL,
|
||||
|
|
|
@ -14,27 +14,6 @@
|
|||
#include <net/xfrm.h>
|
||||
#include <net/protocol.h>
|
||||
|
||||
/* Add encapsulation header.
|
||||
*
|
||||
* The IP header will be moved forward to make space for the encapsulation
|
||||
* header.
|
||||
*/
|
||||
static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
int ihl = iph->ihl * 4;
|
||||
|
||||
skb_set_inner_transport_header(skb, skb_transport_offset(skb));
|
||||
|
||||
skb_set_network_header(skb, -x->props.header_len);
|
||||
skb->mac_header = skb->network_header +
|
||||
offsetof(struct iphdr, protocol);
|
||||
skb->transport_header = skb->network_header + ihl;
|
||||
__skb_pull(skb, ihl);
|
||||
memmove(skb_network_header(skb), iph, ihl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
|
||||
struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
|
@ -65,7 +44,6 @@ static void xfrm4_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
static struct xfrm_mode xfrm4_transport_mode = {
|
||||
.output = xfrm4_transport_output,
|
||||
.gso_segment = xfrm4_transport_gso_segment,
|
||||
.xmit = xfrm4_transport_xmit,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -124,7 +124,6 @@ static void xfrm4_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
|
|||
static struct xfrm_mode xfrm4_tunnel_mode = {
|
||||
.input2 = xfrm4_mode_tunnel_input,
|
||||
.output2 = xfrm4_mode_tunnel_output,
|
||||
.output = xfrm4_prepare_output,
|
||||
.gso_segment = xfrm4_mode_tunnel_gso_segment,
|
||||
.xmit = xfrm4_mode_tunnel_xmit,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -58,21 +58,6 @@ int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
|||
return xfrm4_extract_header(skb);
|
||||
}
|
||||
|
||||
int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = xfrm_inner_extract_output(x, skb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm4_prepare_output);
|
||||
|
||||
int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
||||
|
|
|
@ -105,7 +105,6 @@ out:
|
|||
static struct xfrm_mode xfrm6_beet_mode = {
|
||||
.input2 = xfrm6_beet_input,
|
||||
.output2 = xfrm6_beet_output,
|
||||
.output = xfrm6_prepare_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_BEET,
|
||||
.flags = XFRM_MODE_FLAG_TUNNEL,
|
||||
|
|
|
@ -33,35 +33,7 @@
|
|||
#include <net/ipv6.h>
|
||||
#include <net/xfrm.h>
|
||||
|
||||
/* Add route optimization header space.
|
||||
*
|
||||
* The IP header and mutable extension headers will be moved forward to make
|
||||
* space for the route optimization header.
|
||||
*/
|
||||
static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
struct ipv6hdr *iph;
|
||||
u8 *prevhdr;
|
||||
int hdr_len;
|
||||
|
||||
iph = ipv6_hdr(skb);
|
||||
|
||||
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
|
||||
if (hdr_len < 0)
|
||||
return hdr_len;
|
||||
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
|
||||
skb_set_network_header(skb, -x->props.header_len);
|
||||
skb->transport_header = skb->network_header + hdr_len;
|
||||
__skb_pull(skb, hdr_len);
|
||||
memmove(ipv6_hdr(skb), iph, hdr_len);
|
||||
|
||||
x->lastused = ktime_get_real_seconds();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xfrm_mode xfrm6_ro_mode = {
|
||||
.output = xfrm6_ro_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_ROUTEOPTIMIZATION,
|
||||
.family = AF_INET6,
|
||||
|
|
|
@ -15,31 +15,6 @@
|
|||
#include <net/xfrm.h>
|
||||
#include <net/protocol.h>
|
||||
|
||||
/* Add encapsulation header.
|
||||
*
|
||||
* The IP header and mutable extension headers will be moved forward to make
|
||||
* space for the encapsulation header.
|
||||
*/
|
||||
static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
struct ipv6hdr *iph;
|
||||
u8 *prevhdr;
|
||||
int hdr_len;
|
||||
|
||||
iph = ipv6_hdr(skb);
|
||||
skb_set_inner_transport_header(skb, skb_transport_offset(skb));
|
||||
|
||||
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
|
||||
if (hdr_len < 0)
|
||||
return hdr_len;
|
||||
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
|
||||
skb_set_network_header(skb, -x->props.header_len);
|
||||
skb->transport_header = skb->network_header + hdr_len;
|
||||
__skb_pull(skb, hdr_len);
|
||||
memmove(ipv6_hdr(skb), iph, hdr_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
|
||||
struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
|
@ -70,7 +45,6 @@ static void xfrm6_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
static struct xfrm_mode xfrm6_transport_mode = {
|
||||
.output = xfrm6_transport_output,
|
||||
.gso_segment = xfrm4_transport_gso_segment,
|
||||
.xmit = xfrm6_transport_xmit,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -123,7 +123,6 @@ static void xfrm6_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
|
|||
static struct xfrm_mode xfrm6_tunnel_mode = {
|
||||
.input2 = xfrm6_mode_tunnel_input,
|
||||
.output2 = xfrm6_mode_tunnel_output,
|
||||
.output = xfrm6_prepare_output,
|
||||
.gso_segment = xfrm6_mode_tunnel_gso_segment,
|
||||
.xmit = xfrm6_mode_tunnel_xmit,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -111,21 +111,6 @@ int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
|||
return xfrm6_extract_header(skb);
|
||||
}
|
||||
|
||||
int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = xfrm_inner_extract_output(x, skb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
skb->ignore_df = 1;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm6_prepare_output);
|
||||
|
||||
int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <net/xfrm.h>
|
||||
|
||||
static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
|
||||
static int xfrm_skb_check_space(struct sk_buff *skb)
|
||||
{
|
||||
|
@ -50,6 +51,166 @@ static struct dst_entry *skb_dst_pop(struct sk_buff *skb)
|
|||
return child;
|
||||
}
|
||||
|
||||
/* Add encapsulation header.
|
||||
*
|
||||
* The IP header will be moved forward to make space for the encapsulation
|
||||
* header.
|
||||
*/
|
||||
static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_INET_XFRM_MODE_TRANSPORT)
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
int ihl = iph->ihl * 4;
|
||||
|
||||
skb_set_inner_transport_header(skb, skb_transport_offset(skb));
|
||||
|
||||
skb_set_network_header(skb, -x->props.header_len);
|
||||
skb->mac_header = skb->network_header +
|
||||
offsetof(struct iphdr, protocol);
|
||||
skb->transport_header = skb->network_header + ihl;
|
||||
__skb_pull(skb, ihl);
|
||||
memmove(skb_network_header(skb), iph, ihl);
|
||||
return 0;
|
||||
#else
|
||||
WARN_ON_ONCE(1);
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Add encapsulation header.
|
||||
*
|
||||
* The IP header and mutable extension headers will be moved forward to make
|
||||
* space for the encapsulation header.
|
||||
*/
|
||||
static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_TRANSPORT)
|
||||
struct ipv6hdr *iph;
|
||||
u8 *prevhdr;
|
||||
int hdr_len;
|
||||
|
||||
iph = ipv6_hdr(skb);
|
||||
skb_set_inner_transport_header(skb, skb_transport_offset(skb));
|
||||
|
||||
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
|
||||
if (hdr_len < 0)
|
||||
return hdr_len;
|
||||
skb_set_mac_header(skb,
|
||||
(prevhdr - x->props.header_len) - skb->data);
|
||||
skb_set_network_header(skb, -x->props.header_len);
|
||||
skb->transport_header = skb->network_header + hdr_len;
|
||||
__skb_pull(skb, hdr_len);
|
||||
memmove(ipv6_hdr(skb), iph, hdr_len);
|
||||
return 0;
|
||||
#else
|
||||
WARN_ON_ONCE(1);
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Add route optimization header space.
|
||||
*
|
||||
* The IP header and mutable extension headers will be moved forward to make
|
||||
* space for the route optimization header.
|
||||
*/
|
||||
static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION)
|
||||
struct ipv6hdr *iph;
|
||||
u8 *prevhdr;
|
||||
int hdr_len;
|
||||
|
||||
iph = ipv6_hdr(skb);
|
||||
|
||||
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
|
||||
if (hdr_len < 0)
|
||||
return hdr_len;
|
||||
skb_set_mac_header(skb,
|
||||
(prevhdr - x->props.header_len) - skb->data);
|
||||
skb_set_network_header(skb, -x->props.header_len);
|
||||
skb->transport_header = skb->network_header + hdr_len;
|
||||
__skb_pull(skb, hdr_len);
|
||||
memmove(ipv6_hdr(skb), iph, hdr_len);
|
||||
|
||||
x->lastused = ktime_get_real_seconds();
|
||||
|
||||
return 0;
|
||||
#else
|
||||
WARN_ON_ONCE(1);
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = xfrm_inner_extract_output(x, skb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
}
|
||||
|
||||
static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
int err;
|
||||
|
||||
err = xfrm_inner_extract_output(x, skb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
skb->ignore_df = 1;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
#else
|
||||
WARN_ON_ONCE(1);
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
switch (x->outer_mode->encap) {
|
||||
case XFRM_MODE_BEET:
|
||||
case XFRM_MODE_TUNNEL:
|
||||
if (x->outer_mode->family == AF_INET)
|
||||
return xfrm4_prepare_output(x, skb);
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
return xfrm6_prepare_output(x, skb);
|
||||
break;
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
if (x->outer_mode->family == AF_INET)
|
||||
return xfrm4_transport_output(x, skb);
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
return xfrm6_transport_output(x, skb);
|
||||
break;
|
||||
case XFRM_MODE_ROUTEOPTIMIZATION:
|
||||
if (x->outer_mode->family == AF_INET6)
|
||||
return xfrm6_ro_output(x, skb);
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_PKTGEN)
|
||||
int pktgen_xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
return xfrm_outer_mode_output(x, skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pktgen_xfrm_outer_mode_output);
|
||||
#endif
|
||||
|
||||
static int xfrm_output_one(struct sk_buff *skb, int err)
|
||||
{
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
|
@ -68,7 +229,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
|
|||
|
||||
skb->mark = xfrm_smark_get(skb->mark, x);
|
||||
|
||||
err = x->outer_mode->output(x, skb);
|
||||
err = xfrm_outer_mode_output(x, skb);
|
||||
if (err) {
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
|
||||
goto error_nolock;
|
||||
|
@ -258,7 +419,7 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_output);
|
||||
|
||||
int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
struct xfrm_mode *inner_mode;
|
||||
if (x->sel.family == AF_UNSPEC)
|
||||
|
@ -271,7 +432,6 @@ int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
|||
return -EAFNOSUPPORT;
|
||||
return inner_mode->afinfo->extract_output(x, skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_inner_extract_output);
|
||||
|
||||
void xfrm_local_error(struct sk_buff *skb, int mtu)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче