@@ -436,16 +436,6 @@ struct xfrm_mode {
*/
int (*input2)(struct xfrm_state *x, struct sk_buff *skb);
- /*
- * This is the actual input entry point.
- *
- * For transport mode and equivalent this would be identical to
- * input2 (which does not need to be set). While tunnel mode
- * and equivalent would set this to the tunnel encapsulation function
- * xfrm4_prepare_input that would in turn call input2.
- */
- int (*input)(struct xfrm_state *x, struct sk_buff *skb);
-
/*
* Add encapsulation header.
*
@@ -128,7 +128,6 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
static struct xfrm_mode xfrm4_beet_mode = {
.input2 = xfrm4_beet_input,
- .input = xfrm_prepare_input,
.output2 = xfrm4_beet_output,
.output = xfrm4_prepare_output,
.owner = THIS_MODULE,
@@ -35,28 +35,6 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-/* Remove encapsulation header.
- *
- * The IP header will be moved over the top of the encapsulation header.
- *
- * On entry, skb->h shall point to where the IP header should be and skb->nh
- * shall be set to where the IP header currently is. skb->data shall point
- * to the start of the payload.
- */
-static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
-{
- int ihl = skb->data - skb_transport_header(skb);
-
- if (skb->transport_header != skb->network_header) {
- memmove(skb_transport_header(skb),
- skb_network_header(skb), ihl);
- skb->network_header = skb->transport_header;
- }
- ip_hdr(skb)->tot_len = htons(skb->len + ihl);
- skb_reset_transport_header(skb);
- return 0;
-}
-
static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
struct sk_buff *skb,
netdev_features_t features)
@@ -87,7 +65,6 @@ static void xfrm4_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
}
static struct xfrm_mode xfrm4_transport_mode = {
- .input = xfrm4_transport_input,
.output = xfrm4_transport_output,
.gso_segment = xfrm4_transport_gso_segment,
.xmit = xfrm4_transport_xmit,
@@ -123,7 +123,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,
- .input = xfrm_prepare_input,
.output2 = xfrm4_mode_tunnel_output,
.output = xfrm4_prepare_output,
.gso_segment = xfrm4_mode_tunnel_gso_segment,
@@ -104,7 +104,6 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
static struct xfrm_mode xfrm6_beet_mode = {
.input2 = xfrm6_beet_input,
- .input = xfrm_prepare_input,
.output2 = xfrm6_beet_output,
.output = xfrm6_prepare_output,
.owner = THIS_MODULE,
@@ -40,29 +40,6 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-/* Remove encapsulation header.
- *
- * The IP header will be moved over the top of the encapsulation header.
- *
- * On entry, skb->h shall point to where the IP header should be and skb->nh
- * shall be set to where the IP header currently is. skb->data shall point
- * to the start of the payload.
- */
-static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
-{
- int ihl = skb->data - skb_transport_header(skb);
-
- if (skb->transport_header != skb->network_header) {
- memmove(skb_transport_header(skb),
- skb_network_header(skb), ihl);
- skb->network_header = skb->transport_header;
- }
- ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
- sizeof(struct ipv6hdr));
- skb_reset_transport_header(skb);
- return 0;
-}
-
static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
struct sk_buff *skb,
netdev_features_t features)
@@ -92,9 +69,7 @@ static void xfrm6_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
}
}
-
static struct xfrm_mode xfrm6_transport_mode = {
- .input = xfrm6_transport_input,
.output = xfrm6_transport_output,
.gso_segment = xfrm4_transport_gso_segment,
.xmit = xfrm6_transport_xmit,
@@ -122,7 +122,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,
- .input = xfrm_prepare_input,
.output2 = xfrm6_mode_tunnel_output,
.output = xfrm6_prepare_output,
.gso_segment = xfrm6_mode_tunnel_gso_segment,
@@ -186,6 +186,74 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
}
EXPORT_SYMBOL(xfrm_prepare_input);
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is. skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_INET4_XFRM_MODE_TRANSPORT)
+ int ihl = skb->data - skb_transport_header(skb);
+
+ if (skb->transport_header != skb->network_header) {
+ memmove(skb_transport_header(skb),
+ skb_network_header(skb), ihl);
+ skb->network_header = skb->transport_header;
+ }
+ ip_hdr(skb)->tot_len = htons(skb->len + ihl);
+ skb_reset_transport_header(skb);
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
+static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_TRANSPORT)
+ int ihl = skb->data - skb_transport_header(skb);
+
+ if (skb->transport_header != skb->network_header) {
+ memmove(skb_transport_header(skb),
+ skb_network_header(skb), ihl);
+ skb->network_header = skb->transport_header;
+ }
+ ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
+ sizeof(struct ipv6hdr));
+ skb_reset_transport_header(skb);
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
+static int xfrm_inner_mode_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+ switch (x->inner_mode->encap) {
+ case XFRM_MODE_BEET:
+ case XFRM_MODE_TUNNEL:
+ return xfrm_prepare_input(x, skb);
+ case XFRM_MODE_TRANSPORT:
+ if (x->inner_mode->family == AF_INET)
+ return xfrm4_transport_input(x, skb);
+ if (x->inner_mode->family == AF_INET6)
+ return xfrm6_transport_input(x, skb);
+ break;
+ case XFRM_MODE_ROUTEOPTIMIZATION:
+ WARN_ON_ONCE(1);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ return -EOPNOTSUPP;
+}
+
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
{
struct net *net = dev_net(skb->dev);
@@ -410,7 +478,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
}
}
- if (inner_mode->input(x, skb)) {
+ if (xfrm_inner_mode_input(x, skb)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
goto drop;
}
No need for any indirection or abstraction here, both functions are pretty much the same and quite small, they also have no external dependencies. With allmodconfig build, size increase of vmlinux is 25 byte: Before: text data bss dec filename 15730207 6936924 4046908 26714039 vmlinux After: 15730208 6936948 4046908 26714064 vmlinux Signed-off-by: Florian Westphal <fw@strlen.de> --- include/net/xfrm.h | 10 ----- net/ipv4/xfrm4_mode_beet.c | 1 - net/ipv4/xfrm4_mode_transport.c | 23 ----------- net/ipv4/xfrm4_mode_tunnel.c | 1 - net/ipv6/xfrm6_mode_beet.c | 1 - net/ipv6/xfrm6_mode_transport.c | 25 ------------ net/ipv6/xfrm6_mode_tunnel.c | 1 - net/xfrm/xfrm_input.c | 70 ++++++++++++++++++++++++++++++++- 8 files changed, 69 insertions(+), 63 deletions(-)