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); } }