ifnet/mbuf: provide KPI to serialize/restore m->m_pkthdr.rcvif
Supplement ifindex table with generation count and use it to serialize & restore an ifnet pointer. Reviewed by: kp Differential revision: https://reviews.freebsd.org/D33266 Fun note: git showe6abef0918
(cherry picked from commite1882428dc
)
This commit is contained in:
parent
80e60e236d
commit
4d7a1361ef
@ -1635,6 +1635,28 @@ m_snd_tag_destroy(struct m_snd_tag *mst)
|
|||||||
counter_u64_add(snd_tag_count, -1);
|
counter_u64_add(snd_tag_count, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
m_rcvif_serialize(struct mbuf *m)
|
||||||
|
{
|
||||||
|
u_short idx, gen;
|
||||||
|
|
||||||
|
M_ASSERTPKTHDR(m);
|
||||||
|
idx = m->m_pkthdr.rcvif->if_index;
|
||||||
|
gen = m->m_pkthdr.rcvif->if_idxgen;
|
||||||
|
m->m_pkthdr.rcvidx = idx;
|
||||||
|
m->m_pkthdr.rcvgen = gen;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ifnet *
|
||||||
|
m_rcvif_restore(struct mbuf *m)
|
||||||
|
{
|
||||||
|
|
||||||
|
M_ASSERTPKTHDR(m);
|
||||||
|
|
||||||
|
return ((m->m_pkthdr.rcvif = ifnet_byindexgen(m->m_pkthdr.rcvidx,
|
||||||
|
m->m_pkthdr.rcvgen)));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate an mbuf with anonymous external pages.
|
* Allocate an mbuf with anonymous external pages.
|
||||||
*/
|
*/
|
||||||
|
49
sys/net/if.c
49
sys/net/if.c
@ -313,7 +313,10 @@ VNET_DEFINE(struct ifgrouphead, ifg_head);
|
|||||||
/* Table of ifnet by index. */
|
/* Table of ifnet by index. */
|
||||||
static int if_index;
|
static int if_index;
|
||||||
static int if_indexlim = 8;
|
static int if_indexlim = 8;
|
||||||
static struct ifnet **ifindex_table;
|
static struct ifindex_entry {
|
||||||
|
struct ifnet *ife_ifnet;
|
||||||
|
uint16_t ife_gencnt;
|
||||||
|
} *ifindex_table;
|
||||||
|
|
||||||
SYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system,
|
SYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system,
|
||||||
CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
||||||
@ -325,8 +328,8 @@ sysctl_ifcount(SYSCTL_HANDLER_ARGS)
|
|||||||
|
|
||||||
IFNET_RLOCK();
|
IFNET_RLOCK();
|
||||||
for (int i = 1; i <= if_index; i++)
|
for (int i = 1; i <= if_index; i++)
|
||||||
if (ifindex_table[i] != NULL &&
|
if (ifindex_table[i].ife_ifnet != NULL &&
|
||||||
ifindex_table[i]->if_vnet == curvnet)
|
ifindex_table[i].ife_ifnet->if_vnet == curvnet)
|
||||||
rv = i;
|
rv = i;
|
||||||
IFNET_RUNLOCK();
|
IFNET_RUNLOCK();
|
||||||
|
|
||||||
@ -370,7 +373,7 @@ ifnet_byindex(u_int idx)
|
|||||||
if (__predict_false(idx > if_index))
|
if (__predict_false(idx > if_index))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
ifp = ck_pr_load_ptr(&ifindex_table[idx]);
|
ifp = ck_pr_load_ptr(&ifindex_table[idx].ife_ifnet);
|
||||||
|
|
||||||
if (curvnet != NULL && ifp != NULL && ifp->if_vnet != curvnet)
|
if (curvnet != NULL && ifp != NULL && ifp->if_vnet != curvnet)
|
||||||
ifp = NULL;
|
ifp = NULL;
|
||||||
@ -391,6 +394,24 @@ ifnet_byindex_ref(u_int idx)
|
|||||||
return (ifp);
|
return (ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ifnet *
|
||||||
|
ifnet_byindexgen(uint16_t idx, uint16_t gen)
|
||||||
|
{
|
||||||
|
struct ifnet *ifp;
|
||||||
|
|
||||||
|
NET_EPOCH_ASSERT();
|
||||||
|
|
||||||
|
if (__predict_false(idx > if_index))
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
ifp = ck_pr_load_ptr(&ifindex_table[idx].ife_ifnet);
|
||||||
|
|
||||||
|
if (ifindex_table[idx].ife_gencnt == gen)
|
||||||
|
return (ifp);
|
||||||
|
else
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Network interface utility routines.
|
* Network interface utility routines.
|
||||||
*
|
*
|
||||||
@ -557,13 +578,13 @@ if_alloc_domain(u_char type, int numa_domain)
|
|||||||
* next slot.
|
* next slot.
|
||||||
*/
|
*/
|
||||||
for (idx = 1; idx <= if_index; idx++) {
|
for (idx = 1; idx <= if_index; idx++) {
|
||||||
if (ifindex_table[idx] == NULL)
|
if (ifindex_table[idx].ife_ifnet == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Catch if_index overflow. */
|
/* Catch if_index overflow. */
|
||||||
if (idx >= if_indexlim) {
|
if (idx >= if_indexlim) {
|
||||||
struct ifnet **new, **old;
|
struct ifindex_entry *new, *old;
|
||||||
int newlim;
|
int newlim;
|
||||||
|
|
||||||
newlim = if_indexlim * 2;
|
newlim = if_indexlim * 2;
|
||||||
@ -579,7 +600,8 @@ if_alloc_domain(u_char type, int numa_domain)
|
|||||||
if_index = idx;
|
if_index = idx;
|
||||||
|
|
||||||
ifp->if_index = idx;
|
ifp->if_index = idx;
|
||||||
ck_pr_store_ptr(&ifindex_table[idx], ifp);
|
ifp->if_idxgen = ifindex_table[idx].ife_gencnt;
|
||||||
|
ck_pr_store_ptr(&ifindex_table[idx].ife_ifnet, ifp);
|
||||||
IFNET_WUNLOCK();
|
IFNET_WUNLOCK();
|
||||||
|
|
||||||
return (ifp);
|
return (ifp);
|
||||||
@ -654,9 +676,10 @@ if_free(struct ifnet *ifp)
|
|||||||
* virtualized and interface would outlive the vnet.
|
* virtualized and interface would outlive the vnet.
|
||||||
*/
|
*/
|
||||||
IFNET_WLOCK();
|
IFNET_WLOCK();
|
||||||
MPASS(ifindex_table[ifp->if_index] == ifp);
|
MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp);
|
||||||
ck_pr_store_ptr(&ifindex_table[ifp->if_index], NULL);
|
ck_pr_store_ptr(&ifindex_table[ifp->if_index].ife_ifnet, NULL);
|
||||||
while (if_index > 0 && ifindex_table[if_index] == NULL)
|
ifindex_table[ifp->if_index].ife_gencnt++;
|
||||||
|
while (if_index > 0 && ifindex_table[if_index].ife_ifnet == NULL)
|
||||||
if_index--;
|
if_index--;
|
||||||
IFNET_WUNLOCK();
|
IFNET_WUNLOCK();
|
||||||
|
|
||||||
@ -805,7 +828,7 @@ if_attach_internal(struct ifnet *ifp, bool vmove)
|
|||||||
struct sockaddr_dl *sdl;
|
struct sockaddr_dl *sdl;
|
||||||
struct ifaddr *ifa;
|
struct ifaddr *ifa;
|
||||||
|
|
||||||
MPASS(ifindex_table[ifp->if_index] == ifp);
|
MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp);
|
||||||
|
|
||||||
#ifdef VIMAGE
|
#ifdef VIMAGE
|
||||||
ifp->if_vnet = curvnet;
|
ifp->if_vnet = curvnet;
|
||||||
@ -4494,8 +4517,8 @@ if_show_ifnet(struct ifnet *ifp)
|
|||||||
IF_DB_PRINTF("%d", if_dunit);
|
IF_DB_PRINTF("%d", if_dunit);
|
||||||
IF_DB_PRINTF("%s", if_description);
|
IF_DB_PRINTF("%s", if_description);
|
||||||
IF_DB_PRINTF("%u", if_index);
|
IF_DB_PRINTF("%u", if_index);
|
||||||
|
IF_DB_PRINTF("%d", if_idxgen);
|
||||||
IF_DB_PRINTF("%u", if_refcount);
|
IF_DB_PRINTF("%u", if_refcount);
|
||||||
IF_DB_PRINTF("%d", if_index_reserved);
|
|
||||||
IF_DB_PRINTF("%p", if_softc);
|
IF_DB_PRINTF("%p", if_softc);
|
||||||
IF_DB_PRINTF("%p", if_l2com);
|
IF_DB_PRINTF("%p", if_l2com);
|
||||||
IF_DB_PRINTF("%p", if_llsoftc);
|
IF_DB_PRINTF("%p", if_llsoftc);
|
||||||
@ -4550,7 +4573,7 @@ DB_SHOW_ALL_COMMAND(ifnets, db_show_all_ifnets)
|
|||||||
u_short idx;
|
u_short idx;
|
||||||
|
|
||||||
for (idx = 1; idx <= if_index; idx++) {
|
for (idx = 1; idx <= if_index; idx++) {
|
||||||
ifp = ifindex_table[idx];
|
ifp = ifindex_table[idx].ife_ifnet;
|
||||||
if (ifp == NULL)
|
if (ifp == NULL)
|
||||||
continue;
|
continue;
|
||||||
db_printf( "%20s ifp=%p\n", ifp->if_xname, ifp);
|
db_printf( "%20s ifp=%p\n", ifp->if_xname, ifp);
|
||||||
|
@ -334,7 +334,7 @@ struct ifnet {
|
|||||||
const char *if_dname; /* driver name */
|
const char *if_dname; /* driver name */
|
||||||
int if_dunit; /* unit or IF_DUNIT_NONE */
|
int if_dunit; /* unit or IF_DUNIT_NONE */
|
||||||
u_short if_index; /* numeric abbreviation for this if */
|
u_short if_index; /* numeric abbreviation for this if */
|
||||||
short if_index_reserved; /* spare space to grow if_index */
|
u_short if_idxgen; /* ... and its generation count */
|
||||||
char if_xname[IFNAMSIZ]; /* external name (name + unit) */
|
char if_xname[IFNAMSIZ]; /* external name (name + unit) */
|
||||||
char *if_description; /* interface description */
|
char *if_description; /* interface description */
|
||||||
|
|
||||||
@ -644,6 +644,13 @@ extern struct sx ifnet_sxlock;
|
|||||||
struct ifnet *ifnet_byindex(u_int);
|
struct ifnet *ifnet_byindex(u_int);
|
||||||
struct ifnet *ifnet_byindex_ref(u_int);
|
struct ifnet *ifnet_byindex_ref(u_int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ifnet_byindexgen() looks up ifnet by index and generation count,
|
||||||
|
* attempting to restore a weak pointer that had been stored across
|
||||||
|
* the epoch.
|
||||||
|
*/
|
||||||
|
struct ifnet *ifnet_byindexgen(uint16_t idx, uint16_t gen);
|
||||||
|
|
||||||
VNET_DECLARE(struct ifnethead, ifnet);
|
VNET_DECLARE(struct ifnethead, ifnet);
|
||||||
VNET_DECLARE(struct ifgrouphead, ifg_head);
|
VNET_DECLARE(struct ifgrouphead, ifg_head);
|
||||||
VNET_DECLARE(struct ifnet *, loif); /* first loopback interface */
|
VNET_DECLARE(struct ifnet *, loif); /* first loopback interface */
|
||||||
|
@ -159,6 +159,10 @@ struct pkthdr {
|
|||||||
union {
|
union {
|
||||||
struct m_snd_tag *snd_tag; /* send tag, if any */
|
struct m_snd_tag *snd_tag; /* send tag, if any */
|
||||||
struct ifnet *rcvif; /* rcv interface */
|
struct ifnet *rcvif; /* rcv interface */
|
||||||
|
struct {
|
||||||
|
uint16_t rcvidx; /* rcv interface index ... */
|
||||||
|
uint16_t rcvgen; /* ... and generation count */
|
||||||
|
};
|
||||||
};
|
};
|
||||||
SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */
|
SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */
|
||||||
int32_t len; /* total packet length */
|
int32_t len; /* total packet length */
|
||||||
@ -862,6 +866,8 @@ int m_snd_tag_alloc(struct ifnet *,
|
|||||||
void m_snd_tag_init(struct m_snd_tag *, struct ifnet *,
|
void m_snd_tag_init(struct m_snd_tag *, struct ifnet *,
|
||||||
const struct if_snd_tag_sw *);
|
const struct if_snd_tag_sw *);
|
||||||
void m_snd_tag_destroy(struct m_snd_tag *);
|
void m_snd_tag_destroy(struct m_snd_tag *);
|
||||||
|
void m_rcvif_serialize(struct mbuf *);
|
||||||
|
struct ifnet *m_rcvif_restore(struct mbuf *);
|
||||||
|
|
||||||
static __inline int
|
static __inline int
|
||||||
m_gettype(int size)
|
m_gettype(int size)
|
||||||
|
Loading…
Reference in New Issue
Block a user