Hi,
This is the second release of the per RS threshold limitation patch.
With it you can set upper and lower thresholds for RS. Once the upper
threshold is reached the RS is not served anymore until the amount of
active + inactive connections drops below the lower threshold.
Please test and report.
Best regards,
Roberto Nibali, ratz
--
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc
Files ipvs-1.0.10-ratz/ipvs/core and
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/core differ
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs.h
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs.h
--- ipvs-1.0.10-ratz/ipvs/ip_vs.h 2003-07-24 20:03:17.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs.h 2003-07-24
20:48:23.000000000 +0200
@@ -24,6 +24,7 @@
* Destination Server Flags
*/
#define IP_VS_DEST_F_AVAILABLE 0x0001 /* Available tag */
+#define IP_VS_DEST_F_OVERLOAD 0x0002 /* server is overloaded */
/*
* IPVS sync daemon states
@@ -113,6 +114,8 @@
u_int16_t dport;
unsigned conn_flags; /* destination flags */
int weight; /* destination weight */
+ u_int32_t u_threshold; /* upper threshold */
+ u_int32_t l_threshold; /* lower threshold */
};
@@ -175,6 +178,9 @@
int weight; /* destination weight */
u_int32_t activeconns; /* active connections */
u_int32_t inactconns; /* inactive connections */
+ u_int32_t u_threshold; /* upper threshold */
+ u_int32_t l_threshold; /* lower threshold */
+
/* statistics */
struct ip_vs_stats_user stats;
@@ -482,11 +488,15 @@
unsigned flags; /* dest status flags */
atomic_t weight; /* server weight */
atomic_t conn_flags; /* flags to copy to conn */
- atomic_t activeconns; /* active connections */
- atomic_t inactconns; /* inactive connections */
atomic_t refcnt; /* reference counter */
struct ip_vs_stats stats; /* statistics */
+ /* connection counters and thresholds */
+ atomic_t activeconns; /* active connections */
+ atomic_t inactconns; /* inactive connections */
+ __u32 u_threshold; /* upper threshold */
+ __u32 l_threshold; /* lower threshold */
+
/* for destination cache */
spinlock_t dst_lock; /* lock dst_cache */
struct dst_entry *dst_cache; /* destination cache entry */
@@ -938,6 +948,13 @@
return 0;
}
+/*
+ * Server overloaded?
+ */
+static inline int ip_vs_is_overloaded(struct ip_vs_dest *dest) {
+ return dest->flags & IP_VS_DEST_F_OVERLOAD;
+}
+
#endif /* __KERNEL__ */
#endif /* _IP_VS_H */
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_conn.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_conn.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_conn.c 2003-07-19 08:01:45.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_conn.c 2003-07-24
20:48:23.000000000 +0200
@@ -21,6 +21,7 @@
* and others. Many code here is taken from IP MASQ code of kernel 2.2.
*
* Changes:
+ * Roberto Nibali, ratz: backported per RS threshold limitation from 2.5.x
*
*/
@@ -1043,6 +1044,11 @@
}
}
+static inline int ip_vs_dest_totalconns(struct ip_vs_dest *dest)
+{
+ return atomic_read(&dest->activeconns)
+ + atomic_read(&dest->inactconns);
+}
/*
* Bind a connection entry with a virtual service destination
@@ -1071,6 +1077,9 @@
ip_vs_fwd_tag(cp), ip_vs_state_name(cp->state),
cp->flags, atomic_read(&cp->refcnt),
atomic_read(&dest->refcnt));
+ if (dest->u_threshold != 0 &&
+ ip_vs_dest_totalconns(dest) >= dest->u_threshold)
+ dest->flags |= IP_VS_DEST_F_OVERLOAD;
}
@@ -1141,6 +1150,21 @@
NIPQUAD(ct->vaddr), ntohs(ct->vport),
NIPQUAD(ct->daddr), ntohs(ct->dport));
+ if (dest->l_threshold != 0) {
+ if (ip_vs_dest_totalconns(dest) < dest->l_threshold) {
+ dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
+ }
+ } else if (dest->u_threshold != 0) {
+ /* I'm not so sure if this is a good idea. --ratz */
+ if (ip_vs_dest_totalconns(dest) * 4 < dest->u_threshold
* 3) {
+ dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
+ }
+ } else {
+ if (dest->flags & IP_VS_DEST_F_OVERLOAD) {
+ dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
+ }
+ }
+
/*
* Invalidate the connection template
*/
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_ctl.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_ctl.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_ctl.c 2003-07-19 08:01:45.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_ctl.c 2003-07-24
20:48:23.000000000 +0200
@@ -17,6 +17,7 @@
* 2 of the License, or (at your option) any later version.
*
* Changes:
+ * Roberto Nibali, ratz: backported per RS threshold limitation from 2.5.x
*
*/
@@ -700,6 +701,12 @@
/* set the dest status flags */
dest->flags |= IP_VS_DEST_F_AVAILABLE;
+
+ if (ur->u_threshold == 0 || ur->u_threshold > dest->u_threshold) {
+ dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
+ }
+ dest->u_threshold = ur->u_threshold;
+ dest->l_threshold = ur->l_threshold;
}
@@ -1896,6 +1903,8 @@
entry.port = dest->port;
entry.flags = atomic_read(&dest->conn_flags);
entry.weight = atomic_read(&dest->weight);
+ entry.u_threshold = dest->u_threshold;
+ entry.l_threshold = dest->l_threshold;
entry.activeconns = atomic_read(&dest->activeconns);
entry.inactconns = atomic_read(&dest->inactconns);
__ip_vs_copy_stats(&entry.stats, &dest->stats);
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_dh.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_dh.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_dh.c 2001-10-19 17:05:17.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_dh.c 2003-07-24
20:48:23.000000000 +0200
@@ -218,7 +218,8 @@
if (!dest
|| !(dest->flags & IP_VS_DEST_F_AVAILABLE)
|| atomic_read(&dest->weight) <= 0
- || is_overloaded(dest)) {
+ || is_overloaded(dest)
+ || ip_vs_is_overloaded(dest)) {
return NULL;
}
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_lblc.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_lblc.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_lblc.c 2002-03-25 13:44:35.000000000 +0100
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_lblc.c 2003-07-24
20:48:23.000000000 +0200
@@ -478,6 +478,8 @@
l = &svc->destinations;
for (e=l->next; e!=l; e=e->next) {
least = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(least))
+ continue;
if (atomic_read(&least->weight) > 0) {
loh = atomic_read(&least->activeconns) * 50
+ atomic_read(&least->inactconns);
@@ -492,6 +494,8 @@
nextstage:
for (e=e->next; e!=l; e=e->next) {
dest = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(dest))
+ continue;
doh = atomic_read(&dest->activeconns) * 50
+ atomic_read(&dest->inactconns);
if (loh * atomic_read(&dest->weight) >
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_lblcr.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_lblcr.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_lblcr.c 2002-03-25 13:44:35.000000000 +0100
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_lblcr.c 2003-07-24
20:48:23.000000000 +0200
@@ -183,6 +183,8 @@
/* select the first destination server, whose weight > 0 */
for (e=set->list; e!=NULL; e=e->next) {
least = e->dest;
+ if (ip_vs_is_overloaded(least))
+ continue;
if ((atomic_read(&least->weight) > 0)
&& (least->flags & IP_VS_DEST_F_AVAILABLE)) {
loh = atomic_read(&least->activeconns) * 50
@@ -197,6 +199,8 @@
nextstage:
for (e=e->next; e!=NULL; e=e->next) {
dest = e->dest;
+ if (ip_vs_is_overloaded(dest))
+ continue;
doh = atomic_read(&dest->activeconns) * 50
+ atomic_read(&dest->inactconns);
if ((loh * atomic_read(&dest->weight) >
@@ -728,6 +732,8 @@
l = &svc->destinations;
for (e=l->next; e!=l; e=e->next) {
least = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(least))
+ continue;
if (atomic_read(&least->weight) > 0) {
loh = atomic_read(&least->activeconns) * 50
+ atomic_read(&least->inactconns);
@@ -742,6 +748,8 @@
nextstage:
for (e=e->next; e!=l; e=e->next) {
dest = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(dest))
+ continue;
doh = atomic_read(&dest->activeconns) * 50
+ atomic_read(&dest->inactconns);
if (loh * atomic_read(&dest->weight) >
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_lc.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_lc.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_lc.c 2003-04-11 16:02:35.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_lc.c 2003-07-24
20:48:23.000000000 +0200
@@ -84,6 +84,8 @@
l = &svc->destinations;
for (e=l->next; e!=l; e=e->next) {
least = list_entry (e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(least))
+ continue;
if (atomic_read(&least->weight) > 0) {
loh = ip_vs_lc_dest_overhead(least);
goto nextstage;
@@ -97,7 +99,8 @@
nextstage:
for (e=e->next; e!=l; e=e->next) {
dest = list_entry(e, struct ip_vs_dest, n_list);
- if (atomic_read(&dest->weight) == 0)
+ if (ip_vs_is_overloaded(dest)
+ || atomic_read(&dest->weight) == 0)
continue;
doh = ip_vs_lc_dest_overhead(dest);
if (doh < loh) {
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_nq.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_nq.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_nq.c 2003-05-20 19:05:02.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_nq.c 2003-07-24
20:48:23.000000000 +0200
@@ -104,6 +104,8 @@
l = &svc->destinations;
for (e=l->next; e!=l; e=e->next) {
least = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(least))
+ continue;
if (atomic_read(&least->weight) > 0) {
loh = ip_vs_nq_dest_overhead(least);
@@ -122,6 +124,8 @@
nextstage:
for (e=e->next; e!=l; e=e->next) {
dest = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(dest))
+ continue;
doh = ip_vs_nq_dest_overhead(dest);
/* return the server directly if it is idle */
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_rr.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_rr.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_rr.c 2001-10-19 17:05:17.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_rr.c 2003-07-24
20:48:23.000000000 +0200
@@ -73,7 +73,8 @@
continue;
}
dest = list_entry(q, struct ip_vs_dest, n_list);
- if (atomic_read(&dest->weight) > 0)
+ if (!ip_vs_is_overloaded(dest)
+ && atomic_read(&dest->weight) > 0)
/* HIT */
goto out;
q = q->next;
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_sed.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_sed.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_sed.c 2003-05-20 19:05:02.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_sed.c 2003-07-24
20:48:23.000000000 +0200
@@ -108,6 +108,8 @@
l = &svc->destinations;
for (e=l->next; e!=l; e=e->next) {
least = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(least))
+ continue;
if (atomic_read(&least->weight) > 0) {
loh = ip_vs_sed_dest_overhead(least);
goto nextstage;
@@ -121,6 +123,8 @@
nextstage:
for (e=e->next; e!=l; e=e->next) {
dest = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(dest))
+ continue;
doh = ip_vs_sed_dest_overhead(dest);
if (loh * atomic_read(&dest->weight) >
doh * atomic_read(&least->weight)) {
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_sh.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_sh.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_sh.c 2001-10-19 17:05:17.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_sh.c 2003-07-24
20:48:23.000000000 +0200
@@ -215,7 +215,8 @@
if (!dest
|| !(dest->flags & IP_VS_DEST_F_AVAILABLE)
|| atomic_read(&dest->weight) <= 0
- || is_overloaded(dest)) {
+ || is_overloaded(dest)
+ || ip_vs_is_overloaded(dest)) {
return NULL;
}
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_wlc.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_wlc.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_wlc.c 2003-04-11 16:02:35.000000000 +0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_wlc.c 2003-07-24
20:48:23.000000000 +0200
@@ -96,6 +96,8 @@
l = &svc->destinations;
for (e=l->next; e!=l; e=e->next) {
least = list_entry(e, struct ip_vs_dest, n_list);
+ if (ip_vs_is_overloaded(least))
+ continue;
if (atomic_read(&least->weight) > 0) {
loh = ip_vs_wlc_dest_overhead(least);
goto nextstage;
@@ -109,7 +111,8 @@
nextstage:
for (e=e->next; e!=l; e=e->next) {
dest = list_entry(e, struct ip_vs_dest, n_list);
-
+ if (ip_vs_is_overloaded(dest))
+ continue;
doh = ip_vs_wlc_dest_overhead(dest);
if (loh * atomic_read(&dest->weight) >
doh * atomic_read(&least->weight)) {
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ip_vs_wrr.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_wrr.c
--- ipvs-1.0.10-ratz/ipvs/ip_vs_wrr.c 2002-03-25 13:44:35.000000000 +0100
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ip_vs_wrr.c 2003-07-24
20:48:23.000000000 +0200
@@ -196,7 +196,8 @@
if (mark->cl != &svc->destinations) {
/* not at the head of the list */
dest = list_entry(mark->cl, struct ip_vs_dest, n_list);
- if (atomic_read(&dest->weight) >= mark->cw) {
+ if (!ip_vs_is_overloaded(dest)
+ && atomic_read(&dest->weight) >= mark->cw) {
write_unlock(&svc->sched_lock);
break;
}
diff -Nur --exclude-from exclude-lvs ipvs-1.0.10-ratz/ipvs/ipvsadm/ipvsadm.c
ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ipvsadm/ipvsadm.c
--- ipvs-1.0.10-ratz/ipvs/ipvsadm/ipvsadm.c 2003-04-11 16:02:38.000000000
+0200
+++ ipvs-1.0.10-ratz-per_RS_threshold/ipvs/ipvsadm/ipvsadm.c 2003-07-25
07:52:20.000000000 +0200
@@ -52,6 +52,7 @@
* Horms : added -v option
* Wensong Zhang : rewrite most code of parsing options and
* processing options.
+ * Roberto Nibali, ratz: Added support for threshold limitation
*
*
* ippfvsadm - Port Fowarding & Virtual Server ADMinistration program
@@ -168,7 +169,10 @@
#define OPT_STATS 0x01000
#define OPT_RATE 0x02000
#define OPT_SORT 0x04000
-#define NUMBER_OF_OPT 15
+#define OPT_UTHRESHOLD 0x08000
+#define OPT_LTHRESHOLD 0x10000
+#define OPT_THRESHOLDS 0x20000
+#define NUMBER_OF_OPT 18
static const char* optnames[] = {
"numeric",
@@ -186,6 +190,9 @@
"stats",
"rate",
"sort",
+ "u-threshold",
+ "l-threshold",
+ "thresholds",
};
/*
@@ -198,22 +205,22 @@
*/
static const char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
{
- /* -n -c svc -s -p -M -r fwd -w -mc -to dmn -st
-rt srt */
-/*INSERT*/ {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'x', 'x',
'x', 'x', 'x'},
-/*ADD*/ {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x'},
-/*EDIT*/ {'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'},
-/*FLUSH*/ {'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', '1', '1', '
', ' ', ' '},
-/*ADD-SERVER*/{'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', 'x', 'x', 'x',
'x', 'x', 'x'},
-/*DEL-SERVER*/{'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x'},
-/*EDIT-SRV*/ {'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'},
-/*START-D*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x',
'x', 'x', 'x'},
-/*STOP-D*/ {'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'},
-/*SAVE*/ {' ', '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'},
+ /* -n -c svc -s -p -M -r fwd -w -mc -to dmn -st
-rt srt -x -y thr */
+/*INSERT*/ {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'x', 'x',
'x', 'x', 'x', 'x', 'x', 'x'},
+/*ADD*/ {'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'},
+/*DEL*/ {'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'},
+/*LIST*/ {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', '1', '
', ' ', ' ', 'x', 'x', ' '},
+/*ADD-SERVER*/{'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', 'x', 'x', 'x',
'x', 'x', 'x', ' ', ' ', 'x'},
+/*DEL-SERVER*/{'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x', 'x', 'x', 'x'},
+/*EDIT-SRV*/ {'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'},
+/*START-D*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x',
'x', 'x', 'x', 'x', 'x', 'x'},
+/*STOP-D*/ {'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'},
+/*SAVE*/ {' ', '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'},
};
/* printing format flags */
@@ -223,6 +230,7 @@
#define FMT_STATS 0x0004
#define FMT_RATE 0x0008
#define FMT_SORT 0x0010
+#define FMT_THRESHOLDS 0x0020
#define SERVICE_NONE 0x0
#define SERVICE_ADDR 0x1
@@ -238,7 +246,7 @@
/* various parsing helpers & parsing functions */
static int str_is_digit(const char *str);
-static int string_to_number(const char *s, int min, int max);
+static int string_to_number(const char *s, unsigned int min, unsigned int max);
static int host_to_addr(const char *name, struct in_addr *addr);
static char * addr_to_host(struct in_addr *addr);
static char * addr_to_anyname(struct in_addr *addr);
@@ -355,6 +363,9 @@
{"stats", '\0', POPT_ARG_NONE, NULL, '7'},
{"rate", '\0', POPT_ARG_NONE, NULL, '8'},
{"sort", '\0', POPT_ARG_NONE, NULL, '9'},
+ {"u-threshold", 'x', POPT_ARG_STRING, &optarg, 'x'},
+ {"l-threshold", 'y', POPT_ARG_STRING, &optarg, 'y'},
+ {"thresholds", '\0', POPT_ARG_NONE, NULL, '0'},
{NULL, 0, 0, NULL, 0}
};
@@ -490,9 +501,24 @@
case 'w':
set_option(options, OPT_WEIGHT);
if ((ur->weight =
- string_to_number(optarg, 0, 65535)) == -1)
+ string_to_number(optarg, 0, UINT16_MAX)) == -1)
fail(2, "illegal weight specified");
break;
+ case 'x':
+ set_option(options, OPT_UTHRESHOLD);
+ if ((ur->u_threshold =
+ string_to_number(optarg, 0, UINT32_MAX)) == -1)
+ fail(2, "illegal u_threshold specified");
+ break;
+ case 'y':
+ set_option(options, OPT_LTHRESHOLD);
+ if ((ur->l_threshold =
+ string_to_number(optarg, 0, UINT32_MAX)) == -1)
+ fail(2, "illegal l_threshold specified");
+ if (ur->l_threshold > ur->u_threshold) {
+ fail(2, "l_threshold must be smaller than
u_threshold");
+ }
+ break;
case 'c':
set_option(options, OPT_CONNECTION);
break;
@@ -522,6 +548,10 @@
set_option(options, OPT_SORT);
*format |= FMT_SORT;
break;
+ case '0':
+ set_option(options, OPT_THRESHOLDS);
+ *format |= FMT_THRESHOLDS;
+ break;
default:
fail(2, "invalid option");
}
@@ -604,6 +634,9 @@
{"stats", 0, 0, '7'},
{"rate", 0, 0, '8'},
{"sort", 0, 0, '9'},
+ {"u-threshold", 1, 0, 'x'},
+ {"l-threshold", 1, 0, 'y'},
+ {"thresholds", 0, 0, '0'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
@@ -762,9 +795,24 @@
case 'w':
set_option(options, OPT_WEIGHT);
if ((ur->weight =
- string_to_number(optarg,0,65535)) == -1)
+ string_to_number(optarg, 0, UINT16_MAX)) == -1)
fail(2, "illegal weight specified");
break;
+ case 'x':
+ set_option(options, OPT_UTHRESHOLD);
+ if ((ur->u_threshold =
+ string_to_number(optarg, 0, UINT32_MAX)) == -1)
+ fail(2, "illegal u_threshold specified");
+ break;
+ case 'y':
+ set_option(options, OPT_LTHRESHOLD);
+ if ((ur->l_threshold =
+ string_to_number(optarg, 0, UINT32_MAX)) == -1)
+ fail(2, "illegal l_threshold specified");
+ if (ur->l_threshold > ur->u_threshold) {
+ fail(2, "l_threshold must be smaller than
u_threshold");
+ }
+ break;
case 'c':
set_option(options, OPT_CONNECTION);
break;
@@ -794,6 +842,10 @@
set_option(options, OPT_SORT);
*format |= FMT_SORT;
break;
+ case '0':
+ set_option(options, OPT_THRESHOLDS);
+ *format |= FMT_THRESHOLDS;
+ break;
default:
fail(2, "invalid option");
}
@@ -853,7 +905,8 @@
if ((options & OPT_CONNECTION
|| options & OPT_TIMEOUT
|| options & OPT_DAEMON)
- && (options & OPT_STATS || options & OPT_RATE))
+ && (options & OPT_STATS || options & OPT_RATE
+ || options & OPT_THRESHOLDS))
fail(2, "options conflicts in the list command");
if (options & OPT_CONNECTION)
@@ -914,13 +967,13 @@
}
-static int string_to_number(const char *s, int min, int max)
+static int string_to_number(const char *s, unsigned int min, unsigned int max)
{
- long number;
+ unsigned long number;
char *end;
errno = 0;
- number = strtol(s, &end, 10);
+ number = strtoul(s, &end, 10);
if (*end == '\0' && end != s) {
/* We parsed a number, let's see if we want this. */
if (errno != ERANGE && min <= number && number <= max)
@@ -1023,7 +1076,7 @@
if (portp != NULL){
result |= SERVICE_PORT;
- if ((portn=string_to_number(portp+1, 0, 65535)) != -1)
+ if ((portn=string_to_number(portp+1, 0, UINT16_MAX)) != -1)
*port = htons(portn);
else if ((portn=service_to_port(portp+1, proto)) != -1)
*port = htons(portn);
@@ -1120,7 +1173,7 @@
" %s -C\n"
" %s -R\n"
" %s -S [-n]\n"
- " %s -a|e -t|u|f service-address -r server-address [-g|i|m]
[-w weight]\n"
+ " %s -a|e -t|u|f service-address -r server-address [Options]\n"
" %s -d -t|u|f service-address -r server-address\n"
" %s -L|l [options]\n"
" %s -Z [-t|u|f service-address]\n"
@@ -1166,12 +1219,15 @@
" --ipip -i ipip encapsulation
(tunneling)\n"
" --masquerading -m masquerading (NAT)\n"
" --weight -w weight capacity of real
server\n"
+ " --u-threshold -x uthreshold upper threshold of
connections\n"
+ " --l-threshold -y lthreshold lower threshold of
connections\n"
" --mcast-interface interface multicast interface for
connection sync\n"
" --connection -c output of current IPVS
connections\n"
" --timeout output of timeout (tcp
tcpfin udp)\n"
" --daemon output of daemon
information\n"
" --stats output of statistics
information\n"
" --rate output of rate
information\n"
+ " --thresholds output of thresholds
information\n"
" --sort sorting output of
service/server entries\n"
" --numeric -n numeric output of
addresses and ports\n",
DEF_SCHED);
@@ -1411,6 +1467,12 @@
" -> RemoteAddress:Port\n",
"Prot LocalAddress:Port",
"CPS", "InPPS", "OutPPS", "InBPS", "OutBPS");
+ else if (format & FMT_THRESHOLDS)
+ printf("%-33s %-10s %-10s %-10s %-10s\n"
+ " -> RemoteAddress:Port\n",
+ "Prot LocalAddress:Port",
+ "Uthreshold", "Lthreshold", "ActiveConn", "InActConn");
+
else if (!(format & FMT_RULE))
printf("Prot LocalAddress:Port Scheduler Flags\n"
" -> RemoteAddress:Port Forward Weight
ActiveConn InActConn\n");
@@ -1527,6 +1589,11 @@
print_largenum(e->stats.inbps);
print_largenum(e->stats.outbps);
printf("\n");
+ } else if (format & FMT_THRESHOLDS) {
+ printf(" -> %-28s %-10u %-10u %-10u %-10u\n", dname,
+ e->u_threshold, e->l_threshold,
+ e->activeconns, e->inactconns);
+
} else
printf(" -> %-28s %-7s %-6d %-10u %-10u\n",
dname, fwd_name(e->flags),
|