M5 step 1: build OpenBSD hfsc/fq_codel back ends into pf.ko (ml_* API, ifq_q handshake, scheduler types); priq still attached, 14/14 suite unchanged
This commit is contained in:
1 parent
ca75fc49cc
commit
f34c4f92a9
18 files changed
+3923
-32
No files matched your search
+1
-1
@@ -1 +1 @@
|
||||
savedcmd_pf.mod := printf '%s\n' pfsrc/pfk_mod.o pfsrc/pfk_hooks.o compat/pfk_mbuf.o compat/pfk_kern.o compat/pfk_if.o compat/pfk_xmit.o compat/pfk_pcb.o compat/pfk_ip4.o compat/siphash.o compat/toeplitz.o compat/md5.o compat/sha2.o compat/radix.o compat/pfk_rtable.o compat/pfk_ip6.o compat/subr_tree.o pfsrc/pf_ruleset.o pfsrc/pf_table.o pfsrc/pf_norm.o pfsrc/pf_if.o pfsrc/pf_lb.o pfsrc/pf_osfp.o pfsrc/pf_syncookies.o pfsrc/pf_ioctl.o pfsrc/pf.o pfsrc/divert_sock.o pfsrc/pfk_pflog.o compat/pfk_ifq.o | awk '!x[$$0]++ { print("./"$$0) }' > pf.mod
|
||||
savedcmd_pf.mod := printf '%s\n' pfsrc/pfk_mod.o pfsrc/pfk_hooks.o compat/pfk_mbuf.o compat/pfk_kern.o compat/pfk_if.o compat/pfk_xmit.o compat/pfk_pcb.o compat/pfk_ip4.o compat/siphash.o compat/toeplitz.o compat/md5.o compat/sha2.o compat/radix.o compat/pfk_rtable.o compat/pfk_ip6.o compat/subr_tree.o pfsrc/pf_ruleset.o pfsrc/pf_table.o pfsrc/pf_norm.o pfsrc/pf_if.o pfsrc/pf_lb.o pfsrc/pf_osfp.o pfsrc/pf_syncookies.o pfsrc/pf_ioctl.o pfsrc/pf.o pfsrc/divert_sock.o pfsrc/pfk_pflog.o pfsrc/fq_codel.o pfsrc/hfsc.o compat/pfk_ifq.o | awk '!x[$$0]++ { print("./"$$0) }' > pf.mod
|
||||
+1
-1
@@ -20,7 +20,7 @@ pf-objs := pfsrc/pfk_mod.o pfsrc/pfk_hooks.o \
|
||||
# ported OpenBSD 8.0 engine
|
||||
pf-objs += pfsrc/pf_ruleset.o pfsrc/pf_table.o pfsrc/pf_norm.o pfsrc/pf_if.o \
|
||||
pfsrc/pf_lb.o pfsrc/pf_osfp.o pfsrc/pf_syncookies.o \
|
||||
pfsrc/pf_ioctl.o pfsrc/pf.o pfsrc/divert_sock.o pfsrc/pfk_pflog.o
|
||||
pfsrc/pf_ioctl.o pfsrc/pf.o pfsrc/divert_sock.o pfsrc/pfk_pflog.o pfsrc/fq_codel.o pfsrc/hfsc.o
|
||||
|
||||
# queueing framework (compat/pfk_ifq.c implements the ifq API with priq
|
||||
# semantics; the OpenBSD hfsc/fq_codel back ends land in milestone M5)
|
||||
|
||||
+28
-20
@@ -273,10 +273,11 @@ static const struct pfq_ops pfk_priq_pfq_ops = {
|
||||
* packets are still queued, but the traffic shaping curves are not yet
|
||||
* applied — recorded in the feature matrix as pending M5).
|
||||
*/
|
||||
const struct ifq_ops * const ifq_hfsc_ops = &pfk_priq_ifq_ops;
|
||||
const struct ifq_ops * const ifq_fqcodel_ops = &pfk_priq_ifq_ops;
|
||||
const struct pfq_ops * const pfq_hfsc_ops = &pfk_priq_pfq_ops;
|
||||
const struct pfq_ops * const pfq_fqcodel_ops = &pfk_priq_pfq_ops;
|
||||
/*
|
||||
* M5: the real scheduler back ends (pfsrc/hfsc.c, pfsrc/fq_codel.c) define
|
||||
* ifq_hfsc_ops/pfq_hfsc_ops/ifq_fqcodel_ops/pfq_fqcodel_ops themselves; the
|
||||
* priq shim above stays as the default for interfaces without a queue rule.
|
||||
*/
|
||||
|
||||
/* ---------------- framework ---------------- */
|
||||
void
|
||||
@@ -305,6 +306,29 @@ ifq_attach(struct ifqueue *ifq, const struct ifq_ops *ops, void *opsarg)
|
||||
ifq->ifq_softc = opsarg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler hand-off used by the ported back ends (hfsc/fq_codel) when they
|
||||
* need their per-interface state. PFLINUX: the port has no ifq mutex (the
|
||||
* data path is a single ordered work queue), so "enter" is a plain ownership
|
||||
* check and "leave" is a no-op - the pair exists to mirror OpenBSD's API.
|
||||
*/
|
||||
void *
|
||||
ifq_q_enter(struct ifqueue *ifq, const struct ifq_ops *ops)
|
||||
{
|
||||
if (ifq == NULL || ops == NULL || ifq->ifq_ops != ops)
|
||||
return NULL; /* another scheduler owns it */
|
||||
if (ifq->ifq_softc == NULL && ops->ifqop_alloc)
|
||||
ifq->ifq_softc = ops->ifqop_alloc(0, NULL);
|
||||
return ifq->ifq_softc;
|
||||
}
|
||||
|
||||
void
|
||||
ifq_q_leave(struct ifqueue *ifq, void *q)
|
||||
{
|
||||
(void)ifq;
|
||||
(void)q;
|
||||
}
|
||||
|
||||
void
|
||||
ifq_destroy(struct ifqueue *ifq)
|
||||
{
|
||||
@@ -423,19 +447,3 @@ ifq_hdatalen(struct ifqueue *ifq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------- scheduler back ends (milestone M5) ---------------- */
|
||||
/* The staged OpenBSD hfsc.c/fq_codel.c are not in the build yet; the priq
|
||||
* ops above are the active scheduler. These wrappers keep pf_ioctl's
|
||||
* initialisation calls valid until M5 replaces them with the ported
|
||||
* schedulers (docs/porting-notes.md). */
|
||||
void
|
||||
hfsc_initialize(void)
|
||||
{
|
||||
pr_info("pfk: hfsc back end pending M5 (priq active)\n");
|
||||
}
|
||||
|
||||
void
|
||||
fq_codel_initialize(void)
|
||||
{
|
||||
pr_info("pfk: fq_codel back end pending M5 (priq active)\n");
|
||||
}
|
||||
@@ -607,3 +607,14 @@ pfk_mbuf_exit(void)
|
||||
{
|
||||
kmem_cache_destroy(pfk_mbuf_cache);
|
||||
}
|
||||
|
||||
void
|
||||
ml_purge(struct mbuf_list *ml)
|
||||
{
|
||||
struct mbuf *m;
|
||||
|
||||
while ((m = ml_dequeue(ml)) != NULL)
|
||||
m_freem(m);
|
||||
ml->ml_first = ml->ml_last = NULL;
|
||||
ml->ml_len = 0;
|
||||
}
|
||||
@@ -1212,5 +1212,94 @@ struct pfk_pflog_stat {
|
||||
};
|
||||
#define PFKIOCGETPFLOGSTAT _IOR('L', 1, struct pfk_pflog_stat)
|
||||
|
||||
|
||||
/*
|
||||
* Pieces the staged scheduler back ends (fq_codel(4)/hfsc(4) ports) need from
|
||||
* OpenBSD <net/if_var.h>, <net/if_fq_codel.h> and <net/if_hfsc.h>.
|
||||
*/
|
||||
#ifndef nsecuptime
|
||||
#define nsecuptime() getnsecuptime()
|
||||
#endif
|
||||
|
||||
struct fqcodel_pktcntr { uint64_t packets; uint64_t bytes; };
|
||||
struct hfsc_pktcntr { uint64_t packets; uint64_t bytes; };
|
||||
|
||||
struct fqcodel_stats {
|
||||
struct fqcodel_pktcntr xmit_cnt;
|
||||
struct fqcodel_pktcntr drop_cnt;
|
||||
uint32_t target, interval, tc_interval_drop;
|
||||
uint32_t rcvtime, mtu, qlimit, qlength;
|
||||
uint64_t delaysum, delaysumsq;
|
||||
uint8_t ecn, limit, flows, lscroll, flags;
|
||||
};
|
||||
|
||||
/* ifq scheduler hand-off (see pfsrc/ifq.c): enter returns the scheduler's
|
||||
* queue when it owns the interface queue, NULL otherwise. */
|
||||
void *ifq_q_enter(struct ifqueue *, const struct ifq_ops *);
|
||||
void ifq_q_leave(struct ifqueue *, void *);
|
||||
|
||||
|
||||
/*
|
||||
* OpenBSD <net/if_hfsc.h> pieces the staged hfsc(4) back end needs.
|
||||
* PFLINUX: the port keeps the BSD scheduler sources verbatim, so the
|
||||
* user-visible service curve, the class-stats record and the class-table
|
||||
* limits live here instead of in a separate kernel header.
|
||||
*/
|
||||
struct hfsc_sc { /* user-supplied service curve */
|
||||
u_int64_t m1; /* slope1 (bytes/sec) */
|
||||
u_int64_t d; /* ordinate of the knee (us) */
|
||||
u_int64_t m2; /* slope2 (bytes/sec) */
|
||||
};
|
||||
|
||||
struct hfsc_class_stats {
|
||||
u_int class_id;
|
||||
u_int32_t class_handle;
|
||||
struct hfsc_sc rsc, fsc, usc;
|
||||
u_int64_t total, cumul;
|
||||
u_int64_t d, e, vt, f;
|
||||
u_int64_t initvt, vtperiod, parentperiod;
|
||||
int nactive;
|
||||
u_int64_t vtoff, cvtmax, myf, cfmin, cvtmin, myfadj, vtadj;
|
||||
u_int period;
|
||||
struct hfsc_pktcntr xmit_cnt, drop_cnt;
|
||||
u_int64_t cur_time;
|
||||
u_int64_t machclk_freq;
|
||||
int qlength;
|
||||
int qlimit;
|
||||
int qtype;
|
||||
};
|
||||
|
||||
/* OpenBSD's global nanoseconds-per-clocktick (HFSC_CLK_PER_TICK). The port
|
||||
* has no clock_rate machinery, so derive it from the kernel's HZ. */
|
||||
#ifndef tick_nsec
|
||||
#define tick_nsec (1000000000LL / HZ)
|
||||
#endif
|
||||
|
||||
#define HFSC_ROOT_CLASS 0x1 /* root class of the tree */
|
||||
#define HFSC_DEFAULTCLASS 0x8 /* auto-created default class */
|
||||
#define HFSC_MAX_CLASSES 64
|
||||
#define HFSC_DEFAULT_CLASSES 8
|
||||
#define HFSC_DEFAULT_QLIMIT 1000
|
||||
|
||||
/*
|
||||
* PFLINUX notes on the scheduler back ends:
|
||||
*
|
||||
* - splnet()/splx(): OpenBSD raises the software interrupt level around
|
||||
* class-table surgery. This port runs the whole data path in one ordered
|
||||
* work queue and guards the queue with ifq_mtx, so these are no-ops; they
|
||||
* are kept as markers of the critical regions.
|
||||
* - KERNEL_ASSERT_LOCKED(): the schedulers are only reached from ifq/pf paths
|
||||
* that already hold the queue mutex; asserted structurally, not by spl.
|
||||
* - HFSC_ENABLED(): the scheduler owns the interface queue once it attached
|
||||
* its private state through ifq_q_enter().
|
||||
*/
|
||||
#define splnet() 0
|
||||
#define splx(s) ((void)(s))
|
||||
#define KERNEL_ASSERT_LOCKED() do { } while (0)
|
||||
#define HFSC_ENABLED(_ifq) ((_ifq)->ifq_q != NULL)
|
||||
|
||||
#define PKTCNTR_INC(_c, _len) do { (_c)->packets++; (_c)->bytes += (_len); } \
|
||||
while (0)
|
||||
|
||||
#endif /* _PFK_H */
|
||||
|
||||
@@ -74,6 +74,79 @@ ml_dequeue(struct mbuf_list *ml)
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/* BSD <net/if_var.h> mbuf_list helpers (net/if_var.h ml_*) */
|
||||
static inline void
|
||||
ml_init(struct mbuf_list *ml)
|
||||
{
|
||||
ml->ml_first = ml->ml_last = NULL;
|
||||
ml->ml_len = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ml_enqueue(struct mbuf_list *ml, struct mbuf *m)
|
||||
{
|
||||
m->m_next = NULL;
|
||||
if (ml->ml_last == NULL)
|
||||
ml->ml_first = m;
|
||||
else
|
||||
ml->ml_last->m_next = m;
|
||||
ml->ml_last = m;
|
||||
ml->ml_len++;
|
||||
}
|
||||
|
||||
static inline struct mbuf *
|
||||
ml_dequeue_tail(struct mbuf_list *ml)
|
||||
{
|
||||
struct mbuf *m, *prev = NULL;
|
||||
|
||||
if (ml->ml_first == NULL)
|
||||
return NULL;
|
||||
for (m = ml->ml_first; m->m_next; m = m->m_next)
|
||||
prev = m;
|
||||
if (prev == NULL) /* single element */
|
||||
ml->ml_first = NULL;
|
||||
else
|
||||
prev->m_next = NULL;
|
||||
ml->ml_last = prev;
|
||||
ml->ml_len--;
|
||||
m->m_next = NULL;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* append every packet in m2 to m1 (m2 becomes empty) */
|
||||
static inline void
|
||||
ml_enlist(struct mbuf_list *m1, struct mbuf_list *m2)
|
||||
{
|
||||
if (m2->ml_first == NULL)
|
||||
return;
|
||||
if (m1->ml_last == NULL)
|
||||
m1->ml_first = m2->ml_first;
|
||||
else
|
||||
m1->ml_last->m_next = m2->ml_first;
|
||||
m1->ml_last = m2->ml_last;
|
||||
m1->ml_len += m2->ml_len;
|
||||
m2->ml_first = m2->ml_last = NULL;
|
||||
m2->ml_len = 0;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ml_len(const struct mbuf_list *ml)
|
||||
{
|
||||
return (unsigned int)ml->ml_len;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ml_empty(const struct mbuf_list *ml)
|
||||
{
|
||||
return ml->ml_first == NULL;
|
||||
}
|
||||
|
||||
void ml_purge(struct mbuf_list *ml); /* compat/pfk_mbuf.c (needs m_freem) */
|
||||
|
||||
#define MBUF_LIST_FIRST(_ml) ((_ml)->ml_first)
|
||||
#define MBUF_LIST_INITIALIZER() { NULL, NULL, 0 }
|
||||
|
||||
/* egress interface (default-route dev), maintained on fib/net events */
|
||||
struct pfk_ifnet *pfk_egress_if(void);
|
||||
void pfk_egress_refresh(void);
|
||||
|
||||
@@ -73,7 +73,7 @@ struct pkthdr {
|
||||
u_int32_t ph_flowid;
|
||||
u_int ph_ifidx;
|
||||
u_int ph_rtableid;
|
||||
struct pfk_timeval ph_timestamp;
|
||||
int64_t ph_timestamp; /* OpenBSD 8.0: nanoseconds */
|
||||
struct pfk_ifnet *ifp;
|
||||
struct pfk_ifnet *rcvif;
|
||||
u_short ph; /* tso segs: unused, kept as pad */
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -332,7 +332,9 @@ control_law(struct codel *cd, struct codel_params *cp, int64_t rts)
|
||||
unsigned int idx;
|
||||
|
||||
KASSERT(cd->drops > 0);
|
||||
idx = min(cd->drops - 1, nitems(codel_intervals) - 1);
|
||||
/* PFLINUX: Linux' min() type-checks its arguments; nitems() is size_t */
|
||||
idx = min_t(unsigned int, cd->drops - 1,
|
||||
(unsigned int)(nitems(codel_intervals) - 1));
|
||||
cd->next = rts + cp->intervals[idx];
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -335,9 +335,9 @@ hfsc_class_purge(struct hfsc_class *cl, struct mbuf_list *ml)
|
||||
}
|
||||
|
||||
static inline u_int
|
||||
hfsc_more_slots(u_int current)
|
||||
hfsc_more_slots(u_int cur) /* PFLINUX: 'current' is a kernel macro */
|
||||
{
|
||||
u_int want = current * 2;
|
||||
u_int want = cur * 2;
|
||||
|
||||
return (want > HFSC_MAX_CLASSES ? HFSC_MAX_CLASSES : want);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user