Signed-off-by: Quentin Armitage <quentin@xxxxxxxxxxxxxxx>
---
SCHEDULERS | 2 +-
ipvsadm.8 | 10 ++++++++++
ipvsadm.c | 31 +++++++++++++++++++++++++++----
3 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/SCHEDULERS b/SCHEDULERS
index 187c07d..06d3357 100644
--- a/SCHEDULERS
+++ b/SCHEDULERS
@@ -1 +1 @@
-rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq|fo|ovf
+rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq|fo|ovf|mh
diff --git a/ipvsadm.8 b/ipvsadm.8
index 18b6dc5..f0439dd 100644
--- a/ipvsadm.8
+++ b/ipvsadm.8
@@ -276,6 +276,16 @@ of connections exceeds its weight.
server if there is one, instead of waiting for a fast one; if all the
servers are busy, it adopts the Shortest Expected Delay policy to
assign the job.
+.sp
+\fBmh\fR - Maglev Hashing: assigns a preference list of all the lookup
+table positions to each destination and populate the table with
+the most-preferred position of destinations. Then it is to select
+destination with the hash key of source IP address through looking
+up a the lookup table. This provides consistent hashing with minimal
+disruption on destination changes and load balancing.
+This scheduler has two flags: mh-fallback, which enables fallback to a
+different server if the selected server was unavailable, and mh-port,
+which adds the source port number to the hash computation.
.TP
.B -p, --persistent [\fItimeout\fP]
Specify that a virtual service is persistent. If this option is
diff --git a/ipvsadm.c b/ipvsadm.c
index 7695006..7942908 100644
--- a/ipvsadm.c
+++ b/ipvsadm.c
@@ -270,6 +270,16 @@ static const char
commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
#define CONN_PROC_FILE "/proc/net/ip_vs_conn"
+/* Unfortunately include/linux/ip_vs.h doesn't yet define
+ * the following
+ */
+#ifndef IP_VS_SVC_F_SCHED_MH_FALLBACK
+#define IP_VS_SVC_F_SCHED_MH_FALLBACK IP_VS_SVC_F_SCHED1
+#endif
+#ifndef IP_VS_SVC_F_SCHED_MH_PORT
+#define IP_VS_SVC_F_SCHED_MH_PORT IP_VS_SVC_F_SCHED2
+#endif
+
struct ipvs_command_entry {
int cmd;
ipvs_service_t svc;
@@ -1145,6 +1155,16 @@ static unsigned int parse_sched_flags(const char *sched,
char *optarg)
if (strcmp(sched, "sh"))
fail(2, "incompatible scheduler flag `%s'",
flag);
+ } else if (!strcmp(flag, "mh-fallback")) {
+ flags |= IP_VS_SVC_F_SCHED_MH_FALLBACK;
+ if (strcmp(sched, "mh"))
+ fail(2, "incompatible scheduler flag `%s'",
+ flag);
+ } else if (!strcmp(flag, "mh-port")) {
+ flags |= IP_VS_SVC_F_SCHED_MH_PORT;
+ if (strcmp(sched, "mh"))
+ fail(2, "incompatible scheduler flag `%s'",
+ flag);
} else {
fail(2, "invalid scheduler flag `%s'", flag);
}
@@ -1589,16 +1609,19 @@ static void print_sched_flags(ipvs_service_entry_t *se)
strcat(flags, "sh-fallback,");
if (se->flags & IP_VS_SVC_F_SCHED_SH_PORT)
strcat(flags, "sh-port,");
- if (se->flags & IP_VS_SVC_F_SCHED3)
- strcat(flags, "flag-3,");
+ } else if (!strcmp(se->sched_name, "mh")) {
+ if (se->flags & IP_VS_SVC_F_SCHED_MH_FALLBACK)
+ strcat(flags, "mh-fallback,");
+ if (se->flags & IP_VS_SVC_F_SCHED_MH_PORT)
+ strcat(flags, "mh-port,");
} else {
if (se->flags & IP_VS_SVC_F_SCHED1)
strcat(flags, "flag-1,");
if (se->flags & IP_VS_SVC_F_SCHED2)
strcat(flags, "flag-2,");
- if (se->flags & IP_VS_SVC_F_SCHED3)
- strcat(flags, "flag-3,");
}
+ if (se->flags & IP_VS_SVC_F_SCHED3)
+ strcat(flags, "flag-3,");
if (flags[0]) {
flags[strlen(flags)-1] = '\0';
--
2.13.7
|