  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD: src/sys/kern/kern_tc.c,v 1.191 2010/09/21 08:02:02 mav Exp $");
  
-diff -aur --unidirectional-new-file sys/net/bpf.c FreeBSD-CURRENT/net/bpf.c
---- sys/net/bpf.c	2010-12-09 15:46:09.000000000 +1100
-+++ FreeBSD-CURRENT/net/bpf.c	2010-12-09 16:27:51.000000000 +1100
+@@ -21,6 +28,12 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_tc
+ #include <sys/timetc.h>
+ #include <sys/timex.h>
+ 
++#ifdef FFCLOCK
++#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/malloc.h>
++#endif	/* FFCLOCK */
++
+ /*
+  * A large step happens on boot.  This constant detects such steps.
+  * It is relatively small so that ntp_update_second gets called enough
+@@ -53,6 +66,9 @@ struct timehands {
+ 	int64_t			th_adjustment;
+ 	uint64_t		th_scale;
+ 	u_int	 		th_offset_count;
++#ifdef FFCLOCK
++	ffcounter_t		ffcounter_record;
++#endif
+ 	struct bintime		th_offset;
+ 	struct timeval		th_microtime;
+ 	struct timespec		th_nanotime;
+@@ -61,6 +77,30 @@ struct timehands {
+ 	struct timehands	*th_next;
+ };
+ 
++#ifdef FFCLOCK
++static struct timehands th0;
++static struct timehands th9 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th0};
++static struct timehands th8 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th9};
++static struct timehands th7 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th8};
++static struct timehands th6 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th7};
++static struct timehands th5 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th6};
++static struct timehands th4 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th5};
++static struct timehands th3 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th4};
++static struct timehands th2 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th3};
++static struct timehands th1 = { NULL, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th2};
++static struct timehands th0 = {
++	&dummy_timecounter,
++	0,
++	(uint64_t)-1 / 1000000,
++	0,
++	0,
++	{1, 0},
++	{0, 0},
++	{0, 0},
++	1,
++	&th1
++};
++#else
+ static struct timehands th0;
+ static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th0};
+ static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th9};
+@@ -82,6 +122,7 @@ static struct timehands th0 = {
+ 	1,
+ 	&th1
+ };
++#endif	/* FFCLOCK */
+ 
+ static struct timehands *volatile timehands = &th0;
+ struct timecounter *timecounter = &dummy_timecounter;
+@@ -300,6 +341,254 @@ getmicrotime(struct timeval *tvp)
+ 	} while (gen == 0 || gen != th->th_generation);
+ }
+ 
++
++/*
++ * All Feed-forward clock functions
++ */
++#ifdef FFCLOCK
++static int sysctl_kern_timecounter_passthrough = 0;
++SYSCTL_INT(_kern_timecounter, OID_AUTO, passthrough, CTLFLAG_RW,
++	&sysctl_kern_timecounter_passthrough, 0,
++	"Select universal Feed-Forward timecounter for OS virtualization");
++
++
++/* Global data structure containing clock estimates */ 
++static struct feedforward_clock ffclock;
++
++MALLOC_DECLARE(M_FFCLOCK);
++MALLOC_DEFINE(M_FFCLOCK, "FFCLOCK", "Feed-Forward Clock estimates");
++
++
++static void
++init_ffclock(struct feedforward_clock *ffclock)
++{
++	unsigned long sz;
++	sz = sizeof(struct ffclock_estimate);
++
++	ffclock->updated = 0;
++	ffclock->cest	= (struct ffclock_estimate *) malloc(sz, M_FFCLOCK, M_WAITOK | M_ZERO);
++	ffclock->ocest	= (struct ffclock_estimate *) malloc(sz, M_FFCLOCK, M_WAITOK | M_ZERO);
++	ffclock->ucest	= (struct ffclock_estimate *) malloc(sz, M_FFCLOCK, M_WAITOK | M_ZERO);
++}
++
++
++/* 
++ * We need to have a boot time from the RTC clock or the like to get 
++ * kickstarted. init_ffclock is called before inittodr(), so cannot put the code
++ * there. Need to be called from tc_setclock(), once only.
++ */
++static void
++reset_ffclock(struct feedforward_clock *ffclock, struct timehands *th)
++{
++	uint64_t freq;
++	struct timecounter *tc;
++	struct ffclock_estimate *cest;
++	struct ffclock_data *cdata;
++
++	cest = ffclock->ucest;
++	cdata = &(cest->cdata);
++
++	/*
++	 * If called with a timehand, the timecounter is being changed and we
++	 * restart fresh. If not, the clock is being set from tc_setclock (note that
++	 * this may occur several times during boot).
++	 */ 
++	if (th) {
++		th->ffcounter_record = 0;
++		cdata->ffcounter = 0;
++		tc = th->th_counter;
++	}
++	else {
++		/* 
++		 * Strictly speaking, we should record the ffcounter when the RTC clock is
++		 * read from initoddr(), but not worse the trouble (is RTC trustworthy
++		 * anyway?). Let's keep it simple
++		 */ 
++		cdata->ffcounter = read_ffcounter();
++		tc = timehands->th_counter;
++	}
++	freq = tc->tc_frequency;
++
++	/* Numbers here are a bit magic */
++	// TODO should check these values ... again
++	cdata->phat_shift = 58;
++	cdata->time_shift = 32;
++	cdata->countdiff_maxbits = 30;
++
++	cdata->phat_int = ((1LL << 63) / freq) >> (63 - cdata->phat_shift); 
++
++	cdata->time_int = (boottimebin.sec << cdata->time_shift)
++		+ (boottimebin.frac >> (64 - cdata->time_shift));
++
++	if (++cest->gen == 0)
++		cest->gen = 1;
++
++	ffclock->ucest = ffclock->cest;
++	ffclock->cest = cest;
++	
++	cdata = &(ffclock->cest->cdata);
++	printf("reset_ffclock: %s - phat_int = %llu (%llu Hz), time_int = %llu (%llu.%llu s)\n",
++			tc->tc_name,
++			(long long unsigned) cdata->phat_int,
++			(long long unsigned) freq,
++			(long long unsigned) cdata->time_int,
++			(long long unsigned) boottimebin.sec, 
++			(long long unsigned) boottimebin.frac);
++
++	/* XXX Technically, should lock, but if radclock module not loaded?
++	 * Also, should make the radclock restart if the counter has changed!!
++	 */	
++}
++
++
++/* 
++ * Update to prevent overflow. This is no adjustment of the clock parameters.
++ * Assumption: timehands is the current one
++ */
++static void
++update_ffclock(struct feedforward_clock *ffclock)
++{
++	struct ffclock_estimate *tmp;
++	struct ffclock_data *cdata;
++	struct timehands *th;
++	ffcounter_t cdiff;
++
++	/*
++	 * If the clock has been updated by the synchronisation daemon, this new
++	 * data is the more up to date one.
++	 */
++	if ( ffclock->updated )
++	{
++		ffclock->ucest->gen = ffclock->cest->gen;
++		if (++ffclock->ucest->gen == 0)
++			ffclock->ucest->gen = 1;
++
++		tmp = ffclock->cest;
++		ffclock->cest = ffclock->ucest;
++		ffclock->ucest = tmp;
++		ffclock->updated = 0;
++		return;
++	}
++
++	/*
++	 * If we just changed the timecounter, we have nothing to do in here
++	 */
++	cdata = &(ffclock->cest->cdata);
++	th = timehands;
++	if ( cdata->ffcounter > th->ffcounter_record )
++		return;
++
++	/*
++	 * Update time mark 
++	 */
++	*(ffclock->ocest) = *(ffclock->cest);	
++	cdata = &(ffclock->ocest->cdata);
++
++	cdiff = th->ffcounter_record - cdata->ffcounter;
++	cdata->time_int += ((cdata->phat_int * cdiff) >> (cdata->phat_shift - cdata->time_shift));
++	cdata->ffcounter = th->ffcounter_record;
++	if (++ffclock->ocest->gen == 0)
++		ffclock->ocest->gen = 1;
++
++	tmp = ffclock->cest;
++	ffclock->cest = ffclock->ocest;
++	ffclock->ocest = tmp;
++}
++
++
++
++void
++ffcounter2bintime(ffcounter_t *ffcounter, struct bintime *bt)
++{
++	ffcounter_t countdiff;
++	uint64_t time_f;
++	uint64_t frac;
++	struct ffclock_data *cdata;
++	uint8_t gen;
++
++	/* Synchronization algorithm (userland) should update the fixed point data
++	 * often enough to make sure the timeval does not overflow. If no sync algo
++	 * updates the data, we loose precision, but in that case, nobody is tracking
++	 * the clock drift anyway ... so send warning and stop worrying.
++	 */
++
++	/* No locking to prevent clock data to be updated. Check that the generation
++	 * has not changed instead.
++	 */
++	do {
++		gen = ffclock.cest->gen;
++		cdata = &(ffclock.cest->cdata);
++
++		countdiff = *ffcounter - cdata->ffcounter;
++
++		/*
++		 * update_ffclock() should prevent countdiff to become to large and the
++		 * corresponding time interval added to overflow. Just send warning in
++		 * the unlikely event this is happening.
++		 */
++		if (countdiff & ~((1ll << (cdata->countdiff_maxbits +1)) - 1))
++		{
++			printf("ffclock: warning stamp may overflow timeval at %llu! "
++					"(countdiff = %llu, maxbits = %u)\n", 
++					(long long unsigned) *ffcounter,
++					(long long unsigned) countdiff,
++					cdata->countdiff_maxbits);
++		}
++		/* Add the counter delta in second to the recorded fixed point time */
++		time_f 	= cdata->time_int
++			+ ((cdata->phat_int * countdiff) >> (cdata->phat_shift - cdata->time_shift));
++
++		bt->sec  = time_f >> cdata->time_shift;
++
++/*
++		printf("ffclock: ffcounter = %llu bt->sec = %llu, time_int = %llu\n",
++				(long long unsigned) *ffcounter,
++			   	(long long unsigned) bt->sec, 
++				(long long unsigned) (cdata->time_int >> cdata->time_shift));
++*/
++		// gives me headaches again
++		// frac * ( 2^64 - 2^time_shift) ... that should be the correct resolution
++		frac = time_f - ((uint64_t) bt->sec << cdata->time_shift);
++		bt->frac = frac * ((uint64_t) 1LL << (64 - cdata->time_shift));
++
++	} while (gen == 0 || gen != ffclock.cest->gen);
++}
++
++
++static __inline uint64_t
++tc_get_timecount_fake64(struct timecounter *tc)
++{
++	u_int count;
++	count = tc->tc_get_timecount(tc);
++	return (uint64_t) count;
++}
++
++
++ffcounter_t
++read_ffcounter(void)
++{
++	struct timecounter *tc;
++	struct timehands *th;
++	u_int gen, delta;
++	ffcounter_t ffcounter;
++
++	if ( sysctl_kern_timecounter_passthrough ) {
++		tc = timehands->th_counter;
++		return tc->tc_get_timecount_64(tc);
++	}
++	else {
++		do {
++			th = timehands;
++			gen = th->th_generation;
++			delta = tc_delta(th);
++			ffcounter = th->ffcounter_record;
++		} while ( gen == 0 || gen != th->th_generation);
++
++		return(ffcounter + delta);
++	}
++}
++#endif	/* FFCLOCK */
++
+ /*
+  * Initialize a new timecounter and possibly use it.
+  */
+@@ -325,7 +614,13 @@ tc_init(struct timecounter *tc)
+ 		    tc->tc_name, (uintmax_t)tc->tc_frequency,
+ 		    tc->tc_quality);
+ 	}
+-
++#ifdef FFCLOCK
++	/* XXX this is a very ugly but good enough to cover my back */
++	if ( (strcmp(tc->tc_name, "TSC") != 0) && (strcmp(tc->tc_name, "ixen") != 0) )
++	{
++		tc->tc_get_timecount_64 = &tc_get_timecount_fake64;
++	}
++#endif
+ 	tc->tc_next = timecounters;
+ 	timecounters = tc;
+ 	/*
+@@ -391,6 +686,10 @@ tc_setclock(struct timespec *ts)
+ 	boottimebin = bt;
+ 	bintime2timeval(&bt, &boottime);
+ 
++#ifdef FFCLOCK
++	reset_ffclock(&ffclock, NULL);
++#endif	/* FFCLOCK */
++
+ 	/* XXX fiddle all the little crinkly bits around the fiords... */
+ 	tc_windup();
+ 	nanotime(&taft);
+@@ -440,6 +739,11 @@ tc_windup(void)
+ 		ncount = timecounter->tc_get_timecount(timecounter);
+ 	else
+ 		ncount = 0;
++
++#ifdef FFCLOCK
++	th->ffcounter_record += delta;
++#endif
++
+ 	th->th_offset_count += delta;
+ 	th->th_offset_count &= th->th_counter->tc_counter_mask;
+ 	bintime_addx(&th->th_offset, th->th_scale * delta);
+@@ -486,6 +790,10 @@ tc_windup(void)
+ 		th->th_offset_count = ncount;
+ 		tc_min_ticktock_freq = max(1, timecounter->tc_frequency /
+ 		    (((uint64_t)timecounter->tc_counter_mask + 1) / 3));
++
++		#ifdef FFCLOCK
++		reset_ffclock(&ffclock, th);
++		#endif
+ 	}
+ 
+ 	/*-
+@@ -528,6 +836,11 @@ tc_windup(void)
+ 	time_second = th->th_microtime.tv_sec;
+ 	time_uptime = th->th_offset.sec;
+ 	timehands = th;
++
++
++#ifdef FFCLOCK
++	update_ffclock(&ffclock);
++#endif
+ }
+ 
+ /* Report or change the active timecounter hardware. */
+@@ -594,6 +907,10 @@ pps_ioctl(u_long cmd, caddr_t data, stru
+ {
+ 	pps_params_t *app;
+ 	struct pps_fetch_args *fapi;
++#ifdef FFCLOCK
++	struct ffclock_pps_fetch_args *ffclock_fapi;
++#endif
++
+ #ifdef PPS_SYNC
+ 	struct pps_kcbind_args *kapi;
+ #endif
+@@ -627,6 +944,19 @@ pps_ioctl(u_long cmd, caddr_t data, stru
+ 		pps->ppsinfo.current_mode = pps->ppsparam.mode;
+ 		fapi->pps_info_buf = pps->ppsinfo;
+ 		return (0);
++
++#ifdef FFCLOCK
++	case FFCLOCK_PPS_IOC_FETCH:
++		ffclock_fapi = (struct ffclock_pps_fetch_args *)data;
++		if (ffclock_fapi->tsformat && ffclock_fapi->tsformat != PPS_TSFMT_TSPEC)
++			return (EINVAL);
++		if (ffclock_fapi->timeout.tv_sec || ffclock_fapi->timeout.tv_nsec)
++			return (EOPNOTSUPP);
++		pps->ppsinfo.current_mode = pps->ppsparam.mode;
++		ffclock_fapi->pps_info_buf = pps->ffclock_ppsinfo;
++		return (0);
++#endif 	/* FFCLOCK */
++
+ 	case PPS_IOC_KCBIND:
+ #ifdef PPS_SYNC
+ 		kapi = (struct pps_kcbind_args *)data;
+@@ -679,6 +1009,12 @@ pps_event(struct pps_state *pps, int eve
+ 	u_int tcount, *pcount;
+ 	int foff, fhard;
+ 	pps_seq_t *pseq;
++#ifdef FFCLOCK
++	struct timespec *ffclock_tsp;
++	pps_seq_t *ffclock_pseq;
++	ffcounter_t *ffcounter;
++	ffcounter_t ffcounter_record;
++#endif
+ 
+ 	KASSERT(pps != NULL, ("NULL pps pointer in pps_event"));
+ 	/* If the timecounter was wound up underneath us, bail out. */
+@@ -693,6 +1029,11 @@ pps_event(struct pps_state *pps, int eve
+ 		fhard = pps->kcmode & PPS_CAPTUREASSERT;
+ 		pcount = &pps->ppscount[0];
+ 		pseq = &pps->ppsinfo.assert_sequence;
++#ifdef FFCLOCK
++		ffcounter = &pps->ffclock_ppsinfo.assert_ffcounter;
++		ffclock_tsp = &pps->ffclock_ppsinfo.assert_timestamp;
++		ffclock_pseq = &pps->ffclock_ppsinfo.assert_sequence;
++#endif
+ 	} else {
+ 		tsp = &pps->ppsinfo.clear_timestamp;
+ 		osp = &pps->ppsparam.clear_offset;
+@@ -700,6 +1041,11 @@ pps_event(struct pps_state *pps, int eve
+ 		fhard = pps->kcmode & PPS_CAPTURECLEAR;
+ 		pcount = &pps->ppscount[1];
+ 		pseq = &pps->ppsinfo.clear_sequence;
++#ifdef FFCLOCK
++		ffcounter = &pps->ffclock_ppsinfo.clear_ffcounter;
++		ffclock_tsp = &pps->ffclock_ppsinfo.clear_timestamp;
++		ffclock_pseq = &pps->ffclock_ppsinfo.clear_sequence;
++#endif
+ 	}
+ 
+ 	/*
+@@ -716,6 +1062,9 @@ pps_event(struct pps_state *pps, int eve
+ 	/* Convert the count to a timespec. */
+ 	tcount = pps->capcount - pps->capth->th_offset_count;
+ 	tcount &= pps->capth->th_counter->tc_counter_mask;
++#ifdef FFCLOCK
++	ffcounter_record = pps->capth->ffcounter_record;
++#endif
+ 	bt = pps->capth->th_offset;
+ 	bintime_addx(&bt, pps->capth->th_scale * tcount);
+ 	bintime_add(&bt, &boottimebin);
+@@ -728,6 +1077,11 @@ pps_event(struct pps_state *pps, int eve
+ 	*pcount = pps->capcount;
+ 	(*pseq)++;
+ 	*tsp = ts;
++#ifdef FFCLOCK
++	(*ffclock_pseq)++;
++	*ffclock_tsp = ts;
++	*ffcounter = (ffcounter_record + tcount);
++#endif
+ 
+ 	if (foff) {
+ 		timespecadd(tsp, osp);
+@@ -802,6 +1156,10 @@ inittimecounter(void *dummy)
+ 	p = (tc_tick * 1000000) / hz;
+ 	printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
+ 
++#ifdef FFCLOCK
++	init_ffclock(&ffclock);
++#endif
++
+ 	/* warm up new timecounter (again) and get rolling. */
+ 	(void)timecounter->tc_get_timecount(timecounter);
+ 	(void)timecounter->tc_get_timecount(timecounter);
+diff -apur --unidirectional-new-file sys/modules/Makefile FreeBSD-CURRENT/modules/Makefile
+--- sys/modules/Makefile	2010-12-09 17:45:09.000000000 +1100
++++ FreeBSD-CURRENT/modules/Makefile	2010-12-09 17:45:32.000000000 +1100
+@@ -241,6 +241,7 @@ SUBDIR=	${_3dfx} \
+ 	${_pst} \
+ 	pty  \
+ 	puc \
++	ffclock \
+ 	ral \
+ 	ralfw \
+ 	${_random} \
+diff -apur --unidirectional-new-file sys/modules/ffclock/Makefile FreeBSD-CURRENT/modules/ffclock/Makefile
+--- sys/modules/ffclock/Makefile	1970-01-01 10:00:00.000000000 +1000
++++ FreeBSD-CURRENT/modules/ffclock/Makefile	2010-12-09 17:45:32.000000000 +1100
+@@ -0,0 +1,15 @@
++# This make file creates the .ko module for retrieving the vitual counter through syscall.
++
++.PATH: ${.CURDIR}/../../kern
++
++KMOD    =  ffclock
++SRCS    =  ffclock.c
++
++SRCS+=	opt_ffclock.h
++
++.if !defined(KERNBUILDDIR)
++opt_ffclock.h:
++	echo "#define FFCLOCK 1" > opt_ffclock.h
++.endif
++
++.include <bsd.kmod.mk>
+diff -apur --unidirectional-new-file sys/net/bpf.c FreeBSD-CURRENT/net/bpf.c
+--- sys/net/bpf.c	2010-12-09 17:45:10.000000000 +1100
++++ FreeBSD-CURRENT/net/bpf.c	2010-12-09 17:45:32.000000000 +1100
 @@ -7,6 +7,12 @@
   * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
   * Berkeley Laboratory.

  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
diff -aur --unidirectional-new-file sys/i386/i386/tsc.c FreeBSD-CURRENT/i386/i386/tsc.c
--- sys/i386/i386/tsc.c	2010-12-09 15:46:09.000000000 +1100
+++ FreeBSD-CURRENT/i386/i386/tsc.c	2010-12-09 16:27:51.000000000 +1100
@@ -2,6 +2,12 @@
  * Copyright (C) 1998-2003 Poul-Henning Kamp
  * All rights reserved.

  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -90,8 +96,13 @@ MALLOC_DEFINE(M_BPF, "BPF", "BPF data");
 
 #define PRINET  26			/* interruptible */
 
+#ifdef FFCLOCK
+#define	SIZEOF_BPF_HDR(type)	\
+    (offsetof(type, ffcounter_stamp) + sizeof(((type *)0)->ffcounter_stamp))
+#else
 #define	SIZEOF_BPF_HDR(type)	\
     (offsetof(type, bh_hdrlen) + sizeof(((type *)0)->bh_hdrlen))
+#endif	/* FFCLOCK */
 
 #ifdef COMPAT_FREEBSD32
 #include <sys/mount.h>
@@ -111,6 +122,10 @@ struct bpf_hdr32 {
 	uint32_t	bh_datalen;	/* original length of packet */
 	uint16_t	bh_hdrlen;	/* length of bpf header (this struct
 					   plus alignment padding) */
+#ifdef FFCLOCK
+	u_short     padding;        /* padding to align the fields */
+	ffcounter_t  ffcounter_stamp;   /* raw virtual timecounter timestamp for this packet */      
+#endif
 };
 #endif
 
@@ -151,9 +166,15 @@ static int	bpf_setif(struct bpf_d *, str
 static void	bpf_timed_out(void *);
 static __inline void
 		bpf_wakeup(struct bpf_d *);
+#ifdef FFCLOCK
+static void catchpacket(struct bpf_d *, u_char *, u_int, u_int,
+			void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int),
+			struct bintime *, ffcounter_t *);
+#else
 static void	catchpacket(struct bpf_d *, u_char *, u_int, u_int,
 		    void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int),
 		    struct bintime *);
+#endif
 static void	reset_d(struct bpf_d *);
 static int	 bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
 static int	bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
@@ -172,6 +193,11 @@ SYSCTL_INT(_net_bpf, OID_AUTO, zerocopy_
     &bpf_zerocopy_enable, 0, "Enable new zero-copy BPF buffer sessions");
 SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_MPSAFE | CTLFLAG_RW,
     bpf_stats_sysctl, "bpf statistics portal");
+#ifdef FFCLOCK
+static int bpf_ffclock_tstamp = 0; 
+SYSCTL_INT(_net_bpf, OID_AUTO, ffclock_tstamp, CTLFLAG_RW,
+	&bpf_ffclock_tstamp, 0, "Set BPF to timestamp using Feed-Forward clock by default");
+#endif /* FFCLOCK */
 
 static	d_open_t	bpfopen;
 static	d_read_t	bpfread;
@@ -698,6 +724,14 @@ bpfopen(struct cdev *dev, int flags, int
 	callout_init_mtx(&d->bd_callout, &d->bd_mtx, 0);
 	knlist_init_mtx(&d->bd_sel.si_note, &d->bd_mtx);
 
+#ifdef FFCLOCK
+	/* Timestamping mode for this device, default is use the system clock.
+	 * Need BPF_T_MONOTONIC to avoid bpf_bintime2ts to add bootime.
+	 */
+	if (bpf_ffclock_tstamp)
+		d->bd_tstamp = d->bd_tstamp | BPF_T_FFCLOCK | BPF_T_MONOTONIC;
+#endif /* FFCLOCK */
+
 	return (0);
 }
 
@@ -1817,6 +1851,9 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, 
 #endif
 	u_int slen;
 	int gottime;
+#ifdef FFCLOCK
+	ffcounter_t ffcounter;
+#endif
 
 	gottime = BPF_TSTAMP_NONE;
 	BPFIF_LOCK(bp);
@@ -1839,12 +1876,22 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, 
 		if (slen != 0) {
 			d->bd_fcount++;
 			if (gottime < bpf_ts_quality(d->bd_tstamp))
+			{
 				gottime = bpf_gettime(&bt, d->bd_tstamp, NULL);
+#ifdef FFCLOCK
+				ffcounter = read_ffcounter();
+#endif
+			}
 #ifdef MAC
 			if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
+#ifdef FFCLOCK
+				catchpacket(d, pkt, pktlen, slen,
+				    bpf_append_bytes, &bt, &ffcounter);
+#else
 				catchpacket(d, pkt, pktlen, slen,
 				    bpf_append_bytes, &bt);
+#endif	/* FFCLOCK */
 		}
 		BPFD_UNLOCK(d);
 	}
@@ -1868,6 +1915,9 @@ bpf_mtap(struct bpf_if *bp, struct mbuf 
 #endif
 	u_int pktlen, slen;
 	int gottime;
+#ifdef FFCLOCK
+	ffcounter_t ffcounter;
+#endif
 
 	/* Skip outgoing duplicate packets. */
 	if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1895,12 +1945,23 @@ bpf_mtap(struct bpf_if *bp, struct mbuf 
 		if (slen != 0) {
 			d->bd_fcount++;
 			if (gottime < bpf_ts_quality(d->bd_tstamp))
+			{
 				gottime = bpf_gettime(&bt, d->bd_tstamp, m);
+
+#ifdef FFCLOCK
+				ffcounter = read_ffcounter();
+#endif
+			}
 #ifdef MAC
 			if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
+#ifdef FFCLOCK
+				catchpacket(d, (u_char *)m, pktlen, slen,
+				    bpf_append_mbuf, &bt, &ffcounter);
+#else
 				catchpacket(d, (u_char *)m, pktlen, slen,
 				    bpf_append_mbuf, &bt);
+#endif 	/* FFCLOCK */
 		}
 		BPFD_UNLOCK(d);
 	}
@@ -1919,6 +1980,9 @@ bpf_mtap2(struct bpf_if *bp, void *data,
 	struct bpf_d *d;
 	u_int pktlen, slen;
 	int gottime;
+#ifdef FFCLOCK
+	ffcounter_t ffcounter;
+#endif 	/* FFCLOCK */
 
 	/* Skip outgoing duplicate packets. */
 	if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1948,12 +2012,22 @@ bpf_mtap2(struct bpf_if *bp, void *data,
 		if (slen != 0) {
 			d->bd_fcount++;
 			if (gottime < bpf_ts_quality(d->bd_tstamp))
+			{
 				gottime = bpf_gettime(&bt, d->bd_tstamp, m);
+#ifdef FFCLOCK
+				ffcounter = read_ffcounter();
+#endif 	/* FFCLOCK */
+			}
 #ifdef MAC
 			if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
+#ifdef FFCLOCK
+				catchpacket(d, (u_char *)m, pktlen, slen,
+				    bpf_append_mbuf, &bt, &ffcounter);
+#else
 				catchpacket(d, (u_char *)&mb, pktlen, slen,
 				    bpf_append_mbuf, &bt);
+#endif
 		}
 		BPFD_UNLOCK(d);
 	}
@@ -1995,6 +2069,7 @@ bpf_hdrlen(struct bpf_d *d)
 	return (hdrlen - d->bd_bif->bif_hdrlen);
 }
 
+
 static void
 bpf_bintime2ts(struct bintime *bt, struct bpf_ts *ts, int tstype)
 {
@@ -2025,6 +2100,8 @@ bpf_bintime2ts(struct bintime *bt, struc
 	}
 }
 
+
+
 /*
  * Move the packet data from interface memory (pkt) into the
  * store buffer.  "cpfn" is the routine called to do the actual data
@@ -2032,10 +2109,16 @@ bpf_bintime2ts(struct bintime *bt, struc
  * bpf_append_mbuf is passed in to copy mbuf chains.  In the latter case,
  * pkt is really an mbuf.
  */
+#ifdef FFCLOCK
 static void
 catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
     void (*cpfn)(struct bpf_d *, caddr_t, u_int, void *, u_int),
+    struct bintime *bt, ffcounter_t *ffcounter)
+#else
+catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
+    void (*cpfn)(struct bpf_d *, caddr_t, u_int, void *, u_int),
     struct bintime *bt)
+#endif
 {
 	struct bpf_xhdr hdr;
 #ifndef BURN_BRIDGES
@@ -2049,6 +2132,11 @@ catchpacket(struct bpf_d *d, u_char *pkt
 	int do_timestamp;
 	int tstype;
 
+// XXX FFCLOCK DEBUG XXX
+//	struct bpf_if *bp;
+//	bp = d->bd_bif;
+// XXX FFCLOCK DEBUG XXX	
+
 	BPFD_LOCK_ASSERT(d);
 
 	/*
@@ -2118,17 +2206,33 @@ catchpacket(struct bpf_d *d, u_char *pkt
 	if (tstype == BPF_T_NONE || BPF_T_FORMAT(tstype) == BPF_T_MICROTIME) {
 		struct bpf_ts ts;
 		if (do_timestamp)
+		{
+#ifdef FFCLOCK
+			/* If asked, use the RADclock to generate the bintime timestamp */
+			if ( (tstype & BPF_T_FFCLOCK) == BPF_T_FFCLOCK )
+				ffcounter2bintime(ffcounter, bt);
+#endif	/* FFCLOCK */
 			bpf_bintime2ts(bt, &ts, tstype);
+		}
 #ifdef COMPAT_FREEBSD32
 		if (d->bd_compat32) {
 			bzero(&hdr32_old, sizeof(hdr32_old));
 			if (do_timestamp) {
+#ifdef FFCLOCK
+				hdr32_old.ffcounter_stamp = *ffcounter;
+#endif
 				hdr32_old.bh_tstamp.tv_sec = ts.bt_sec;
 				hdr32_old.bh_tstamp.tv_usec = ts.bt_frac;
 			}
 			hdr32_old.bh_datalen = pktlen;
 			hdr32_old.bh_hdrlen = hdrlen;
 			hdr32_old.bh_caplen = caplen;
+
+// XXX FFCLOCK DEBUG XXX
+//if_printf(bp->bif_ifp, "radcatch: hdr32_old with hdrlen= %d, ffcounter= %llu\n",
+//	   	hdrlen, (long long unsigned) *ffcounter);
+// XXX FFCLOCK DEBUG XXX
+
 			bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr32_old,
 			    sizeof(hdr32_old));
 			goto copy;
@@ -2136,12 +2240,21 @@ catchpacket(struct bpf_d *d, u_char *pkt
 #endif
 		bzero(&hdr_old, sizeof(hdr_old));
 		if (do_timestamp) {
+#ifdef FFCLOCK
+			hdr_old.ffcounter_stamp = *ffcounter;
+#endif
 			hdr_old.bh_tstamp.tv_sec = ts.bt_sec;
 			hdr_old.bh_tstamp.tv_usec = ts.bt_frac;
 		}
 		hdr_old.bh_datalen = pktlen;
 		hdr_old.bh_hdrlen = hdrlen;
 		hdr_old.bh_caplen = caplen;
+
+// XXX FFCLOCK DEBUG XXX
+//if_printf(bp->bif_ifp, "radcatch: hdr_old with hdrlen= %d, ffcounter= %llu\n",
+//	   	hdrlen, (long long unsigned) *ffcounter);
+// XXX FFCLOCK DEBUG XXX
+
 		bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr_old,
 		    sizeof(hdr_old));
 		goto copy;
@@ -2154,10 +2267,23 @@ catchpacket(struct bpf_d *d, u_char *pkt
 	 */
 	bzero(&hdr, sizeof(hdr));
 	if (do_timestamp)
+	{
+#ifdef FFCLOCK
+		hdr.ffcounter_stamp = *ffcounter;
+		if ( (tstype & BPF_T_FFCLOCK) == BPF_T_FFCLOCK )
+			ffcounter2bintime(ffcounter, bt);
+#endif	/* FFCLOCK */
 		bpf_bintime2ts(bt, &hdr.bh_tstamp, tstype);
+	}
 	hdr.bh_datalen = pktlen;
 	hdr.bh_hdrlen = hdrlen;
 	hdr.bh_caplen = caplen;
+
+// XXX FFCLOCK DEBUG XXX
+//if_printf(bp->bif_ifp, "radcatch: xhdr with hdrlen= %d, ffcounter= %llu\n",
+//	   	hdrlen, (long long unsigned) *ffcounter);
+// XXX FFCLOCK DEBUG XXX
+
 	bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr, sizeof(hdr));
 
 	/*
diff -apur --unidirectional-new-file sys/net/bpf.h FreeBSD-CURRENT/net/bpf.h
--- sys/net/bpf.h	2010-12-09 17:45:10.000000000 +1100
+++ FreeBSD-CURRENT/net/bpf.h	2010-12-09 17:45:32.000000000 +1100
@@ -7,6 +7,12 @@
  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
  * Berkeley Laboratory.
