Skip to contentSkip to conversation

ipvs: make "no destination available" message more informative

PATCH In review Patrick Schaaf 2 participants 5 messages Feb 11, 2011 – Feb 16, 2011

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ipvs: make "no destination available" message more informative

When IP_VS schedulers do not find a destination, they output a terse "WLC: no destination available" message through kernel syslog, which I can not only make sense of because syslog puts them in a logfile together with keepalived checker results.

This patch makes the output a bit more informative, by telling you which virtual service failed to find a destination.

Example output:

kernel: [1539214.552233] IPVS: wlc: TCP 192.168.8.30:22 - no destination available
kernel: [1539299.674418] IPVS: wlc: FWM 22 0x00000016 - no destination available

I have tested the code for IPv4 and FWM services, as you can see from the example; I do not have an IPv6 setup to test the third code path with.

To avoid code duplication, I put a new function ip_vs_scheduler_err() into ip_vs_sched.c, and use that from the schedulers instead of calling IP_VS_ERR_RL directly.

The patch is against 2.6.36.2, as that's what I have running. It still applies with two hunks shifted to 2.6.38-rc4, and builds there without warnings.

Please review and consider for inclusion in upcoming kernels.

best regards
Patrick

include/net/ip_vs.h +1 -0
diff -pur -X patch.exclude linux-2.6.36.2/include/net/ip_vs.h linux-2.6.36.2-bof/include/net/ip_vs.h
@@ -789,6 +789,7 @@ ip_vs_schedule(struct ip_vs_service *svc
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 			struct ip_vs_protocol *pp);
 
+extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
 
 /*
  *      IPVS control data and functions (from ip_vs_ctl.c)
net/netfilter/ipvs/ip_vs_lblc.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_lblc.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_lblc.c
@@ -511,7 +511,7 @@ ip_vs_lblc_schedule(struct ip_vs_service
 	/* No cache entry or it is invalid, time to schedule */
 	dest = __ip_vs_lblc_schedule(svc);
 	if (!dest) {
-		IP_VS_ERR_RL("LBLC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_lblcr.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_lblcr.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -694,7 +694,7 @@ ip_vs_lblcr_schedule(struct ip_vs_servic
 		/* The cache entry is invalid, time to schedule */
 		dest = __ip_vs_lblcr_schedule(svc);
 		if (!dest) {
-			IP_VS_ERR_RL("LBLCR: no destination available\n");
+			ip_vs_scheduler_err(svc, "no destination available");
 			read_unlock(&svc->sched_lock);
 			return NULL;
 		}
net/netfilter/ipvs/ip_vs_lc.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_lc.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_lc.c
@@ -70,7 +70,7 @@ ip_vs_lc_schedule(struct ip_vs_service *
 	}
 
 	if (!least)
-		IP_VS_ERR_RL("LC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 	else
 		IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
 			      "inactconns %d\n",
net/netfilter/ipvs/ip_vs_nq.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_nq.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_nq.c
@@ -99,7 +99,7 @@ ip_vs_nq_schedule(struct ip_vs_service *
 	}
 
 	if (!least) {
-		IP_VS_ERR_RL("NQ: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_rr.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_rr.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_rr.c
@@ -72,7 +72,7 @@ ip_vs_rr_schedule(struct ip_vs_service *
 		q = q->next;
 	} while (q != p);
 	write_unlock(&svc->sched_lock);
-	IP_VS_ERR_RL("RR: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
   out:
net/netfilter/ipvs/ip_vs_sched.c +28 -0
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_sched.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_sched.c
@@ -29,6 +29,7 @@
 
 #include <net/ip_vs.h>
 
+EXPORT_SYMBOL(ip_vs_scheduler_err);
 /*
  *  IPVS scheduler list
  */
@@ -163,6 +164,33 @@ void ip_vs_scheduler_put(struct ip_vs_sc
 		module_put(scheduler->module);
 }
 
+/*
+ * Common error output helper for schedulers
+ */
+
+void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
+{
+	if (svc->fwmark) {
+		IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n",
+			svc->scheduler->name, svc->fwmark, svc->fwmark, msg);
+		return;
+	}
+#ifdef CONFIG_IP_VS_IPV6
+	if (svc->af == AF_INET6) {
+		IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
+			svc->scheduler->name,
+			ip_vs_proto_name(svc->protocol),
+			&svc->addr.in6, ntohs(svc->port),
+			msg);
+		return;
+	}
+#endif
+	IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n",
+		svc->scheduler->name,
+		ip_vs_proto_name(svc->protocol),
+		&svc->addr.ip, ntohs(svc->port),
+		msg);
+}
 
 /*
  *  Register a scheduler in the scheduler list
net/netfilter/ipvs/ip_vs_sed.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_sed.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_sed.c
@@ -87,7 +87,7 @@ ip_vs_sed_schedule(struct ip_vs_service
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("SED: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
net/netfilter/ipvs/ip_vs_sh.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_sh.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_sh.c
@@ -223,7 +223,7 @@ ip_vs_sh_schedule(struct ip_vs_service *
 	    || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
 	    || atomic_read(&dest->weight) <= 0
 	    || is_overloaded(dest)) {
-		IP_VS_ERR_RL("SH: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_wlc.c +1 -1
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_wlc.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_wlc.c
@@ -75,7 +75,7 @@ ip_vs_wlc_schedule(struct ip_vs_service
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("WLC: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
net/netfilter/ipvs/ip_vs_wrr.c +8 -6
diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_wrr.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_wrr.c
@@ -147,8 +147,9 @@ ip_vs_wrr_schedule(struct ip_vs_service
 
 			if (mark->cl == mark->cl->next) {
 				/* no dest entry */
-				IP_VS_ERR_RL("WRR: no destination available: "
-					     "no destinations present\n");
+				ip_vs_scheduler_err(svc,
+					"no destination available: "
+					"no destinations present");
 				dest = NULL;
 				goto out;
 			}
@@ -162,8 +163,8 @@ ip_vs_wrr_schedule(struct ip_vs_service
 				 */
 				if (mark->cw == 0) {
 					mark->cl = &svc->destinations;
-					IP_VS_ERR_RL("WRR: no destination "
-						     "available\n");
+					ip_vs_scheduler_err(svc,
+						"no destination available");
 					dest = NULL;
 					goto out;
 				}
@@ -185,8 +186,9 @@ ip_vs_wrr_schedule(struct ip_vs_service
 			/* back to the start, and no dest is found.
 			   It is only possible when all dests are OVERLOADED */
 			dest = NULL;
-			IP_VS_ERR_RL("WRR: no destination available: "
-				     "all destinations are overloaded\n");
+			ip_vs_scheduler_err(svc,
+				"no destination available: "
+				"all destinations are overloaded");
 			goto out;
 		}
 	}
maintainer
#1 lore raw
Quoted 23 lines · Patrick Schaaf

When IP_VS schedulers do not find a destination, they output a terse "WLC: no destination available" message through kernel syslog, which I can not only make sense of because syslog puts them in a logfile together with keepalived checker results.

This patch makes the output a bit more informative, by telling you which virtual service failed to find a destination.

Example output:

kernel: [1539214.552233] IPVS: wlc: TCP 192.168.8.30:22 - no destination available
kernel: [1539299.674418] IPVS: wlc: FWM 22 0x00000016 - no destination available

I have tested the code for IPv4 and FWM services, as you can see from the example; I do not have an IPv6 setup to test the third code path with.

To avoid code duplication, I put a new function ip_vs_scheduler_err() into ip_vs_sched.c, and use that from the schedulers instead of calling IP_VS_ERR_RL directly.

Quoted 5 lines

The patch is against 2.6.36.2, as that's what I have running. It still applies with two hunks shifted to 2.6.38-rc4, and builds there without warnings.

Please review and consider for inclusion in upcoming kernels.

Hi Patrick,

Thanks, this looks good to me.
I will apply it with the minor modification noted below.

Quoted 96 lines

diff -pur -X patch.exclude linux-2.6.36.2/include/net/ip_vs.h linux-2.6.36.2-bof/include/net/ip_vs.h

include/net/ip_vs.h +1 -0
@@ -789,6 +789,7 @@ ip_vs_schedule(struct ip_vs_service *svc
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 			struct ip_vs_protocol *pp);
 
+extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
 
 /*
  *      IPVS control data and functions (from ip_vs_ctl.c)

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_lblc.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_lblc.c

net/netfilter/ipvs/ip_vs_lblc.c +1 -1
@@ -511,7 +511,7 @@ ip_vs_lblc_schedule(struct ip_vs_service
 	/* No cache entry or it is invalid, time to schedule */
 	dest = __ip_vs_lblc_schedule(svc);
 	if (!dest) {
-		IP_VS_ERR_RL("LBLC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_lblcr.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_lblcr.c

net/netfilter/ipvs/ip_vs_lblcr.c +1 -1
@@ -694,7 +694,7 @@ ip_vs_lblcr_schedule(struct ip_vs_servic
 		/* The cache entry is invalid, time to schedule */
 		dest = __ip_vs_lblcr_schedule(svc);
 		if (!dest) {
-			IP_VS_ERR_RL("LBLCR: no destination available\n");
+			ip_vs_scheduler_err(svc, "no destination available");
 			read_unlock(&svc->sched_lock);
 			return NULL;
 		}

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_lc.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_lc.c

net/netfilter/ipvs/ip_vs_lc.c +1 -1
@@ -70,7 +70,7 @@ ip_vs_lc_schedule(struct ip_vs_service *
 	}
 
 	if (!least)
-		IP_VS_ERR_RL("LC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 	else
 		IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
 			      "inactconns %d\n",

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_nq.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_nq.c

net/netfilter/ipvs/ip_vs_nq.c +1 -1
@@ -99,7 +99,7 @@ ip_vs_nq_schedule(struct ip_vs_service *
 	}
 
 	if (!least) {
-		IP_VS_ERR_RL("NQ: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_rr.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_rr.c

net/netfilter/ipvs/ip_vs_rr.c +1 -1
@@ -72,7 +72,7 @@ ip_vs_rr_schedule(struct ip_vs_service *
 		q = q->next;
 	} while (q != p);
 	write_unlock(&svc->sched_lock);
-	IP_VS_ERR_RL("RR: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
   out:

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_sched.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_sched.c

net/netfilter/ipvs/ip_vs_sched.c +11 -0
@@ -29,6 +29,7 @@
 
 #include <net/ip_vs.h>
 
+EXPORT_SYMBOL(ip_vs_scheduler_err);
 /*
  *  IPVS scheduler list
  */
@@ -163,6 +164,33 @@ void ip_vs_scheduler_put(struct ip_vs_sc
 		module_put(scheduler->module);
 }
 
+/*
+ * Common error output helper for schedulers
+ */
+
+void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
+{
+	if (svc->fwmark) {
+		IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n",
+			svc->scheduler->name, svc->fwmark, svc->fwmark, msg);
+		return;

net/netfilter/ipvs/ip_vs_sched.c void ip_vs_scheduler_put(struct ip_vs_sc · line 186

Quoted 10 lines
net/netfilter/ipvs/ip_vs_sched.c +10 -0
+	}
+#ifdef CONFIG_IP_VS_IPV6
+	if (svc->af == AF_INET6) {
+		IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
+			svc->scheduler->name,
+			ip_vs_proto_name(svc->protocol),
+			&svc->addr.in6, ntohs(svc->port),
+			msg);
+		return;
+	}

I will add "else" here.

Quoted 84 lines
net/netfilter/ipvs/ip_vs_sched.c +7 -0
+#endif
+	IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n",
+		svc->scheduler->name,
+		ip_vs_proto_name(svc->protocol),
+		&svc->addr.ip, ntohs(svc->port),
+		msg);
+}
 
 /*
  *  Register a scheduler in the scheduler list

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_sed.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_sed.c

net/netfilter/ipvs/ip_vs_sed.c +1 -1
@@ -87,7 +87,7 @@ ip_vs_sed_schedule(struct ip_vs_service
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("SED: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_sh.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_sh.c

net/netfilter/ipvs/ip_vs_sh.c +1 -1
@@ -223,7 +223,7 @@ ip_vs_sh_schedule(struct ip_vs_service *
 	    || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
 	    || atomic_read(&dest->weight) <= 0
 	    || is_overloaded(dest)) {
-		IP_VS_ERR_RL("SH: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_wlc.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_wlc.c

net/netfilter/ipvs/ip_vs_wlc.c +1 -1
@@ -75,7 +75,7 @@ ip_vs_wlc_schedule(struct ip_vs_service
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("WLC: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*

diff -pur -X patch.exclude linux-2.6.36.2/net/netfilter/ipvs/ip_vs_wrr.c linux-2.6.36.2-bof/net/netfilter/ipvs/ip_vs_wrr.c

net/netfilter/ipvs/ip_vs_wrr.c +8 -6
@@ -147,8 +147,9 @@ ip_vs_wrr_schedule(struct ip_vs_service
 
 			if (mark->cl == mark->cl->next) {
 				/* no dest entry */
-				IP_VS_ERR_RL("WRR: no destination available: "
-					     "no destinations present\n");
+				ip_vs_scheduler_err(svc,
+					"no destination available: "
+					"no destinations present");
 				dest = NULL;
 				goto out;
 			}
@@ -162,8 +163,8 @@ ip_vs_wrr_schedule(struct ip_vs_service
 				 */
 				if (mark->cw == 0) {
 					mark->cl = &svc->destinations;
-					IP_VS_ERR_RL("WRR: no destination "
-						     "available\n");
+					ip_vs_scheduler_err(svc,
+						"no destination available");
 					dest = NULL;
 					goto out;
 				}
@@ -185,8 +186,9 @@ ip_vs_wrr_schedule(struct ip_vs_service
 			/* back to the start, and no dest is found.
 			   It is only possible when all dests are OVERLOADED */
 			dest = NULL;
-			IP_VS_ERR_RL("WRR: no destination available: "
-				     "all destinations are overloaded\n");
+			ip_vs_scheduler_err(svc,
+				"no destination available: "
+				"all destinations are overloaded");
 			goto out;
 		}
 	}
maintainer
#2 lore raw
Quoted 28 lines · Simon Horman
Quoted 27 lines · Patrick Schaaf

When IP_VS schedulers do not find a destination, they output a terse "WLC: no destination available" message through kernel syslog, which I can not only make sense of because syslog puts them in a logfile together with keepalived checker results.

This patch makes the output a bit more informative, by telling you which virtual service failed to find a destination.

Example output:

kernel: [1539214.552233] IPVS: wlc: TCP 192.168.8.30:22 - no destination available
kernel: [1539299.674418] IPVS: wlc: FWM 22 0x00000016 - no destination available

I have tested the code for IPv4 and FWM services, as you can see from the example; I do not have an IPv6 setup to test the third code path with.

To avoid code duplication, I put a new function ip_vs_scheduler_err() into ip_vs_sched.c, and use that from the schedulers instead of calling IP_VS_ERR_RL directly.

The patch is against 2.6.36.2, as that's what I have running. It still applies with two hunks shifted to 2.6.38-rc4, and builds there without warnings.

Quoted 6 lines
Quoted 1 line

Please review and consider for inclusion in upcoming kernels.

Hi Patrick,

Thanks, this looks good to me.
I will apply it with the minor modification noted below.

Hi Patrick,

I have slightly modified the IPv4/IPv6 logic in ip_vs_scheduler_err() and tested the code with both IPv4 and IPv6. It seems to work well :-)

I also did some indentation reformatting of ip_vs_scheduler_err() while I was there.

Could you please provide me with a Signed-Off-By line in your capacity as the original author of the patch? Details can be found in Documentation/SubmittingPatches.

I believe that the best place for it is before my Signed-Off-By line. Simply replying to this email (on-list) is sufficient.

From: Patrick Schaaf <[email protected]>

ipvs: make "no destination available" message more informative

When IP_VS schedulers do not find a destination, they output a terse "WLC: no destination available" message through kernel syslog, which I can not only make sense of because syslog puts them in a logfile together with keepalived checker results.

This patch makes the output a bit more informative, by telling you which virtual service failed to find a destination.

Example output:

kernel: [1539214.552233] IPVS: wlc: TCP 192.168.8.30:22 - no destination available
kernel: [1539299.674418] IPVS: wlc: FWM 22 0x00000016 - no destination available

I have tested the code for IPv4 and FWM services, as you can see from the example; I do not have an IPv6 setup to test the third code path with.

To avoid code duplication, I put a new function ip_vs_scheduler_err() into ip_vs_sched.c, and use that from the schedulers instead of calling IP_VS_ERR_RL directly.

---

v2
* Minor correction to IPv6/IPv4 logic in ip_vs_scheduler_err()
* Reformatting of ip_vs_scheduler_err()

---
 include/net/ip_vs.h              |    3 ++-
 net/netfilter/ipvs/ip_vs_lblc.c  |    2 +-
 net/netfilter/ipvs/ip_vs_lblcr.c |    2 +-
 net/netfilter/ipvs/ip_vs_lc.c    |    2 +-
 net/netfilter/ipvs/ip_vs_nq.c    |    2 +-
 net/netfilter/ipvs/ip_vs_rr.c    |    2 +-
 net/netfilter/ipvs/ip_vs_sched.c |   25 +++++++++++++++++++++++++
 net/netfilter/ipvs/ip_vs_sed.c   |    2 +-
 net/netfilter/ipvs/ip_vs_sh.c    |    2 +-
 net/netfilter/ipvs/ip_vs_wlc.c   |    2 +-
 net/netfilter/ipvs/ip_vs_wrr.c   |   14 ++++++++------
 11 files changed, 43 insertions(+), 15 deletions(-)
include/net/ip_vs.h +2 -1
index 5d75fea..6e91713 100644
@@ -772,7 +772,6 @@ struct ip_vs_app {
 	/* ip_vs_app finish */
 	int (*done_conn)(struct ip_vs_app *, struct ip_vs_conn *);
 
-
 	/* not used now */
 	int (*bind_conn)(struct ip_vs_app *, struct ip_vs_conn *,
 			 struct ip_vs_protocol *);
@@ -1019,6 +1018,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 			struct ip_vs_proto_data *pd);
 
+extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
+
 
 /*
  *      IPVS control data and functions (from ip_vs_ctl.c)
net/netfilter/ipvs/ip_vs_lblc.c +1 -1
index 00b5ffa..4a9c8cd 100644
@@ -510,7 +510,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	/* No cache entry or it is invalid, time to schedule */
 	dest = __ip_vs_lblc_schedule(svc);
 	if (!dest) {
-		IP_VS_ERR_RL("LBLC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_lblcr.c +1 -1
index bfa25f1..bd329b1 100644
@@ -692,7 +692,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		/* The cache entry is invalid, time to schedule */
 		dest = __ip_vs_lblcr_schedule(svc);
 		if (!dest) {
-			IP_VS_ERR_RL("LBLCR: no destination available\n");
+			ip_vs_scheduler_err(svc, "no destination available");
 			read_unlock(&svc->sched_lock);
 			return NULL;
 		}
net/netfilter/ipvs/ip_vs_lc.c +1 -1
index 4f69db1..6063800 100644
@@ -70,7 +70,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	}
 
 	if (!least)
-		IP_VS_ERR_RL("LC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 	else
 		IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
 			      "inactconns %d\n",
net/netfilter/ipvs/ip_vs_nq.c +1 -1
index c413e18..984d9c1 100644
@@ -99,7 +99,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	}
 
 	if (!least) {
-		IP_VS_ERR_RL("NQ: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_rr.c +1 -1
index e210f37..c49b388 100644
@@ -72,7 +72,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		q = q->next;
 	} while (q != p);
 	write_unlock(&svc->sched_lock);
-	IP_VS_ERR_RL("RR: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
   out:
net/netfilter/ipvs/ip_vs_sched.c +25 -0
index 076ebe0..08dbdd5 100644
@@ -29,6 +29,7 @@
 
 #include <net/ip_vs.h>
 
+EXPORT_SYMBOL(ip_vs_scheduler_err);
 /*
  *  IPVS scheduler list
  */
@@ -146,6 +147,30 @@ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler)
 		module_put(scheduler->module);
 }
 
+/*
+ * Common error output helper for schedulers
+ */
+
+void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
+{
+	if (svc->fwmark) {
+		IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n",
+			     svc->scheduler->name, svc->fwmark,
+			     svc->fwmark, msg);
+#ifdef CONFIG_IP_VS_IPV6
+	} else if (svc->af == AF_INET6) {
+		IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
+			     svc->scheduler->name,
+			     ip_vs_proto_name(svc->protocol),
+			     &svc->addr.in6, ntohs(svc->port), msg);
+#endif
+	} else {
+		IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n",
+			     svc->scheduler->name,
+			     ip_vs_proto_name(svc->protocol),
+			     &svc->addr.ip, ntohs(svc->port), msg);
+	}
+}
 
 /*
  *  Register a scheduler in the scheduler list
net/netfilter/ipvs/ip_vs_sed.c +1 -1
index 1ab75a9..89ead24 100644
@@ -87,7 +87,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("SED: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
net/netfilter/ipvs/ip_vs_sh.c +1 -1
index e6cc174..b5e2556 100644
@@ -223,7 +223,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	    || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
 	    || atomic_read(&dest->weight) <= 0
 	    || is_overloaded(dest)) {
-		IP_VS_ERR_RL("SH: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_wlc.c +1 -1
index bbddfdb..fdf0f58 100644
@@ -75,7 +75,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("WLC: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
net/netfilter/ipvs/ip_vs_wrr.c +8 -6
index 30db633..1ef41f5 100644
@@ -147,8 +147,9 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 
 			if (mark->cl == mark->cl->next) {
 				/* no dest entry */
-				IP_VS_ERR_RL("WRR: no destination available: "
-					     "no destinations present\n");
+				ip_vs_scheduler_err(svc,
+					"no destination available: "
+					"no destinations present");
 				dest = NULL;
 				goto out;
 			}
@@ -162,8 +163,8 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 				 */
 				if (mark->cw == 0) {
 					mark->cl = &svc->destinations;
-					IP_VS_ERR_RL("WRR: no destination "
-						     "available\n");
+					ip_vs_scheduler_err(svc,
+						"no destination available");
 					dest = NULL;
 					goto out;
 				}
@@ -185,8 +186,9 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			/* back to the start, and no dest is found.
 			   It is only possible when all dests are OVERLOADED */
 			dest = NULL;
-			IP_VS_ERR_RL("WRR: no destination available: "
-				     "all destinations are overloaded\n");
+			ip_vs_scheduler_err(svc,
+				"no destination available: "
+				"all destinations are overloaded");
 			goto out;
 		}
 	}
