Skip to content

Commit

Permalink
patch: support dcdn toa (#913)
Browse files Browse the repository at this point in the history
Decode aliyun's toa and encode it to the format of DPVS. It's a workaround when the traffic of DPVS is from aliyun l4lb.
  • Loading branch information
ytwang0320 authored Sep 15, 2023
1 parent d683835 commit af47c02
Showing 1 changed file with 139 additions and 0 deletions.
139 changes: 139 additions & 0 deletions patch/dcdn-toa.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
From 55e8e5da2b4b0893d36cb3f621bedf9833c4ea50 Mon Sep 17 00:00:00 2001
From: wangyetong <[email protected]>
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

0 comments on commit af47c02

Please sign in to comment.