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 by Simon Horman. Signed-off-by: Simon Horman Index: ipvsadm-1.24/ipvsadm.c =================================================================== --- ipvsadm-1.24.orig/ipvsadm.c 2005-12-11 01:00:07.000000000 +0900 +++ ipvsadm-1.24/ipvsadm.c 2010-04-13 10:50:10.000000000 +0900 @@ -184,7 +184,8 @@ static const char* cmdnames[] = { #define OPT_SORT 0x040000 #define OPT_SYNCID 0x080000 #define OPT_EXACT 0x100000 -#define NUMBER_OF_OPT 21 +#define OPT_ONEPACKET 0x200000 +#define NUMBER_OF_OPT 22 static const char* optnames[] = { "numeric", @@ -208,6 +209,7 @@ static const char* optnames[] = { "sort", "syncid", "exact", + "ops", }; /* @@ -393,6 +395,7 @@ parse_options(int argc, char **argv, str {"persistent-conn", '\0', POPT_ARG_NONE, NULL, 'P'}, {"sort", '\0', POPT_ARG_NONE, NULL, '0'}, {"exact", 'X', POPT_ARG_NONE, NULL, 'X'}, + {"ops", 'o', POPT_ARG_NONE, NULL, 'o'}, {NULL, 0, 0, NULL, 0} }; @@ -497,7 +500,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; @@ -599,6 +602,10 @@ parse_options(int argc, char **argv, str set_option(options, OPT_EXACT); *format |= FMT_EXACT; 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)); @@ -645,7 +652,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:cnX"; + const char *optstring = "AEDCZSRaedlLhvt:u:f:s:M:p::r:gmiw:x:y:cnoX"; const struct option long_options[] = { {"add-service", 0, 0, 'A'}, {"edit-service", 0, 0, 'E'}, @@ -688,6 +695,7 @@ parse_options(int argc, char **argv, str {"persistent-conn", 0, 0, 'P'}, {"sort", 0, 0, '0'}, {"exact", 0, 0, 'X'}, + {"ops", 0, 0, 'o'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; @@ -811,7 +819,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++]; @@ -916,6 +924,10 @@ parse_options(int argc, char **argv, str set_option(options, OPT_EXACT); *format |= FMT_EXACT; 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]); } @@ -974,10 +986,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); @@ -1343,6 +1360,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); @@ -1653,6 +1671,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, format); @@ -1677,6 +1697,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");