[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>
diff --git a/net/atm/lec.c b/net/atm/lec.c
index a075248..47e1eae 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -686,9 +686,19 @@
         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 @@
                 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 @@
                         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 */