commit a451ecb489dab08b5946549f7f5b80ef37d802b3 Author: Jan Friesse <jfriesse@redhat.com> Date: Wed Sep 15 17:49:07 2010 +0200 One Packet Scheduler support This patch adds the One-Packet Scheduler for IPVS to RHEL5. Resolves BZ#633636 diff --git a/ipvsadm.8 b/ipvsadm.8 index 519e191..9c245ec 100644 --- a/ipvsadm.8 +++ b/ipvsadm.8 @@ -37,7 +37,7 @@ ipvsadm \- Linux Virtual Server administration .SH SYNOPSIS .B ipvsadm -A|E -t|u|f \fIservice-address\fP [-s \fIscheduler\fP] .ti 15 -.B [-p [\fItimeout\fP]] [-M \fInetmask\fP] +.B [-p [\fItimeout\fP]] [-O] [-M \fInetmask\fP] .br .B ipvsadm -D -t|u|f \fIservice-address\fP .br @@ -393,6 +393,13 @@ service entries are sorted in ascending order by <protocol, address, port>. The real server entries are sorted in ascending order by <address, port>. .TP +.B -O, --ops +Specify that a virtual service uses one-packet scheduling. This +option can be used only for UDP services. If this option is specified, +all connections are created only to schedule one packet. +Option is useful to schedule UDP packets from same client port to different +real servers. +.TP .B -n, --numeric Numeric output. IP addresses and port numbers will be printed in numeric format rather than as as host names and services respectively, diff --git a/ipvsadm.c b/ipvsadm.c index e6a6ea6..6762d79 100644 --- a/ipvsadm.c +++ b/ipvsadm.c @@ -182,7 +182,8 @@ static const char* cmdnames[] = { #define OPT_PERSISTENTCONN 0x20000 #define OPT_SORT 0x40000 #define OPT_SYNCID 0x80000 -#define NUMBER_OF_OPT 20 +#define OPT_ONEPACKET 0x100000 +#define NUMBER_OF_OPT 21 static const char* optnames[] = { "numeric", @@ -205,6 +206,7 @@ static const char* optnames[] = { "persistent-conn", "sort", "syncid", + "ops", }; /* @@ -217,21 +219,21 @@ static const char* optnames[] = { */ static const char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = { - /* -n -c svc -s -p -M -r fwd -w -x -y -mc tot dmn -st -rt thr -pc srt sid */ -/*ADD*/ {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' '}, -/*EDIT*/ {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*DEL*/ {'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*FLUSH*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*LIST*/ {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', '1', ' ', ' ', ' ', ' ', ' ', 'x'}, -/*ADDSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*DELSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*EDITSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*TIMEOUT*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*STARTD*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' '}, -/*STOPD*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' '}, -/*RESTORE*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*SAVE*/ {' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, -/*ZERO*/ {'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, + /* -n -c svc -s -p -M -r fwd -w -x -y -mc tot dmn -st -rt thr -pc srt sid ops*/ +/*ADD*/ {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' '}, +/*EDIT*/ {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' '}, +/*DEL*/ {'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*FLUSH*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*LIST*/ {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', '1', ' ', ' ', ' ', ' ', ' ', ' ', 'x'}, +/*ADDSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*DELSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*EDITSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*TIMEOUT*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*STARTD*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x'}, +/*STOPD*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x'}, +/*RESTORE*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*SAVE*/ {' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, +/*ZERO*/ {'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, }; /* printing format flags */ @@ -388,6 +390,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, {"thresholds", '\0', POPT_ARG_NONE, NULL, '9'}, {"persistent-conn", '\0', POPT_ARG_NONE, NULL, 'P'}, {"sort", '\0', POPT_ARG_NONE, NULL, '0'}, + {"ops", 'O', POPT_ARG_NONE, NULL, 'O'}, {NULL, 0, 0, NULL, 0} }; @@ -492,10 +495,14 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, break; case 'p': set_option(options, OPT_PERSISTENT); - ce->svc.flags = IP_VS_SVC_F_PERSISTENT; + ce->svc.flags |= IP_VS_SVC_F_PERSISTENT; ce->svc.timeout = parse_timeout(optarg, 1, MAX_TIMEOUT); break; + case 'O': + set_option(options, OPT_ONEPACKET); + ce->svc.flags |= IP_VS_SVC_F_ONEPACKET; + break; case 'M': set_option(options, OPT_NETMASK); parse = parse_netmask(optarg, &ce->svc.netmask); @@ -960,10 +967,15 @@ static int process_options(int argc, char **argv, int reading_stdin) if (ce.cmd == CMD_ADD || ce.cmd == CMD_EDIT) { /* Make sure that port zero service is persistent */ if (!ce.svc.fwmark && !ce.svc.port && - (ce.svc.flags != IP_VS_SVC_F_PERSISTENT)) + (!(ce.svc.flags & IP_VS_SVC_F_PERSISTENT))) fail(2, "Zero port specified " "for non-persistent service"); + if (ce.svc.flags & IP_VS_SVC_F_ONEPACKET && + !ce.svc.fwmark && ce.svc.protocol != IPPROTO_UDP) + fail(2, "One-Packet Scheduling is only " + "for UDP virtual services"); + /* Set the default scheduling algorithm if not specified */ if (strlen(ce.svc.sched_name) == 0) strcpy(ce.svc.sched_name, DEF_SCHED); @@ -1328,6 +1340,7 @@ static void usage_exit(const char *program, const int exit_status) " --thresholds output of thresholds information\n" " --persistent-conn output of persistent connection info\n" " --sort sorting output of service/server entries\n" + " --ops -O one-packet scheduling\n" " --numeric -n numeric output of addresses and ports\n", DEF_SCHED); @@ -1629,6 +1642,9 @@ print_service_entry(ipvs_service_entry_t *se, unsigned int format) printf(" -M %s", inet_ntoa(mask)); } } + if (se->flags & IP_VS_SVC_F_ONEPACKET) { + printf(" -O"); + } } else if (format & FMT_STATS) { printf("%-33s", svc_name); print_largenum(se->stats.conns); @@ -1653,6 +1669,9 @@ print_service_entry(ipvs_service_entry_t *se, unsigned int format) printf(" mask %s", inet_ntoa(mask)); } } + if (se->flags & IP_VS_SVC_F_ONEPACKET) { + printf(" ops"); + } } printf("\n"); diff --git a/kernheaders/net/ip_vs.h b/kernheaders/net/ip_vs.h index 9ba2479..59c6dca 100644 --- a/kernheaders/net/ip_vs.h +++ b/kernheaders/net/ip_vs.h @@ -19,6 +19,7 @@ */ #define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */ #define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */ +#define IP_VS_SVC_F_ONEPACKET 0x0004 /* one-packet scheduling */ /* * Destination Server Flags