aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorScott Talbert <scott.talbert@lmco.com>2005-09-29 20:30:54 -0400
committerDavid S. Miller <davem@davemloft.net>2005-09-29 20:30:54 -0400
commit4a7097fcc431ab2ccf509d8342831873138c814a (patch)
tree66439a1679e5c60df9f6237abb41a8912376efd7 /net
parent09e9ec87111ba818d8171262b15ba4c357eb1d27 (diff)
[ATM]: [lec] attempt to support cisco failover
From: Scott Talbert <scott.talbert@lmco.com> Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/atm/lec.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c
index a0752487026d..47e1eae97461 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -686,9 +686,19 @@ static unsigned char lec_ctrl_magic[] = {
686 0x01, 686 0x01,
687 0x01 }; 687 0x01 };
688 688
689#define LEC_DATA_DIRECT_8023 2
690#define LEC_DATA_DIRECT_8025 3
691
692static int lec_is_data_direct(struct atm_vcc *vcc)
693{
694 return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
695 (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
696}
697
689static void 698static void
690lec_push(struct atm_vcc *vcc, struct sk_buff *skb) 699lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
691{ 700{
701 unsigned long flags;
692 struct net_device *dev = (struct net_device *)vcc->proto_data; 702 struct net_device *dev = (struct net_device *)vcc->proto_data;
693 struct lec_priv *priv = (struct lec_priv *)dev->priv; 703 struct lec_priv *priv = (struct lec_priv *)dev->priv;
694 704
@@ -728,7 +738,8 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
728 skb_queue_tail(&sk->sk_receive_queue, skb); 738 skb_queue_tail(&sk->sk_receive_queue, skb);
729 sk->sk_data_ready(sk, skb->len); 739 sk->sk_data_ready(sk, skb->len);
730 } else { /* Data frame, queue to protocol handlers */ 740 } else { /* Data frame, queue to protocol handlers */
731 unsigned char *dst; 741 struct lec_arp_table *entry;
742 unsigned char *src, *dst;
732 743
733 atm_return(vcc,skb->truesize); 744 atm_return(vcc,skb->truesize);
734 if (*(uint16_t *)skb->data == htons(priv->lecid) || 745 if (*(uint16_t *)skb->data == htons(priv->lecid) ||
@@ -741,10 +752,30 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
741 return; 752 return;
742 } 753 }
743#ifdef CONFIG_TR 754#ifdef CONFIG_TR
744 if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest; 755 if (priv->is_trdev)
756 dst = ((struct lecdatahdr_8025 *) skb->data)->h_dest;
745 else 757 else
746#endif 758#endif
747 dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest; 759 dst = ((struct lecdatahdr_8023 *) skb->data)->h_dest;
760
761 /* If this is a Data Direct VCC, and the VCC does not match
762 * the LE_ARP cache entry, delete the LE_ARP cache entry.
763 */
764 spin_lock_irqsave(&priv->lec_arp_lock, flags);
765 if (lec_is_data_direct(vcc)) {
766#ifdef CONFIG_TR
767 if (priv->is_trdev)
768 src = ((struct lecdatahdr_8025 *) skb->data)->h_source;
769 else
770#endif
771 src = ((struct lecdatahdr_8023 *) skb->data)->h_source;
772 entry = lec_arp_find(priv, src);
773 if (entry && entry->vcc != vcc) {
774 lec_arp_remove(priv, entry);
775 kfree(entry);
776 }
777 }
778 spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
748 779
749 if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */ 780 if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */
750 !priv->is_proxy && /* Proxy wants all the packets */ 781 !priv->is_proxy && /* Proxy wants all the packets */