Download raw body.
pfctl show fragment info
On Fri, Apr 19, 2024 at 08:12:08PM +0200, Claudio Jeker wrote:
> On Fri, Apr 19, 2024 at 07:43:05PM +0200, Alexander Bluhm wrote:
> > Hi,
> >
> > I would like to show pf fragment reassembly counters.
> >
> > # pfctl -si -v
> > ...
> > Fragments
> > current entries 26
> > searches 1055 0.3/s
> > inserts 1037 0.3/s
> > removals 1011 0.3/s
> >
> > ok?
>
> Please also add it to systat(1) which uses sysctl and kern.pfstatus.
fragment Count 30
fragment searches 417 2.78
fragment inserts 414 2.76
fragment removals 384 2.56
ok?
bluhm
Index: sys/net/pf_ioctl.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_ioctl.c,v
diff -u -p -r1.415 pf_ioctl.c
--- sys/net/pf_ioctl.c 6 Jul 2023 04:55:05 -0000 1.415
+++ sys/net/pf_ioctl.c 19 Apr 2024 18:35:47 -0000
@@ -1955,6 +1955,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
struct pf_status *s = (struct pf_status *)addr;
NET_LOCK();
PF_LOCK();
+ PF_FRAG_LOCK();
+ pf_status.fragments = pf_nfrents;
+ memcpy(pf_status.ncounters, pf_nfrentcounters,
+ sizeof(pf_status.ncounters));
+ PF_FRAG_UNLOCK();
memcpy(s, &pf_status, sizeof(struct pf_status));
pfi_update_status(s->ifname, s);
PF_UNLOCK();
@@ -1996,6 +2001,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
memset(pf_status.counters, 0, sizeof(pf_status.counters));
memset(pf_status.fcounters, 0, sizeof(pf_status.fcounters));
memset(pf_status.scounters, 0, sizeof(pf_status.scounters));
+ memset(pf_status.ncounters, 0, sizeof(pf_status.ncounters));
+ PF_FRAG_LOCK();
+ memset(pf_nfrentcounters, 0, sizeof(pf_nfrentcounters));
+ PF_FRAG_UNLOCK();
pf_status.since = getuptime();
PF_UNLOCK();
@@ -3271,6 +3280,11 @@ pf_sysctl(void *oldp, size_t *oldlenp, v
NET_LOCK_SHARED();
PF_LOCK();
+ PF_FRAG_LOCK();
+ pf_status.fragments = pf_nfrents;
+ memcpy(pf_status.ncounters, pf_nfrentcounters,
+ sizeof(pf_status.ncounters));
+ PF_FRAG_UNLOCK();
memcpy(&pfs, &pf_status, sizeof(struct pf_status));
pfi_update_status(pfs.ifname, &pfs);
PF_UNLOCK();
Index: sys/net/pf_norm.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_norm.c,v
diff -u -p -r1.229 pf_norm.c
--- sys/net/pf_norm.c 10 Oct 2023 11:25:31 -0000 1.229
+++ sys/net/pf_norm.c 19 Apr 2024 18:18:21 -0000
@@ -150,13 +150,12 @@ int pf_reassemble6(struct mbuf **, st
/* Globals */
struct pool pf_frent_pl, pf_frag_pl, pf_frnode_pl;
struct pool pf_state_scrub_pl;
-int pf_nfrents;
+uint32_t pf_nfrents;
+uint64_t pf_nfrentcounters[NCNT_MAX];
struct mutex pf_frag_mtx;
#define PF_FRAG_LOCK_INIT() mtx_init(&pf_frag_mtx, IPL_SOFTNET)
-#define PF_FRAG_LOCK() mtx_enter(&pf_frag_mtx)
-#define PF_FRAG_UNLOCK() mtx_leave(&pf_frag_mtx)
void
pf_normalize_init(void)
@@ -233,7 +232,7 @@ void
pf_flush_fragments(void)
{
struct pf_fragment *frag;
- int goal;
+ u_int goal;
goal = pf_nfrents * 9 / 10;
DPFPRINTF(LOG_NOTICE, "trying to free > %d frents", pf_nfrents - goal);
@@ -268,6 +267,7 @@ pf_free_fragment(struct pf_fragment *fra
/* Free all fragment entries */
while ((frent = TAILQ_FIRST(&frag->fr_queue)) != NULL) {
TAILQ_REMOVE(&frag->fr_queue, frent, fr_next);
+ pf_nfrentcounters[NCNT_FRAG_REMOVALS]++;
m_freem(frent->fe_m);
pool_put(&pf_frent_pl, frent);
pf_nfrents--;
@@ -283,6 +283,7 @@ pf_find_fragment(struct pf_frnode *key,
u_int32_t stale;
frnode = RB_FIND(pf_frnode_tree, &pf_frnode_tree, key);
+ pf_nfrentcounters[NCNT_FRAG_SEARCH]++;
if (frnode == NULL)
return (NULL);
KASSERT(frnode->fn_fragments >= 1);
@@ -405,6 +406,7 @@ pf_frent_insert(struct pf_fragment *frag
KASSERT(prev->fe_off + prev->fe_len <= frent->fe_off);
TAILQ_INSERT_AFTER(&frag->fr_queue, prev, frent, fr_next);
}
+ pf_nfrentcounters[NCNT_FRAG_INSERT]++;
if (frag->fr_firstoff[index] == NULL) {
KASSERT(prev == NULL || pf_frent_index(prev) < index);
@@ -456,6 +458,7 @@ pf_frent_remove(struct pf_fragment *frag
}
TAILQ_REMOVE(&frag->fr_queue, frent, fr_next);
+ pf_nfrentcounters[NCNT_FRAG_REMOVALS]++;
KASSERT(frag->fr_entries[index] > 0);
frag->fr_entries[index]--;
@@ -742,6 +745,7 @@ pf_join_fragment(struct pf_fragment *fra
frent = TAILQ_FIRST(&frag->fr_queue);
TAILQ_REMOVE(&frag->fr_queue, frent, fr_next);
+ pf_nfrentcounters[NCNT_FRAG_REMOVALS]++;
m = frent->fe_m;
/* Strip off any trailing bytes */
@@ -756,6 +760,7 @@ pf_join_fragment(struct pf_fragment *fra
while ((frent = TAILQ_FIRST(&frag->fr_queue)) != NULL) {
TAILQ_REMOVE(&frag->fr_queue, frent, fr_next);
+ pf_nfrentcounters[NCNT_FRAG_REMOVALS]++;
m2 = frent->fe_m;
/* Strip off ip header */
m_adj(m2, frent->fe_hdrlen);
Index: sys/net/pfvar.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pfvar.h,v
diff -u -p -r1.535 pfvar.h
--- sys/net/pfvar.h 1 Jan 2024 22:16:51 -0000 1.535
+++ sys/net/pfvar.h 19 Apr 2024 18:18:21 -0000
@@ -1192,6 +1192,11 @@ enum pfi_kif_refs {
#define SCNT_SRC_NODE_REMOVALS 2
#define SCNT_MAX 3
+#define NCNT_FRAG_SEARCH 0
+#define NCNT_FRAG_INSERT 1
+#define NCNT_FRAG_REMOVALS 2
+#define NCNT_MAX 3
+
#define REASON_SET(a, x) \
do { \
if ((void *)(a) != NULL) { \
@@ -1206,6 +1211,7 @@ struct pf_status {
u_int64_t lcounters[LCNT_MAX]; /* limit counters */
u_int64_t fcounters[FCNT_MAX];
u_int64_t scounters[SCNT_MAX];
+ u_int64_t ncounters[NCNT_MAX];
u_int64_t pcounters[2][2][3];
u_int64_t bcounters[2][2];
u_int64_t stateid;
@@ -1215,6 +1221,7 @@ struct pf_status {
u_int32_t states;
u_int32_t states_halfopen;
u_int32_t src_nodes;
+ u_int32_t fragments;
u_int32_t debug;
u_int32_t hostid;
u_int32_t reass; /* reassembly */
Index: sys/net/pfvar_priv.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pfvar_priv.h,v
diff -u -p -r1.35 pfvar_priv.h
--- sys/net/pfvar_priv.h 1 Jan 2024 22:16:51 -0000 1.35
+++ sys/net/pfvar_priv.h 19 Apr 2024 18:37:27 -0000
@@ -368,8 +368,12 @@ extern struct timeout pf_purge_to;
struct pf_state *pf_state_ref(struct pf_state *);
void pf_state_unref(struct pf_state *);
+extern uint32_t pf_nfrents;
+extern uint64_t pf_nfrentcounters[NCNT_MAX];
+
extern struct rwlock pf_lock;
extern struct rwlock pf_state_lock;
+extern struct mutex pf_frag_mtx;
extern struct mutex pf_inp_mtx;
#define PF_LOCK() do { \
@@ -414,6 +418,9 @@ extern struct mutex pf_inp_mtx;
splassert_fail(RW_WRITE, \
rw_status(&pf_state_lock), __func__);\
} while (0)
+
+#define PF_FRAG_LOCK() mtx_enter(&pf_frag_mtx)
+#define PF_FRAG_UNLOCK() mtx_leave(&pf_frag_mtx)
/* for copies to/from network byte order */
void pf_state_peer_hton(const struct pf_state_peer *,
Index: sbin/pfctl/pfctl_parser.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sbin/pfctl/pfctl_parser.c,v
diff -u -p -r1.350 pfctl_parser.c
--- sbin/pfctl/pfctl_parser.c 7 Feb 2024 23:53:44 -0000 1.350
+++ sbin/pfctl/pfctl_parser.c 19 Apr 2024 12:53:03 -0000
@@ -519,7 +519,8 @@ print_pool(struct pf_pool *pool, u_int16
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
-const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
+const char *pf_scounters[SCNT_MAX+1] = FCNT_NAMES;
+const char *pf_ncounters[NCNT_MAX+1] = FCNT_NAMES;
void
print_status(struct pf_status *s, struct pfctl_watermarks *synflwats, int opts)
@@ -613,6 +614,20 @@ print_status(struct pf_status *s, struct
if (runtime > 0)
printf("%14.1f/s\n",
(double)s->scounters[i] / (double)runtime);
+ else
+ printf("%14s\n", "");
+ }
+ }
+ if (opts & PF_OPT_VERBOSE) {
+ printf("Fragments\n");
+ printf(" %-25s %14u %14s\n", "current entries",
+ s->fragments, "");
+ for (i = 0; i < NCNT_MAX; i++) {
+ printf(" %-25s %14lld ", pf_ncounters[i],
+ s->ncounters[i]);
+ if (runtime > 0)
+ printf("%14.1f/s\n",
+ (double)s->ncounters[i] / (double)runtime);
else
printf("%14s\n", "");
}
Index: usr.bin/systat/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.bin/systat/pf.c,v
diff -u -p -r1.13 pf.c
--- usr.bin/systat/pf.c 14 Sep 2020 11:15:30 -0000 1.13
+++ usr.bin/systat/pf.c 19 Apr 2024 18:31:07 -0000
@@ -44,7 +44,8 @@ void print_fld_double(field_def *, doubl
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
-const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
+const char *pf_scounters[SCNT_MAX+1] = FCNT_NAMES;
+const char *pf_ncounters[NCNT_MAX+1] = FCNT_NAMES;
static struct pf_status status;
int num_pf = 0;
@@ -104,6 +105,7 @@ read_pf(void)
num_disp += FCNT_MAX + 2;
num_disp += SCNT_MAX + 2;
+ num_disp += NCNT_MAX + 2;
num_disp += PFRES_MAX + 1;
num_disp += LCNT_MAX + 1;
@@ -294,6 +296,17 @@ print_pf(void)
(double)s->scounters[i] / (double)tm);
else
ADD_LINE_V("src track", pf_scounters[i], s->scounters[i]);
+ }
+
+ ADD_EMPTY_LINE;
+ ADD_LINE_V("fragment", "Count", s->fragments);
+
+ for (i = 0; i < NCNT_MAX; i++) {
+ if (tm > 0)
+ ADD_LINE_VR("fragment", pf_ncounters[i], s->ncounters[i],
+ (double)s->ncounters[i] / (double)tm);
+ else
+ ADD_LINE_V("fragment", pf_ncounters[i], s->ncounters[i]);
}
ADD_EMPTY_LINE;
pfctl show fragment info