]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: connection: implement passive reverse
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 27 Jul 2023 13:56:34 +0000 (15:56 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 24 Aug 2023 12:44:33 +0000 (14:44 +0200)
Define a new method conn_reverse(). This method is used to reverse a
connection from frontend to backend or vice-versa depending on its
initial status.

For the moment, passive reverse only is implemented. This covers the
transition from frontend to backend side. The connection is detached
from its owner session which can then be freed. Then the connection is
linked to the server instance.

only for passive connection on
frontend to transfer them on the backend side. This requires to free the
connection session after detaching it from.

include/haproxy/connection-t.h
include/haproxy/connection.h
src/connection.c

index eb02bbcf225719695b40f775f0b06d0ab83b9286..98a010e0355323d8d7b5a310298a1cfcdce9d851 100644 (file)
@@ -543,6 +543,11 @@ struct connection {
         * thus only present if conn.target is of type OBJ_TYPE_SERVER
         */
        struct conn_hash_node *hash_node;
+
+       /* Members used if connection must be reversed. */
+       struct {
+               enum obj_type *target; /* Server for passive reverse. */
+       } reverse;
 };
 
 /* node for backend connection in the idle trees for http-reuse
index 8cf22ef4f55158c43f7f3124c391805d0d7a198f..3cb13e6847fd28a58c24f7b7f7ac752e241517dd 100644 (file)
@@ -100,6 +100,9 @@ void conn_hash_update(char *buf, size_t *idx,
                       enum conn_hash_params_t type);
 uint64_t conn_hash_digest(char *buf, size_t bufsize,
                           enum conn_hash_params_t flags);
+
+int conn_reverse(struct connection *conn);
+
 const char *conn_err_code_str(struct connection *c);
 int xprt_add_hs(struct connection *conn);
 void register_mux_proto(struct mux_proto_list *list);
index b45a23285a5413e868fbab89e1a41eb46fd3a58f..f6ac7dbf5030bd0f2554515a2ef864436f5db827 100644 (file)
@@ -435,6 +435,7 @@ void conn_init(struct connection *conn, void *target)
        conn->proxy_unique_id = IST_NULL;
        conn->hash_node = NULL;
        conn->xprt = NULL;
+       conn->reverse.target = NULL;
 }
 
 /* Initialize members used for backend connections.
@@ -2433,6 +2434,56 @@ uint64_t conn_calculate_hash(const struct conn_hash_params *params)
        return hash;
 }
 
+/* Reverse a <conn> connection instance. This effectively moves the connection
+ * from frontend to backend side or vice-versa depending on its initial status.
+ *
+ * For passive reversal, 'reverse' member points to the server used as the new
+ * connection target. Once transition is completed, the connection appears as a
+ * normal backend connection.
+ *
+ * Returns 0 on success else non-zero.
+ */
+int conn_reverse(struct connection *conn)
+{
+       struct conn_hash_params hash_params;
+       int64_t hash = 0;
+       struct session *sess = conn->owner;
+
+       if (!conn_is_back(conn)) {
+               /* srv must have been set by a previous 'attach-srv' rule. */
+               struct server *srv = objt_server(conn->reverse.target);
+               BUG_ON(!srv);
+
+               if (conn_backend_init(conn))
+                       return 1;
+
+               /* Initialize hash value for usage as idle conns. */
+               memset(&hash_params, 0, sizeof(hash_params));
+               hash_params.target = srv;
+
+               hash = conn_calculate_hash(&hash_params);
+               conn->hash_node->node.key = hash;
+
+               conn->target = &srv->obj_type;
+               srv_use_conn(srv, conn);
+
+               /* Free the session after detaching the connection from it. */
+               session_unown_conn(sess, conn);
+               sess->origin = NULL;
+               session_free(sess);
+               conn_set_owner(conn, NULL, NULL);
+       }
+       else {
+               ABORT_NOW();
+       }
+
+       /* Invert source and destination addresses if already set. */
+       SWAP(conn->src, conn->dst);
+
+       conn->reverse.target = NULL;
+       return 0;
+}
+
 /* Handler of the task of mux_stopping_data.
  * Called on soft-stop.
  */