Commit fe19a8fe authored by Matteo Croce's avatar Matteo Croce Committed by Pablo Neira Ayuso

ipvs: avoid indirect calls when calculating checksums

The function pointer ip_vs_protocol->csum_check is only used in protocol
specific code, and never in the generic one.
Remove the function pointer from struct ip_vs_protocol and call the
checksum functions directly.
This reduces the performance impact of the Spectre mitigation, and
should give a small improvement even with RETPOLINES disabled.
Signed-off-by: default avatarMatteo Croce <mcroce@redhat.com>
Acked-by: default avatarJulian Anastasov <ja@ssi.bg>
Acked-by: default avatarSimon Horman <horms@verge.net.au>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent e2f7cc72
...@@ -453,9 +453,6 @@ struct ip_vs_protocol { ...@@ -453,9 +453,6 @@ struct ip_vs_protocol {
int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp, int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph); struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
int (*csum_check)(int af, struct sk_buff *skb,
struct ip_vs_protocol *pp);
const char *(*state_name)(int state); const char *(*state_name)(int state);
void (*state_transition)(struct ip_vs_conn *cp, int direction, void (*state_transition)(struct ip_vs_conn *cp, int direction,
......
...@@ -129,7 +129,6 @@ struct ip_vs_protocol ip_vs_protocol_ah = { ...@@ -129,7 +129,6 @@ struct ip_vs_protocol ip_vs_protocol_ah = {
.conn_out_get = ah_esp_conn_out_get, .conn_out_get = ah_esp_conn_out_get,
.snat_handler = NULL, .snat_handler = NULL,
.dnat_handler = NULL, .dnat_handler = NULL,
.csum_check = NULL,
.state_transition = NULL, .state_transition = NULL,
.register_app = NULL, .register_app = NULL,
.unregister_app = NULL, .unregister_app = NULL,
...@@ -152,7 +151,6 @@ struct ip_vs_protocol ip_vs_protocol_esp = { ...@@ -152,7 +151,6 @@ struct ip_vs_protocol ip_vs_protocol_esp = {
.conn_out_get = ah_esp_conn_out_get, .conn_out_get = ah_esp_conn_out_get,
.snat_handler = NULL, .snat_handler = NULL,
.dnat_handler = NULL, .dnat_handler = NULL,
.csum_check = NULL,
.state_transition = NULL, .state_transition = NULL,
.register_app = NULL, .register_app = NULL,
.unregister_app = NULL, .unregister_app = NULL,
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
#include <net/sctp/checksum.h> #include <net/sctp/checksum.h>
#include <net/ip_vs.h> #include <net/ip_vs.h>
static int
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
static int static int
sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd, struct ip_vs_proto_data *pd,
...@@ -105,7 +108,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -105,7 +108,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!sctp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* Call application helper if needed */ /* Call application helper if needed */
...@@ -152,7 +155,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -152,7 +155,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!sctp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* Call application helper if needed */ /* Call application helper if needed */
...@@ -587,7 +590,6 @@ struct ip_vs_protocol ip_vs_protocol_sctp = { ...@@ -587,7 +590,6 @@ struct ip_vs_protocol ip_vs_protocol_sctp = {
.conn_out_get = ip_vs_conn_out_get_proto, .conn_out_get = ip_vs_conn_out_get_proto,
.snat_handler = sctp_snat_handler, .snat_handler = sctp_snat_handler,
.dnat_handler = sctp_dnat_handler, .dnat_handler = sctp_dnat_handler,
.csum_check = sctp_csum_check,
.state_name = sctp_state_name, .state_name = sctp_state_name,
.state_transition = sctp_state_transition, .state_transition = sctp_state_transition,
.app_conn_bind = sctp_app_conn_bind, .app_conn_bind = sctp_app_conn_bind,
......
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
#include <net/ip_vs.h> #include <net/ip_vs.h>
static int
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
static int static int
tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd, struct ip_vs_proto_data *pd,
...@@ -166,7 +169,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -166,7 +169,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!tcp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* Call application helper if needed */ /* Call application helper if needed */
...@@ -192,7 +195,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -192,7 +195,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
tcp_fast_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr, tcp_fast_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
cp->dport, cp->vport); cp->dport, cp->vport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -244,7 +247,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -244,7 +247,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!tcp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* /*
...@@ -275,7 +278,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -275,7 +278,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
tcp_fast_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr, tcp_fast_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr,
cp->vport, cp->dport); cp->vport, cp->dport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -736,7 +739,6 @@ struct ip_vs_protocol ip_vs_protocol_tcp = { ...@@ -736,7 +739,6 @@ struct ip_vs_protocol ip_vs_protocol_tcp = {
.conn_out_get = ip_vs_conn_out_get_proto, .conn_out_get = ip_vs_conn_out_get_proto,
.snat_handler = tcp_snat_handler, .snat_handler = tcp_snat_handler,
.dnat_handler = tcp_dnat_handler, .dnat_handler = tcp_dnat_handler,
.csum_check = tcp_csum_check,
.state_name = tcp_state_name, .state_name = tcp_state_name,
.state_transition = tcp_state_transition, .state_transition = tcp_state_transition,
.app_conn_bind = tcp_app_conn_bind, .app_conn_bind = tcp_app_conn_bind,
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#include <net/ip.h> #include <net/ip.h>
#include <net/ip6_checksum.h> #include <net/ip6_checksum.h>
static int
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
static int static int
udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd, struct ip_vs_proto_data *pd,
...@@ -156,7 +159,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -156,7 +159,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!udp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* /*
...@@ -186,7 +189,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -186,7 +189,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
udp_fast_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr, udp_fast_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
cp->dport, cp->vport); cp->dport, cp->vport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -239,7 +242,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -239,7 +242,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!udp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* /*
...@@ -270,7 +273,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -270,7 +273,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
udp_fast_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr, udp_fast_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr,
cp->vport, cp->dport); cp->vport, cp->dport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -494,7 +497,6 @@ struct ip_vs_protocol ip_vs_protocol_udp = { ...@@ -494,7 +497,6 @@ struct ip_vs_protocol ip_vs_protocol_udp = {
.conn_out_get = ip_vs_conn_out_get_proto, .conn_out_get = ip_vs_conn_out_get_proto,
.snat_handler = udp_snat_handler, .snat_handler = udp_snat_handler,
.dnat_handler = udp_dnat_handler, .dnat_handler = udp_dnat_handler,
.csum_check = udp_csum_check,
.state_transition = udp_state_transition, .state_transition = udp_state_transition,
.state_name = udp_state_name, .state_name = udp_state_name,
.register_app = udp_register_app, .register_app = udp_register_app,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment