pf: store state creation/expiration timestamps with milisecond precision

The primary beneficiary is pflow(4), which expects milisecond precision
in timestamps.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D43112
This commit is contained in:
Kristof Provost 2023-12-07 14:35:11 +01:00
parent 6bd36d1cf4
commit 0493260115
8 changed files with 47 additions and 32 deletions

View file

@ -1061,8 +1061,8 @@ struct pf_kstate {
struct pf_ksrc_node *nat_src_node;
u_int64_t packets[2];
u_int64_t bytes[2];
u_int32_t creation;
u_int32_t expire;
u_int64_t creation;
u_int64_t expire;
u_int32_t pfsync_time;
struct pf_rule_actions act;
u_int16_t tag;
@ -2238,6 +2238,22 @@ pf_release_staten(struct pf_kstate *s, u_int n)
return (0);
}
static __inline uint64_t
pf_get_uptime(void)
{
struct timeval t;
microuptime(&t);
return ((t.tv_sec * 1000) + (t.tv_usec / 1000));
}
static __inline uint64_t
pf_get_time(void)
{
struct timeval t;
microtime(&t);
return ((t.tv_sec * 1000) + (t.tv_usec / 1000));
}
extern struct pf_kstate *pf_find_state_byid(uint64_t, uint32_t);
extern struct pf_kstate *pf_find_state_all(struct pf_state_key_cmp *,
u_int, int *);

View file

@ -611,8 +611,8 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)
/* copy to state */
bcopy(&sp->pfs_1301.rt_addr, &st->rt_addr, sizeof(st->rt_addr));
st->creation = time_uptime - ntohl(sp->pfs_1301.creation);
st->expire = time_uptime;
st->creation = (time_uptime - ntohl(sp->pfs_1301.creation)) * 1000;
st->expire = pf_get_uptime();
if (sp->pfs_1301.expire) {
uint32_t timeout;
@ -621,7 +621,7 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version)
timeout = V_pf_default_rule.timeout[sp->pfs_1301.timeout];
/* sp->expire may have been adaptively scaled by export. */
st->expire -= timeout - ntohl(sp->pfs_1301.expire);
st->expire -= (timeout - ntohl(sp->pfs_1301.expire)) * 1000;
}
st->direction = sp->pfs_1301.direction;
@ -1198,7 +1198,7 @@ pfsync_in_upd(struct mbuf *m, int offset, int count, int flags, int action)
if (sync < 2) {
pfsync_alloc_scrub_memory(&sp->pfs_1301.dst, &st->dst);
pf_state_peer_ntoh(&sp->pfs_1301.dst, &st->dst);
st->expire = time_uptime;
st->expire = pf_get_uptime();
st->timeout = sp->pfs_1301.timeout;
}
st->pfsync_time = time_uptime;
@ -1285,7 +1285,7 @@ pfsync_in_upd_c(struct mbuf *m, int offset, int count, int flags, int action)
if (sync < 2) {
pfsync_alloc_scrub_memory(&up->dst, &st->dst);
pf_state_peer_ntoh(&up->dst, &st->dst);
st->expire = time_uptime;
st->expire = pf_get_uptime();
st->timeout = up->timeout;
}
st->pfsync_time = time_uptime;

View file

