@@ -135,6 +135,10 @@ static const struct garp_state_trans {
},
};
+static void garp_join_timer_arm(struct garp_applicant *app);
+
+
+
static int garp_attr_cmp(const struct garp_attr *attr,
const void *data, u8 len, u8 type)
{
@@ -238,6 +242,7 @@ static int garp_pdu_append_end_mark(stru
static void garp_pdu_queue(struct garp_applicant *app)
{
+ bool need_arm_timer;
if (!app->pdu)
return;
@@ -250,15 +255,37 @@ static void garp_pdu_queue(struct garp_a
llc_mac_hdr_init(app->pdu, app->dev->dev_addr,
app->app->proto.group_address);
- skb_queue_tail(&app->queue, app->pdu);
+ printk(KERN_INFO "garp_pdu_queue app %p\n", app);
+ /*
+ * [this function always to be called under app lock under
+ * normal operation]
+ * Make sure to arm the timer upon encountering our first packet;
+ * further packets queued by us will then be allowed to accumulate
+ * until timer ultimately fires.
+ */
+ need_arm_timer = skb_queue_empty(&app->queue);
+ __skb_queue_tail(&app->queue, app->pdu);
app->pdu = NULL;
+ if (need_arm_timer)
+ garp_join_timer_arm(app);
}
static void garp_queue_xmit(struct garp_applicant *app)
{
struct sk_buff *skb;
+ struct sk_buff_head dequeue; /* accumul. requests to be handled */
+
+ printk(KERN_INFO "garp_queue_xmit app %p\n", app);
+
+ /* Atomically move over all incoming pdus into our processing queue.
+ This is needed to provide some reliable criteria whether our timer
+ should be rearmed or not. */
+ spin_lock_bh(&app->lock);
+ __skb_queue_head_init(&dequeue);
+ skb_queue_splice_init(&app->queue, &dequeue);
+ spin_unlock_bh(&app->lock);
- while ((skb = skb_dequeue(&app->queue)))
+ while ((skb = skb_dequeue(&dequeue)))
dev_queue_xmit(skb);
}
@@ -398,6 +425,7 @@ static void garp_join_timer_arm(struct g
unsigned long delay;
delay = (u64)msecs_to_jiffies(garp_join_time) * net_random() >> 32;
+ printk(KERN_INFO "garp_join_timer_arm app %p jiffies %lu delay %lu\n", app, jiffies, delay);
mod_timer(&app->join_timer, jiffies + delay);
}
@@ -411,7 +439,6 @@ static void garp_join_timer(unsigned lon
spin_unlock(&app->lock);
garp_queue_xmit(app);
- garp_join_timer_arm(app);
}
static int garp_pdu_parse_end_mark(struct sk_buff *skb)
@@ -586,7 +613,6 @@ int garp_init_applicant(struct net_devic
skb_queue_head_init(&app->queue);
rcu_assign_pointer(dev->garp_port->applicants[appl->type], app);
setup_timer(&app->join_timer, garp_join_timer, (unsigned long)app);
- garp_join_timer_arm(app);
return 0;
err3: