diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/atm/lec.c | 153 |
1 files changed, 80 insertions, 73 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c index aefd278d6af6..5da5753157f9 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -285,7 +285,6 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, | |||
285 | 285 | ||
286 | /* Make sure we have room for lec_id */ | 286 | /* Make sure we have room for lec_id */ |
287 | if (skb_headroom(skb) < 2) { | 287 | if (skb_headroom(skb) < 2) { |
288 | |||
289 | pr_debug("reallocating skb\n"); | 288 | pr_debug("reallocating skb\n"); |
290 | skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); | 289 | skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); |
291 | kfree_skb(skb); | 290 | kfree_skb(skb); |
@@ -508,34 +507,31 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | |||
508 | break; | 507 | break; |
509 | case l_should_bridge: | 508 | case l_should_bridge: |
510 | #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) | 509 | #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) |
511 | { | 510 | { |
512 | pr_debug("%s: bridge zeppelin asks about %pM\n", | 511 | pr_debug("%s: bridge zeppelin asks about %pM\n", |
513 | dev->name, mesg->content.proxy.mac_addr); | 512 | dev->name, mesg->content.proxy.mac_addr); |
514 | 513 | ||
515 | if (br_fdb_test_addr_hook == NULL) | 514 | if (br_fdb_test_addr_hook == NULL) |
516 | break; | 515 | break; |
517 | 516 | ||
518 | if (br_fdb_test_addr_hook(dev, | 517 | if (br_fdb_test_addr_hook(dev, mesg->content.proxy.mac_addr)) { |
519 | mesg->content.proxy.mac_addr)) { | 518 | /* hit from bridge table, send LE_ARP_RESPONSE */ |
520 | /* hit from bridge table, send LE_ARP_RESPONSE */ | 519 | struct sk_buff *skb2; |
521 | struct sk_buff *skb2; | 520 | struct sock *sk; |
522 | struct sock *sk; | 521 | |
523 | 522 | pr_debug("%s: entry found, responding to zeppelin\n", | |
524 | pr_debug("%s: entry found, responding to zeppelin\n", | 523 | dev->name); |
525 | dev->name); | 524 | skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); |
526 | skb2 = alloc_skb(sizeof(struct atmlec_msg), | 525 | if (skb2 == NULL) |
527 | GFP_ATOMIC); | 526 | break; |
528 | if (skb2 == NULL) | 527 | skb2->len = sizeof(struct atmlec_msg); |
529 | break; | 528 | skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); |
530 | skb2->len = sizeof(struct atmlec_msg); | 529 | atm_force_charge(priv->lecd, skb2->truesize); |
531 | skb_copy_to_linear_data(skb2, mesg, | 530 | sk = sk_atm(priv->lecd); |
532 | sizeof(*mesg)); | 531 | skb_queue_tail(&sk->sk_receive_queue, skb2); |
533 | atm_force_charge(priv->lecd, skb2->truesize); | 532 | sk->sk_data_ready(sk, skb2->len); |
534 | sk = sk_atm(priv->lecd); | ||
535 | skb_queue_tail(&sk->sk_receive_queue, skb2); | ||
536 | sk->sk_data_ready(sk, skb2->len); | ||
537 | } | ||
538 | } | 533 | } |
534 | } | ||
539 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ | 535 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ |
540 | break; | 536 | break; |
541 | default: | 537 | default: |
@@ -561,7 +557,7 @@ static void lec_atm_close(struct atm_vcc *vcc) | |||
561 | 557 | ||
562 | if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) | 558 | if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) |
563 | pr_info("%s closing with messages pending\n", dev->name); | 559 | pr_info("%s closing with messages pending\n", dev->name); |
564 | while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) { | 560 | while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) { |
565 | atm_return(vcc, skb->truesize); | 561 | atm_return(vcc, skb->truesize); |
566 | dev_kfree_skb(skb); | 562 | dev_kfree_skb(skb); |
567 | } | 563 | } |
@@ -1748,6 +1744,50 @@ static void lec_arp_expire_vcc(unsigned long data) | |||
1748 | lec_arp_put(to_remove); | 1744 | lec_arp_put(to_remove); |
1749 | } | 1745 | } |
1750 | 1746 | ||
1747 | static bool __lec_arp_check_expire(struct lec_arp_table *entry, | ||
1748 | unsigned long now, | ||
1749 | struct lec_priv *priv) | ||
1750 | { | ||
1751 | unsigned long time_to_check; | ||
1752 | |||
1753 | if ((entry->flags) & LEC_REMOTE_FLAG && priv->topology_change) | ||
1754 | time_to_check = priv->forward_delay_time; | ||
1755 | else | ||
1756 | time_to_check = priv->aging_time; | ||
1757 | |||
1758 | pr_debug("About to expire: %lx - %lx > %lx\n", | ||
1759 | now, entry->last_used, time_to_check); | ||
1760 | if (time_after(now, entry->last_used + time_to_check) && | ||
1761 | !(entry->flags & LEC_PERMANENT_FLAG) && | ||
1762 | !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ | ||
1763 | /* Remove entry */ | ||
1764 | pr_debug("Entry timed out\n"); | ||
1765 | lec_arp_remove(priv, entry); | ||
1766 | lec_arp_put(entry); | ||
1767 | } else { | ||
1768 | /* Something else */ | ||
1769 | if ((entry->status == ESI_VC_PENDING || | ||
1770 | entry->status == ESI_ARP_PENDING) && | ||
1771 | time_after_eq(now, entry->timestamp + | ||
1772 | priv->max_unknown_frame_time)) { | ||
1773 | entry->timestamp = jiffies; | ||
1774 | entry->packets_flooded = 0; | ||
1775 | if (entry->status == ESI_VC_PENDING) | ||
1776 | send_to_lecd(priv, l_svc_setup, | ||
1777 | entry->mac_addr, | ||
1778 | entry->atm_addr, | ||
1779 | NULL); | ||
1780 | } | ||
1781 | if (entry->status == ESI_FLUSH_PENDING && | ||
1782 | time_after_eq(now, entry->timestamp + | ||
1783 | priv->path_switching_delay)) { | ||
1784 | lec_arp_hold(entry); | ||
1785 | return true; | ||
1786 | } | ||
1787 | } | ||
1788 | |||
1789 | return false; | ||
1790 | } | ||
1751 | /* | 1791 | /* |
1752 | * Expire entries. | 1792 | * Expire entries. |
1753 | * 1. Re-set timer | 1793 | * 1. Re-set timer |
@@ -1772,7 +1812,6 @@ static void lec_arp_check_expire(struct work_struct *work) | |||
1772 | struct hlist_node *node, *next; | 1812 | struct hlist_node *node, *next; |
1773 | struct lec_arp_table *entry; | 1813 | struct lec_arp_table *entry; |
1774 | unsigned long now; | 1814 | unsigned long now; |
1775 | unsigned long time_to_check; | ||
1776 | int i; | 1815 | int i; |
1777 | 1816 | ||
1778 | pr_debug("%p\n", priv); | 1817 | pr_debug("%p\n", priv); |
@@ -1782,51 +1821,19 @@ restart: | |||
1782 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1821 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1783 | hlist_for_each_entry_safe(entry, node, next, | 1822 | hlist_for_each_entry_safe(entry, node, next, |
1784 | &priv->lec_arp_tables[i], next) { | 1823 | &priv->lec_arp_tables[i], next) { |
1785 | if ((entry->flags) & LEC_REMOTE_FLAG && | 1824 | if (__lec_arp_check_expire(entry, now, priv)) { |
1786 | priv->topology_change) | 1825 | struct sk_buff *skb; |
1787 | time_to_check = priv->forward_delay_time; | 1826 | struct atm_vcc *vcc = entry->vcc; |
1788 | else | 1827 | |
1789 | time_to_check = priv->aging_time; | 1828 | spin_unlock_irqrestore(&priv->lec_arp_lock, |
1790 | 1829 | flags); | |
1791 | pr_debug("About to expire: %lx - %lx > %lx\n", | 1830 | while ((skb = skb_dequeue(&entry->tx_wait))) |
1792 | now, entry->last_used, time_to_check); | 1831 | lec_send(vcc, skb); |
1793 | if (time_after(now, entry->last_used + time_to_check) && | 1832 | entry->last_used = jiffies; |
1794 | !(entry->flags & LEC_PERMANENT_FLAG) && | 1833 | entry->status = ESI_FORWARD_DIRECT; |
1795 | !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ | ||
1796 | /* Remove entry */ | ||
1797 | pr_debug("Entry timed out\n"); | ||
1798 | lec_arp_remove(priv, entry); | ||
1799 | lec_arp_put(entry); | 1834 | lec_arp_put(entry); |
1800 | } else { | 1835 | |
1801 | /* Something else */ | 1836 | goto restart; |
1802 | if ((entry->status == ESI_VC_PENDING || | ||
1803 | entry->status == ESI_ARP_PENDING) && | ||
1804 | time_after_eq(now, | ||
1805 | entry->timestamp + | ||
1806 | priv->max_unknown_frame_time)) { | ||
1807 | entry->timestamp = jiffies; | ||
1808 | entry->packets_flooded = 0; | ||
1809 | if (entry->status == ESI_VC_PENDING) | ||
1810 | send_to_lecd(priv, l_svc_setup, | ||
1811 | entry->mac_addr, | ||
1812 | entry->atm_addr, | ||
1813 | NULL); | ||
1814 | } | ||
1815 | if (entry->status == ESI_FLUSH_PENDING && | ||
1816 | time_after_eq(now, entry->timestamp + | ||
1817 | priv->path_switching_delay)) { | ||
1818 | struct sk_buff *skb; | ||
1819 | struct atm_vcc *vcc = entry->vcc; | ||
1820 | |||
1821 | lec_arp_hold(entry); | ||
1822 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | ||
1823 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) | ||
1824 | lec_send(vcc, skb); | ||
1825 | entry->last_used = jiffies; | ||
1826 | entry->status = ESI_FORWARD_DIRECT; | ||
1827 | lec_arp_put(entry); | ||
1828 | goto restart; | ||
1829 | } | ||
1830 | } | 1837 | } |
1831 | } | 1838 | } |
1832 | } | 1839 | } |
@@ -2237,7 +2244,7 @@ restart: | |||
2237 | lec_arp_hold(entry); | 2244 | lec_arp_hold(entry); |
2238 | spin_unlock_irqrestore(&priv->lec_arp_lock, | 2245 | spin_unlock_irqrestore(&priv->lec_arp_lock, |
2239 | flags); | 2246 | flags); |
2240 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) | 2247 | while ((skb = skb_dequeue(&entry->tx_wait))) |
2241 | lec_send(vcc, skb); | 2248 | lec_send(vcc, skb); |
2242 | entry->last_used = jiffies; | 2249 | entry->last_used = jiffies; |
2243 | entry->status = ESI_FORWARD_DIRECT; | 2250 | entry->status = ESI_FORWARD_DIRECT; |