This one is similar to my previous dump diff. I'd like to iterate on the radix-tree to flush flows, this will allows us to get rid of the global list.
ok? Index: net/pfkeyv2.c =================================================================== RCS file: /cvs/src/sys/net/pfkeyv2.c,v retrieving revision 1.169 diff -u -p -r1.169 pfkeyv2.c --- net/pfkeyv2.c 27 Oct 2017 08:27:14 -0000 1.169 +++ net/pfkeyv2.c 30 Oct 2017 10:22:42 -0000 @@ -165,6 +165,8 @@ int pfkeyv2_usrreq(struct socket *, int, int pfkeyv2_output(struct mbuf *, struct socket *, struct sockaddr *, struct mbuf *); int pfkey_sendup(struct keycb *, struct mbuf *, int); +int pfkeyv2_sa_flush(struct tdb *, void *, int); +int pfkeyv2_policy_flush(struct ipsec_policy *, void *, unsigned int); int pfkeyv2_sysctl_policydumper(struct ipsec_policy *, void *, unsigned int); /* @@ -861,7 +863,7 @@ pfkeyv2_dump_walker(struct tdb *sa, void * Delete an SA. */ int -pfkeyv2_flush_walker(struct tdb *sa, void *satype_vp, int last) +pfkeyv2_sa_flush(struct tdb *sa, void *satype_vp, int last) { if (!(*((u_int8_t *) satype_vp)) || sa->tdb_satype == *((u_int8_t *) satype_vp)) @@ -946,7 +948,7 @@ pfkeyv2_send(struct socket *so, void *me int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST; int delflag = 0; struct sockaddr_encap encapdst, encapnetmask; - struct ipsec_policy *ipo, *tmpipo; + struct ipsec_policy *ipo; struct ipsec_acquire *ipa; struct radix_node_head *rnh; struct radix_node *rn = NULL; @@ -1476,12 +1478,7 @@ pfkeyv2_send(struct socket *so, void *me switch (smsg->sadb_msg_satype) { case SADB_SATYPE_UNSPEC: - for (ipo = TAILQ_FIRST(&ipsec_policy_head); - ipo != NULL; ipo = tmpipo) { - tmpipo = TAILQ_NEXT(ipo, ipo_list); - if (ipo->ipo_rdomain == rdomain) - ipsec_delete_policy(ipo); - } + spd_table_walk(rdomain, pfkeyv2_policy_flush, NULL); /* FALLTHROUGH */ case SADB_SATYPE_AH: case SADB_SATYPE_ESP: @@ -1490,7 +1487,7 @@ pfkeyv2_send(struct socket *so, void *me #ifdef TCP_SIGNATURE case SADB_X_SATYPE_TCPSIGNATURE: #endif /* TCP_SIGNATURE */ - tdb_walk(rdomain, pfkeyv2_flush_walker, + tdb_walk(rdomain, pfkeyv2_sa_flush, (u_int8_t *) &(smsg->sadb_msg_satype)); break; @@ -2381,6 +2378,18 @@ pfkeyv2_sysctl_policydumper(struct ipsec done: if (buffer) free(buffer, M_PFKEY, 0); + return (error); +} + +int +pfkeyv2_policy_flush(struct ipsec_policy *ipo, void *arg, unsigned int tableid) +{ + int error; + + error = ipsec_delete_policy(ipo); + if (error == 0) + error = EAGAIN; + return (error); } Index: net/pfkeyv2.h =================================================================== RCS file: /cvs/src/sys/net/pfkeyv2.h,v retrieving revision 1.78 diff -u -p -r1.78 pfkeyv2.h --- net/pfkeyv2.h 27 Oct 2017 08:27:14 -0000 1.78 +++ net/pfkeyv2.h 30 Oct 2017 10:16:08 -0000 @@ -378,7 +378,6 @@ int pfkeyv2_send(struct socket *, void * int pfkeyv2_sendmessage(void **, int, struct socket *, u_int8_t, int, u_int); int pfkeyv2_dump_policy(struct ipsec_policy *, void **, void **, int *); int pfkeyv2_dump_walker(struct tdb *, void *, int); -int pfkeyv2_flush_walker(struct tdb *, void *, int); int pfkeyv2_get_proto_alg(u_int8_t, u_int8_t *, int *); int pfkeyv2_sysctl(int *, u_int, void *, size_t *, void *, size_t); int pfkeyv2_sysctl_walker(struct tdb *, void *, int); Index: netinet/ip_spd.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_spd.c,v retrieving revision 1.94 diff -u -p -r1.94 ip_spd.c --- netinet/ip_spd.c 27 Oct 2017 08:27:14 -0000 1.94 +++ netinet/ip_spd.c 30 Oct 2017 10:19:31 -0000 @@ -117,16 +117,20 @@ spd_table_add(unsigned int rtableid) int spd_table_walk(unsigned int rtableid, - int (*walker)(struct ipsec_policy *, void *, unsigned int), void *arg) + int (*func)(struct ipsec_policy *, void *, unsigned int), void *arg) { struct radix_node_head *rnh; + int (*walker)(struct radix_node *, void *, u_int) = (void *)func; + int error; rnh = spd_table_get(rtableid); if (rnh == NULL) return (0); - return (rn_walktree(rnh, - (int (*)(struct radix_node *, void *, u_int))walker, arg)); + while ((error = rn_walktree(rnh, walker, arg)) == EAGAIN) + continue; + + return (error); } /*