I am not sure if the small patch helps you but you may want to try it out
(version 0.8.0). It is a part of much larger patch, so I am not realy sure if it
works alone (it should), you probably would not want the whole thing.
It uses a linked lists of protocol handlers (just like normal Linux). There is
also a check for the interface where the frame came from.
Good luck,
Petr Grillinger
diff -urNp -x '\.*' -x '*.[ao]' .rtnet-0.8.0/stack/stack_mgr.c
rtnet-0.8.0-pg/stack/stack_mgr.c
--- .rtnet-0.8.0/stack/stack_mgr.c 2004-10-28 18:05:41.000000000 +0200
+++ rtnet-0.8.0-pg/stack/stack_mgr.c 2004-12-27 13:18:42.000000000 +0100
@@ -46,20 +46,12 @@ int rtdev_add_pack(struct rtpacket_type
rtos_spin_lock_irqsave(&rt_packets_lock, flags);
- if (rt_packets[hash] == NULL) {
- rt_packets[hash] = pt;
-
- pt->refcount = 0;
-
- rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
-
- return 0;
- }
- else {
- rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
-
- return -EADDRNOTAVAIL;
- }
+ pt->next = rt_packets[hash];
+ rt_packets[hash] = pt;
+ pt->refcount = 0;
+
+ rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
+ return 0;
}
@@ -84,22 +76,22 @@ int rtdev_remove_pack(struct rtpacket_ty
rtos_spin_lock_irqsave(&rt_packets_lock, flags);
- if ((rt_packets[hash] != NULL) &&
- (rt_packets[hash]->type == pt->type)) {
- rt_packets[hash] = NULL;
-
- if (pt->refcount > 0)
- ret = -EAGAIN;
-
- rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
-
- return ret;
+ struct rtpacket_type **rtp = &(rt_packets[hash]);
+
+ while ((*rtp) != NULL) {
+ if (*rtp == pt) {
+ *rtp = pt->next;
+ if (pt->refcount > 0)
+ ret = -EAGAIN;
+ goto out;
+ }
+ rtp = &((*rtp)->next);
}
- else {
- rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
+ ret = -ENOENT;
- return -ENOENT;
- }
+out:
+ rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
+ return ret;
}
@@ -185,28 +177,38 @@ static void do_stacktask(int mgr_id)
hash = ntohs(skb->protocol) & (MAX_RT_PROTOCOLS-1);
rtos_spin_lock_irqsave(&rt_packets_lock, flags);
-
pt = rt_packets[hash];
- if ((pt != NULL) && (pt->type == skb->protocol)) {
- pt->refcount++;
- rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
-
- pt->handler(skb, pt);
-
- rtos_spin_lock_irqsave(&rt_packets_lock, flags);
- pt->refcount--;
- rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
- } else {
- rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
-
- /* don't warn if running in promiscuous mode (RTcap...?) */
- if ((rtdev->flags & IFF_PROMISC) == 0)
- rtos_print("RTnet: unknown layer-3 protocol\n");
-
- kfree_rtskb(skb);
+ int proto_cnt = 0,
+ if_cnt = 0;
+ for ( ; pt; pt = pt->next) {
+ if (pt->type == skb->protocol) {
+ if (!pt->ifindex || pt->ifindex == skb->rtdev->ifindex) {
+ pt->refcount++;
+ rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
+
+ pt->handler(skb, pt);
+
+ rtos_spin_lock_irqsave(&rt_packets_lock, flags);
+ pt->refcount--;
+ if_cnt++;
+ }
+ proto_cnt++;
+ }
}
-
+ rtos_spin_unlock_irqrestore(&rt_packets_lock, flags);
+
+ /* don't warn if running in promiscuous mode (RTcap...?) */
+ if ((rtdev->flags & IFF_PROMISC) == 0) {
+ if (proto_cnt == 0)
+ rtos_print("RTnet: missing handler for protocol 0x%04x\n",
+ ntohs(skb->protocol));
+ else if (if_cnt == 0)
+ rtos_print("RTnet: missing handler for protocol 0x%04x,
interface %d\n",
+ ntohs(skb->protocol), skb->rtdev->ifindex);
+ }
+ kfree_rtskb(skb);
rtdev_dereference(rtdev);
}
}