From: Julian Anastasov ipvsadm: one-packet scheduling Allow one-packet scheduling for UDP connections. When the fwmark-based or normal virtual service is marked with '-o' or '--ops' options all connections are created only to schedule one packet. Useful to schedule UDP packets from same client port to different real servers. Recommended with RR or WRR schedulers (the connections are not visible with ipvsadm -L). Up-port of http://www.ssi.bg/~ja/tmp/ops-ipvsadm-1.21-1.diff to ipvsadm-1.24-10 by Simon Horman. Signed-off-by: Simon Horman Index: ipvsadm-1.24-10/ipvsadm.c =================================================================== --- ipvsadm-1.24-10.orig/ipvsadm.c 2004-01-10 18:39:03.000000000 +0900 +++ ipvsadm-1.24-10/ipvsadm.c 2010-04-13 10:57:53.000000000 +0900 @@ -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 0x200000 +#define NUMBER_OF_OPT 21 static const char* optnames[] = { "numeric", @@ -205,6 +206,7 @@ static const char* optnames[] = { "persistent-conn", "sort", "syncid", + "ops", }; /* @@ -388,6 +390,7 @@ parse_options(int argc, char **argv, str {"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,7 +495,7 @@ parse_options(int argc, char **argv, str 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; @@ -590,6 +593,10 @@ parse_options(int argc, char **argv, str set_option(options, OPT_SORT); *format |= FMT_SORT; break; + case 'o': + set_option(options, OPT_ONEPACKET); + ur->vs_flags |= IP_VS_SVC_F_ONEPACKET; + break; default: fail(2, "invalid option `%s'", poptBadOption(context, POPT_BADOPTION_NOALIAS)); @@ -636,7 +643,7 @@ parse_options(int argc, char **argv, str unsigned int *options, unsigned int *format) { int c, parse; - const char *optstring = "AEDCZSRaedlLhvt:u:f:s:M:p::r:gmiw:x:y:cn"; + const char *optstring = "AEDCZSRaedlLhvt:u:f:s:M:p::r:gmiw:x:y:cno"; const struct option long_options[] = { {"add-service", 0, 0, 'A'}, {"edit-service", 0, 0, 'E'}, @@ -678,6 +685,7 @@ parse_options(int argc, char **argv, str {"thresholds", 0, 0, '9'}, {"persistent-conn", 0, 0, 'P'}, {"sort", 0, 0, '0'}, + {"ops", 0, 0, 'o'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; @@ -801,7 +809,7 @@ parse_options(int argc, char **argv, str break; case 'p': set_option(options, OPT_PERSISTENT); - ce->svc.flags = IP_VS_SVC_F_PERSISTENT; + ce->svc.flags |= IP_VS_SVC_F_PERSISTENT; if (!optarg && optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') optarg = argv[optind++]; @@ -902,6 +910,10 @@ parse_options(int argc, char **argv, str set_option(options, OPT_SORT); *format |= FMT_SORT; break; + case 'o': + set_option(options, OPT_ONEPACKET); + ce->svc.flags |= IP_VS_SVC_F_ONEPACKET; + break; default: fail(2, "invalid option `%s'", argv[optind-1]); } @@ -960,10 +972,15 @@ static int process_options(int argc, cha 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 +1345,7 @@ static void usage_exit(const char *progr " --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 +1647,8 @@ print_service_entry(ipvs_service_entry_t printf(" -M %s", inet_ntoa(mask)); } } + if (se->flags & IP_VS_SVC_F_ONEPACKET) + printf(" ops"); } else if (format & FMT_STATS) { printf("%-33s", svc_name); print_largenum(se->stats.conns); @@ -1653,6 +1673,8 @@ print_service_entry(ipvs_service_entry_t printf(" mask %s", inet_ntoa(mask)); } } + if (se->flags & IP_VS_SVC_F_ONEPACKET) + printf(" ops"); } printf("\n");