Signature · 1 line
1.7.2.3
#3 lore raw

Hi Simon,

Quoted 8 lines · Simon Horman
Quoted 2 lines

Thanks, this looks good to me.
I will apply it with the minor modification noted below.

I have slightly modified the IPv4/IPv6 logic in ip_vs_scheduler_err() and tested the code with both IPv4 and IPv6. It seems to work well :-)

I also did some indentation reformatting of ip_vs_scheduler_err() while I was there.

Thank you for taking your time and looking at it. I'm fine with your changes. Signoff follows.

The first hunk of your patch deletes an empty line in ip_vs.h that is unrelated to the other changes. Fine with me too, just thought I'd note it.

Quoted 21 lines

From: Patrick Schaaf <[email protected]>

ipvs: make "no destination available" message more informative

When IP_VS schedulers do not find a destination, they output a terse "WLC: no destination available" message through kernel syslog, which I can not only make sense of because syslog puts them in a logfile together with keepalived checker results.

This patch makes the output a bit more informative, by telling you which virtual service failed to find a destination.

Example output:

kernel: [1539214.552233] IPVS: wlc: TCP 192.168.8.30:22 - no destination available
kernel: [1539299.674418] IPVS: wlc: FWM 22 0x00000016 - no destination available

I have tested the code for IPv4 and FWM services, as you can see from the example; I do not have an IPv6 setup to test the third code path with.

