pf 4.1 Update available for testing

Eygene Ryabinkin rea-fbsd at codelabs.ru
Wed Jun 20 19:04:30 UTC 2007


Nate, Max, good day.

Wed, Jun 20, 2007 at 07:26:09PM +0400, Eygene Ryabinkin wrote:
> Fine, thanks!  So, you're happy with the way the problem was fixed?
> I see that another function that uses tbr_callout is tbr_timeout,
> but it will not be called before tbr_set.  So it seems to me that
> callout initialisation only in tbr_set is enough.  But maybe I am
> missing something?

After some thinking I came to the idea that one more patch must be
applied.  The variables machclk_usepcc and machclk_per_tick can be
left uninitialised following the same codepath as for tbr_callout:
tsc_freq_changed() touches only machclk_freq, but init_machclk
touches all three variables.

This error can potentially be responsible to the weird bandwidth
values I am having with the altq on my notebook.  The issue is
described on the thread
  http://lists.freebsd.org/pipermail/freebsd-current/2007-April/070730.html
Basically, I am setting one BW limit in pf.conf and seeing another
one (much lower)  via the ifstat utility.

I was able only to test the compilation of the new patched kernel.
No bandwidth tests were done: I have no access to the fast LAN link
up to the Monday, 24th, sorry.  May be I will be able to setup
ng_eiface and test with it, but I am not fluent with the netgraph.
Will post an update if tests will be carried.

But I am pretty sure that the altq_subr.c should be patched to
properly handle the initialization of these two variables.  The
only question is how to do it: via my patch or using some different
strategy.

No more words, the patch is attached.  Comments are welcome!
-- 
Eygene
-------------- next part --------------
diff --git a/sys/contrib/altq/altq/altq_subr.c b/sys/contrib/altq/altq/altq_subr.c
index 0c6e485..0ca01db 100644
--- a/sys/contrib/altq/altq/altq_subr.c
+++ b/sys/contrib/altq/altq/altq_subr.c
@@ -129,6 +129,28 @@ static struct ip4_frag	*ip4f_alloc(void);
 static void 	ip4f_free(struct ip4_frag *);
 #endif /* ALTQ3_CLFIER_COMPAT */
 
+static inline void
+machclk_set_freq(u_int32_t _newfreq);
+static inline void
+machclk_init_pcc(void);
+/*
+ * We do machclk_init_pcc() here because machclk_freq can be
+ * already initialized by tsc_freq_changed() or simular, but
+ * machclk_usepcc will not be properly initialized then.
+ * We could call machclk_init_pcc() from the tsc_freq_changed(),
+ * but the then calls to the machclk_init_pcc() will be more
+ * frequent.  It is microoptimisation and it can be dropped
+ * in favor of the more clean code.
+ */
+#define INIT_MACHCLK \
+	do {				\
+		if (machclk_freq == 0)		\
+			init_machclk();		\
+		else				\
+			machclk_init_pcc();	\
+	} while(0)
+	
+
 /*
  * alternate queueing support routines
  */
@@ -384,8 +406,7 @@ tbr_set(ifq, profile)
 		tbr_dequeue_ptr = tbr_dequeue;
 
 	tbr_callout_init();
-	if (machclk_freq == 0)
-		init_machclk();
+	INIT_MACHCLK;
 	if (machclk_freq == 0) {
 		printf("tbr_set: no cpu clock available!\n");
 		return (ENXIO);
@@ -599,8 +620,7 @@ altq_add(struct pf_altq *a)
 	if (a->qname[0] != 0)
 		return (altq_add_queue(a));
 
-	if (machclk_freq == 0)
-		init_machclk();
+	INIT_MACHCLK;
 	if (machclk_freq == 0)
 		panic("altq_add: no cpu clock");
 
@@ -912,7 +932,7 @@ tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 		return;
 
 	/* Total setting for this level gives the new frequency in MHz. */
-	machclk_freq = level->total_set.freq * 1000000;
+	machclk_set_freq(level->total_set.freq * 1000000);
 }
 EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
     EVENTHANDLER_PRI_ANY);
@@ -935,9 +955,14 @@ tbr_callout_init(void)
 }
 #endif /* __FreeBSD_version >= 600000 */
 
-void
-init_machclk(void)
+static inline void
+machclk_init_pcc(void)
 {
+	static int called = 0;
+
+	if (called)
+		return;
+
 	machclk_usepcc = 1;
 
 #if (!defined(__i386__) && !defined(__alpha__)) || defined(ALTQ_NOPCC)
@@ -955,11 +980,24 @@ init_machclk(void)
 	    tsc_is_broken))
 		machclk_usepcc = 0;
 #endif
+	called = 1;
+}
+
+static inline void
+machclk_set_freq(u_int32_t newfreq)
+{
+	machclk_freq = newfreq;
+	machclk_per_tick = machclk_freq / hz;
+}
+
+void
+init_machclk(void)
+{
+	machclk_init_pcc();
 
 	if (machclk_usepcc == 0) {
 		/* emulate 256MHz using microtime() */
-		machclk_freq = 1000000 << MACHCLK_SHIFT;
-		machclk_per_tick = machclk_freq / hz;
+		machclk_set_freq(1000000 << MACHCLK_SHIFT);
 #ifdef ALTQ_DEBUG
 		printf("altq: emulate %uHz cpu clock\n", machclk_freq);
 #endif
@@ -1011,7 +1049,7 @@ init_machclk(void)
 			machclk_freq = (u_int)((end - start) * 1000000 / diff);
 	}
 
-	machclk_per_tick = machclk_freq / hz;
+	machclk_set_freq(machclk_freq);
 
 #ifdef ALTQ_DEBUG
 	printf("altq: CPU clock: %uHz\n", machclk_freq);


More information about the freebsd-pf mailing list