On Mon, May 19 2025 at 04:49:00 PM -0700, Junio C Hamano
<gitster@xxxxxxxxx> wrote:
Phillip Wood <phillip.wood123@xxxxxxxxx> writes:
As brian has already said I think it would be better to have a
Makefile knob to control this which defaults to being on for
linux. Take a look at the various USE_xxx definitions in the
Makefile
and config.mak.uname for setting default compile flags for different
operating systems.
Also another check if a socket is supported by looking for a return
value of
"EAI_SOCKTYPE" (not EINVAL) and fallback to regular TCP if that is
returned.
EAI_SOCKTYPE should work across different UNIX systems as this is a
posix error code.
That error is not mentioned in the documentation for MCTCP on Linux
[1]. Please make sure your code checks for the errno values
described
in the documentation.
Also according to RFC 6897, "MPTCP is designed to be totally
backward compatible to applications". I understand that this is
quite unlike introducing IPv6 into IPv4-only world. You can tell
the system that supports MPTCP to use it in specific ways by
updating your application, but your system's local policy may
allow MPTCP to automatically set up multiple subflows even your
application is not quite aware of MPTCP.
So, ... I somehow would be mildly surprised if Git were a kind of
application that needs to take advantage of "several additional
degrees of freedom that applications may wish to exploit" by using
API that is "a simple extension of TCP's interface for MPTCP-aware
applications". Requiring a simple application like ours to tweak
and rebuild in today's world does not sound like a winning strategy
to promote a technology that "is designed to be totally backward
compatible to applications", at least to me.
Taking into scenario that i have WiFi access and regular Ethernet access
on my Laptop and i'm cloning or pulling a large set of code from git
(which uses
regular ethernet as primary interface and WiFi as secondary.)
On the regular TCP, my connection will reset when disconnecting
(plugging off) from Ethernet
and switching to WiFi but MPTCP solves that issue for me and allows
uninterrupted
work on git cloning/pulling, especially when i have to work with huge
codebases.
I think that's the relevant use-case for a laptop user working with git.
Apple had been using MPTCP for 12 years and their cloud services run on
Linux servers with iOS clients and for that i can say that it's pretty
much production ready.
And it's not just Apple. Intel and RedHat had been involved and
RedHat[1] pretty much
are into MPTCP.
Honestly, i love reading the git codebase as it is very simple and
straightforward and
i think my previous patches were a bit too big and needs to be
simplified so,
I have reached out to Matthieu Baerts <matttbe@xxxxxxxxxx> who works on
Linux MPTCP
on this issue and i've greatly simplified the code from his comments.
(I've also added him to the loop in this email)
The patch i am attaching is a preview (still WIP) as i need some
feedback from the linux
mptcp developers if my implementation is correct. But it's greatly
simplified to follow
git codebase's structure.
Changed the part for the git server daemon to enable mptcp by
default[0] and modified
the git client to use .gitconfig (global or per repository) with:
git config --global core.mptcp true (or a single repo without --global)
which defaults to false (mptcp disabled for client) as per[0] and
removed client-side the env var configuration.
[0]
https://www.mptcp.dev/faq.html#why--when-should-mptcp-be-enabled-by-default
(Thanks @matt!)
[1]
https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/getting-started-with-multipath-tcp_configuring-and-managing-networking#proc_monitoring-mptcp-sub-flows_getting-started-with-multipath-tcp
diff --git a/cache.h b/cache.h
index eba12487b9..6839b3acbc 100644
--- a/cache.h
+++ b/cache.h
@@ -944,6 +944,7 @@ extern int verify_ce_order;
/* Environment bits from configuration mechanism */
extern int trust_executable_bit;
+extern int enable_mptcp;
extern int trust_ctime;
extern int check_stat;
extern int quote_path_fully;
diff --git a/config.c b/config.c
index 2317a76696..833396aa4b 100644
--- a/config.c
+++ b/config.c
@@ -1464,6 +1464,11 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "core.editor"))
return git_config_string(&editor_program, var, value);
+ if (!strcmp(var, "core.mptcp")) {
+ enable_mptcp = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "core.commentchar")) {
if (!value)
return config_error_nonbool(var);
diff --git a/connect.c b/connect.c
index eaf7d6d261..ebeac99bd6 100644
--- a/connect.c
+++ b/connect.c
@@ -721,6 +721,16 @@ static void enable_keepalive(int sockfd)
error_errno(_("unable to set SO_KEEPALIVE on socket"));
}
+static const int needs_mptcp(void)
+{
+ int mptcp = 0;
+
+ if (git_config_get_bool("core.mptcp", &mptcp))
+ return mptcp;
+
+ return mptcp;
+}
+
#ifndef NO_IPV6
static const char *ai_name(const struct addrinfo *ai)
@@ -770,7 +780,11 @@ static int git_tcp_connect_sock(char *host, int flags)
for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
sockfd = socket(ai->ai_family,
- ai->ai_socktype, ai->ai_protocol);
+ ai->ai_socktype,
+#ifdef IPPROTO_MPTCP
+ needs_mptcp() ? IPPROTO_MPTCP :
+#endif
+ ai->ai_protocol);
if ((sockfd < 0) ||
(connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) {
strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
@@ -817,6 +831,7 @@ static int git_tcp_connect_sock(char *host, int flags)
char **ap;
unsigned int nport;
int cnt;
+ const int needs_mptcp;
get_host_and_port(&host, &port);
diff --git a/daemon.c b/daemon.c
index b1fcbe0d6f..08a16ccf03 100644
--- a/daemon.c
+++ b/daemon.c
@@ -17,6 +17,7 @@ static enum log_destination {
} log_destination = LOG_DESTINATION_UNSET;
static int verbose;
static int reuseaddr;
+static int mptcp;
static int informative_errors;
static const char daemon_usage[] =
@@ -1007,6 +1008,10 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
for (ai = ai0; ai; ai = ai->ai_next) {
int sockfd;
+#if defined(__linux__) && defined(IPPROTO_MPTCP)
+ sockfd = socket(ai->ai_family, ai->ai_socktype, IPPROTO_MPTCP);
+ if (sockfd < 0)
+#endif
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd < 0)
continue;
@@ -1360,6 +1365,10 @@ int cmd_main(int argc, const char **argv)
reuseaddr = 1;
continue;
}
+ if (!strcmp(arg, "--mptcp")) {
+ mptcp = 1;
+ continue;
+ }
if (!strcmp(arg, "--user-path")) {
user_path = "";
continue;
diff --git a/environment.c b/environment.c
index 9da7f3c1a1..72f1adef6c 100644
--- a/environment.c
+++ b/environment.c
@@ -33,6 +33,7 @@ int warn_ambiguous_refs = 1;
int warn_on_object_refname_ambiguity = 1;
int repository_format_precious_objects;
int repository_format_worktree_config;
+int enable_mptcp;
const char *git_commit_encoding;
const char *git_log_output_encoding;
char *apply_default_whitespace;