Page MenuHomeFreeBSD

D33266.diff
No OneTemporary

D33266.diff

diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -1635,6 +1635,28 @@
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.
*/
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -313,7 +313,10 @@
/* Table of ifnet by index. */
static int if_index;
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,
CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
@@ -325,8 +328,8 @@
IFNET_RLOCK();
for (int i = 1; i <= if_index; i++)
- if (ifindex_table[i] != NULL &&
- ifindex_table[i]->if_vnet == curvnet)
+ if (ifindex_table[i].ife_ifnet != NULL &&
+ ifindex_table[i].ife_ifnet->if_vnet == curvnet)
rv = i;
IFNET_RUNLOCK();
@@ -370,7 +373,7 @@
if (__predict_false(idx > if_index))
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)
ifp = NULL;
@@ -391,6 +394,24 @@
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);
+}
+
struct ifaddr *
ifaddr_byindex(u_short idx)
{
@@ -571,13 +592,13 @@
* next slot.
*/
for (idx = 1; idx <= if_index; idx++) {
- if (ifindex_table[idx] == NULL)
+ if (ifindex_table[idx].ife_ifnet == NULL)
break;
}
/* Catch if_index overflow. */
if (idx >= if_indexlim) {
- struct ifnet **new, **old;
+ struct ifindex_entry *new, *old;
int newlim;
newlim = if_indexlim * 2;
@@ -593,7 +614,8 @@
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();
return (ifp);
@@ -668,9 +690,10 @@
* virtualized and interface would outlive the vnet.
*/
IFNET_WLOCK();
- MPASS(ifindex_table[ifp->if_index] == ifp);
- ck_pr_store_ptr(&ifindex_table[ifp->if_index], NULL);
- while (if_index > 0 && ifindex_table[if_index] == NULL)
+ MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp);
+ ck_pr_store_ptr(&ifindex_table[ifp->if_index].ife_ifnet, NULL);
+ ifindex_table[ifp->if_index].ife_gencnt++;
+ while (if_index > 0 && ifindex_table[if_index].ife_ifnet == NULL)
if_index--;
IFNET_WUNLOCK();
@@ -819,7 +842,7 @@
struct sockaddr_dl *sdl;
struct ifaddr *ifa;
- MPASS(ifindex_table[ifp->if_index] == ifp);
+ MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp);
#ifdef VIMAGE
ifp->if_vnet = curvnet;
@@ -4508,8 +4531,8 @@
IF_DB_PRINTF("%d", if_dunit);
IF_DB_PRINTF("%s", if_description);
IF_DB_PRINTF("%u", if_index);
+ IF_DB_PRINTF("%d", if_idxgen);
IF_DB_PRINTF("%u", if_refcount);
- IF_DB_PRINTF("%d", if_index_reserved);
IF_DB_PRINTF("%p", if_softc);
IF_DB_PRINTF("%p", if_l2com);
IF_DB_PRINTF("%p", if_llsoftc);
@@ -4564,7 +4587,7 @@
u_short idx;
for (idx = 1; idx <= if_index; idx++) {
- ifp = ifindex_table[idx];
+ ifp = ifindex_table[idx].ife_ifnet;
if (ifp == NULL)
continue;
db_printf( "%20s ifp=%p\n", ifp->if_xname, ifp);
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -334,7 +334,7 @@
const char *if_dname; /* driver name */
int if_dunit; /* unit or IF_DUNIT_NONE */
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_description; /* interface description */
@@ -644,6 +644,13 @@
struct ifnet *ifnet_byindex(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);
+
/*
* Given the index, ifaddr_byindex() returns the one and only
* link-level ifaddr for the interface. You are not supposed to use
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -159,6 +159,10 @@
union {
struct m_snd_tag *snd_tag; /* send tag, if any */
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 */
int32_t len; /* total packet length */
@@ -862,6 +866,8 @@
void m_snd_tag_init(struct m_snd_tag *, struct ifnet *,
const struct if_snd_tag_sw *);
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
m_gettype(int size)

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 2, 10:28 PM (5 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29171552
Default Alt Text
D33266.diff (5 KB)

Event Timeline