Thanks to Murphy for help debugging this.
del_switch_port(p);
rcu_assign_pointer(dps[dp->dp_idx], NULL);
+ /* Kill off local_port dev references from buffered packets that have
+ * associated dst entries. */
+ synchronize_rcu();
+ fwd_discard_all();
+
/* Destroy dp->netdev. (Must follow deleting switch ports since
* dp->local_port has a reference to it.) */
dp_dev_destroy(dp);
return skb;
}
+void fwd_discard_all(void)
+{
+ unsigned long int flags;
+ int i;
+
+ spin_lock_irqsave(&buffer_lock, flags);
+ for (i = 0; i < N_PKT_BUFFERS; i++) {
+ kfree_skb(buffers[i].skb);
+ buffers[i].skb = NULL;
+ }
+ spin_unlock_irqrestore(&buffer_lock, flags);
+}
+
static void discard_skb(uint32_t id)
{
unsigned long int flags;
void fwd_exit(void)
{
- int i;
-
- for (i = 0; i < N_PKT_BUFFERS; i++)
- kfree_skb(buffers[i].skb);
+ fwd_discard_all();
}
/* Utility functions. */
const void *, size_t);
uint32_t fwd_save_skb(struct sk_buff *skb);
+void fwd_discard_all(void);
void fwd_exit(void);