dummynet: use m_rcvif_serialize/restore when queueing packets

This fixed panic with interface being removed while packet
was sitting on a queue.  This allows to pass all dummynet
tests including forthcoming dummynet:ipfw_interface_removal
and dummynet:pf_interface_removal and demonstrates use of
m_rcvif_serialize() and m_rcvif_restore().

Reviewed by:		kp
Differential revision:	https://reviews.freebsd.org/D33267
This commit is contained in:
Gleb Smirnoff 2022-01-26 21:58:50 -08:00
parent e1882428dc
commit 165746f4e4
6 changed files with 46 additions and 7 deletions

View File

@ -192,8 +192,9 @@ struct mbuf *
codel_extract_head(struct dn_queue *q, aqm_time_t *pkt_ts)
{
struct m_tag *mtag;
struct mbuf *m = q->mq.head;
struct mbuf *m;
next: m = q->mq.head;
if (m == NULL)
return m;
q->mq.head = m->m_nextpkt;
@ -213,6 +214,11 @@ codel_extract_head(struct dn_queue *q, aqm_time_t *pkt_ts)
*pkt_ts = *(aqm_time_t *)(mtag + 1);
m_tag_delete(m,mtag);
}
if (m->m_pkthdr.rcvif != NULL &&
__predict_false(m_rcvif_restore(m) == NULL)) {
m_freem(m);
goto next;
}
return m;
}

View File

@ -328,8 +328,9 @@ static struct mbuf *
pie_extract_head(struct dn_queue *q, aqm_time_t *pkt_ts, int getts)
{
struct m_tag *mtag;
struct mbuf *m = q->mq.head;
struct mbuf *m;
next: m = q->mq.head;
if (m == NULL)
return m;
q->mq.head = m->m_nextpkt;
@ -351,6 +352,11 @@ pie_extract_head(struct dn_queue *q, aqm_time_t *pkt_ts, int getts)
m_tag_delete(m,mtag);
}
}
if (m->m_pkthdr.rcvif != NULL &&
__predict_false(m_rcvif_restore(m) == NULL)) {
m_freem(m);
goto next;
}
return m;
}

View File

@ -170,7 +170,10 @@ int ipdn_bound_var(int *v, int dflt, int lo, int hi, const char *msg);
static __inline struct mbuf*
dn_dequeue(struct dn_queue *q)
{
struct mbuf *m = q->mq.head;
struct mbuf *m;
next:
m = q->mq.head;
if (m == NULL)
return NULL;
#ifdef NEW_AQM
@ -190,6 +193,11 @@ dn_dequeue(struct dn_queue *q)
}
if (q->ni.length == 0) /* queue is now idle */
q->q_time = V_dn_cfg.curr_time;
if (m->m_pkthdr.rcvif != NULL &&
__predict_false(m_rcvif_restore(m) == NULL)) {
m_freem(m);
goto next;
}
return m;
}

View File

@ -138,8 +138,9 @@ fq_update_stats(struct fq_codel_flow *q, struct fq_codel_si *si, int len,
__inline static struct mbuf *
fq_codel_extract_head(struct fq_codel_flow *q, aqm_time_t *pkt_ts, struct fq_codel_si *si)
{
struct mbuf *m = q->mq.head;
struct mbuf *m;
next: m = q->mq.head;
if (m == NULL)
return m;
q->mq.head = m->m_nextpkt;
@ -159,7 +160,11 @@ fq_codel_extract_head(struct fq_codel_flow *q, aqm_time_t *pkt_ts, struct fq_cod
*pkt_ts = *(aqm_time_t *)(mtag + 1);
m_tag_delete(m,mtag);
}
if (m->m_pkthdr.rcvif != NULL &&
__predict_false(m_rcvif_restore(m) == NULL)) {
m_freem(m);
goto next;
}
return m;
}

View File

@ -338,8 +338,9 @@ __inline static struct mbuf *
fq_pie_extract_head(struct fq_pie_flow *q, aqm_time_t *pkt_ts,
struct fq_pie_si *si, int getts)
{
struct mbuf *m = q->mq.head;
struct mbuf *m;
next: m = q->mq.head;
if (m == NULL)
return m;
q->mq.head = m->m_nextpkt;
@ -361,6 +362,11 @@ fq_pie_extract_head(struct fq_pie_flow *q, aqm_time_t *pkt_ts,
m_tag_delete(m,mtag);
}
}
if (m->m_pkthdr.rcvif != NULL &&
__predict_false(m_rcvif_restore(m) == NULL)) {
m_freem(m);
goto next;
}
return m;
}

View File

@ -500,6 +500,8 @@ dn_enqueue(struct dn_queue *q, struct mbuf* m, int drop)
goto drop;
if (f->plr && random() < f->plr)
goto drop;
if (m->m_pkthdr.rcvif != NULL)
m_rcvif_serialize(m);
#ifdef NEW_AQM
/* Call AQM enqueue function */
if (q->fs->aqmfp)
@ -548,7 +550,11 @@ transmit_event(struct mq *q, struct delay_line *dline, uint64_t now)
break;
dline->mq.head = m->m_nextpkt;
dline->mq.count--;
mq_append(q, m);
if (m->m_pkthdr.rcvif != NULL &&
__predict_false(m_rcvif_restore(m) == NULL))
m_freem(m);
else
mq_append(q, m);
}
if (m != NULL) {
dline->oid.subtype = 1; /* in heap */
@ -617,6 +623,8 @@ serve_sched(struct mq *q, struct dn_sch_inst *si, uint64_t now)
si->credit -= len_scaled;
/* Move packet in the delay line */
dn_tag_get(m)->output_time = V_dn_cfg.curr_time + s->link.delay ;
if (m->m_pkthdr.rcvif != NULL)
m_rcvif_serialize(m);
mq_append(&si->dline.mq, m);
}