From b781b12bec7962745d32ad0923a576b9a83110bd Mon Sep 17 00:00:00 2001 From: wangyetong Date: Fri, 15 Sep 2023 09:14:22 +0800 Subject: [PATCH] patch: support dcdn toa --- patch/dcdn-toa.patch | 139 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 patch/dcdn-toa.patch diff --git a/patch/dcdn-toa.patch b/patch/dcdn-toa.patch new file mode 100644 index 000000000..5107fcd42 --- /dev/null +++ b/patch/dcdn-toa.patch @@ -0,0 +1,139 @@ +From 55e8e5da2b4b0893d36cb3f621bedf9833c4ea50 Mon Sep 17 00:00:00 2001 +From: wangyetong +Date: Thu, 14 Sep 2023 15:33:42 +0800 +Subject: [PATCH] added dcdn toa + +--- + include/ipvs/conn.h | 5 +++++ + include/ipvs/proto_tcp.h | 2 ++ + src/ipvs/ip_vs_proto_tcp.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 60 insertions(+), 1 deletion(-) + +diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h +index fa0bdeb..88dcb44 100644 +--- a/include/ipvs/conn.h ++++ b/include/ipvs/conn.h +@@ -166,6 +166,11 @@ struct dp_vs_conn { + /* flag for gfwip */ + bool outwall; + ++ /* dcdn toa found or not */ ++ bool dcdn_found; ++ /* dcdn toa address */ ++ struct in_addr dcdn_addr; ++ + } __rte_cache_aligned; + + /* for syn-proxy to save all ack packet in conn before rs's syn-ack arrives */ +diff --git a/include/ipvs/proto_tcp.h b/include/ipvs/proto_tcp.h +index 9f5162a..41d5646 100644 +--- a/include/ipvs/proto_tcp.h ++++ b/include/ipvs/proto_tcp.h +@@ -28,6 +28,7 @@ enum { + TCP_OPT_SACK_PERM = 4, + TCP_OPT_SACK = 5, + TCP_OPT_TIMESTAMP = 8, ++ TCP_OPT_DCDN_ADDR = 28, + TCP_OPT_ADDR = 254, /* non-standard */ + }; + +@@ -35,6 +36,7 @@ enum { + #define TCP_OLEN_TIMESTAMP 10 + #define TCP_OLEN_IP4_ADDR 8 + #define TCP_OLEN_IP6_ADDR 20 ++#define TOA_DCDN_IPV4 1 + + #define TCP_OLEN_TSTAMP_ALIGNED 12 + #define TCP_OLEN_SACK_BASE 2 +diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c +index cbb7cb2..2cd889a 100644 +--- a/src/ipvs/ip_vs_proto_tcp.c ++++ b/src/ipvs/ip_vs_proto_tcp.c +@@ -305,6 +305,43 @@ static void tcp_in_remove_ts(struct tcphdr *tcph) + } + } + ++/* check dcdn toa option */ ++static inline int tcp_in_check_toa(struct dp_vs_conn *conn, struct tcphdr *tcph, struct in_addr *addr) ++{ ++ unsigned char *ptr; ++ int len; ++ ++ ptr = (unsigned char *)(tcph + 1); ++ len = (tcph->doff << 2) - sizeof(struct tcphdr); ++ ++ while (len > 0) { ++ int opcode = *ptr++; ++ int opsize; ++ ++ switch (opcode) { ++ case TCP_OPT_EOL: ++ return EDPVS_NOTEXIST; ++ case TCP_OPT_NOP: ++ len--; ++ continue; ++ default: ++ opsize = *ptr++; ++ if (opsize < 2) /* silly options */ ++ return EDPVS_NOTEXIST; ++ if (opsize > len) ++ return EDPVS_NOTEXIST; /* partial options */ ++ if ((opcode == TCP_OPT_DCDN_ADDR) ++ && (*ptr == TOA_DCDN_IPV4) && (opsize == TCP_OLEN_IP4_ADDR - 1) && addr) { ++ memcpy(addr, ptr + 1, sizeof(struct in_addr)); ++ return EDPVS_OK; ++ } ++ ptr += opsize - 2; ++ len -= opsize; ++ } ++ } ++ return EDPVS_NOTEXIST; ++} ++ + static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + struct tcphdr *tcph) + { +@@ -382,7 +419,10 @@ static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + + if (conn->af == AF_INET) { + struct tcpopt_ip4_addr *toa_ip4 = (struct tcpopt_ip4_addr *)(tcph + 1); +- toa_ip4->addr = conn->caddr.in; ++ if (conn->dcdn_found) ++ toa_ip4->addr = conn->dcdn_addr; ++ else ++ toa_ip4->addr = conn->caddr.in; + } + else { + struct tcpopt_ip6_addr *toa_ip6 = (struct tcpopt_ip6_addr *)(tcph + 1); +@@ -694,9 +734,13 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, + struct dp_vs_conn *conn, struct rte_mbuf *mbuf) + { + struct tcphdr *th; ++ struct in_addr dcdn_addr; + /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ + int af = tuplehash_out(conn).af; + int iphdrlen = ((AF_INET6 == af) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); ++#ifdef CONFIG_DPVS_IPVS_DEBUG ++ char dcdn_buf[64]; ++#endif + + if (mbuf_may_pull(mbuf, iphdrlen + sizeof(*th)) != 0) + return EDPVS_INVPKT; +@@ -720,6 +764,14 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, + if (th->syn && !th->ack) { + tcp_in_remove_ts(th); + tcp_in_init_seq(conn, mbuf, th); ++ if (tcp_in_check_toa(conn, th, &dcdn_addr) == EDPVS_OK) { ++ conn->dcdn_found = true; ++ conn->dcdn_addr = dcdn_addr; ++#ifdef CONFIG_DPVS_IPVS_DEBUG ++ inet_ntop(AF_INET, &dcdn_addr, dcdn_buf, sizeof(dcdn_buf)); ++ RTE_LOG(DEBUG, IPVS, "get dcdn toa addr %s\n", dcdn_buf); ++#endif ++ } + tcp_in_add_toa(conn, mbuf, th); + } + +-- +1.8.3.1 +