@ -2037,12 +2037,12 @@ pf_state_expires(const struct pf_kstate *state)
if (states < end) {
timeout = (u_int64_t)timeout * (end - states) /
(end - start);
return (state->expire + timeout);
return ((state->expire / 1000) + timeout);
}
else
return (time_uptime);
}
return (state->expire + timeout);
return ((state->expire / 1000) + timeout);
}
void
@ -4951,8 +4951,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
s->rt = r->rt;
}
s->creation = time_uptime;
s->expire = time_uptime;
s->creation = s->expire = pf_get_uptime();
if (sn != NULL)
s->src_node = sn;
@ -5426,7 +5425,7 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
pf_set_protostate(*state, PF_PEER_BOTH, TCPS_TIME_WAIT);
/* update expire time */
(*state)->expire = time_uptime;
(*state)->expire = pf_get_uptime();
if (src->state >= TCPS_FIN_WAIT_2 &&
dst->state >= TCPS_FIN_WAIT_2)
(*state)->timeout = PFTM_TCP_CLOSED;
@ -5622,7 +5621,7 @@ pf_tcp_track_sloppy(struct pf_kstate **state, struct pf_pdesc *pd, u_short *reas
pf_set_protostate(*state, PF_PEER_BOTH, TCPS_TIME_WAIT);
/* update expire time */
(*state)->expire = time_uptime;
(*state)->expire = pf_get_uptime();
if (src->state >= TCPS_FIN_WAIT_2 &&
dst->state >= TCPS_FIN_WAIT_2)
(*state)->timeout = PFTM_TCP_CLOSED;
@ -5870,7 +5869,7 @@ pf_test_state_udp(struct pf_kstate **state, struct pfi_kkif *kif,
pf_set_protostate(*state, pdst, PFUDPS_MULTIPLE);
/* update expire time */
(*state)->expire = time_uptime;
(*state)->expire = pf_get_uptime();
if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE)
(*state)->timeout = PFTM_UDP_MULTIPLE;
else
@ -5971,7 +5970,7 @@ pf_test_state_sctp(struct pf_kstate **state, struct pfi_kkif *kif,
return (PF_DROP);
}
(*state)->expire = time_uptime;
(*state)->expire = pf_get_uptime();
/* translate source/destination address, if necessary */
if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
@ -6478,7 +6477,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct pfi_kkif *kif,
STATE_LOOKUP(kif, &key, *state, pd);
(*state)->expire = time_uptime;
(*state)->expire = pf_get_uptime();
(*state)->timeout = PFTM_ICMP_ERROR_REPLY;
/* translate source/destination address, if necessary */
@ -7063,7 +7062,7 @@ pf_test_state_other(struct pf_kstate **state, struct pfi_kkif *kif,
pf_set_protostate(*state, pdst, PFOTHERS_MULTIPLE);
/* update expire time */
(*state)->expire = time_uptime;
(*state)->expire = pf_get_uptime();
if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE)
(*state)->timeout = PFTM_OTHER_MULTIPLE;
else

View file

@ -5483,7 +5483,7 @@ pfsync_state_export(union pfsync_state_union *sp, struct pf_kstate *st, int msg_
/* copy from state */
strlcpy(sp->pfs_1301.ifname, st->kif->pfik_name, sizeof(sp->pfs_1301.ifname));
bcopy(&st->rt_addr, &sp->pfs_1301.rt_addr, sizeof(sp->pfs_1301.rt_addr));
sp->pfs_1301.creation = htonl(time_uptime - st->creation);
sp->pfs_1301.creation = htonl(time_uptime - (st->creation / 1000));
sp->pfs_1301.expire = pf_state_expires(st);
if (sp->pfs_1301.expire <= time_uptime)
sp->pfs_1301.expire = htonl(0);
@ -5574,7 +5574,7 @@ pf_state_export(struct pf_state_export *sp, struct pf_kstate *st)
strlcpy(sp->orig_ifname, st->orig_kif->pfik_name,
sizeof(sp->orig_ifname));
bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
sp->creation = htonl(time_uptime - st->creation);
sp->creation = htonl(time_uptime - (st->creation / 1000));
sp->expire = pf_state_expires(st);
if (sp->expire <= time_uptime)
sp->expire = htonl(0);

View file

@ -169,7 +169,7 @@ dump_state(struct nlpcb *nlp, const struct nlmsghdr *hdr, struct pf_kstate *s,
nlattr_add_string(nw, PF_ST_IFNAME, s->kif->pfik_name);
nlattr_add_string(nw, PF_ST_ORIG_IFNAME, s->orig_kif->pfik_name);
dump_addr(nw, PF_ST_RT_ADDR, &s->rt_addr, af);
nlattr_add_u32(nw, PF_ST_CREATION, time_uptime - s->creation);
nlattr_add_u32(nw, PF_ST_CREATION, time_uptime - (s->creation / 1000));
uint32_t expire = pf_state_expires(s);
if (expire > time_uptime)
expire = expire - time_uptime;

View file

@ -1745,7 +1745,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
getmicrouptime(&uptime);
if (src->scrub && (src->scrub->pfss_flags & PFSS_PAWS) &&
(uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
time_uptime - state->creation > TS_MAX_CONN)) {
time_uptime - (state->creation / 1000) > TS_MAX_CONN)) {
if (V_pf_status.debug >= PF_DEBUG_MISC) {
DPFPRINTF(("src idled out of PAWS\n"));
pf_print_state(state);

View file

@ -974,7 +974,7 @@ pf_state_to_nvstate(const struct pf_kstate *s)
s->anchor.ptr ? s->anchor.ptr->nr : -1);
nvlist_add_number(nvl, "nat_rule",
s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1);
nvlist_add_number(nvl, "creation", s->creation);
nvlist_add_number(nvl, "creation", s->creation / 1000);
expire = pf_state_expires(s);
if (expire <= time_uptime)

View file

@ -543,9 +543,9 @@ copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2,
* or was created / expired before this machine came up due to pfsync.
*/
flow1->flow_start = flow2->flow_start = st->creation < 0 ||
st->creation > st->expire ? htonl(0) : htonl(st->creation * 1000);
st->creation > st->expire ? htonl(0) : htonl(st->creation);
flow1->flow_finish = flow2->flow_finish = st->expire < 0 ? htonl(0) :
htonl(st->expire * 1000);
htonl(st->expire);
flow1->tcp_flags = flow2->tcp_flags = 0;
flow1->protocol = flow2->protocol = sk->proto;
flow1->tos = flow2->tos = st->rule.ptr->tos;
@ -579,10 +579,10 @@ copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1,
flow1->flow_start = flow2->flow_start = htobe64((time_second -
time_uptime)*1000);
else
flow1->flow_start = flow2->flow_start = htobe64((time_second -
(time_uptime - st->creation))*1000);
flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
(time_uptime - st->expire))*1000);
flow1->flow_start = flow2->flow_start = htobe64((pf_get_time() -
(pf_get_uptime() - st->creation)));
flow1->flow_finish = flow2->flow_finish = htobe64((pf_get_time() -
(pf_get_uptime() - st->expire)));
flow1->protocol = flow2->protocol = sk->proto;
flow1->tos = flow2->tos = st->rule.ptr->tos;
@ -618,10 +618,10 @@ copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1,
flow1->flow_start = flow2->flow_start = htobe64((time_second -
time_uptime)*1000);
else
flow1->flow_start = flow2->flow_start = htobe64((time_second -
(time_uptime - st->creation))*1000);
flow1->flow_finish = flow2->flow_finish = htobe64((time_second -
(time_uptime - st->expire))*1000);
flow1->flow_start = flow2->flow_start = htobe64((pf_get_time() -
(pf_get_uptime() - st->creation)));
flow1->flow_finish = flow2->flow_finish = htobe64((pf_get_time() -
(pf_get_uptime() - st->expire)));
flow1->protocol = flow2->protocol = sk->proto;
flow1->tos = flow2->tos = st->rule.ptr->tos;