Quoted 5 lines

To avoid code duplication, I put a new function ip_vs_scheduler_err() into ip_vs_sched.c, and use that from the schedulers instead of calling IP_VS_ERR_RL directly.

Quoted 227 lines

---

v2
* Minor correction to IPv6/IPv4 logic in ip_vs_scheduler_err()
* Reformatting of ip_vs_scheduler_err()

---
 include/net/ip_vs.h              |    3 ++-
 net/netfilter/ipvs/ip_vs_lblc.c  |    2 +-
 net/netfilter/ipvs/ip_vs_lblcr.c |    2 +-
 net/netfilter/ipvs/ip_vs_lc.c    |    2 +-
 net/netfilter/ipvs/ip_vs_nq.c    |    2 +-
 net/netfilter/ipvs/ip_vs_rr.c    |    2 +-
 net/netfilter/ipvs/ip_vs_sched.c |   25 +++++++++++++++++++++++++
 net/netfilter/ipvs/ip_vs_sed.c   |    2 +-
 net/netfilter/ipvs/ip_vs_sh.c    |    2 +-
 net/netfilter/ipvs/ip_vs_wlc.c   |    2 +-
 net/netfilter/ipvs/ip_vs_wrr.c   |   14 ++++++++------
 11 files changed, 43 insertions(+), 15 deletions(-)
