mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
pf: Add per-rule timestamps for rule and eth_rule
Similar to ipfw rule timestamps, these timestamps internally are uint32_t snaps of the system time in seconds. The timestamp is CPU local and updated each time a rule or a state associated with a rule or state is matched. Reviewed by: kp Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D34970
This commit is contained in:
parent
1452bfcd9b
commit
0abcc1d2d3
|
@ -512,6 +512,10 @@ pf_nvrule_to_rule(const nvlist_t *nvl, struct pfctl_rule *rule)
|
||||||
pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL);
|
pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL);
|
||||||
pf_nvuint_64_array(nvl, "bytes", 2, rule->bytes, NULL);
|
pf_nvuint_64_array(nvl, "bytes", 2, rule->bytes, NULL);
|
||||||
|
|
||||||
|
if (nvlist_exists_number(nvl, "timestamp")) {
|
||||||
|
rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp");
|
||||||
|
}
|
||||||
|
|
||||||
rule->os_fingerprint = nvlist_get_number(nvl, "os_fingerprint");
|
rule->os_fingerprint = nvlist_get_number(nvl, "os_fingerprint");
|
||||||
|
|
||||||
rule->rtableid = nvlist_get_number(nvl, "rtableid");
|
rule->rtableid = nvlist_get_number(nvl, "rtableid");
|
||||||
|
@ -642,6 +646,10 @@ pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule)
|
||||||
rule->bytes[0] = nvlist_get_number(nvl, "bytes-in");
|
rule->bytes[0] = nvlist_get_number(nvl, "bytes-in");
|
||||||
rule->bytes[1] = nvlist_get_number(nvl, "bytes-out");
|
rule->bytes[1] = nvlist_get_number(nvl, "bytes-out");
|
||||||
|
|
||||||
|
if (nvlist_exists_number(nvl, "timestamp")) {
|
||||||
|
rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp");
|
||||||
|
}
|
||||||
|
|
||||||
strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE);
|
strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE);
|
||||||
strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"),
|
strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"),
|
||||||
PF_TAG_NAME_SIZE);
|
PF_TAG_NAME_SIZE);
|
||||||
|
@ -737,7 +745,7 @@ pfctl_get_eth_rule(int dev, uint32_t nr, uint32_t ticket,
|
||||||
nvlist_add_number(nvl, "nr", nr);
|
nvlist_add_number(nvl, "nr", nr);
|
||||||
nvlist_add_bool(nvl, "clear", clear);
|
nvlist_add_bool(nvl, "clear", clear);
|
||||||
|
|
||||||
if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULE, 2048, &nvl)) != 0)
|
if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULE, 4096, &nvl)) != 0)
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|
||||||
pfctl_nveth_rule_to_eth_rule(nvl, rule);
|
pfctl_nveth_rule_to_eth_rule(nvl, rule);
|
||||||
|
|
|
@ -99,6 +99,7 @@ struct pfctl_eth_rule {
|
||||||
uint64_t evaluations;
|
uint64_t evaluations;
|
||||||
uint64_t packets[2];
|
uint64_t packets[2];
|
||||||
uint64_t bytes[2];
|
uint64_t bytes[2];
|
||||||
|
uint32_t last_active_timestamp;
|
||||||
|
|
||||||
/* Action */
|
/* Action */
|
||||||
char qname[PF_QNAME_SIZE];
|
char qname[PF_QNAME_SIZE];
|
||||||
|
@ -171,6 +172,7 @@ struct pfctl_rule {
|
||||||
uint64_t evaluations;
|
uint64_t evaluations;
|
||||||
uint64_t packets[2];
|
uint64_t packets[2];
|
||||||
uint64_t bytes[2];
|
uint64_t bytes[2];
|
||||||
|
uint32_t last_active_timestamp;
|
||||||
|
|
||||||
struct pfi_kif *kif;
|
struct pfi_kif *kif;
|
||||||
struct pfctl_anchor *anchor;
|
struct pfctl_anchor *anchor;
|
||||||
|
|
|
@ -1016,6 +1016,18 @@ pfctl_print_eth_rule_counters(struct pfctl_eth_rule *rule, int opts)
|
||||||
(unsigned long long)(rule->bytes[0] +
|
(unsigned long long)(rule->bytes[0] +
|
||||||
rule->bytes[1]));
|
rule->bytes[1]));
|
||||||
}
|
}
|
||||||
|
if (opts & PF_OPT_VERBOSE2) {
|
||||||
|
char timestr[30];
|
||||||
|
|
||||||
|
if (rule->last_active_timestamp != 0) {
|
||||||
|
time_t last_active = rule->last_active_timestamp;
|
||||||
|
bcopy(ctime(&last_active), timestr, sizeof(timestr));
|
||||||
|
*strchr(timestr, '\n') = '\0';
|
||||||
|
} else {
|
||||||
|
snprintf(timestr, sizeof(timestr), "N/A");
|
||||||
|
}
|
||||||
|
printf(" [ Last Active Time: %s ]\n", timestr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1055,6 +1067,17 @@ pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
|
||||||
(unsigned)rule->cuid, (unsigned)rule->cpid,
|
(unsigned)rule->cuid, (unsigned)rule->cpid,
|
||||||
(uintmax_t)rule->states_tot);
|
(uintmax_t)rule->states_tot);
|
||||||
}
|
}
|
||||||
|
if (opts & PF_OPT_VERBOSE2) {
|
||||||
|
char timestr[30];
|
||||||
|
if (rule->last_active_timestamp != 0) {
|
||||||
|
time_t last_active = rule->last_active_timestamp;
|
||||||
|
bcopy(ctime(&last_active), timestr, sizeof(timestr));
|
||||||
|
*strchr(timestr, '\n') = '\0';
|
||||||
|
} else {
|
||||||
|
snprintf(timestr, sizeof(timestr), "N/A");
|
||||||
|
}
|
||||||
|
printf(" [ Last Active Time: %s ]\n", timestr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -286,6 +286,26 @@ pf_counter_u64_zero(struct pf_counter_u64 *pfcu64)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define pf_get_timestamp(prule)({ \
|
||||||
|
uint32_t _ts = 0; \
|
||||||
|
uint32_t __ts; \
|
||||||
|
int cpu; \
|
||||||
|
CPU_FOREACH(cpu) { \
|
||||||
|
__ts = *zpcpu_get_cpu(prule->timestamp, cpu); \
|
||||||
|
if (__ts > _ts) \
|
||||||
|
_ts = __ts; \
|
||||||
|
} \
|
||||||
|
_ts; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define pf_update_timestamp(prule) \
|
||||||
|
do { \
|
||||||
|
critical_enter(); \
|
||||||
|
*zpcpu_get((prule)->timestamp) = time_second; \
|
||||||
|
critical_exit(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
SYSCTL_DECL(_net_pf);
|
SYSCTL_DECL(_net_pf);
|
||||||
MALLOC_DECLARE(M_PFHASH);
|
MALLOC_DECLARE(M_PFHASH);
|
||||||
|
|
||||||
|
@ -657,6 +677,7 @@ struct pf_keth_rule {
|
||||||
counter_u64_t evaluations;
|
counter_u64_t evaluations;
|
||||||
counter_u64_t packets[2];
|
counter_u64_t packets[2];
|
||||||
counter_u64_t bytes[2];
|
counter_u64_t bytes[2];
|
||||||
|
uint32_t *timestamp;
|
||||||
|
|
||||||
/* Action */
|
/* Action */
|
||||||
char qname[PF_QNAME_SIZE];
|
char qname[PF_QNAME_SIZE];
|
||||||
|
@ -696,6 +717,7 @@ struct pf_krule {
|
||||||
struct pf_counter_u64 evaluations;
|
struct pf_counter_u64 evaluations;
|
||||||
struct pf_counter_u64 packets[2];
|
struct pf_counter_u64 packets[2];
|
||||||
struct pf_counter_u64 bytes[2];
|
struct pf_counter_u64 bytes[2];
|
||||||
|
uint32_t *timestamp;
|
||||||
|
|
||||||
struct pfi_kkif *kif;
|
struct pfi_kkif *kif;
|
||||||
struct pf_kanchor *anchor;
|
struct pf_kanchor *anchor;
|
||||||
|
|
|
@ -3971,6 +3971,7 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0)
|
||||||
/* Execute action. */
|
/* Execute action. */
|
||||||
counter_u64_add(r->packets[dir == PF_OUT], 1);
|
counter_u64_add(r->packets[dir == PF_OUT], 1);
|
||||||
counter_u64_add(r->bytes[dir == PF_OUT], m_length(m, NULL));
|
counter_u64_add(r->bytes[dir == PF_OUT], m_length(m, NULL));
|
||||||
|
pf_update_timestamp(r);
|
||||||
|
|
||||||
/* Shortcut. Don't tag if we're just going to drop anyway. */
|
/* Shortcut. Don't tag if we're just going to drop anyway. */
|
||||||
if (r->action == PF_DROP) {
|
if (r->action == PF_DROP) {
|
||||||
|
@ -7198,6 +7199,8 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *
|
||||||
dirndx = (dir == PF_OUT);
|
dirndx = (dir == PF_OUT);
|
||||||
pf_counter_u64_add_protected(&r->packets[dirndx], 1);
|
pf_counter_u64_add_protected(&r->packets[dirndx], 1);
|
||||||
pf_counter_u64_add_protected(&r->bytes[dirndx], pd.tot_len);
|
pf_counter_u64_add_protected(&r->bytes[dirndx], pd.tot_len);
|
||||||
|
pf_update_timestamp(r);
|
||||||
|
|
||||||
if (a != NULL) {
|
if (a != NULL) {
|
||||||
pf_counter_u64_add_protected(&a->packets[dirndx], 1);
|
pf_counter_u64_add_protected(&a->packets[dirndx], 1);
|
||||||
pf_counter_u64_add_protected(&a->bytes[dirndx], pd.tot_len);
|
pf_counter_u64_add_protected(&a->bytes[dirndx], pd.tot_len);
|
||||||
|
|
|
@ -344,6 +344,8 @@ pfattach_vnet(void)
|
||||||
V_pf_default_rule.states_tot = counter_u64_alloc(M_WAITOK);
|
V_pf_default_rule.states_tot = counter_u64_alloc(M_WAITOK);
|
||||||
V_pf_default_rule.src_nodes = counter_u64_alloc(M_WAITOK);
|
V_pf_default_rule.src_nodes = counter_u64_alloc(M_WAITOK);
|
||||||
|
|
||||||
|
V_pf_default_rule.timestamp = uma_zalloc_pcpu(pcpu_zone_4, M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
#ifdef PF_WANT_32_TO_64_COUNTER
|
#ifdef PF_WANT_32_TO_64_COUNTER
|
||||||
V_pf_kifmarker = malloc(sizeof(*V_pf_kifmarker), PFI_MTYPE, M_WAITOK | M_ZERO);
|
V_pf_kifmarker = malloc(sizeof(*V_pf_kifmarker), PFI_MTYPE, M_WAITOK | M_ZERO);
|
||||||
V_pf_rulemarker = malloc(sizeof(*V_pf_rulemarker), M_PFRULE, M_WAITOK | M_ZERO);
|
V_pf_rulemarker = malloc(sizeof(*V_pf_rulemarker), M_PFRULE, M_WAITOK | M_ZERO);
|
||||||
|
@ -530,6 +532,7 @@ pf_free_eth_rule(struct pf_keth_rule *rule)
|
||||||
counter_u64_free(rule->packets[i]);
|
counter_u64_free(rule->packets[i]);
|
||||||
counter_u64_free(rule->bytes[i]);
|
counter_u64_free(rule->bytes[i]);
|
||||||
}
|
}
|
||||||
|
uma_zfree_pcpu(pcpu_zone_4, rule->timestamp);
|
||||||
pf_keth_anchor_remove(rule);
|
pf_keth_anchor_remove(rule);
|
||||||
|
|
||||||
free(rule, M_PFRULE);
|
free(rule, M_PFRULE);
|
||||||
|
@ -1801,6 +1804,7 @@ pf_krule_free(struct pf_krule *rule)
|
||||||
counter_u64_free(rule->states_cur);
|
counter_u64_free(rule->states_cur);
|
||||||
counter_u64_free(rule->states_tot);
|
counter_u64_free(rule->states_tot);
|
||||||
counter_u64_free(rule->src_nodes);
|
counter_u64_free(rule->src_nodes);
|
||||||
|
uma_zfree_pcpu(pcpu_zone_4, rule->timestamp);
|
||||||
|
|
||||||
mtx_destroy(&rule->rpool.mtx);
|
mtx_destroy(&rule->rpool.mtx);
|
||||||
free(rule, M_PFRULE);
|
free(rule, M_PFRULE);
|
||||||
|
@ -2130,6 +2134,7 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
|
||||||
rule->states_cur = counter_u64_alloc(M_WAITOK);
|
rule->states_cur = counter_u64_alloc(M_WAITOK);
|
||||||
rule->states_tot = counter_u64_alloc(M_WAITOK);
|
rule->states_tot = counter_u64_alloc(M_WAITOK);
|
||||||
rule->src_nodes = counter_u64_alloc(M_WAITOK);
|
rule->src_nodes = counter_u64_alloc(M_WAITOK);
|
||||||
|
rule->timestamp = uma_zalloc_pcpu(pcpu_zone_4, M_WAITOK | M_ZERO);
|
||||||
rule->cuid = td->td_ucred->cr_ruid;
|
rule->cuid = td->td_ucred->cr_ruid;
|
||||||
rule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
|
rule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
|
||||||
TAILQ_INIT(&rule->rpool.list);
|
TAILQ_INIT(&rule->rpool.list);
|
||||||
|
@ -2832,6 +2837,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||||
rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK);
|
rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK);
|
||||||
if (rule == NULL)
|
if (rule == NULL)
|
||||||
ERROUT(ENOMEM);
|
ERROUT(ENOMEM);
|
||||||
|
rule->timestamp = NULL;
|
||||||
|
|
||||||
error = pf_nveth_rule_to_keth_rule(nvl, rule);
|
error = pf_nveth_rule_to_keth_rule(nvl, rule);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
|
@ -2844,6 +2850,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||||
rule->packets[i] = counter_u64_alloc(M_WAITOK);
|
rule->packets[i] = counter_u64_alloc(M_WAITOK);
|
||||||
rule->bytes[i] = counter_u64_alloc(M_WAITOK);
|
rule->bytes[i] = counter_u64_alloc(M_WAITOK);
|
||||||
}
|
}
|
||||||
|
rule->timestamp = uma_zalloc_pcpu(pcpu_zone_4,
|
||||||
|
M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
PF_RULES_WLOCK();
|
PF_RULES_WLOCK();
|
||||||
|
|
||||||
|
@ -6697,6 +6705,7 @@ pf_unload_vnet(void)
|
||||||
counter_u64_free(V_pf_default_rule.states_cur);
|
counter_u64_free(V_pf_default_rule.states_cur);
|
||||||
counter_u64_free(V_pf_default_rule.states_tot);
|
counter_u64_free(V_pf_default_rule.states_tot);
|
||||||
counter_u64_free(V_pf_default_rule.src_nodes);
|
counter_u64_free(V_pf_default_rule.src_nodes);
|
||||||
|
uma_zfree_pcpu(pcpu_zone_4, V_pf_default_rule.timestamp);
|
||||||
|
|
||||||
for (int i = 0; i < PFRES_MAX; i++)
|
for (int i = 0; i < PFRES_MAX; i++)
|
||||||
counter_u64_free(V_pf_status.counters[i]);
|
counter_u64_free(V_pf_status.counters[i]);
|
||||||
|
|
|
@ -737,6 +737,7 @@ pf_krule_to_nvrule(struct pf_krule *rule)
|
||||||
nvlist_append_number_array(nvl, "bytes",
|
nvlist_append_number_array(nvl, "bytes",
|
||||||
pf_counter_u64_fetch(&rule->bytes[i]));
|
pf_counter_u64_fetch(&rule->bytes[i]));
|
||||||
}
|
}
|
||||||
|
nvlist_add_number(nvl, "timestamp", pf_get_timestamp(rule));
|
||||||
|
|
||||||
nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint);
|
nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint);
|
||||||
|
|
||||||
|
@ -1098,6 +1099,7 @@ pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule)
|
||||||
nvlist_add_number(nvl, "bytes-out",
|
nvlist_add_number(nvl, "bytes-out",
|
||||||
counter_u64_fetch(krule->bytes[1]));
|
counter_u64_fetch(krule->bytes[1]));
|
||||||
|
|
||||||
|
nvlist_add_number(nvl, "timestamp", pf_get_timestamp(krule));
|
||||||
nvlist_add_string(nvl, "qname", krule->qname);
|
nvlist_add_string(nvl, "qname", krule->qname);
|
||||||
nvlist_add_string(nvl, "tagname", krule->tagname);
|
nvlist_add_string(nvl, "tagname", krule->tagname);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue