DF-0604 / fix.diff
diff --git a/sys/net/pf/pf_if.c b/sys/net/pf/pf_if.c --- a/sys/net/pf/pf_if.c +++ b/sys/net/pf/pf_if.c @@ -84,6 +84,14 @@ static void pfi_kif_update(struct pfi_kif *); static void pfi_dynaddr_update(struct pfi_dynaddr *); +struct netmsg_pfitable { + struct netmsg_base base; + struct pfr_ktable *kt; + struct pfi_kif *kif; + int net; + int flags; +}; + static void pfi_table_update(struct pfr_ktable *, struct pfi_kif *, int, int); static void pfi_instance_add(struct ifnet *, int, int); @@ -503,7 +511,7 @@ } static void -pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) +_pfi_table_update_body(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) { int e, size2 = 0; struct ifg_member *ifgm; @@ -527,6 +535,39 @@ } } +static void +pfi_table_update_dispatch(netmsg_t nmsg) +{ + struct netmsg_pfitable *msg = (struct netmsg_pfitable *)nmsg; + + _pfi_table_update_body(msg->kt, msg->kif, msg->net, msg->flags); + netisr_replymsg(&nmsg->base, 0); +} + +/* + * DF-0604 fix: dispatch the entire buffer-update critical section to netisr0. + * All callers (ifaddr_event already on netisr0, pfioctl on caller CPU, etc.) + * now serialize on netisr0's single thread, eliminating the cross-CPU race + * on the global pfi_buffer/pfi_buffer_cnt/pfi_buffer_max. + */ +static void +pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags) +{ + if (mycpuid == 0) { + _pfi_table_update_body(kt, kif, net, flags); + } else { + struct netmsg_pfitable msg; + + netmsg_init(&msg.base, NULL, &curthread->td_msgport, 0, + pfi_table_update_dispatch); + msg.kt = kt; + msg.kif = kif; + msg.net = net; + msg.flags = flags; + netisr_domsg(&msg.base, 0); + } +} + struct netmsg_pfiadd { struct netmsg_base base; |