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:
parent
e1882428dc
commit
165746f4e4
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user