]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipvs: pass parsed transport offset to state handlers
authorYizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
Mon, 6 Jul 2026 10:16:22 +0000 (18:16 +0800)
committerFlorian Westphal <fw@strlen.de>
Wed, 8 Jul 2026 13:33:44 +0000 (15:33 +0200)
IPVS callers already parse the packet into struct ip_vs_iphdr before
updating connection state. For IPv6 this records the real
transport-header offset after extension headers in iph.len.

Pass this parsed transport offset through ip_vs_set_state() and the
protocol state_transition() callback so protocol handlers can use the
same packet context as scheduling and NAT handling. This patch only
changes the common callback plumbing and adapts the protocol callback
signatures; TCP and SCTP start using the value in follow-up patches.

Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Florian Westphal <fw@strlen.de>
include/net/ip_vs.h
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/ipvs/ip_vs_proto_tcp.c
net/netfilter/ipvs/ip_vs_proto_udp.c

index 49297fec448a8209b5f8b993b1b8ad008a1549ea..417ff51f62fc8edb80475706832e9c6008854893 100644 (file)
@@ -752,7 +752,8 @@ struct ip_vs_protocol {
 
        void (*state_transition)(struct ip_vs_conn *cp, int direction,
                                 const struct sk_buff *skb,
-                                struct ip_vs_proto_data *pd);
+                                struct ip_vs_proto_data *pd,
+                                unsigned int iph_len);
 
        int (*register_app)(struct netns_ipvs *ipvs, struct ip_vs_app *inc);
 
index 906f2c3616763849ef67458d5d48ff741339489e..f79c098696366268e41d4e4afcdda111ad92e5fc 100644 (file)
@@ -398,10 +398,10 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
 static inline void
 ip_vs_set_state(struct ip_vs_conn *cp, int direction,
                const struct sk_buff *skb,
-               struct ip_vs_proto_data *pd)
+               struct ip_vs_proto_data *pd, unsigned int iph_len)
 {
        if (likely(pd->pp->state_transition))
-               pd->pp->state_transition(cp, direction, skb, pd);
+               pd->pp->state_transition(cp, direction, skb, pd, iph_len);
 }
 
 static inline int
@@ -803,7 +803,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
                ip_vs_in_stats(cp, skb);
 
                /* set state */
-               ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
+               ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd, iph->len);
 
                /* transmit the first SYN packet */
                ret = cp->packet_xmit(skb, cp, pd->pp, iph);
@@ -1484,7 +1484,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 
 after_nat:
        ip_vs_out_stats(cp, skb);
-       ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd);
+       ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd, iph->len);
        skb->ipvs_property = 1;
        if (!(cp->flags & IP_VS_CONN_F_NFCT))
                ip_vs_notrack(skb);
@@ -2233,7 +2233,7 @@ ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state
        IP_VS_DBG_PKT(11, af, pp, skb, iph.off, "Incoming packet");
 
        ip_vs_in_stats(cp, skb);
-       ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
+       ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd, iph.len);
        if (cp->packet_xmit)
                ret = cp->packet_xmit(skb, cp, pp, &iph);
                /* do not touch skb anymore */
index 63c78a1f3918a79690616227c217a4c8edac05f5..394367b7b3887956166c69f78cb0e25a4fe2877c 100644 (file)
@@ -468,7 +468,8 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
 
 static void
 sctp_state_transition(struct ip_vs_conn *cp, int direction,
-               const struct sk_buff *skb, struct ip_vs_proto_data *pd)
+               const struct sk_buff *skb, struct ip_vs_proto_data *pd,
+               unsigned int iph_len)
 {
        spin_lock_bh(&cp->lock);
        set_sctp_state(pd, cp, direction, skb);
index 8cc0a8ce62411261e5b3e39df764817fb788695c..2d3f6aeafe522d35219eaf628ec77e3e3c89e8e8 100644 (file)
@@ -579,7 +579,8 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
 static void
 tcp_state_transition(struct ip_vs_conn *cp, int direction,
                     const struct sk_buff *skb,
-                    struct ip_vs_proto_data *pd)
+                    struct ip_vs_proto_data *pd,
+                    unsigned int iph_len)
 {
        struct tcphdr _tcph, *th;
 
index f9de632e38cdd6b93e4baa3817ab566fdbd2df5c..58f9e255927e2eb6442308457faf4692a55957e0 100644 (file)
@@ -444,7 +444,8 @@ static const char * udp_state_name(int state)
 static void
 udp_state_transition(struct ip_vs_conn *cp, int direction,
                     const struct sk_buff *skb,
-                    struct ip_vs_proto_data *pd)
+                    struct ip_vs_proto_data *pd,
+                    unsigned int iph_len)
 {
        if (unlikely(!pd)) {
                pr_err("UDP no ns data\n");