Date: Mon, 11 Apr 2016 10:00:38 +0000 (UTC) From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r297816 - head/sys/net Message-ID: <201604111000.u3BA0cYD089783@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bz Date: Mon Apr 11 10:00:38 2016 New Revision: 297816 URL: https://svnweb.freebsd.org/changeset/base/297816 Log: During if_vmove() we call if_detach_internal() which in turn calls the event handler notifying about interface departure and one of the consumers will detach if_bpf. There is no way for us to re-attach this easily as the DLT and hdrlen are only given on interface creation. Add a function to allow us to query the DLT and hdrlen from a current BPF attachment and after if_attach_internal() manually re-add the if_bpf attachment using these values. Found by panics triggered by nd6 packets running past BPF_MTAP() with no proper if_bpf pointer on the interface. Also add a basic DDB show function to investigate the if_bpf attachment of an interface. Reviewed by: gnn MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D5896 Modified: head/sys/net/bpf.c head/sys/net/bpf.h head/sys/net/if.c Modified: head/sys/net/bpf.c ============================================================================== --- head/sys/net/bpf.c Mon Apr 11 09:52:24 2016 (r297815) +++ head/sys/net/bpf.c Mon Apr 11 10:00:38 2016 (r297816) @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "opt_bpf.h" #include "opt_compat.h" +#include "opt_ddb.h" #include "opt_netgraph.h" #include <sys/types.h> @@ -67,6 +68,10 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> +#ifdef DDB +#include <ddb/ddb.h> +#endif + #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> @@ -2569,6 +2574,32 @@ bpfattach2(struct ifnet *ifp, u_int dlt, if_printf(ifp, "bpf attached\n"); } +#ifdef VIMAGE +/* + * When moving interfaces between vnet instances we need a way to + * query the dlt and hdrlen before detach so we can re-attch the if_bpf + * after the vmove. We unfortunately have no device driver infrastructure + * to query the interface for these values after creation/attach, thus + * add this as a workaround. + */ +int +bpf_get_bp_params(struct bpf_if *bp, u_int *bif_dlt, u_int *bif_hdrlen) +{ + + if (bp == NULL) + return (ENXIO); + if (bif_dlt == NULL && bif_hdrlen == NULL) + return (0); + + if (bif_dlt != NULL) + *bif_dlt = bp->bif_dlt; + if (bif_hdrlen != NULL) + *bif_hdrlen = bp->bif_hdrlen; + + return (0); +} +#endif + /* * Detach bpf from an interface. This involves detaching each descriptor * associated with the interface. Notify each descriptor as it's detached @@ -2977,3 +3008,34 @@ bpf_validate(const struct bpf_insn *f, i } #endif /* !DEV_BPF && !NETGRAPH_BPF */ + +#ifdef DDB +static void +bpf_show_bpf_if(struct bpf_if *bpf_if) +{ + + if (bpf_if == NULL) + return; + db_printf("%p:\n", bpf_if); +#define BPF_DB_PRINTF(f, e) db_printf(" %s = " f "\n", #e, bpf_if->e); + /* bif_ext.bif_next */ + /* bif_ext.bif_dlist */ + BPF_DB_PRINTF("%#x", bif_dlt); + BPF_DB_PRINTF("%u", bif_hdrlen); + BPF_DB_PRINTF("%p", bif_ifp); + /* bif_lock */ + /* bif_wlist */ + BPF_DB_PRINTF("%#x", bif_flags); +} + +DB_SHOW_COMMAND(bpf_if, db_show_bpf_if) +{ + + if (!have_addr) { + db_printf("usage: show bpf_if <struct bpf_if *>\n"); + return; + } + + bpf_show_bpf_if((struct bpf_if *)addr); +} +#endif Modified: head/sys/net/bpf.h ============================================================================== --- head/sys/net/bpf.h Mon Apr 11 09:52:24 2016 (r297815) +++ head/sys/net/bpf.h Mon Apr 11 10:00:38 2016 (r297816) @@ -1469,6 +1469,9 @@ void bpf_mtap2(struct bpf_if *, void *, void bpfattach(struct ifnet *, u_int, u_int); void bpfattach2(struct ifnet *, u_int, u_int, struct bpf_if **); void bpfdetach(struct ifnet *); +#ifdef VIMAGE +int bpf_get_bp_params(struct bpf_if *, u_int *, u_int *); +#endif void bpfilterattach(int); u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int); Modified: head/sys/net/if.c ============================================================================== --- head/sys/net/if.c Mon Apr 11 09:52:24 2016 (r297815) +++ head/sys/net/if.c Mon Apr 11 10:00:38 2016 (r297816) @@ -1021,8 +1021,16 @@ void if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { struct if_clone *ifc; + u_int bif_dlt, bif_hdrlen; int rc; + /* + * if_detach_internal() will call the eventhandler to notify + * interface departure. That will detach if_bpf. We need to + * safe the dlt and hdrlen so we can re-attach it later. + */ + bpf_get_bp_params(ifp->if_bpf, &bif_dlt, &bif_hdrlen); + /* * Detach from current vnet, but preserve LLADDR info, do not * mark as dead etc. so that the ifnet can be reattached later. @@ -1062,6 +1070,9 @@ if_vmove(struct ifnet *ifp, struct vnet if_attach_internal(ifp, 1, ifc); + if (ifp->if_bpf == NULL) + bpfattach(ifp, bif_dlt, bif_hdrlen); + CURVNET_RESTORE(); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604111000.u3BA0cYD089783>