include/net/ip_vs.h +2 -1
index 5d75fea..6e91713 100644
@@ -772,7 +772,6 @@ struct ip_vs_app {
 	/* ip_vs_app finish */
 	int (*done_conn)(struct ip_vs_app *, struct ip_vs_conn *);
 
-
 	/* not used now */
 	int (*bind_conn)(struct ip_vs_app *, struct ip_vs_conn *,
 			 struct ip_vs_protocol *);
@@ -1019,6 +1018,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 			struct ip_vs_proto_data *pd);
 
+extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
+
 
 /*
  *      IPVS control data and functions (from ip_vs_ctl.c)
net/netfilter/ipvs/ip_vs_lblc.c +1 -1
index 00b5ffa..4a9c8cd 100644
@@ -510,7 +510,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	/* No cache entry or it is invalid, time to schedule */
 	dest = __ip_vs_lblc_schedule(svc);
 	if (!dest) {
-		IP_VS_ERR_RL("LBLC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_lblcr.c +1 -1
index bfa25f1..bd329b1 100644
@@ -692,7 +692,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		/* The cache entry is invalid, time to schedule */
 		dest = __ip_vs_lblcr_schedule(svc);
 		if (!dest) {
-			IP_VS_ERR_RL("LBLCR: no destination available\n");
+			ip_vs_scheduler_err(svc, "no destination available");
 			read_unlock(&svc->sched_lock);
 			return NULL;
 		}
net/netfilter/ipvs/ip_vs_lc.c +1 -1
index 4f69db1..6063800 100644
@@ -70,7 +70,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	}
 
 	if (!least)
-		IP_VS_ERR_RL("LC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 	else
 		IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
 			      "inactconns %d\n",
net/netfilter/ipvs/ip_vs_nq.c +1 -1
index c413e18..984d9c1 100644
@@ -99,7 +99,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	}
 
 	if (!least) {
-		IP_VS_ERR_RL("NQ: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_rr.c +1 -1
index e210f37..c49b388 100644
@@ -72,7 +72,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		q = q->next;
 	} while (q != p);
 	write_unlock(&svc->sched_lock);
-	IP_VS_ERR_RL("RR: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
   out:
net/netfilter/ipvs/ip_vs_sched.c +25 -0
index 076ebe0..08dbdd5 100644
@@ -29,6 +29,7 @@
 
 #include <net/ip_vs.h>
 
+EXPORT_SYMBOL(ip_vs_scheduler_err);
 /*
  *  IPVS scheduler list
  */
@@ -146,6 +147,30 @@ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler)
 		module_put(scheduler->module);
 }
 
+/*
+ * Common error output helper for schedulers
+ */
+
+void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
+{
+	if (svc->fwmark) {
+		IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n",
+			     svc->scheduler->name, svc->fwmark,
+			     svc->fwmark, msg);
+#ifdef CONFIG_IP_VS_IPV6
+	} else if (svc->af == AF_INET6) {
+		IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
+			     svc->scheduler->name,
+			     ip_vs_proto_name(svc->protocol),
+			     &svc->addr.in6, ntohs(svc->port), msg);
+#endif
+	} else {
+		IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n",
+			     svc->scheduler->name,
+			     ip_vs_proto_name(svc->protocol),
+			     &svc->addr.ip, ntohs(svc->port), msg);
+	}
+}
 
 /*
  *  Register a scheduler in the scheduler list
net/netfilter/ipvs/ip_vs_sed.c +1 -1
index 1ab75a9..89ead24 100644
@@ -87,7 +87,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("SED: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
net/netfilter/ipvs/ip_vs_sh.c +1 -1
index e6cc174..b5e2556 100644
@@ -223,7 +223,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	    || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
 	    || atomic_read(&dest->weight) <= 0
 	    || is_overloaded(dest)) {
-		IP_VS_ERR_RL("SH: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
net/netfilter/ipvs/ip_vs_wlc.c +1 -1
index bbddfdb..fdf0f58 100644
@@ -75,7 +75,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("WLC: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
net/netfilter/ipvs/ip_vs_wrr.c +8 -6
index 30db633..1ef41f5 100644
@@ -147,8 +147,9 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 
 			if (mark->cl == mark->cl->next) {
 				/* no dest entry */
