|
@@ -16,6 +16,7 @@
|
|
|
#include <linux/init.h>
|
|
#include <linux/init.h>
|
|
|
|
|
|
|
|
static struct sk_buff_head loopback_queue;
|
|
static struct sk_buff_head loopback_queue;
|
|
|
|
|
+#define ROSE_LOOPBACK_LIMIT 1000
|
|
|
static struct timer_list loopback_timer;
|
|
static struct timer_list loopback_timer;
|
|
|
|
|
|
|
|
static void rose_set_loopback_timer(void);
|
|
static void rose_set_loopback_timer(void);
|
|
@@ -35,29 +36,27 @@ static int rose_loopback_running(void)
|
|
|
|
|
|
|
|
int rose_loopback_queue(struct sk_buff *skb, struct rose_neigh *neigh)
|
|
int rose_loopback_queue(struct sk_buff *skb, struct rose_neigh *neigh)
|
|
|
{
|
|
{
|
|
|
- struct sk_buff *skbn;
|
|
|
|
|
|
|
+ struct sk_buff *skbn = NULL;
|
|
|
|
|
|
|
|
- skbn = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
|
|
|
+ if (skb_queue_len(&loopback_queue) < ROSE_LOOPBACK_LIMIT)
|
|
|
|
|
+ skbn = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
|
|
|
|
- kfree_skb(skb);
|
|
|
|
|
-
|
|
|
|
|
- if (skbn != NULL) {
|
|
|
|
|
|
|
+ if (skbn) {
|
|
|
|
|
+ consume_skb(skb);
|
|
|
skb_queue_tail(&loopback_queue, skbn);
|
|
skb_queue_tail(&loopback_queue, skbn);
|
|
|
|
|
|
|
|
if (!rose_loopback_running())
|
|
if (!rose_loopback_running())
|
|
|
rose_set_loopback_timer();
|
|
rose_set_loopback_timer();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ kfree_skb(skb);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
static void rose_set_loopback_timer(void)
|
|
static void rose_set_loopback_timer(void)
|
|
|
{
|
|
{
|
|
|
- del_timer(&loopback_timer);
|
|
|
|
|
-
|
|
|
|
|
- loopback_timer.expires = jiffies + 10;
|
|
|
|
|
- add_timer(&loopback_timer);
|
|
|
|
|
|
|
+ mod_timer(&loopback_timer, jiffies + 10);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void rose_loopback_timer(struct timer_list *unused)
|
|
static void rose_loopback_timer(struct timer_list *unused)
|
|
@@ -68,8 +67,12 @@ static void rose_loopback_timer(struct timer_list *unused)
|
|
|
struct sock *sk;
|
|
struct sock *sk;
|
|
|
unsigned short frametype;
|
|
unsigned short frametype;
|
|
|
unsigned int lci_i, lci_o;
|
|
unsigned int lci_i, lci_o;
|
|
|
|
|
+ int count;
|
|
|
|
|
|
|
|
- while ((skb = skb_dequeue(&loopback_queue)) != NULL) {
|
|
|
|
|
|
|
+ for (count = 0; count < ROSE_LOOPBACK_LIMIT; count++) {
|
|
|
|
|
+ skb = skb_dequeue(&loopback_queue);
|
|
|
|
|
+ if (!skb)
|
|
|
|
|
+ return;
|
|
|
if (skb->len < ROSE_MIN_LEN) {
|
|
if (skb->len < ROSE_MIN_LEN) {
|
|
|
kfree_skb(skb);
|
|
kfree_skb(skb);
|
|
|
continue;
|
|
continue;
|
|
@@ -106,6 +109,8 @@ static void rose_loopback_timer(struct timer_list *unused)
|
|
|
kfree_skb(skb);
|
|
kfree_skb(skb);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ if (!skb_queue_empty(&loopback_queue))
|
|
|
|
|
+ mod_timer(&loopback_timer, jiffies + 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void __exit rose_loopback_clear(void)
|
|
void __exit rose_loopback_clear(void)
|