Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/wg/if_wg.c
Show First 20 Lines • Show All 351 Lines • ▼ Show 20 Lines | |||||
static void wg_queue_enlist_staged(struct wg_queue *, struct wg_packet_list *); | static void wg_queue_enlist_staged(struct wg_queue *, struct wg_packet_list *); | ||||
static void wg_queue_delist_staged(struct wg_queue *, struct wg_packet_list *); | static void wg_queue_delist_staged(struct wg_queue *, struct wg_packet_list *); | ||||
static void wg_queue_purge(struct wg_queue *); | static void wg_queue_purge(struct wg_queue *); | ||||
static int wg_queue_both(struct wg_queue *, struct wg_queue *, struct wg_packet *); | static int wg_queue_both(struct wg_queue *, struct wg_queue *, struct wg_packet *); | ||||
static struct wg_packet *wg_queue_dequeue_serial(struct wg_queue *); | static struct wg_packet *wg_queue_dequeue_serial(struct wg_queue *); | ||||
static struct wg_packet *wg_queue_dequeue_parallel(struct wg_queue *); | static struct wg_packet *wg_queue_dequeue_parallel(struct wg_queue *); | ||||
static bool wg_input(struct mbuf *, int, struct inpcb *, const struct sockaddr *, void *); | static bool wg_input(struct mbuf *, int, struct inpcb *, const struct sockaddr *, void *); | ||||
static void wg_peer_send_staged(struct wg_peer *); | static void wg_peer_send_staged(struct wg_peer *); | ||||
static int wg_clone_create(struct if_clone *, int, caddr_t); | static int wg_clone_create(struct if_clone *ifc, char *name, size_t len, | ||||
struct ifc_data *ifd, struct ifnet **ifpp); | |||||
static void wg_qflush(struct ifnet *); | static void wg_qflush(struct ifnet *); | ||||
static inline int determine_af_and_pullup(struct mbuf **m, sa_family_t *af); | static inline int determine_af_and_pullup(struct mbuf **m, sa_family_t *af); | ||||
static int wg_xmit(struct ifnet *, struct mbuf *, sa_family_t, uint32_t); | static int wg_xmit(struct ifnet *, struct mbuf *, sa_family_t, uint32_t); | ||||
static int wg_transmit(struct ifnet *, struct mbuf *); | static int wg_transmit(struct ifnet *, struct mbuf *); | ||||
static int wg_output(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); | static int wg_output(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); | ||||
static void wg_clone_destroy(struct ifnet *); | static int wg_clone_destroy(struct if_clone *ifc, struct ifnet *ifp, | ||||
uint32_t flags); | |||||
static bool wgc_privileged(struct wg_softc *); | static bool wgc_privileged(struct wg_softc *); | ||||
static int wgc_get(struct wg_softc *, struct wg_data_io *); | static int wgc_get(struct wg_softc *, struct wg_data_io *); | ||||
static int wgc_set(struct wg_softc *, struct wg_data_io *); | static int wgc_set(struct wg_softc *, struct wg_data_io *); | ||||
static int wg_up(struct wg_softc *); | static int wg_up(struct wg_softc *); | ||||
static void wg_down(struct wg_softc *); | static void wg_down(struct wg_softc *); | ||||
static void wg_reassign(struct ifnet *, struct vnet *, char *unused); | static void wg_reassign(struct ifnet *, struct vnet *, char *unused); | ||||
static void wg_init(void *); | static void wg_init(void *); | ||||
static int wg_ioctl(struct ifnet *, u_long, caddr_t); | static int wg_ioctl(struct ifnet *, u_long, caddr_t); | ||||
▲ Show 20 Lines • Show All 2,334 Lines • ▼ Show 20 Lines | wg_down(struct wg_softc *sc) | ||||
if_link_state_change(sc->sc_ifp, LINK_STATE_DOWN); | if_link_state_change(sc->sc_ifp, LINK_STATE_DOWN); | ||||
wg_socket_uninit(sc); | wg_socket_uninit(sc); | ||||
sx_xunlock(&sc->sc_lock); | sx_xunlock(&sc->sc_lock); | ||||
} | } | ||||
static int | static int | ||||
wg_clone_create(struct if_clone *ifc, int unit, caddr_t params) | wg_clone_create(struct if_clone *ifc, char *name, size_t len, | ||||
struct ifc_data *ifd, struct ifnet **ifpp) | |||||
{ | { | ||||
struct wg_softc *sc; | struct wg_softc *sc; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
sc = malloc(sizeof(*sc), M_WG, M_WAITOK | M_ZERO); | sc = malloc(sizeof(*sc), M_WG, M_WAITOK | M_ZERO); | ||||
sc->sc_local = noise_local_alloc(sc); | sc->sc_local = noise_local_alloc(sc); | ||||
Show All 37 Lines | wg_clone_create(struct if_clone *ifc, char *name, size_t len, | ||||
wg_queue_init(&sc->sc_encrypt_parallel, "encp"); | wg_queue_init(&sc->sc_encrypt_parallel, "encp"); | ||||
wg_queue_init(&sc->sc_decrypt_parallel, "decp"); | wg_queue_init(&sc->sc_decrypt_parallel, "decp"); | ||||
sx_init(&sc->sc_lock, "wg softc lock"); | sx_init(&sc->sc_lock, "wg softc lock"); | ||||
ifp->if_softc = sc; | ifp->if_softc = sc; | ||||
ifp->if_capabilities = ifp->if_capenable = WG_CAPS; | ifp->if_capabilities = ifp->if_capenable = WG_CAPS; | ||||
if_initname(ifp, wgname, unit); | if_initname(ifp, wgname, ifd->unit); | ||||
if_setmtu(ifp, DEFAULT_MTU); | if_setmtu(ifp, DEFAULT_MTU); | ||||
ifp->if_flags = IFF_NOARP | IFF_MULTICAST; | ifp->if_flags = IFF_NOARP | IFF_MULTICAST; | ||||
ifp->if_init = wg_init; | ifp->if_init = wg_init; | ||||
ifp->if_reassign = wg_reassign; | ifp->if_reassign = wg_reassign; | ||||
ifp->if_qflush = wg_qflush; | ifp->if_qflush = wg_qflush; | ||||
ifp->if_transmit = wg_transmit; | ifp->if_transmit = wg_transmit; | ||||
ifp->if_output = wg_output; | ifp->if_output = wg_output; | ||||
ifp->if_ioctl = wg_ioctl; | ifp->if_ioctl = wg_ioctl; | ||||
if_attach(ifp); | if_attach(ifp); | ||||
bpfattach(ifp, DLT_NULL, sizeof(uint32_t)); | bpfattach(ifp, DLT_NULL, sizeof(uint32_t)); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; | ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; | ||||
ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD; | ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD; | ||||
#endif | #endif | ||||
sx_xlock(&wg_sx); | sx_xlock(&wg_sx); | ||||
LIST_INSERT_HEAD(&wg_list, sc, sc_entry); | LIST_INSERT_HEAD(&wg_list, sc, sc_entry); | ||||
sx_xunlock(&wg_sx); | sx_xunlock(&wg_sx); | ||||
*ifpp = ifp; | |||||
return (0); | return (0); | ||||
free_aip4: | free_aip4: | ||||
RADIX_NODE_HEAD_DESTROY(sc->sc_aip4); | RADIX_NODE_HEAD_DESTROY(sc->sc_aip4); | ||||
free(sc->sc_aip4, M_RTABLE); | free(sc->sc_aip4, M_RTABLE); | ||||
free_decrypt: | free_decrypt: | ||||
free(sc->sc_decrypt, M_WG); | free(sc->sc_decrypt, M_WG); | ||||
free(sc->sc_encrypt, M_WG); | free(sc->sc_encrypt, M_WG); | ||||
noise_local_free(sc->sc_local, NULL); | noise_local_free(sc->sc_local, NULL); | ||||
free(sc, M_WG); | free(sc, M_WG); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
static void | static void | ||||
wg_clone_deferred_free(struct noise_local *l) | wg_clone_deferred_free(struct noise_local *l) | ||||
{ | { | ||||
struct wg_softc *sc = noise_local_arg(l); | struct wg_softc *sc = noise_local_arg(l); | ||||
free(sc, M_WG); | free(sc, M_WG); | ||||
atomic_add_int(&clone_count, -1); | atomic_add_int(&clone_count, -1); | ||||
} | } | ||||
static void | static int | ||||
wg_clone_destroy(struct ifnet *ifp) | wg_clone_destroy(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) | ||||
{ | { | ||||
struct wg_softc *sc = ifp->if_softc; | struct wg_softc *sc = ifp->if_softc; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
sx_xlock(&wg_sx); | sx_xlock(&wg_sx); | ||||
ifp->if_softc = NULL; | ifp->if_softc = NULL; | ||||
sx_xlock(&sc->sc_lock); | sx_xlock(&sc->sc_lock); | ||||
sc->sc_flags |= WGF_DYING; | sc->sc_flags |= WGF_DYING; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | wg_clone_destroy(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) | ||||
cookie_checker_free(&sc->sc_cookie); | cookie_checker_free(&sc->sc_cookie); | ||||
if (cred != NULL) | if (cred != NULL) | ||||
crfree(cred); | crfree(cred); | ||||
if_detach(sc->sc_ifp); | if_detach(sc->sc_ifp); | ||||
if_free(sc->sc_ifp); | if_free(sc->sc_ifp); | ||||
noise_local_free(sc->sc_local, wg_clone_deferred_free); | noise_local_free(sc->sc_local, wg_clone_deferred_free); | ||||
return (0); | |||||
} | } | ||||
static void | static void | ||||
wg_qflush(struct ifnet *ifp __unused) | wg_qflush(struct ifnet *ifp __unused) | ||||
{ | { | ||||
} | } | ||||
/* | /* | ||||
Show All 26 Lines | wg_init(void *xsc) | ||||
sc = xsc; | sc = xsc; | ||||
wg_up(sc); | wg_up(sc); | ||||
} | } | ||||
static void | static void | ||||
vnet_wg_init(const void *unused __unused) | vnet_wg_init(const void *unused __unused) | ||||
{ | { | ||||
V_wg_cloner = if_clone_simple(wgname, wg_clone_create, wg_clone_destroy, | struct if_clone_addreq req = { | ||||
0); | .create_f = wg_clone_create, | ||||
.destroy_f = wg_clone_destroy, | |||||
.flags = IFC_F_AUTOUNIT, | |||||
}; | |||||
V_wg_cloner = ifc_attach_cloner(wgname, &req); | |||||
kevans: What's the practical difference between `if_clone_simple` and `ifc_attach_cloner` that's… | |||||
Not Done Inline ActionsI think this is a follow-up of https://reviews.freebsd.org/D36636 , and should be re-titled . zlei: I think this is a follow-up of https://reviews.freebsd.org/D36636 , and should be re-titled . | |||||
Not Done Inline ActionsYes, this is just moving to the "newer" clone API it seems, but no functional change. The title of the review should be updated to reflect that. jhb: Yes, this is just moving to the "newer" clone API it seems, but no functional change. The… | |||||
Done Inline ActionsWhen I tried to create a wg interface in a jail, it failed, and dtrace indicated that the failure was in ifc_create_ifp . This patch fixed it. Or at least, this patch "fixed" it. But it's possible that that failure was due to a different reason. Perhaps because my build was a few weeks old, or perhaps I ran into https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264981 . I'll retest again without this patch, probably next weekend. asomers: When I tried to create a wg interface in a jail, it failed, and dtrace indicated that the… | |||||
} | } | ||||
VNET_SYSINIT(vnet_wg_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, | VNET_SYSINIT(vnet_wg_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, | ||||
vnet_wg_init, NULL); | vnet_wg_init, NULL); | ||||
static void | static void | ||||
vnet_wg_uninit(const void *unused __unused) | vnet_wg_uninit(const void *unused __unused) | ||||
{ | { | ||||
if (V_wg_cloner) | if (V_wg_cloner) | ||||
if_clone_detach(V_wg_cloner); | ifc_detach_cloner(V_wg_cloner); | ||||
} | } | ||||
VNET_SYSUNINIT(vnet_wg_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, | VNET_SYSUNINIT(vnet_wg_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, | ||||
vnet_wg_uninit, NULL); | vnet_wg_uninit, NULL); | ||||
static int | static int | ||||
wg_prison_remove(void *obj, void *data __unused) | wg_prison_remove(void *obj, void *data __unused) | ||||
{ | { | ||||
const struct prison *pr = obj; | const struct prison *pr = obj; | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
wg_module_deinit(void) | wg_module_deinit(void) | ||||
{ | { | ||||
VNET_ITERATOR_DECL(vnet_iter); | VNET_ITERATOR_DECL(vnet_iter); | ||||
VNET_LIST_RLOCK(); | VNET_LIST_RLOCK(); | ||||
VNET_FOREACH(vnet_iter) { | VNET_FOREACH(vnet_iter) { | ||||
struct if_clone *clone = VNET_VNET(vnet_iter, wg_cloner); | struct if_clone *clone = VNET_VNET(vnet_iter, wg_cloner); | ||||
if (clone) { | if (clone) { | ||||
if_clone_detach(clone); | ifc_detach_cloner(clone); | ||||
VNET_VNET(vnet_iter, wg_cloner) = NULL; | VNET_VNET(vnet_iter, wg_cloner) = NULL; | ||||
} | } | ||||
} | } | ||||
VNET_LIST_RUNLOCK(); | VNET_LIST_RUNLOCK(); | ||||
NET_EPOCH_WAIT(); | NET_EPOCH_WAIT(); | ||||
MPASS(LIST_EMPTY(&wg_list)); | MPASS(LIST_EMPTY(&wg_list)); | ||||
osd_jail_deregister(wg_osd_jail_slot); | osd_jail_deregister(wg_osd_jail_slot); | ||||
cookie_deinit(); | cookie_deinit(); | ||||
Show All 28 Lines |
What's the practical difference between if_clone_simple and ifc_attach_cloner that's changing something here? I note that I don't seem to have any problems creating a wg interface in a vnet jail, so I'm not sure I actually understand the problem.