-				IP_VS_ERR_RL("WRR: no destination available: "
-					     "no destinations present\n");
+				ip_vs_scheduler_err(svc,
+					"no destination available: "
+					"no destinations present");
 				dest = NULL;
 				goto out;
 			}
@@ -162,8 +163,8 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 				 */
 				if (mark->cw == 0) {
 					mark->cl = &svc->destinations;
-					IP_VS_ERR_RL("WRR: no destination "
-						     "available\n");
+					ip_vs_scheduler_err(svc,
+						"no destination available");
 					dest = NULL;
 					goto out;
 				}
@@ -185,8 +186,9 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			/* back to the start, and no dest is found.
 			   It is only possible when all dests are OVERLOADED */
 			dest = NULL;
-			IP_VS_ERR_RL("WRR: no destination available: "
-				     "all destinations are overloaded\n");
+			ip_vs_scheduler_err(svc,
+				"no destination available: "
+				"all destinations are overloaded");
 			goto out;
 		}
 	}
maintainer
#4 lore raw
Quoted 6 lines · Patrick Schaaf

Hi Simon,

Quoted 3 lines · Simon Horman
Quoted 2 lines

Thanks, this looks good to me.
I will apply it with the minor modification noted below.

Quoted 8 lines
Quoted 5 lines

I have slightly modified the IPv4/IPv6 logic in ip_vs_scheduler_err() and tested the code with both IPv4 and IPv6. It seems to work well :-)

I also did some indentation reformatting of ip_vs_scheduler_err() while I was there.

Thank you for taking your time and looking at it. I'm fine with your changes. Signoff follows.

Thanks.

Quoted 3 lines

The first hunk of your patch deletes an empty line in ip_vs.h that is unrelated to the other changes. Fine with me too, just thought I'd note it.

Ooops, I'll remove that hunk.