Index: sys/net/pfvar.h =================================================================== --- sys/net/pfvar.h +++ sys/net/pfvar.h @@ -1402,6 +1402,7 @@ #define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface) #define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill) #define DIOCKEEPCOUNTERS _IOWR('D', 92, struct pfioc_nv) +#define DIOCGETSTATESSTATSNV _IOWR('D', 93, struct pfioc_nv) struct pf_ifspeed_v0 { char ifname[IFNAMSIZ]; Index: sys/netpfil/pf/pf_ioctl.c =================================================================== --- sys/netpfil/pf/pf_ioctl.c +++ sys/netpfil/pf/pf_ioctl.c @@ -140,6 +140,8 @@ #define V_pf_altq_running VNET(pf_altq_running) #endif +#define PFNV_STATE_SIZE_ESTIMATE 2048 + #define TAGID_MAX 50000 struct pf_tagname { TAILQ_ENTRY(pf_tagname) namehash_entries; @@ -209,6 +211,7 @@ static int pf_clearstates_nv(struct pfioc_nv *); static int pf_getstate(struct pfioc_nv *); static int pf_getstates(struct pfioc_nv *); +static int pf_getstatesstats(struct pfioc_nv *); static int pf_clear_tables(void); static void pf_clear_srcnodes(struct pf_ksrc_node *); static void pf_kill_srcnodes(struct pfioc_src_node_kill *); @@ -2109,6 +2112,7 @@ case DIOCSETDEBUG: case DIOCGETSTATES: case DIOCGETSTATESNV: + case DIOCGETSTATESSTATSNV: case DIOCGETTIMEOUT: case DIOCCLRRULECTRS: case DIOCGETLIMIT: @@ -2162,6 +2166,7 @@ case DIOCGETSTATUS: case DIOCGETSTATES: case DIOCGETSTATESNV: + case DIOCGETSTATESSTATSNV: case DIOCGETTIMEOUT: case DIOCGETLIMIT: case DIOCGETALTQSV0: @@ -2876,6 +2881,11 @@ break; } + case DIOCGETSTATESSTATSNV: { + error = pf_getstatesstats((struct pfioc_nv *)addr); + break; + } + case DIOCGETSTATUS: { struct pf_status *s = (struct pf_status *)addr; @@ -5118,6 +5128,40 @@ return (error); } +static int +pf_getstatesstats(struct pfioc_nv *nv) +{ + nvlist_t *nvl; + void *nvlpacked = NULL; + int error = 0; + +#define ERROUT(x) ERROUT_FUNCTION(errout, x) + + nvl = nvlist_create(0); + if (nvl == NULL) + ERROUT(ENOMEM); + + nvlist_add_number(nvl, "states", uma_zone_get_cur(V_pf_state_z)); + nvlist_add_number(nvl, "state_size_hint", PFNV_STATE_SIZE_ESTIMATE); + + nvlpacked = nvlist_pack(nvl, &nv->len); + if (nvlpacked == NULL) + ERROUT(ENOMEM); + + if (nv->size == 0) + ERROUT(0); + else if (nv->size < nv->len) + ERROUT(ENOSPC); + + error = copyout(nvlpacked, nv->data, nv->len); + +#undef ERROUT +errout: + free(nvlpacked, M_NVLIST); + nvlist_destroy(nvl); + return (error); +} + /* * XXX - Check for version missmatch!!! */