Index: head/sys/net/bpf.h =================================================================== --- head/sys/net/bpf.h +++ head/sys/net/bpf.h @@ -1469,6 +1469,9 @@ 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); Index: head/sys/net/bpf.c =================================================================== --- head/sys/net/bpf.c +++ head/sys/net/bpf.c @@ -39,6 +39,7 @@ #include "opt_bpf.h" #include "opt_compat.h" +#include "opt_ddb.h" #include "opt_netgraph.h" #include @@ -67,6 +68,10 @@ #include +#ifdef DDB +#include +#endif + #include #include #include @@ -2569,6 +2574,32 @@ 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 @@ } #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 \n"); + return; + } + + bpf_show_bpf_if((struct bpf_if *)addr); +} +#endif Index: head/sys/net/if.c =================================================================== --- head/sys/net/if.c +++ head/sys/net/if.c @@ -1021,8 +1021,16 @@ 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_attach_internal(ifp, 1, ifc); + if (ifp->if_bpf == NULL) + bpfattach(ifp, bif_dlt, bif_hdrlen); + CURVNET_RESTORE(); }