[ATM]: [lec] attempt to support cisco failover
authorScott Talbert <scott.talbert@lmco.com>
Fri, 30 Sep 2005 00:30:54 +0000 (17:30 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 30 Sep 2005 00:30:54 +0000 (17:30 -0700)
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>
net/atm/lec.c

index a0752487026d5f299ab9044592a4652fbaab3508..47e1eae9746160666ee3131a847a61452b0fb857 100644 (file)
@@ -686,9 +686,19 @@ static unsigned char lec_ctrl_magic[] = {
         0x01,
         0x01 };
 
+#define LEC_DATA_DIRECT_8023  2
+#define LEC_DATA_DIRECT_8025  3
+
+static int lec_is_data_direct(struct atm_vcc *vcc)
+{ 
+       return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
+               (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
+} 
+
 static void 
 lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
 {
+       unsigned long flags;
         struct net_device *dev = (struct net_device *)vcc->proto_data;
         struct lec_priv *priv = (struct lec_priv *)dev->priv; 
 
@@ -728,7 +738,8 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
                 skb_queue_tail(&sk->sk_receive_queue, skb);
                 sk->sk_data_ready(sk, skb->len);
         } else { /* Data frame, queue to protocol handlers */
-                unsigned char *dst;
+               struct lec_arp_table *entry;
+                unsigned char *src, *dst;
 
                 atm_return(vcc,skb->truesize);
                 if (*(uint16_t *)skb->data == htons(priv->lecid) ||
@@ -741,10 +752,30 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
                         return;
                 }
 #ifdef CONFIG_TR
-                if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
+                if (priv->is_trdev)
+                       dst = ((struct lecdatahdr_8025 *) skb->data)->h_dest;
                 else
 #endif
-                dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
+               dst = ((struct lecdatahdr_8023 *) skb->data)->h_dest;
+
+               /* If this is a Data Direct VCC, and the VCC does not match
+                * the LE_ARP cache entry, delete the LE_ARP cache entry.
+                */
+               spin_lock_irqsave(&priv->lec_arp_lock, flags);
+               if (lec_is_data_direct(vcc)) {
+#ifdef CONFIG_TR
+                       if (priv->is_trdev)
+                               src = ((struct lecdatahdr_8025 *) skb->data)->h_source;
+                       else
+#endif
+                       src = ((struct lecdatahdr_8023 *) skb->data)->h_source;
+                       entry = lec_arp_find(priv, src);
+                       if (entry && entry->vcc != vcc) {
+                               lec_arp_remove(priv, entry);
+                               kfree(entry);
+                       }
+               }
+               spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
                 if (!(dst[0]&0x01) &&   /* Never filter Multi/Broadcast */
                     !priv->is_proxy &&  /* Proxy wants all the packets */