diff options
-rw-r--r-- | net/atm/lec.c | 1783 |
1 files changed, 899 insertions, 884 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c index 543960c86fa8..d2b44e91badf 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -1418,7 +1418,6 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr, | |||
1418 | * | 1418 | * |
1419 | * lec_arpc.c was added here when making | 1419 | * lec_arpc.c was added here when making |
1420 | * lane client modular. October 1997 | 1420 | * lane client modular. October 1997 |
1421 | * | ||
1422 | */ | 1421 | */ |
1423 | 1422 | ||
1424 | #include <linux/types.h> | 1423 | #include <linux/types.h> |
@@ -1429,7 +1428,6 @@ static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr, | |||
1429 | #include <linux/inetdevice.h> | 1428 | #include <linux/inetdevice.h> |
1430 | #include <net/route.h> | 1429 | #include <net/route.h> |
1431 | 1430 | ||
1432 | |||
1433 | #if 0 | 1431 | #if 0 |
1434 | #define DPRINTK(format,args...) | 1432 | #define DPRINTK(format,args...) |
1435 | /* | 1433 | /* |
@@ -1452,296 +1450,294 @@ static void lec_arp_expire_arp(unsigned long data); | |||
1452 | /* | 1450 | /* |
1453 | * Initialization of arp-cache | 1451 | * Initialization of arp-cache |
1454 | */ | 1452 | */ |
1455 | static void | 1453 | static void lec_arp_init(struct lec_priv *priv) |
1456 | lec_arp_init(struct lec_priv *priv) | ||
1457 | { | 1454 | { |
1458 | unsigned short i; | 1455 | unsigned short i; |
1459 | 1456 | ||
1460 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1457 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1461 | priv->lec_arp_tables[i] = NULL; | 1458 | priv->lec_arp_tables[i] = NULL; |
1462 | } | 1459 | } |
1463 | spin_lock_init(&priv->lec_arp_lock); | 1460 | spin_lock_init(&priv->lec_arp_lock); |
1464 | init_timer(&priv->lec_arp_timer); | 1461 | init_timer(&priv->lec_arp_timer); |
1465 | priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL; | 1462 | priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL; |
1466 | priv->lec_arp_timer.data = (unsigned long)priv; | 1463 | priv->lec_arp_timer.data = (unsigned long)priv; |
1467 | priv->lec_arp_timer.function = lec_arp_check_expire; | 1464 | priv->lec_arp_timer.function = lec_arp_check_expire; |
1468 | add_timer(&priv->lec_arp_timer); | 1465 | add_timer(&priv->lec_arp_timer); |
1469 | } | 1466 | } |
1470 | 1467 | ||
1471 | static void | 1468 | static void lec_arp_clear_vccs(struct lec_arp_table *entry) |
1472 | lec_arp_clear_vccs(struct lec_arp_table *entry) | ||
1473 | { | 1469 | { |
1474 | if (entry->vcc) { | 1470 | if (entry->vcc) { |
1475 | struct atm_vcc *vcc = entry->vcc; | 1471 | struct atm_vcc *vcc = entry->vcc; |
1476 | struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); | 1472 | struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc); |
1477 | struct net_device *dev = (struct net_device*) vcc->proto_data; | 1473 | struct net_device *dev = (struct net_device *)vcc->proto_data; |
1478 | 1474 | ||
1479 | vcc->pop = vpriv->old_pop; | 1475 | vcc->pop = vpriv->old_pop; |
1480 | if (vpriv->xoff) | 1476 | if (vpriv->xoff) |
1481 | netif_wake_queue(dev); | 1477 | netif_wake_queue(dev); |
1482 | kfree(vpriv); | 1478 | kfree(vpriv); |
1483 | vcc->user_back = NULL; | 1479 | vcc->user_back = NULL; |
1484 | vcc->push = entry->old_push; | 1480 | vcc->push = entry->old_push; |
1485 | vcc_release_async(vcc, -EPIPE); | 1481 | vcc_release_async(vcc, -EPIPE); |
1486 | vcc = NULL; | 1482 | vcc = NULL; |
1487 | } | 1483 | } |
1488 | if (entry->recv_vcc) { | 1484 | if (entry->recv_vcc) { |
1489 | entry->recv_vcc->push = entry->old_recv_push; | 1485 | entry->recv_vcc->push = entry->old_recv_push; |
1490 | vcc_release_async(entry->recv_vcc, -EPIPE); | 1486 | vcc_release_async(entry->recv_vcc, -EPIPE); |
1491 | entry->recv_vcc = NULL; | 1487 | entry->recv_vcc = NULL; |
1492 | } | 1488 | } |
1493 | } | 1489 | } |
1494 | 1490 | ||
1495 | /* | 1491 | /* |
1496 | * Insert entry to lec_arp_table | 1492 | * Insert entry to lec_arp_table |
1497 | * LANE2: Add to the end of the list to satisfy 8.1.13 | 1493 | * LANE2: Add to the end of the list to satisfy 8.1.13 |
1498 | */ | 1494 | */ |
1499 | static inline void | 1495 | static inline void |
1500 | lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add) | 1496 | lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add) |
1501 | { | 1497 | { |
1502 | unsigned short place; | 1498 | unsigned short place; |
1503 | struct lec_arp_table *tmp; | 1499 | struct lec_arp_table *tmp; |
1504 | 1500 | ||
1505 | place = HASH(to_add->mac_addr[ETH_ALEN-1]); | 1501 | place = HASH(to_add->mac_addr[ETH_ALEN - 1]); |
1506 | tmp = priv->lec_arp_tables[place]; | 1502 | tmp = priv->lec_arp_tables[place]; |
1507 | to_add->next = NULL; | 1503 | to_add->next = NULL; |
1508 | if (tmp == NULL) | 1504 | if (tmp == NULL) |
1509 | priv->lec_arp_tables[place] = to_add; | 1505 | priv->lec_arp_tables[place] = to_add; |
1510 | 1506 | ||
1511 | else { /* add to the end */ | 1507 | else { /* add to the end */ |
1512 | while (tmp->next) | 1508 | while (tmp->next) |
1513 | tmp = tmp->next; | 1509 | tmp = tmp->next; |
1514 | tmp->next = to_add; | 1510 | tmp->next = to_add; |
1515 | } | 1511 | } |
1516 | 1512 | ||
1517 | DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", | 1513 | DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", |
1518 | 0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1], | 1514 | 0xff & to_add->mac_addr[0], 0xff & to_add->mac_addr[1], |
1519 | 0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3], | 1515 | 0xff & to_add->mac_addr[2], 0xff & to_add->mac_addr[3], |
1520 | 0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]); | 1516 | 0xff & to_add->mac_addr[4], 0xff & to_add->mac_addr[5]); |
1521 | } | 1517 | } |
1522 | 1518 | ||
1523 | /* | 1519 | /* |
1524 | * Remove entry from lec_arp_table | 1520 | * Remove entry from lec_arp_table |
1525 | */ | 1521 | */ |
1526 | static int | 1522 | static int |
1527 | lec_arp_remove(struct lec_priv *priv, | 1523 | lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) |
1528 | struct lec_arp_table *to_remove) | ||
1529 | { | 1524 | { |
1530 | unsigned short place; | 1525 | unsigned short place; |
1531 | struct lec_arp_table *tmp; | 1526 | struct lec_arp_table *tmp; |
1532 | int remove_vcc=1; | 1527 | int remove_vcc = 1; |
1533 | 1528 | ||
1534 | if (!to_remove) { | 1529 | if (!to_remove) { |
1535 | return -1; | 1530 | return -1; |
1536 | } | 1531 | } |
1537 | place = HASH(to_remove->mac_addr[ETH_ALEN-1]); | 1532 | place = HASH(to_remove->mac_addr[ETH_ALEN - 1]); |
1538 | tmp = priv->lec_arp_tables[place]; | 1533 | tmp = priv->lec_arp_tables[place]; |
1539 | if (tmp == to_remove) { | 1534 | if (tmp == to_remove) { |
1540 | priv->lec_arp_tables[place] = tmp->next; | 1535 | priv->lec_arp_tables[place] = tmp->next; |
1541 | } else { | 1536 | } else { |
1542 | while(tmp && tmp->next != to_remove) { | 1537 | while (tmp && tmp->next != to_remove) { |
1543 | tmp = tmp->next; | 1538 | tmp = tmp->next; |
1544 | } | 1539 | } |
1545 | if (!tmp) {/* Entry was not found */ | 1540 | if (!tmp) { /* Entry was not found */ |
1546 | return -1; | 1541 | return -1; |
1547 | } | 1542 | } |
1548 | } | 1543 | } |
1549 | tmp->next = to_remove->next; | 1544 | tmp->next = to_remove->next; |
1550 | del_timer(&to_remove->timer); | 1545 | del_timer(&to_remove->timer); |
1551 | 1546 | ||
1552 | /* If this is the only MAC connected to this VCC, also tear down | 1547 | /* If this is the only MAC connected to this VCC, also tear down |
1553 | the VCC */ | 1548 | the VCC */ |
1554 | if (to_remove->status >= ESI_FLUSH_PENDING) { | 1549 | if (to_remove->status >= ESI_FLUSH_PENDING) { |
1555 | /* | 1550 | /* |
1556 | * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT | 1551 | * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT |
1557 | */ | 1552 | */ |
1558 | for(place = 0; place < LEC_ARP_TABLE_SIZE; place++) { | 1553 | for (place = 0; place < LEC_ARP_TABLE_SIZE; place++) { |
1559 | for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) { | 1554 | for (tmp = priv->lec_arp_tables[place]; tmp != NULL; |
1560 | if (memcmp(tmp->atm_addr, to_remove->atm_addr, | 1555 | tmp = tmp->next) { |
1561 | ATM_ESA_LEN)==0) { | 1556 | if (memcmp |
1562 | remove_vcc=0; | 1557 | (tmp->atm_addr, to_remove->atm_addr, |
1563 | break; | 1558 | ATM_ESA_LEN) == 0) { |
1564 | } | 1559 | remove_vcc = 0; |
1565 | } | 1560 | break; |
1566 | } | 1561 | } |
1567 | if (remove_vcc) | 1562 | } |
1568 | lec_arp_clear_vccs(to_remove); | 1563 | } |
1569 | } | 1564 | if (remove_vcc) |
1570 | skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */ | 1565 | lec_arp_clear_vccs(to_remove); |
1571 | 1566 | } | |
1572 | DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", | 1567 | skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */ |
1573 | 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1], | 1568 | |
1574 | 0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3], | 1569 | DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", |
1575 | 0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]); | 1570 | 0xff & to_remove->mac_addr[0], 0xff & to_remove->mac_addr[1], |
1576 | return 0; | 1571 | 0xff & to_remove->mac_addr[2], 0xff & to_remove->mac_addr[3], |
1572 | 0xff & to_remove->mac_addr[4], 0xff & to_remove->mac_addr[5]); | ||
1573 | return 0; | ||
1577 | } | 1574 | } |
1578 | 1575 | ||
1579 | #if DEBUG_ARP_TABLE | 1576 | #if DEBUG_ARP_TABLE |
1580 | static char* | 1577 | static char *get_status_string(unsigned char st) |
1581 | get_status_string(unsigned char st) | ||
1582 | { | 1578 | { |
1583 | switch(st) { | 1579 | switch (st) { |
1584 | case ESI_UNKNOWN: | 1580 | case ESI_UNKNOWN: |
1585 | return "ESI_UNKNOWN"; | 1581 | return "ESI_UNKNOWN"; |
1586 | case ESI_ARP_PENDING: | 1582 | case ESI_ARP_PENDING: |
1587 | return "ESI_ARP_PENDING"; | 1583 | return "ESI_ARP_PENDING"; |
1588 | case ESI_VC_PENDING: | 1584 | case ESI_VC_PENDING: |
1589 | return "ESI_VC_PENDING"; | 1585 | return "ESI_VC_PENDING"; |
1590 | case ESI_FLUSH_PENDING: | 1586 | case ESI_FLUSH_PENDING: |
1591 | return "ESI_FLUSH_PENDING"; | 1587 | return "ESI_FLUSH_PENDING"; |
1592 | case ESI_FORWARD_DIRECT: | 1588 | case ESI_FORWARD_DIRECT: |
1593 | return "ESI_FORWARD_DIRECT"; | 1589 | return "ESI_FORWARD_DIRECT"; |
1594 | default: | 1590 | default: |
1595 | return "<UNKNOWN>"; | 1591 | return "<UNKNOWN>"; |
1596 | } | 1592 | } |
1597 | } | 1593 | } |
1598 | #endif | 1594 | #endif |
1599 | 1595 | ||
1600 | static void | 1596 | static void dump_arp_table(struct lec_priv *priv) |
1601 | dump_arp_table(struct lec_priv *priv) | ||
1602 | { | 1597 | { |
1603 | #if DEBUG_ARP_TABLE | 1598 | #if DEBUG_ARP_TABLE |
1604 | int i,j, offset; | 1599 | int i, j, offset; |
1605 | struct lec_arp_table *rulla; | 1600 | struct lec_arp_table *rulla; |
1606 | char buf[1024]; | 1601 | char buf[1024]; |
1607 | struct lec_arp_table **lec_arp_tables = | 1602 | struct lec_arp_table **lec_arp_tables = |
1608 | (struct lec_arp_table **)priv->lec_arp_tables; | 1603 | (struct lec_arp_table **)priv->lec_arp_tables; |
1609 | struct lec_arp_table *lec_arp_empty_ones = | 1604 | struct lec_arp_table *lec_arp_empty_ones = |
1610 | (struct lec_arp_table *)priv->lec_arp_empty_ones; | 1605 | (struct lec_arp_table *)priv->lec_arp_empty_ones; |
1611 | struct lec_arp_table *lec_no_forward = | 1606 | struct lec_arp_table *lec_no_forward = |
1612 | (struct lec_arp_table *)priv->lec_no_forward; | 1607 | (struct lec_arp_table *)priv->lec_no_forward; |
1613 | struct lec_arp_table *mcast_fwds = priv->mcast_fwds; | 1608 | struct lec_arp_table *mcast_fwds = priv->mcast_fwds; |
1614 | 1609 | ||
1615 | 1610 | printk("Dump %p:\n", priv); | |
1616 | printk("Dump %p:\n",priv); | 1611 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1617 | for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { | 1612 | rulla = lec_arp_tables[i]; |
1618 | rulla = lec_arp_tables[i]; | 1613 | offset = 0; |
1619 | offset = 0; | 1614 | offset += sprintf(buf, "%d: %p\n", i, rulla); |
1620 | offset += sprintf(buf,"%d: %p\n",i, rulla); | 1615 | while (rulla) { |
1621 | while (rulla) { | 1616 | offset += sprintf(buf + offset, "Mac:"); |
1622 | offset += sprintf(buf+offset,"Mac:"); | 1617 | for (j = 0; j < ETH_ALEN; j++) { |
1623 | for(j=0;j<ETH_ALEN;j++) { | 1618 | offset += sprintf(buf + offset, |
1624 | offset+=sprintf(buf+offset, | 1619 | "%2.2x ", |
1625 | "%2.2x ", | 1620 | rulla->mac_addr[j] & 0xff); |
1626 | rulla->mac_addr[j]&0xff); | 1621 | } |
1627 | } | 1622 | offset += sprintf(buf + offset, "Atm:"); |
1628 | offset +=sprintf(buf+offset,"Atm:"); | 1623 | for (j = 0; j < ATM_ESA_LEN; j++) { |
1629 | for(j=0;j<ATM_ESA_LEN;j++) { | 1624 | offset += sprintf(buf + offset, |
1630 | offset+=sprintf(buf+offset, | 1625 | "%2.2x ", |
1631 | "%2.2x ", | 1626 | rulla->atm_addr[j] & 0xff); |
1632 | rulla->atm_addr[j]&0xff); | 1627 | } |
1633 | } | 1628 | offset += sprintf(buf + offset, |
1634 | offset+=sprintf(buf+offset, | 1629 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", |
1635 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", | 1630 | rulla->vcc ? rulla->vcc->vpi : 0, |
1636 | rulla->vcc?rulla->vcc->vpi:0, | 1631 | rulla->vcc ? rulla->vcc->vci : 0, |
1637 | rulla->vcc?rulla->vcc->vci:0, | 1632 | rulla->recv_vcc ? rulla->recv_vcc-> |
1638 | rulla->recv_vcc?rulla->recv_vcc->vpi:0, | 1633 | vpi : 0, |
1639 | rulla->recv_vcc?rulla->recv_vcc->vci:0, | 1634 | rulla->recv_vcc ? rulla->recv_vcc-> |
1640 | rulla->last_used, | 1635 | vci : 0, rulla->last_used, |
1641 | rulla->timestamp, rulla->no_tries); | 1636 | rulla->timestamp, rulla->no_tries); |
1642 | offset+=sprintf(buf+offset, | 1637 | offset += |
1643 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1638 | sprintf(buf + offset, |
1644 | rulla->flags, rulla->packets_flooded, | 1639 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1645 | get_status_string(rulla->status)); | 1640 | rulla->flags, rulla->packets_flooded, |
1646 | offset+=sprintf(buf+offset,"->%p\n",rulla->next); | 1641 | get_status_string(rulla->status)); |
1647 | rulla = rulla->next; | 1642 | offset += sprintf(buf + offset, "->%p\n", rulla->next); |
1648 | } | 1643 | rulla = rulla->next; |
1649 | printk("%s",buf); | 1644 | } |
1650 | } | 1645 | printk("%s", buf); |
1651 | rulla = lec_no_forward; | 1646 | } |
1652 | if (rulla) | 1647 | rulla = lec_no_forward; |
1653 | printk("No forward\n"); | 1648 | if (rulla) |
1654 | while(rulla) { | 1649 | printk("No forward\n"); |
1655 | offset=0; | 1650 | while (rulla) { |
1656 | offset += sprintf(buf+offset,"Mac:"); | 1651 | offset = 0; |
1657 | for(j=0;j<ETH_ALEN;j++) { | 1652 | offset += sprintf(buf + offset, "Mac:"); |
1658 | offset+=sprintf(buf+offset,"%2.2x ", | 1653 | for (j = 0; j < ETH_ALEN; j++) { |
1659 | rulla->mac_addr[j]&0xff); | 1654 | offset += sprintf(buf + offset, "%2.2x ", |
1660 | } | 1655 | rulla->mac_addr[j] & 0xff); |
1661 | offset +=sprintf(buf+offset,"Atm:"); | 1656 | } |
1662 | for(j=0;j<ATM_ESA_LEN;j++) { | 1657 | offset += sprintf(buf + offset, "Atm:"); |
1663 | offset+=sprintf(buf+offset,"%2.2x ", | 1658 | for (j = 0; j < ATM_ESA_LEN; j++) { |
1664 | rulla->atm_addr[j]&0xff); | 1659 | offset += sprintf(buf + offset, "%2.2x ", |
1665 | } | 1660 | rulla->atm_addr[j] & 0xff); |
1666 | offset+=sprintf(buf+offset, | 1661 | } |
1667 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", | 1662 | offset += sprintf(buf + offset, |
1668 | rulla->vcc?rulla->vcc->vpi:0, | 1663 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", |
1669 | rulla->vcc?rulla->vcc->vci:0, | 1664 | rulla->vcc ? rulla->vcc->vpi : 0, |
1670 | rulla->recv_vcc?rulla->recv_vcc->vpi:0, | 1665 | rulla->vcc ? rulla->vcc->vci : 0, |
1671 | rulla->recv_vcc?rulla->recv_vcc->vci:0, | 1666 | rulla->recv_vcc ? rulla->recv_vcc->vpi : 0, |
1672 | rulla->last_used, | 1667 | rulla->recv_vcc ? rulla->recv_vcc->vci : 0, |
1673 | rulla->timestamp, rulla->no_tries); | 1668 | rulla->last_used, |
1674 | offset+=sprintf(buf+offset, | 1669 | rulla->timestamp, rulla->no_tries); |
1675 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1670 | offset += sprintf(buf + offset, |
1676 | rulla->flags, rulla->packets_flooded, | 1671 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1677 | get_status_string(rulla->status)); | 1672 | rulla->flags, rulla->packets_flooded, |
1678 | offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); | 1673 | get_status_string(rulla->status)); |
1679 | rulla = rulla->next; | 1674 | offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next); |
1680 | printk("%s",buf); | 1675 | rulla = rulla->next; |
1681 | } | 1676 | printk("%s", buf); |
1682 | rulla = lec_arp_empty_ones; | 1677 | } |
1683 | if (rulla) | 1678 | rulla = lec_arp_empty_ones; |
1684 | printk("Empty ones\n"); | 1679 | if (rulla) |
1685 | while(rulla) { | 1680 | printk("Empty ones\n"); |
1686 | offset=0; | 1681 | while (rulla) { |
1687 | offset += sprintf(buf+offset,"Mac:"); | 1682 | offset = 0; |
1688 | for(j=0;j<ETH_ALEN;j++) { | 1683 | offset += sprintf(buf + offset, "Mac:"); |
1689 | offset+=sprintf(buf+offset,"%2.2x ", | 1684 | for (j = 0; j < ETH_ALEN; j++) { |
1690 | rulla->mac_addr[j]&0xff); | 1685 | offset += sprintf(buf + offset, "%2.2x ", |
1691 | } | 1686 | rulla->mac_addr[j] & 0xff); |
1692 | offset +=sprintf(buf+offset,"Atm:"); | 1687 | } |
1693 | for(j=0;j<ATM_ESA_LEN;j++) { | 1688 | offset += sprintf(buf + offset, "Atm:"); |
1694 | offset+=sprintf(buf+offset,"%2.2x ", | 1689 | for (j = 0; j < ATM_ESA_LEN; j++) { |
1695 | rulla->atm_addr[j]&0xff); | 1690 | offset += sprintf(buf + offset, "%2.2x ", |
1696 | } | 1691 | rulla->atm_addr[j] & 0xff); |
1697 | offset+=sprintf(buf+offset, | 1692 | } |
1698 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", | 1693 | offset += sprintf(buf + offset, |
1699 | rulla->vcc?rulla->vcc->vpi:0, | 1694 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", |
1700 | rulla->vcc?rulla->vcc->vci:0, | 1695 | rulla->vcc ? rulla->vcc->vpi : 0, |
1701 | rulla->recv_vcc?rulla->recv_vcc->vpi:0, | 1696 | rulla->vcc ? rulla->vcc->vci : 0, |
1702 | rulla->recv_vcc?rulla->recv_vcc->vci:0, | 1697 | rulla->recv_vcc ? rulla->recv_vcc->vpi : 0, |
1703 | rulla->last_used, | 1698 | rulla->recv_vcc ? rulla->recv_vcc->vci : 0, |
1704 | rulla->timestamp, rulla->no_tries); | 1699 | rulla->last_used, |
1705 | offset+=sprintf(buf+offset, | 1700 | rulla->timestamp, rulla->no_tries); |
1706 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1701 | offset += sprintf(buf + offset, |
1707 | rulla->flags, rulla->packets_flooded, | 1702 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1708 | get_status_string(rulla->status)); | 1703 | rulla->flags, rulla->packets_flooded, |
1709 | offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); | 1704 | get_status_string(rulla->status)); |
1710 | rulla = rulla->next; | 1705 | offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next); |
1711 | printk("%s",buf); | 1706 | rulla = rulla->next; |
1712 | } | 1707 | printk("%s", buf); |
1713 | 1708 | } | |
1714 | rulla = mcast_fwds; | 1709 | |
1715 | if (rulla) | 1710 | rulla = mcast_fwds; |
1716 | printk("Multicast Forward VCCs\n"); | 1711 | if (rulla) |
1717 | while(rulla) { | 1712 | printk("Multicast Forward VCCs\n"); |
1718 | offset=0; | 1713 | while (rulla) { |
1719 | offset += sprintf(buf+offset,"Mac:"); | 1714 | offset = 0; |
1720 | for(j=0;j<ETH_ALEN;j++) { | 1715 | offset += sprintf(buf + offset, "Mac:"); |
1721 | offset+=sprintf(buf+offset,"%2.2x ", | 1716 | for (j = 0; j < ETH_ALEN; j++) { |
1722 | rulla->mac_addr[j]&0xff); | 1717 | offset += sprintf(buf + offset, "%2.2x ", |
1723 | } | 1718 | rulla->mac_addr[j] & 0xff); |
1724 | offset +=sprintf(buf+offset,"Atm:"); | 1719 | } |
1725 | for(j=0;j<ATM_ESA_LEN;j++) { | 1720 | offset += sprintf(buf + offset, "Atm:"); |
1726 | offset+=sprintf(buf+offset,"%2.2x ", | 1721 | for (j = 0; j < ATM_ESA_LEN; j++) { |
1727 | rulla->atm_addr[j]&0xff); | 1722 | offset += sprintf(buf + offset, "%2.2x ", |
1728 | } | 1723 | rulla->atm_addr[j] & 0xff); |
1729 | offset+=sprintf(buf+offset, | 1724 | } |
1730 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", | 1725 | offset += sprintf(buf + offset, |
1731 | rulla->vcc?rulla->vcc->vpi:0, | 1726 | "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", |
1732 | rulla->vcc?rulla->vcc->vci:0, | 1727 | rulla->vcc ? rulla->vcc->vpi : 0, |
1733 | rulla->recv_vcc?rulla->recv_vcc->vpi:0, | 1728 | rulla->vcc ? rulla->vcc->vci : 0, |
1734 | rulla->recv_vcc?rulla->recv_vcc->vci:0, | 1729 | rulla->recv_vcc ? rulla->recv_vcc->vpi : 0, |
1735 | rulla->last_used, | 1730 | rulla->recv_vcc ? rulla->recv_vcc->vci : 0, |
1736 | rulla->timestamp, rulla->no_tries); | 1731 | rulla->last_used, |
1737 | offset+=sprintf(buf+offset, | 1732 | rulla->timestamp, rulla->no_tries); |
1738 | "Flags:%x, Packets_flooded:%x, Status: %s ", | 1733 | offset += sprintf(buf + offset, |
1739 | rulla->flags, rulla->packets_flooded, | 1734 | "Flags:%x, Packets_flooded:%x, Status: %s ", |
1740 | get_status_string(rulla->status)); | 1735 | rulla->flags, rulla->packets_flooded, |
1741 | offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); | 1736 | get_status_string(rulla->status)); |
1742 | rulla = rulla->next; | 1737 | offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next); |
1743 | printk("%s",buf); | 1738 | rulla = rulla->next; |
1744 | } | 1739 | printk("%s", buf); |
1740 | } | ||
1745 | 1741 | ||
1746 | #endif | 1742 | #endif |
1747 | } | 1743 | } |
@@ -1749,177 +1745,168 @@ dump_arp_table(struct lec_priv *priv) | |||
1749 | /* | 1745 | /* |
1750 | * Destruction of arp-cache | 1746 | * Destruction of arp-cache |
1751 | */ | 1747 | */ |
1752 | static void | 1748 | static void lec_arp_destroy(struct lec_priv *priv) |
1753 | lec_arp_destroy(struct lec_priv *priv) | ||
1754 | { | 1749 | { |
1755 | unsigned long flags; | 1750 | unsigned long flags; |
1756 | struct lec_arp_table *entry, *next; | 1751 | struct lec_arp_table *entry, *next; |
1757 | int i; | 1752 | int i; |
1753 | |||
1754 | del_timer_sync(&priv->lec_arp_timer); | ||
1758 | 1755 | ||
1759 | del_timer_sync(&priv->lec_arp_timer); | 1756 | /* |
1760 | 1757 | * Remove all entries | |
1761 | /* | 1758 | */ |
1762 | * Remove all entries | ||
1763 | */ | ||
1764 | 1759 | ||
1765 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 1760 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
1766 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1761 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1767 | for(entry = priv->lec_arp_tables[i]; entry != NULL; entry=next) { | 1762 | for (entry = priv->lec_arp_tables[i]; entry != NULL; |
1768 | next = entry->next; | 1763 | entry = next) { |
1769 | lec_arp_remove(priv, entry); | 1764 | next = entry->next; |
1770 | kfree(entry); | 1765 | lec_arp_remove(priv, entry); |
1771 | } | 1766 | kfree(entry); |
1772 | } | 1767 | } |
1773 | entry = priv->lec_arp_empty_ones; | 1768 | } |
1774 | while(entry) { | 1769 | entry = priv->lec_arp_empty_ones; |
1775 | next = entry->next; | 1770 | while (entry) { |
1776 | del_timer_sync(&entry->timer); | 1771 | next = entry->next; |
1777 | lec_arp_clear_vccs(entry); | 1772 | del_timer_sync(&entry->timer); |
1778 | kfree(entry); | 1773 | lec_arp_clear_vccs(entry); |
1779 | entry = next; | 1774 | kfree(entry); |
1780 | } | 1775 | entry = next; |
1781 | priv->lec_arp_empty_ones = NULL; | 1776 | } |
1782 | entry = priv->lec_no_forward; | 1777 | priv->lec_arp_empty_ones = NULL; |
1783 | while(entry) { | 1778 | entry = priv->lec_no_forward; |
1784 | next = entry->next; | 1779 | while (entry) { |
1785 | del_timer_sync(&entry->timer); | 1780 | next = entry->next; |
1786 | lec_arp_clear_vccs(entry); | 1781 | del_timer_sync(&entry->timer); |
1787 | kfree(entry); | 1782 | lec_arp_clear_vccs(entry); |
1788 | entry = next; | 1783 | kfree(entry); |
1789 | } | 1784 | entry = next; |
1790 | priv->lec_no_forward = NULL; | 1785 | } |
1791 | entry = priv->mcast_fwds; | 1786 | priv->lec_no_forward = NULL; |
1792 | while(entry) { | 1787 | entry = priv->mcast_fwds; |
1793 | next = entry->next; | 1788 | while (entry) { |
1794 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 1789 | next = entry->next; |
1795 | lec_arp_clear_vccs(entry); | 1790 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
1796 | kfree(entry); | 1791 | lec_arp_clear_vccs(entry); |
1797 | entry = next; | 1792 | kfree(entry); |
1798 | } | 1793 | entry = next; |
1799 | priv->mcast_fwds = NULL; | 1794 | } |
1800 | priv->mcast_vcc = NULL; | 1795 | priv->mcast_fwds = NULL; |
1801 | memset(priv->lec_arp_tables, 0, | 1796 | priv->mcast_vcc = NULL; |
1802 | sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE); | 1797 | memset(priv->lec_arp_tables, 0, |
1798 | sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE); | ||
1803 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1799 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
1804 | } | 1800 | } |
1805 | 1801 | ||
1806 | |||
1807 | /* | 1802 | /* |
1808 | * Find entry by mac_address | 1803 | * Find entry by mac_address |
1809 | */ | 1804 | */ |
1810 | static struct lec_arp_table* | 1805 | static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, |
1811 | lec_arp_find(struct lec_priv *priv, | 1806 | unsigned char *mac_addr) |
1812 | unsigned char *mac_addr) | ||
1813 | { | 1807 | { |
1814 | unsigned short place; | 1808 | unsigned short place; |
1815 | struct lec_arp_table *to_return; | 1809 | struct lec_arp_table *to_return; |
1816 | 1810 | ||
1817 | DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", | 1811 | DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", |
1818 | mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff, | 1812 | mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff, |
1819 | mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff); | 1813 | mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff); |
1820 | place = HASH(mac_addr[ETH_ALEN-1]); | 1814 | place = HASH(mac_addr[ETH_ALEN - 1]); |
1821 | 1815 | ||
1822 | to_return = priv->lec_arp_tables[place]; | 1816 | to_return = priv->lec_arp_tables[place]; |
1823 | while(to_return) { | 1817 | while (to_return) { |
1824 | if (!compare_ether_addr(mac_addr, to_return->mac_addr)) { | 1818 | if (!compare_ether_addr(mac_addr, to_return->mac_addr)) { |
1825 | return to_return; | 1819 | return to_return; |
1826 | } | 1820 | } |
1827 | to_return = to_return->next; | 1821 | to_return = to_return->next; |
1828 | } | 1822 | } |
1829 | return NULL; | 1823 | return NULL; |
1830 | } | 1824 | } |
1831 | 1825 | ||
1832 | static struct lec_arp_table* | 1826 | static struct lec_arp_table *make_entry(struct lec_priv *priv, |
1833 | make_entry(struct lec_priv *priv, unsigned char *mac_addr) | 1827 | unsigned char *mac_addr) |
1834 | { | 1828 | { |
1835 | struct lec_arp_table *to_return; | 1829 | struct lec_arp_table *to_return; |
1836 | 1830 | ||
1837 | to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC); | 1831 | to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC); |
1838 | if (!to_return) { | 1832 | if (!to_return) { |
1839 | printk("LEC: Arp entry kmalloc failed\n"); | 1833 | printk("LEC: Arp entry kmalloc failed\n"); |
1840 | return NULL; | 1834 | return NULL; |
1841 | } | 1835 | } |
1842 | memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); | 1836 | memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); |
1843 | init_timer(&to_return->timer); | 1837 | init_timer(&to_return->timer); |
1844 | to_return->timer.function = lec_arp_expire_arp; | 1838 | to_return->timer.function = lec_arp_expire_arp; |
1845 | to_return->timer.data = (unsigned long) to_return; | 1839 | to_return->timer.data = (unsigned long)to_return; |
1846 | to_return->last_used = jiffies; | 1840 | to_return->last_used = jiffies; |
1847 | to_return->priv = priv; | 1841 | to_return->priv = priv; |
1848 | skb_queue_head_init(&to_return->tx_wait); | 1842 | skb_queue_head_init(&to_return->tx_wait); |
1849 | return to_return; | 1843 | return to_return; |
1850 | } | 1844 | } |
1851 | 1845 | ||
1852 | /* | 1846 | /* Arp sent timer expired */ |
1853 | * | 1847 | static void lec_arp_expire_arp(unsigned long data) |
1854 | * Arp sent timer expired | ||
1855 | * | ||
1856 | */ | ||
1857 | static void | ||
1858 | lec_arp_expire_arp(unsigned long data) | ||
1859 | { | 1848 | { |
1860 | struct lec_arp_table *entry; | 1849 | struct lec_arp_table *entry; |
1861 | 1850 | ||
1862 | entry = (struct lec_arp_table *)data; | 1851 | entry = (struct lec_arp_table *)data; |
1863 | 1852 | ||
1864 | DPRINTK("lec_arp_expire_arp\n"); | 1853 | DPRINTK("lec_arp_expire_arp\n"); |
1865 | if (entry->status == ESI_ARP_PENDING) { | 1854 | if (entry->status == ESI_ARP_PENDING) { |
1866 | if (entry->no_tries <= entry->priv->max_retry_count) { | 1855 | if (entry->no_tries <= entry->priv->max_retry_count) { |
1867 | if (entry->is_rdesc) | 1856 | if (entry->is_rdesc) |
1868 | send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL); | 1857 | send_to_lecd(entry->priv, l_rdesc_arp_xmt, |
1869 | else | 1858 | entry->mac_addr, NULL, NULL); |
1870 | send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL); | 1859 | else |
1871 | entry->no_tries++; | 1860 | send_to_lecd(entry->priv, l_arp_xmt, |
1872 | } | 1861 | entry->mac_addr, NULL, NULL); |
1873 | mod_timer(&entry->timer, jiffies + (1*HZ)); | 1862 | entry->no_tries++; |
1874 | } | 1863 | } |
1864 | mod_timer(&entry->timer, jiffies + (1 * HZ)); | ||
1865 | } | ||
1875 | } | 1866 | } |
1876 | 1867 | ||
1877 | /* | 1868 | /* Unknown/unused vcc expire, remove associated entry */ |
1878 | * | 1869 | static void lec_arp_expire_vcc(unsigned long data) |
1879 | * Unknown/unused vcc expire, remove associated entry | ||
1880 | * | ||
1881 | */ | ||
1882 | static void | ||
1883 | lec_arp_expire_vcc(unsigned long data) | ||
1884 | { | 1870 | { |
1885 | unsigned long flags; | 1871 | unsigned long flags; |
1886 | struct lec_arp_table *to_remove = (struct lec_arp_table*)data; | 1872 | struct lec_arp_table *to_remove = (struct lec_arp_table *)data; |
1887 | struct lec_priv *priv = (struct lec_priv *)to_remove->priv; | 1873 | struct lec_priv *priv = (struct lec_priv *)to_remove->priv; |
1888 | struct lec_arp_table *entry = NULL; | 1874 | struct lec_arp_table *entry = NULL; |
1889 | 1875 | ||
1890 | del_timer(&to_remove->timer); | 1876 | del_timer(&to_remove->timer); |
1891 | 1877 | ||
1892 | DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n", | 1878 | DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n", |
1893 | to_remove, priv, | 1879 | to_remove, priv, |
1894 | to_remove->vcc?to_remove->recv_vcc->vpi:0, | 1880 | to_remove->vcc ? to_remove->recv_vcc->vpi : 0, |
1895 | to_remove->vcc?to_remove->recv_vcc->vci:0); | 1881 | to_remove->vcc ? to_remove->recv_vcc->vci : 0); |
1896 | DPRINTK("eo:%p nf:%p\n",priv->lec_arp_empty_ones,priv->lec_no_forward); | 1882 | DPRINTK("eo:%p nf:%p\n", priv->lec_arp_empty_ones, |
1883 | priv->lec_no_forward); | ||
1897 | 1884 | ||
1898 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 1885 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
1899 | if (to_remove == priv->lec_arp_empty_ones) | 1886 | if (to_remove == priv->lec_arp_empty_ones) |
1900 | priv->lec_arp_empty_ones = to_remove->next; | 1887 | priv->lec_arp_empty_ones = to_remove->next; |
1901 | else { | 1888 | else { |
1902 | entry = priv->lec_arp_empty_ones; | 1889 | entry = priv->lec_arp_empty_ones; |
1903 | while (entry && entry->next != to_remove) | 1890 | while (entry && entry->next != to_remove) |
1904 | entry = entry->next; | 1891 | entry = entry->next; |
1905 | if (entry) | 1892 | if (entry) |
1906 | entry->next = to_remove->next; | 1893 | entry->next = to_remove->next; |
1907 | } | 1894 | } |
1908 | if (!entry) { | 1895 | if (!entry) { |
1909 | if (to_remove == priv->lec_no_forward) { | 1896 | if (to_remove == priv->lec_no_forward) { |
1910 | priv->lec_no_forward = to_remove->next; | 1897 | priv->lec_no_forward = to_remove->next; |
1911 | } else { | 1898 | } else { |
1912 | entry = priv->lec_no_forward; | 1899 | entry = priv->lec_no_forward; |
1913 | while (entry && entry->next != to_remove) | 1900 | while (entry && entry->next != to_remove) |
1914 | entry = entry->next; | 1901 | entry = entry->next; |
1915 | if (entry) | 1902 | if (entry) |
1916 | entry->next = to_remove->next; | 1903 | entry->next = to_remove->next; |
1917 | } | 1904 | } |
1918 | } | 1905 | } |
1919 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1906 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
1920 | 1907 | ||
1921 | lec_arp_clear_vccs(to_remove); | 1908 | lec_arp_clear_vccs(to_remove); |
1922 | kfree(to_remove); | 1909 | kfree(to_remove); |
1923 | } | 1910 | } |
1924 | 1911 | ||
1925 | /* | 1912 | /* |
@@ -1938,64 +1925,68 @@ lec_arp_expire_vcc(unsigned long data) | |||
1938 | * to ESI_FORWARD_DIRECT. This causes the flush period to end | 1925 | * to ESI_FORWARD_DIRECT. This causes the flush period to end |
1939 | * regardless of the progress of the flush protocol. | 1926 | * regardless of the progress of the flush protocol. |
1940 | */ | 1927 | */ |
1941 | static void | 1928 | static void lec_arp_check_expire(unsigned long data) |
1942 | lec_arp_check_expire(unsigned long data) | ||
1943 | { | 1929 | { |
1944 | unsigned long flags; | 1930 | unsigned long flags; |
1945 | struct lec_priv *priv = (struct lec_priv *)data; | 1931 | struct lec_priv *priv = (struct lec_priv *)data; |
1946 | struct lec_arp_table *entry, *next; | 1932 | struct lec_arp_table *entry, *next; |
1947 | unsigned long now; | 1933 | unsigned long now; |
1948 | unsigned long time_to_check; | 1934 | unsigned long time_to_check; |
1949 | int i; | 1935 | int i; |
1950 | 1936 | ||
1951 | DPRINTK("lec_arp_check_expire %p\n",priv); | 1937 | DPRINTK("lec_arp_check_expire %p\n", priv); |
1952 | DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones, | 1938 | DPRINTK("expire: eo:%p nf:%p\n", priv->lec_arp_empty_ones, |
1953 | priv->lec_no_forward); | 1939 | priv->lec_no_forward); |
1954 | now = jiffies; | 1940 | now = jiffies; |
1955 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 1941 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
1956 | for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1942 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1957 | for(entry = priv->lec_arp_tables[i]; entry != NULL; ) { | 1943 | for (entry = priv->lec_arp_tables[i]; entry != NULL;) { |
1958 | if ((entry->flags) & LEC_REMOTE_FLAG && | 1944 | if ((entry->flags) & LEC_REMOTE_FLAG && |
1959 | priv->topology_change) | 1945 | priv->topology_change) |
1960 | time_to_check = priv->forward_delay_time; | 1946 | time_to_check = priv->forward_delay_time; |
1961 | else | 1947 | else |
1962 | time_to_check = priv->aging_time; | 1948 | time_to_check = priv->aging_time; |
1963 | 1949 | ||
1964 | DPRINTK("About to expire: %lx - %lx > %lx\n", | 1950 | DPRINTK("About to expire: %lx - %lx > %lx\n", |
1965 | now,entry->last_used, time_to_check); | 1951 | now, entry->last_used, time_to_check); |
1966 | if( time_after(now, entry->last_used+ | 1952 | if (time_after(now, entry->last_used + time_to_check) |
1967 | time_to_check) && | 1953 | && !(entry->flags & LEC_PERMANENT_FLAG) |
1968 | !(entry->flags & LEC_PERMANENT_FLAG) && | 1954 | && !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ |
1969 | !(entry->mac_addr[0] & 0x01) ) { /* LANE2: 7.1.20 */ | ||
1970 | /* Remove entry */ | 1955 | /* Remove entry */ |
1971 | DPRINTK("LEC:Entry timed out\n"); | 1956 | DPRINTK("LEC:Entry timed out\n"); |
1972 | next = entry->next; | 1957 | next = entry->next; |
1973 | lec_arp_remove(priv, entry); | 1958 | lec_arp_remove(priv, entry); |
1974 | kfree(entry); | 1959 | kfree(entry); |
1975 | entry = next; | 1960 | entry = next; |
1976 | } else { | 1961 | } else { |
1977 | /* Something else */ | 1962 | /* Something else */ |
1978 | if ((entry->status == ESI_VC_PENDING || | 1963 | if ((entry->status == ESI_VC_PENDING || |
1979 | entry->status == ESI_ARP_PENDING) | 1964 | entry->status == ESI_ARP_PENDING) |
1980 | && time_after_eq(now, | 1965 | && time_after_eq(now, |
1981 | entry->timestamp + | 1966 | entry->timestamp + |
1982 | priv->max_unknown_frame_time)) { | 1967 | priv-> |
1968 | max_unknown_frame_time)) { | ||
1983 | entry->timestamp = jiffies; | 1969 | entry->timestamp = jiffies; |
1984 | entry->packets_flooded = 0; | 1970 | entry->packets_flooded = 0; |
1985 | if (entry->status == ESI_VC_PENDING) | 1971 | if (entry->status == ESI_VC_PENDING) |
1986 | send_to_lecd(priv, l_svc_setup, entry->mac_addr, entry->atm_addr, NULL); | 1972 | send_to_lecd(priv, l_svc_setup, |
1973 | entry->mac_addr, | ||
1974 | entry->atm_addr, | ||
1975 | NULL); | ||
1987 | } | 1976 | } |
1988 | if (entry->status == ESI_FLUSH_PENDING | 1977 | if (entry->status == ESI_FLUSH_PENDING |
1989 | && | 1978 | && |
1990 | time_after_eq(now, entry->timestamp+ | 1979 | time_after_eq(now, entry->timestamp + |
1991 | priv->path_switching_delay)) { | 1980 | priv->path_switching_delay)) { |
1992 | struct sk_buff *skb; | 1981 | struct sk_buff *skb; |
1993 | 1982 | ||
1994 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) | 1983 | while ((skb = |
1995 | lec_send(entry->vcc, skb, entry->priv); | 1984 | skb_dequeue(&entry->tx_wait)) != |
1985 | NULL) | ||
1986 | lec_send(entry->vcc, skb, | ||
1987 | entry->priv); | ||
1996 | entry->last_used = jiffies; | 1988 | entry->last_used = jiffies; |
1997 | entry->status = | 1989 | entry->status = ESI_FORWARD_DIRECT; |
1998 | ESI_FORWARD_DIRECT; | ||
1999 | } | 1990 | } |
2000 | entry = entry->next; | 1991 | entry = entry->next; |
2001 | } | 1992 | } |
@@ -2003,93 +1994,101 @@ lec_arp_check_expire(unsigned long data) | |||
2003 | } | 1994 | } |
2004 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1995 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2005 | 1996 | ||
2006 | mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL); | 1997 | mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL); |
2007 | } | 1998 | } |
1999 | |||
2008 | /* | 2000 | /* |
2009 | * Try to find vcc where mac_address is attached. | 2001 | * Try to find vcc where mac_address is attached. |
2010 | * | 2002 | * |
2011 | */ | 2003 | */ |
2012 | static struct atm_vcc* | 2004 | static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, |
2013 | lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, | 2005 | unsigned char *mac_to_find, int is_rdesc, |
2014 | int is_rdesc, struct lec_arp_table **ret_entry) | 2006 | struct lec_arp_table **ret_entry) |
2015 | { | 2007 | { |
2016 | unsigned long flags; | 2008 | unsigned long flags; |
2017 | struct lec_arp_table *entry; | 2009 | struct lec_arp_table *entry; |
2018 | struct atm_vcc *found; | 2010 | struct atm_vcc *found; |
2019 | 2011 | ||
2020 | if (mac_to_find[0] & 0x01) { | 2012 | if (mac_to_find[0] & 0x01) { |
2021 | switch (priv->lane_version) { | 2013 | switch (priv->lane_version) { |
2022 | case 1: | 2014 | case 1: |
2023 | return priv->mcast_vcc; | 2015 | return priv->mcast_vcc; |
2024 | break; | 2016 | break; |
2025 | case 2: /* LANE2 wants arp for multicast addresses */ | 2017 | case 2: /* LANE2 wants arp for multicast addresses */ |
2026 | if (!compare_ether_addr(mac_to_find, bus_mac)) | 2018 | if (!compare_ether_addr(mac_to_find, bus_mac)) |
2027 | return priv->mcast_vcc; | 2019 | return priv->mcast_vcc; |
2028 | break; | 2020 | break; |
2029 | default: | 2021 | default: |
2030 | break; | 2022 | break; |
2031 | } | 2023 | } |
2032 | } | 2024 | } |
2033 | 2025 | ||
2034 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2026 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2035 | entry = lec_arp_find(priv, mac_to_find); | 2027 | entry = lec_arp_find(priv, mac_to_find); |
2036 | 2028 | ||
2037 | if (entry) { | 2029 | if (entry) { |
2038 | if (entry->status == ESI_FORWARD_DIRECT) { | 2030 | if (entry->status == ESI_FORWARD_DIRECT) { |
2039 | /* Connection Ok */ | 2031 | /* Connection Ok */ |
2040 | entry->last_used = jiffies; | 2032 | entry->last_used = jiffies; |
2041 | *ret_entry = entry; | 2033 | *ret_entry = entry; |
2042 | found = entry->vcc; | 2034 | found = entry->vcc; |
2043 | goto out; | 2035 | goto out; |
2044 | } | 2036 | } |
2045 | /* If the LE_ARP cache entry is still pending, reset count to 0 | 2037 | /* |
2038 | * If the LE_ARP cache entry is still pending, reset count to 0 | ||
2046 | * so another LE_ARP request can be made for this frame. | 2039 | * so another LE_ARP request can be made for this frame. |
2047 | */ | 2040 | */ |
2048 | if (entry->status == ESI_ARP_PENDING) { | 2041 | if (entry->status == ESI_ARP_PENDING) { |
2049 | entry->no_tries = 0; | 2042 | entry->no_tries = 0; |
2050 | } | 2043 | } |
2051 | /* Data direct VC not yet set up, check to see if the unknown | 2044 | /* |
2052 | frame count is greater than the limit. If the limit has | 2045 | * Data direct VC not yet set up, check to see if the unknown |
2053 | not been reached, allow the caller to send packet to | 2046 | * frame count is greater than the limit. If the limit has |
2054 | BUS. */ | 2047 | * not been reached, allow the caller to send packet to |
2055 | if (entry->status != ESI_FLUSH_PENDING && | 2048 | * BUS. |
2056 | entry->packets_flooded<priv->maximum_unknown_frame_count) { | 2049 | */ |
2057 | entry->packets_flooded++; | 2050 | if (entry->status != ESI_FLUSH_PENDING && |
2058 | DPRINTK("LEC_ARP: Flooding..\n"); | 2051 | entry->packets_flooded < |
2059 | found = priv->mcast_vcc; | 2052 | priv->maximum_unknown_frame_count) { |
2053 | entry->packets_flooded++; | ||
2054 | DPRINTK("LEC_ARP: Flooding..\n"); | ||
2055 | found = priv->mcast_vcc; | ||
2060 | goto out; | 2056 | goto out; |
2061 | } | 2057 | } |
2062 | /* We got here because entry->status == ESI_FLUSH_PENDING | 2058 | /* |
2059 | * We got here because entry->status == ESI_FLUSH_PENDING | ||
2063 | * or BUS flood limit was reached for an entry which is | 2060 | * or BUS flood limit was reached for an entry which is |
2064 | * in ESI_ARP_PENDING or ESI_VC_PENDING state. | 2061 | * in ESI_ARP_PENDING or ESI_VC_PENDING state. |
2065 | */ | 2062 | */ |
2066 | *ret_entry = entry; | 2063 | *ret_entry = entry; |
2067 | DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc); | 2064 | DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, |
2068 | found = NULL; | 2065 | entry->vcc); |
2069 | } else { | 2066 | found = NULL; |
2070 | /* No matching entry was found */ | 2067 | } else { |
2071 | entry = make_entry(priv, mac_to_find); | 2068 | /* No matching entry was found */ |
2072 | DPRINTK("LEC_ARP: Making entry\n"); | 2069 | entry = make_entry(priv, mac_to_find); |
2073 | if (!entry) { | 2070 | DPRINTK("LEC_ARP: Making entry\n"); |
2074 | found = priv->mcast_vcc; | 2071 | if (!entry) { |
2072 | found = priv->mcast_vcc; | ||
2075 | goto out; | 2073 | goto out; |
2076 | } | 2074 | } |
2077 | lec_arp_add(priv, entry); | 2075 | lec_arp_add(priv, entry); |
2078 | /* We want arp-request(s) to be sent */ | 2076 | /* We want arp-request(s) to be sent */ |
2079 | entry->packets_flooded =1; | 2077 | entry->packets_flooded = 1; |
2080 | entry->status = ESI_ARP_PENDING; | 2078 | entry->status = ESI_ARP_PENDING; |
2081 | entry->no_tries = 1; | 2079 | entry->no_tries = 1; |
2082 | entry->last_used = entry->timestamp = jiffies; | 2080 | entry->last_used = entry->timestamp = jiffies; |
2083 | entry->is_rdesc = is_rdesc; | 2081 | entry->is_rdesc = is_rdesc; |
2084 | if (entry->is_rdesc) | 2082 | if (entry->is_rdesc) |
2085 | send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL); | 2083 | send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, |
2086 | else | 2084 | NULL); |
2087 | send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL); | 2085 | else |
2088 | entry->timer.expires = jiffies + (1*HZ); | 2086 | send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL); |
2089 | entry->timer.function = lec_arp_expire_arp; | 2087 | entry->timer.expires = jiffies + (1 * HZ); |
2090 | add_timer(&entry->timer); | 2088 | entry->timer.function = lec_arp_expire_arp; |
2091 | found = priv->mcast_vcc; | 2089 | add_timer(&entry->timer); |
2092 | } | 2090 | found = priv->mcast_vcc; |
2091 | } | ||
2093 | 2092 | ||
2094 | out: | 2093 | out: |
2095 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2094 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
@@ -2097,30 +2096,31 @@ out: | |||
2097 | } | 2096 | } |
2098 | 2097 | ||
2099 | static int | 2098 | static int |
2100 | lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, | 2099 | lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, |
2101 | unsigned long permanent) | 2100 | unsigned long permanent) |
2102 | { | 2101 | { |
2103 | unsigned long flags; | 2102 | unsigned long flags; |
2104 | struct lec_arp_table *entry, *next; | 2103 | struct lec_arp_table *entry, *next; |
2105 | int i; | 2104 | int i; |
2106 | 2105 | ||
2107 | DPRINTK("lec_addr_delete\n"); | 2106 | DPRINTK("lec_addr_delete\n"); |
2108 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2107 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2109 | for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2108 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2110 | for(entry = priv->lec_arp_tables[i]; entry != NULL; entry = next) { | 2109 | for (entry = priv->lec_arp_tables[i]; entry != NULL; |
2111 | next = entry->next; | 2110 | entry = next) { |
2112 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) | 2111 | next = entry->next; |
2113 | && (permanent || | 2112 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) |
2114 | !(entry->flags & LEC_PERMANENT_FLAG))) { | 2113 | && (permanent || |
2114 | !(entry->flags & LEC_PERMANENT_FLAG))) { | ||
2115 | lec_arp_remove(priv, entry); | 2115 | lec_arp_remove(priv, entry); |
2116 | kfree(entry); | 2116 | kfree(entry); |
2117 | } | 2117 | } |
2118 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2118 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2119 | return 0; | 2119 | return 0; |
2120 | } | 2120 | } |
2121 | } | 2121 | } |
2122 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2122 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2123 | return -1; | 2123 | return -1; |
2124 | } | 2124 | } |
2125 | 2125 | ||
2126 | /* | 2126 | /* |
@@ -2128,109 +2128,109 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, | |||
2128 | */ | 2128 | */ |
2129 | static void | 2129 | static void |
2130 | lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, | 2130 | lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, |
2131 | unsigned char *atm_addr, unsigned long remoteflag, | 2131 | unsigned char *atm_addr, unsigned long remoteflag, |
2132 | unsigned int targetless_le_arp) | 2132 | unsigned int targetless_le_arp) |
2133 | { | 2133 | { |
2134 | unsigned long flags; | 2134 | unsigned long flags; |
2135 | struct lec_arp_table *entry, *tmp; | 2135 | struct lec_arp_table *entry, *tmp; |
2136 | int i; | 2136 | int i; |
2137 | 2137 | ||
2138 | DPRINTK("lec:%s", (targetless_le_arp) ? "targetless ": " "); | 2138 | DPRINTK("lec:%s", (targetless_le_arp) ? "targetless " : " "); |
2139 | DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", | 2139 | DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", |
2140 | mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3], | 2140 | mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], |
2141 | mac_addr[4],mac_addr[5]); | 2141 | mac_addr[4], mac_addr[5]); |
2142 | 2142 | ||
2143 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2143 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2144 | entry = lec_arp_find(priv, mac_addr); | 2144 | entry = lec_arp_find(priv, mac_addr); |
2145 | if (entry == NULL && targetless_le_arp) | 2145 | if (entry == NULL && targetless_le_arp) |
2146 | goto out; /* LANE2: ignore targetless LE_ARPs for which | 2146 | goto out; /* |
2147 | * we have no entry in the cache. 7.1.30 | 2147 | * LANE2: ignore targetless LE_ARPs for which |
2148 | */ | 2148 | * we have no entry in the cache. 7.1.30 |
2149 | if (priv->lec_arp_empty_ones) { | 2149 | */ |
2150 | entry = priv->lec_arp_empty_ones; | 2150 | if (priv->lec_arp_empty_ones) { |
2151 | if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) { | 2151 | entry = priv->lec_arp_empty_ones; |
2152 | priv->lec_arp_empty_ones = entry->next; | 2152 | if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) { |
2153 | } else { | 2153 | priv->lec_arp_empty_ones = entry->next; |
2154 | while(entry->next && memcmp(entry->next->atm_addr, | 2154 | } else { |
2155 | atm_addr, ATM_ESA_LEN)) | 2155 | while (entry->next && memcmp(entry->next->atm_addr, |
2156 | entry = entry->next; | 2156 | atm_addr, ATM_ESA_LEN)) |
2157 | if (entry->next) { | 2157 | entry = entry->next; |
2158 | tmp = entry; | 2158 | if (entry->next) { |
2159 | entry = entry->next; | 2159 | tmp = entry; |
2160 | tmp->next = entry->next; | 2160 | entry = entry->next; |
2161 | } else | 2161 | tmp->next = entry->next; |
2162 | entry = NULL; | 2162 | } else |
2163 | 2163 | entry = NULL; | |
2164 | } | 2164 | |
2165 | if (entry) { | 2165 | } |
2166 | del_timer(&entry->timer); | 2166 | if (entry) { |
2167 | tmp = lec_arp_find(priv, mac_addr); | 2167 | del_timer(&entry->timer); |
2168 | if (tmp) { | 2168 | tmp = lec_arp_find(priv, mac_addr); |
2169 | del_timer(&tmp->timer); | 2169 | if (tmp) { |
2170 | tmp->status = ESI_FORWARD_DIRECT; | 2170 | del_timer(&tmp->timer); |
2171 | memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN); | 2171 | tmp->status = ESI_FORWARD_DIRECT; |
2172 | tmp->vcc = entry->vcc; | 2172 | memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN); |
2173 | tmp->old_push = entry->old_push; | 2173 | tmp->vcc = entry->vcc; |
2174 | tmp->last_used = jiffies; | 2174 | tmp->old_push = entry->old_push; |
2175 | del_timer(&entry->timer); | 2175 | tmp->last_used = jiffies; |
2176 | kfree(entry); | 2176 | del_timer(&entry->timer); |
2177 | entry=tmp; | 2177 | kfree(entry); |
2178 | } else { | 2178 | entry = tmp; |
2179 | entry->status = ESI_FORWARD_DIRECT; | 2179 | } else { |
2180 | memcpy(entry->mac_addr, mac_addr, ETH_ALEN); | 2180 | entry->status = ESI_FORWARD_DIRECT; |
2181 | entry->last_used = jiffies; | 2181 | memcpy(entry->mac_addr, mac_addr, ETH_ALEN); |
2182 | lec_arp_add(priv, entry); | 2182 | entry->last_used = jiffies; |
2183 | } | 2183 | lec_arp_add(priv, entry); |
2184 | if (remoteflag) | 2184 | } |
2185 | entry->flags|=LEC_REMOTE_FLAG; | 2185 | if (remoteflag) |
2186 | else | 2186 | entry->flags |= LEC_REMOTE_FLAG; |
2187 | entry->flags&=~LEC_REMOTE_FLAG; | 2187 | else |
2188 | DPRINTK("After update\n"); | 2188 | entry->flags &= ~LEC_REMOTE_FLAG; |
2189 | dump_arp_table(priv); | 2189 | DPRINTK("After update\n"); |
2190 | goto out; | 2190 | dump_arp_table(priv); |
2191 | } | ||
2192 | } | ||
2193 | entry = lec_arp_find(priv, mac_addr); | ||
2194 | if (!entry) { | ||
2195 | entry = make_entry(priv, mac_addr); | ||
2196 | if (!entry) | ||
2197 | goto out; | 2191 | goto out; |
2198 | entry->status = ESI_UNKNOWN; | 2192 | } |
2199 | lec_arp_add(priv, entry); | 2193 | } |
2200 | /* Temporary, changes before end of function */ | 2194 | entry = lec_arp_find(priv, mac_addr); |
2201 | } | 2195 | if (!entry) { |
2202 | memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); | 2196 | entry = make_entry(priv, mac_addr); |
2203 | del_timer(&entry->timer); | 2197 | if (!entry) |
2204 | for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2198 | goto out; |
2205 | for(tmp = priv->lec_arp_tables[i]; tmp; tmp=tmp->next) { | 2199 | entry->status = ESI_UNKNOWN; |
2206 | if (entry != tmp && | 2200 | lec_arp_add(priv, entry); |
2207 | !memcmp(tmp->atm_addr, atm_addr, | 2201 | /* Temporary, changes before end of function */ |
2208 | ATM_ESA_LEN)) { | 2202 | } |
2209 | /* Vcc to this host exists */ | 2203 | memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); |
2210 | if (tmp->status > ESI_VC_PENDING) { | 2204 | del_timer(&entry->timer); |
2211 | /* | 2205 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2212 | * ESI_FLUSH_PENDING, | 2206 | for (tmp = priv->lec_arp_tables[i]; tmp; tmp = tmp->next) { |
2213 | * ESI_FORWARD_DIRECT | 2207 | if (entry != tmp && |
2214 | */ | 2208 | !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) { |
2215 | entry->vcc = tmp->vcc; | 2209 | /* Vcc to this host exists */ |
2216 | entry->old_push=tmp->old_push; | 2210 | if (tmp->status > ESI_VC_PENDING) { |
2217 | } | 2211 | /* |
2218 | entry->status=tmp->status; | 2212 | * ESI_FLUSH_PENDING, |
2219 | break; | 2213 | * ESI_FORWARD_DIRECT |
2220 | } | 2214 | */ |
2221 | } | 2215 | entry->vcc = tmp->vcc; |
2222 | } | 2216 | entry->old_push = tmp->old_push; |
2223 | if (remoteflag) | 2217 | } |
2224 | entry->flags|=LEC_REMOTE_FLAG; | 2218 | entry->status = tmp->status; |
2225 | else | 2219 | break; |
2226 | entry->flags&=~LEC_REMOTE_FLAG; | 2220 | } |
2227 | if (entry->status == ESI_ARP_PENDING || | 2221 | } |
2228 | entry->status == ESI_UNKNOWN) { | 2222 | } |
2229 | entry->status = ESI_VC_PENDING; | 2223 | if (remoteflag) |
2230 | send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL); | 2224 | entry->flags |= LEC_REMOTE_FLAG; |
2231 | } | 2225 | else |
2232 | DPRINTK("After update2\n"); | 2226 | entry->flags &= ~LEC_REMOTE_FLAG; |
2233 | dump_arp_table(priv); | 2227 | if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) { |
2228 | entry->status = ESI_VC_PENDING; | ||
2229 | send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, | ||
2230 | NULL); | ||
2231 | } | ||
2232 | DPRINTK("After update2\n"); | ||
2233 | dump_arp_table(priv); | ||
2234 | out: | 2234 | out: |
2235 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2235 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2236 | } | 2236 | } |
@@ -2240,299 +2240,312 @@ out: | |||
2240 | */ | 2240 | */ |
2241 | static void | 2241 | static void |
2242 | lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | 2242 | lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, |
2243 | struct atm_vcc *vcc, | 2243 | struct atm_vcc *vcc, |
2244 | void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb)) | 2244 | void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb)) |
2245 | { | 2245 | { |
2246 | unsigned long flags; | 2246 | unsigned long flags; |
2247 | struct lec_arp_table *entry; | 2247 | struct lec_arp_table *entry; |
2248 | int i, found_entry=0; | 2248 | int i, found_entry = 0; |
2249 | 2249 | ||
2250 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2250 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2251 | if (ioc_data->receive == 2) { | 2251 | if (ioc_data->receive == 2) { |
2252 | /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 2252 | /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
2253 | 2253 | ||
2254 | DPRINTK("LEC_ARP: Attaching mcast forward\n"); | 2254 | DPRINTK("LEC_ARP: Attaching mcast forward\n"); |
2255 | #if 0 | 2255 | #if 0 |
2256 | entry = lec_arp_find(priv, bus_mac); | 2256 | entry = lec_arp_find(priv, bus_mac); |
2257 | if (!entry) { | 2257 | if (!entry) { |
2258 | printk("LEC_ARP: Multicast entry not found!\n"); | 2258 | printk("LEC_ARP: Multicast entry not found!\n"); |
2259 | goto out; | 2259 | goto out; |
2260 | } | 2260 | } |
2261 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); | 2261 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); |
2262 | entry->recv_vcc = vcc; | 2262 | entry->recv_vcc = vcc; |
2263 | entry->old_recv_push = old_push; | 2263 | entry->old_recv_push = old_push; |
2264 | #endif | 2264 | #endif |
2265 | entry = make_entry(priv, bus_mac); | 2265 | entry = make_entry(priv, bus_mac); |
2266 | if (entry == NULL) | 2266 | if (entry == NULL) |
2267 | goto out; | 2267 | goto out; |
2268 | del_timer(&entry->timer); | 2268 | del_timer(&entry->timer); |
2269 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); | 2269 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); |
2270 | entry->recv_vcc = vcc; | 2270 | entry->recv_vcc = vcc; |
2271 | entry->old_recv_push = old_push; | 2271 | entry->old_recv_push = old_push; |
2272 | entry->next = priv->mcast_fwds; | 2272 | entry->next = priv->mcast_fwds; |
2273 | priv->mcast_fwds = entry; | 2273 | priv->mcast_fwds = entry; |
2274 | goto out; | 2274 | goto out; |
2275 | } else if (ioc_data->receive == 1) { | 2275 | } else if (ioc_data->receive == 1) { |
2276 | /* Vcc which we don't want to make default vcc, attach it | 2276 | /* |
2277 | anyway. */ | 2277 | * Vcc which we don't want to make default vcc, |
2278 | DPRINTK("LEC_ARP:Attaching data direct, not default :%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", | 2278 | * attach it anyway. |
2279 | ioc_data->atm_addr[0],ioc_data->atm_addr[1], | 2279 | */ |
2280 | ioc_data->atm_addr[2],ioc_data->atm_addr[3], | 2280 | DPRINTK |
2281 | ioc_data->atm_addr[4],ioc_data->atm_addr[5], | 2281 | ("LEC_ARP:Attaching data direct, not default: " |
2282 | ioc_data->atm_addr[6],ioc_data->atm_addr[7], | 2282 | "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", |
2283 | ioc_data->atm_addr[8],ioc_data->atm_addr[9], | 2283 | ioc_data->atm_addr[0], ioc_data->atm_addr[1], |
2284 | ioc_data->atm_addr[10],ioc_data->atm_addr[11], | 2284 | ioc_data->atm_addr[2], ioc_data->atm_addr[3], |
2285 | ioc_data->atm_addr[12],ioc_data->atm_addr[13], | 2285 | ioc_data->atm_addr[4], ioc_data->atm_addr[5], |
2286 | ioc_data->atm_addr[14],ioc_data->atm_addr[15], | 2286 | ioc_data->atm_addr[6], ioc_data->atm_addr[7], |
2287 | ioc_data->atm_addr[16],ioc_data->atm_addr[17], | 2287 | ioc_data->atm_addr[8], ioc_data->atm_addr[9], |
2288 | ioc_data->atm_addr[18],ioc_data->atm_addr[19]); | 2288 | ioc_data->atm_addr[10], ioc_data->atm_addr[11], |
2289 | entry = make_entry(priv, bus_mac); | 2289 | ioc_data->atm_addr[12], ioc_data->atm_addr[13], |
2290 | if (entry == NULL) | 2290 | ioc_data->atm_addr[14], ioc_data->atm_addr[15], |
2291 | ioc_data->atm_addr[16], ioc_data->atm_addr[17], | ||
2292 | ioc_data->atm_addr[18], ioc_data->atm_addr[19]); | ||
2293 | entry = make_entry(priv, bus_mac); | ||
2294 | if (entry == NULL) | ||
2291 | goto out; | 2295 | goto out; |
2292 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); | 2296 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); |
2293 | memset(entry->mac_addr, 0, ETH_ALEN); | 2297 | memset(entry->mac_addr, 0, ETH_ALEN); |
2294 | entry->recv_vcc = vcc; | 2298 | entry->recv_vcc = vcc; |
2295 | entry->old_recv_push = old_push; | 2299 | entry->old_recv_push = old_push; |
2296 | entry->status = ESI_UNKNOWN; | 2300 | entry->status = ESI_UNKNOWN; |
2297 | entry->timer.expires = jiffies + priv->vcc_timeout_period; | 2301 | entry->timer.expires = jiffies + priv->vcc_timeout_period; |
2298 | entry->timer.function = lec_arp_expire_vcc; | 2302 | entry->timer.function = lec_arp_expire_vcc; |
2299 | add_timer(&entry->timer); | 2303 | add_timer(&entry->timer); |
2300 | entry->next = priv->lec_no_forward; | 2304 | entry->next = priv->lec_no_forward; |
2301 | priv->lec_no_forward = entry; | 2305 | priv->lec_no_forward = entry; |
2302 | dump_arp_table(priv); | 2306 | dump_arp_table(priv); |
2303 | goto out; | 2307 | goto out; |
2304 | } | 2308 | } |
2305 | DPRINTK("LEC_ARP:Attaching data direct, default:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", | 2309 | DPRINTK |
2306 | ioc_data->atm_addr[0],ioc_data->atm_addr[1], | 2310 | ("LEC_ARP:Attaching data direct, default: " |
2307 | ioc_data->atm_addr[2],ioc_data->atm_addr[3], | 2311 | "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", |
2308 | ioc_data->atm_addr[4],ioc_data->atm_addr[5], | 2312 | ioc_data->atm_addr[0], ioc_data->atm_addr[1], |
2309 | ioc_data->atm_addr[6],ioc_data->atm_addr[7], | 2313 | ioc_data->atm_addr[2], ioc_data->atm_addr[3], |
2310 | ioc_data->atm_addr[8],ioc_data->atm_addr[9], | 2314 | ioc_data->atm_addr[4], ioc_data->atm_addr[5], |
2311 | ioc_data->atm_addr[10],ioc_data->atm_addr[11], | 2315 | ioc_data->atm_addr[6], ioc_data->atm_addr[7], |
2312 | ioc_data->atm_addr[12],ioc_data->atm_addr[13], | 2316 | ioc_data->atm_addr[8], ioc_data->atm_addr[9], |
2313 | ioc_data->atm_addr[14],ioc_data->atm_addr[15], | 2317 | ioc_data->atm_addr[10], ioc_data->atm_addr[11], |
2314 | ioc_data->atm_addr[16],ioc_data->atm_addr[17], | 2318 | ioc_data->atm_addr[12], ioc_data->atm_addr[13], |
2315 | ioc_data->atm_addr[18],ioc_data->atm_addr[19]); | 2319 | ioc_data->atm_addr[14], ioc_data->atm_addr[15], |
2316 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 2320 | ioc_data->atm_addr[16], ioc_data->atm_addr[17], |
2317 | for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) { | 2321 | ioc_data->atm_addr[18], ioc_data->atm_addr[19]); |
2318 | if (memcmp(ioc_data->atm_addr, entry->atm_addr, | 2322 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2319 | ATM_ESA_LEN)==0) { | 2323 | for (entry = priv->lec_arp_tables[i]; entry; |
2320 | DPRINTK("LEC_ARP: Attaching data direct\n"); | 2324 | entry = entry->next) { |
2321 | DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n", | 2325 | if (memcmp |
2322 | entry->vcc?entry->vcc->vci:0, | 2326 | (ioc_data->atm_addr, entry->atm_addr, |
2323 | entry->recv_vcc?entry->recv_vcc->vci:0); | 2327 | ATM_ESA_LEN) == 0) { |
2324 | found_entry=1; | 2328 | DPRINTK("LEC_ARP: Attaching data direct\n"); |
2325 | del_timer(&entry->timer); | 2329 | DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n", |
2326 | entry->vcc = vcc; | 2330 | entry->vcc ? entry->vcc->vci : 0, |
2327 | entry->old_push = old_push; | 2331 | entry->recv_vcc ? entry->recv_vcc-> |
2328 | if (entry->status == ESI_VC_PENDING) { | 2332 | vci : 0); |
2329 | if(priv->maximum_unknown_frame_count | 2333 | found_entry = 1; |
2330 | ==0) | 2334 | del_timer(&entry->timer); |
2331 | entry->status = | 2335 | entry->vcc = vcc; |
2332 | ESI_FORWARD_DIRECT; | 2336 | entry->old_push = old_push; |
2333 | else { | 2337 | if (entry->status == ESI_VC_PENDING) { |
2334 | entry->timestamp = jiffies; | 2338 | if (priv->maximum_unknown_frame_count |
2335 | entry->status = | 2339 | == 0) |
2336 | ESI_FLUSH_PENDING; | 2340 | entry->status = |
2341 | ESI_FORWARD_DIRECT; | ||
2342 | else { | ||
2343 | entry->timestamp = jiffies; | ||
2344 | entry->status = | ||
2345 | ESI_FLUSH_PENDING; | ||
2337 | #if 0 | 2346 | #if 0 |
2338 | send_to_lecd(priv,l_flush_xmt, | 2347 | send_to_lecd(priv, l_flush_xmt, |
2339 | NULL, | 2348 | NULL, |
2340 | entry->atm_addr, | 2349 | entry->atm_addr, |
2341 | NULL); | 2350 | NULL); |
2342 | #endif | 2351 | #endif |
2343 | } | 2352 | } |
2344 | } else { | 2353 | } else { |
2345 | /* They were forming a connection | 2354 | /* |
2346 | to us, and we to them. Our | 2355 | * They were forming a connection |
2347 | ATM address is numerically lower | 2356 | * to us, and we to them. Our |
2348 | than theirs, so we make connection | 2357 | * ATM address is numerically lower |
2349 | we formed into default VCC (8.1.11). | 2358 | * than theirs, so we make connection |
2350 | Connection they made gets torn | 2359 | * we formed into default VCC (8.1.11). |
2351 | down. This might confuse some | 2360 | * Connection they made gets torn |
2352 | clients. Can be changed if | 2361 | * down. This might confuse some |
2353 | someone reports trouble... */ | 2362 | * clients. Can be changed if |
2354 | ; | 2363 | * someone reports trouble... |
2355 | } | 2364 | */ |
2356 | } | 2365 | ; |
2357 | } | 2366 | } |
2358 | } | 2367 | } |
2359 | if (found_entry) { | 2368 | } |
2360 | DPRINTK("After vcc was added\n"); | 2369 | } |
2361 | dump_arp_table(priv); | 2370 | if (found_entry) { |
2371 | DPRINTK("After vcc was added\n"); | ||
2372 | dump_arp_table(priv); | ||
2362 | goto out; | 2373 | goto out; |
2363 | } | 2374 | } |
2364 | /* Not found, snatch address from first data packet that arrives from | 2375 | /* |
2365 | this vcc */ | 2376 | * Not found, snatch address from first data packet that arrives |
2366 | entry = make_entry(priv, bus_mac); | 2377 | * from this vcc |
2367 | if (!entry) | 2378 | */ |
2379 | entry = make_entry(priv, bus_mac); | ||
2380 | if (!entry) | ||
2368 | goto out; | 2381 | goto out; |
2369 | entry->vcc = vcc; | 2382 | entry->vcc = vcc; |
2370 | entry->old_push = old_push; | 2383 | entry->old_push = old_push; |
2371 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); | 2384 | memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); |
2372 | memset(entry->mac_addr, 0, ETH_ALEN); | 2385 | memset(entry->mac_addr, 0, ETH_ALEN); |
2373 | entry->status = ESI_UNKNOWN; | 2386 | entry->status = ESI_UNKNOWN; |
2374 | entry->next = priv->lec_arp_empty_ones; | 2387 | entry->next = priv->lec_arp_empty_ones; |
2375 | priv->lec_arp_empty_ones = entry; | 2388 | priv->lec_arp_empty_ones = entry; |
2376 | entry->timer.expires = jiffies + priv->vcc_timeout_period; | 2389 | entry->timer.expires = jiffies + priv->vcc_timeout_period; |
2377 | entry->timer.function = lec_arp_expire_vcc; | 2390 | entry->timer.function = lec_arp_expire_vcc; |
2378 | add_timer(&entry->timer); | 2391 | add_timer(&entry->timer); |
2379 | DPRINTK("After vcc was added\n"); | 2392 | DPRINTK("After vcc was added\n"); |
2380 | dump_arp_table(priv); | 2393 | dump_arp_table(priv); |
2381 | out: | 2394 | out: |
2382 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2395 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2383 | } | 2396 | } |
2384 | 2397 | ||
2385 | static void | 2398 | static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) |
2386 | lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) | ||
2387 | { | 2399 | { |
2388 | unsigned long flags; | 2400 | unsigned long flags; |
2389 | struct lec_arp_table *entry; | 2401 | struct lec_arp_table *entry; |
2390 | int i; | 2402 | int i; |
2391 | |||
2392 | DPRINTK("LEC:lec_flush_complete %lx\n",tran_id); | ||
2393 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | ||
2394 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | ||
2395 | for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) { | ||
2396 | if (entry->flush_tran_id == tran_id && | ||
2397 | entry->status == ESI_FLUSH_PENDING) { | ||
2398 | struct sk_buff *skb; | ||
2399 | 2403 | ||
2400 | while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) | 2404 | DPRINTK("LEC:lec_flush_complete %lx\n", tran_id); |
2405 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | ||
2406 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | ||
2407 | for (entry = priv->lec_arp_tables[i]; entry; | ||
2408 | entry = entry->next) { | ||
2409 | if (entry->flush_tran_id == tran_id | ||
2410 | && entry->status == ESI_FLUSH_PENDING) { | ||
2411 | struct sk_buff *skb; | ||
2412 | |||
2413 | while ((skb = | ||
2414 | skb_dequeue(&entry->tx_wait)) != NULL) | ||
2401 | lec_send(entry->vcc, skb, entry->priv); | 2415 | lec_send(entry->vcc, skb, entry->priv); |
2402 | entry->status = ESI_FORWARD_DIRECT; | 2416 | entry->status = ESI_FORWARD_DIRECT; |
2403 | DPRINTK("LEC_ARP: Flushed\n"); | 2417 | DPRINTK("LEC_ARP: Flushed\n"); |
2404 | } | 2418 | } |
2405 | } | 2419 | } |
2406 | } | 2420 | } |
2407 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2421 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2408 | dump_arp_table(priv); | 2422 | dump_arp_table(priv); |
2409 | } | 2423 | } |
2410 | 2424 | ||
2411 | static void | 2425 | static void |
2412 | lec_set_flush_tran_id(struct lec_priv *priv, | 2426 | lec_set_flush_tran_id(struct lec_priv *priv, |
2413 | unsigned char *atm_addr, unsigned long tran_id) | 2427 | unsigned char *atm_addr, unsigned long tran_id) |
2414 | { | 2428 | { |
2415 | unsigned long flags; | 2429 | unsigned long flags; |
2416 | struct lec_arp_table *entry; | 2430 | struct lec_arp_table *entry; |
2417 | int i; | 2431 | int i; |
2418 | 2432 | ||
2419 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2433 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2420 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) | 2434 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) |
2421 | for(entry = priv->lec_arp_tables[i]; entry; entry=entry->next) | 2435 | for (entry = priv->lec_arp_tables[i]; entry; |
2422 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { | 2436 | entry = entry->next) |
2423 | entry->flush_tran_id = tran_id; | 2437 | if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { |
2424 | DPRINTK("Set flush transaction id to %lx for %p\n",tran_id,entry); | 2438 | entry->flush_tran_id = tran_id; |
2425 | } | 2439 | DPRINTK |
2440 | ("Set flush transaction id to %lx for %p\n", | ||
2441 | tran_id, entry); | ||
2442 | } | ||
2426 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2443 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2427 | } | 2444 | } |
2428 | 2445 | ||
2429 | static int | 2446 | static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) |
2430 | lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) | ||
2431 | { | 2447 | { |
2432 | unsigned long flags; | 2448 | unsigned long flags; |
2433 | unsigned char mac_addr[] = { | 2449 | unsigned char mac_addr[] = { |
2434 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 2450 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff |
2435 | struct lec_arp_table *to_add; | 2451 | }; |
2452 | struct lec_arp_table *to_add; | ||
2436 | struct lec_vcc_priv *vpriv; | 2453 | struct lec_vcc_priv *vpriv; |
2437 | int err = 0; | 2454 | int err = 0; |
2438 | 2455 | ||
2439 | if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL))) | 2456 | if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL))) |
2440 | return -ENOMEM; | 2457 | return -ENOMEM; |
2441 | vpriv->xoff = 0; | 2458 | vpriv->xoff = 0; |
2442 | vpriv->old_pop = vcc->pop; | 2459 | vpriv->old_pop = vcc->pop; |
2443 | vcc->user_back = vpriv; | 2460 | vcc->user_back = vpriv; |
2444 | vcc->pop = lec_pop; | 2461 | vcc->pop = lec_pop; |
2445 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2462 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2446 | to_add = make_entry(priv, mac_addr); | 2463 | to_add = make_entry(priv, mac_addr); |
2447 | if (!to_add) { | 2464 | if (!to_add) { |
2448 | vcc->pop = vpriv->old_pop; | 2465 | vcc->pop = vpriv->old_pop; |
2449 | kfree(vpriv); | 2466 | kfree(vpriv); |
2450 | err = -ENOMEM; | 2467 | err = -ENOMEM; |
2451 | goto out; | 2468 | goto out; |
2452 | } | 2469 | } |
2453 | memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN); | 2470 | memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN); |
2454 | to_add->status = ESI_FORWARD_DIRECT; | 2471 | to_add->status = ESI_FORWARD_DIRECT; |
2455 | to_add->flags |= LEC_PERMANENT_FLAG; | 2472 | to_add->flags |= LEC_PERMANENT_FLAG; |
2456 | to_add->vcc = vcc; | 2473 | to_add->vcc = vcc; |
2457 | to_add->old_push = vcc->push; | 2474 | to_add->old_push = vcc->push; |
2458 | vcc->push = lec_push; | 2475 | vcc->push = lec_push; |
2459 | priv->mcast_vcc = vcc; | 2476 | priv->mcast_vcc = vcc; |
2460 | lec_arp_add(priv, to_add); | 2477 | lec_arp_add(priv, to_add); |
2461 | out: | 2478 | out: |
2462 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2479 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2463 | return err; | 2480 | return err; |
2464 | } | 2481 | } |
2465 | 2482 | ||
2466 | static void | 2483 | static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) |
2467 | lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | ||
2468 | { | 2484 | { |
2469 | unsigned long flags; | 2485 | unsigned long flags; |
2470 | struct lec_arp_table *entry, *next; | 2486 | struct lec_arp_table *entry, *next; |
2471 | int i; | 2487 | int i; |
2472 | 2488 | ||
2473 | DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci); | 2489 | DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci); |
2474 | dump_arp_table(priv); | 2490 | dump_arp_table(priv); |
2475 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2491 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2476 | for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { | 2492 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
2477 | for(entry = priv->lec_arp_tables[i];entry; entry=next) { | 2493 | for (entry = priv->lec_arp_tables[i]; entry; entry = next) { |
2478 | next = entry->next; | 2494 | next = entry->next; |
2479 | if (vcc == entry->vcc) { | 2495 | if (vcc == entry->vcc) { |
2480 | lec_arp_remove(priv, entry); | 2496 | lec_arp_remove(priv, entry); |
2481 | kfree(entry); | 2497 | kfree(entry); |
2482 | if (priv->mcast_vcc == vcc) { | 2498 | if (priv->mcast_vcc == vcc) { |
2483 | priv->mcast_vcc = NULL; | 2499 | priv->mcast_vcc = NULL; |
2484 | } | 2500 | } |
2485 | } | 2501 | } |
2486 | } | 2502 | } |
2487 | } | 2503 | } |
2488 | 2504 | ||
2489 | entry = priv->lec_arp_empty_ones; | 2505 | entry = priv->lec_arp_empty_ones; |
2490 | priv->lec_arp_empty_ones = NULL; | 2506 | priv->lec_arp_empty_ones = NULL; |
2491 | while (entry != NULL) { | 2507 | while (entry != NULL) { |
2492 | next = entry->next; | 2508 | next = entry->next; |
2493 | if (entry->vcc == vcc) { /* leave it out from the list */ | 2509 | if (entry->vcc == vcc) { /* leave it out from the list */ |
2494 | lec_arp_clear_vccs(entry); | 2510 | lec_arp_clear_vccs(entry); |
2495 | del_timer(&entry->timer); | 2511 | del_timer(&entry->timer); |
2496 | kfree(entry); | 2512 | kfree(entry); |
2497 | } | 2513 | } else { /* put it back to the list */ |
2498 | else { /* put it back to the list */ | 2514 | entry->next = priv->lec_arp_empty_ones; |
2499 | entry->next = priv->lec_arp_empty_ones; | 2515 | priv->lec_arp_empty_ones = entry; |
2500 | priv->lec_arp_empty_ones = entry; | 2516 | } |
2501 | } | 2517 | entry = next; |
2502 | entry = next; | 2518 | } |
2503 | } | 2519 | |
2504 | 2520 | entry = priv->lec_no_forward; | |
2505 | entry = priv->lec_no_forward; | 2521 | priv->lec_no_forward = NULL; |
2506 | priv->lec_no_forward = NULL; | 2522 | while (entry != NULL) { |
2507 | while (entry != NULL) { | 2523 | next = entry->next; |
2508 | next = entry->next; | 2524 | if (entry->recv_vcc == vcc) { |
2509 | if (entry->recv_vcc == vcc) { | 2525 | lec_arp_clear_vccs(entry); |
2510 | lec_arp_clear_vccs(entry); | 2526 | del_timer(&entry->timer); |
2511 | del_timer(&entry->timer); | 2527 | kfree(entry); |
2512 | kfree(entry); | 2528 | } else { |
2513 | } | 2529 | entry->next = priv->lec_no_forward; |
2514 | else { | 2530 | priv->lec_no_forward = entry; |
2515 | entry->next = priv->lec_no_forward; | 2531 | } |
2516 | priv->lec_no_forward = entry; | 2532 | entry = next; |
2517 | } | 2533 | } |
2518 | entry = next; | 2534 | |
2519 | } | 2535 | entry = priv->mcast_fwds; |
2520 | 2536 | priv->mcast_fwds = NULL; | |
2521 | entry = priv->mcast_fwds; | 2537 | while (entry != NULL) { |
2522 | priv->mcast_fwds = NULL; | 2538 | next = entry->next; |
2523 | while (entry != NULL) { | 2539 | if (entry->recv_vcc == vcc) { |
2524 | next = entry->next; | 2540 | lec_arp_clear_vccs(entry); |
2525 | if (entry->recv_vcc == vcc) { | 2541 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
2526 | lec_arp_clear_vccs(entry); | 2542 | kfree(entry); |
2527 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 2543 | } else { |
2528 | kfree(entry); | 2544 | entry->next = priv->mcast_fwds; |
2529 | } | 2545 | priv->mcast_fwds = entry; |
2530 | else { | 2546 | } |
2531 | entry->next = priv->mcast_fwds; | 2547 | entry = next; |
2532 | priv->mcast_fwds = entry; | 2548 | } |
2533 | } | ||
2534 | entry = next; | ||
2535 | } | ||
2536 | 2549 | ||
2537 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2550 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2538 | dump_arp_table(priv); | 2551 | dump_arp_table(priv); |
@@ -2540,57 +2553,59 @@ lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
2540 | 2553 | ||
2541 | static void | 2554 | static void |
2542 | lec_arp_check_empties(struct lec_priv *priv, | 2555 | lec_arp_check_empties(struct lec_priv *priv, |
2543 | struct atm_vcc *vcc, struct sk_buff *skb) | 2556 | struct atm_vcc *vcc, struct sk_buff *skb) |
2544 | { | 2557 | { |
2545 | unsigned long flags; | 2558 | unsigned long flags; |
2546 | struct lec_arp_table *entry, *prev; | 2559 | struct lec_arp_table *entry, *prev; |
2547 | struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data; | 2560 | struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data; |
2548 | unsigned char *src; | 2561 | unsigned char *src; |
2549 | #ifdef CONFIG_TR | 2562 | #ifdef CONFIG_TR |
2550 | struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data; | 2563 | struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data; |
2551 | 2564 | ||
2552 | if (priv->is_trdev) src = tr_hdr->h_source; | 2565 | if (priv->is_trdev) |
2553 | else | 2566 | src = tr_hdr->h_source; |
2567 | else | ||
2554 | #endif | 2568 | #endif |
2555 | src = hdr->h_source; | 2569 | src = hdr->h_source; |
2556 | 2570 | ||
2557 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | 2571 | spin_lock_irqsave(&priv->lec_arp_lock, flags); |
2558 | entry = priv->lec_arp_empty_ones; | 2572 | entry = priv->lec_arp_empty_ones; |
2559 | if (vcc == entry->vcc) { | 2573 | if (vcc == entry->vcc) { |
2560 | del_timer(&entry->timer); | 2574 | del_timer(&entry->timer); |
2561 | memcpy(entry->mac_addr, src, ETH_ALEN); | 2575 | memcpy(entry->mac_addr, src, ETH_ALEN); |
2562 | entry->status = ESI_FORWARD_DIRECT; | 2576 | entry->status = ESI_FORWARD_DIRECT; |
2563 | entry->last_used = jiffies; | 2577 | entry->last_used = jiffies; |
2564 | priv->lec_arp_empty_ones = entry->next; | 2578 | priv->lec_arp_empty_ones = entry->next; |
2565 | /* We might have got an entry */ | 2579 | /* We might have got an entry */ |
2566 | if ((prev = lec_arp_find(priv,src))) { | 2580 | if ((prev = lec_arp_find(priv, src))) { |
2567 | lec_arp_remove(priv, prev); | 2581 | lec_arp_remove(priv, prev); |
2568 | kfree(prev); | 2582 | kfree(prev); |
2569 | } | 2583 | } |
2570 | lec_arp_add(priv, entry); | 2584 | lec_arp_add(priv, entry); |
2571 | goto out; | 2585 | goto out; |
2572 | } | 2586 | } |
2573 | prev = entry; | 2587 | prev = entry; |
2574 | entry = entry->next; | 2588 | entry = entry->next; |
2575 | while (entry && entry->vcc != vcc) { | 2589 | while (entry && entry->vcc != vcc) { |
2576 | prev= entry; | 2590 | prev = entry; |
2577 | entry = entry->next; | 2591 | entry = entry->next; |
2578 | } | 2592 | } |
2579 | if (!entry) { | 2593 | if (!entry) { |
2580 | DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n"); | 2594 | DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n"); |
2581 | goto out; | 2595 | goto out; |
2582 | } | 2596 | } |
2583 | del_timer(&entry->timer); | 2597 | del_timer(&entry->timer); |
2584 | memcpy(entry->mac_addr, src, ETH_ALEN); | 2598 | memcpy(entry->mac_addr, src, ETH_ALEN); |
2585 | entry->status = ESI_FORWARD_DIRECT; | 2599 | entry->status = ESI_FORWARD_DIRECT; |
2586 | entry->last_used = jiffies; | 2600 | entry->last_used = jiffies; |
2587 | prev->next = entry->next; | 2601 | prev->next = entry->next; |
2588 | if ((prev = lec_arp_find(priv, src))) { | 2602 | if ((prev = lec_arp_find(priv, src))) { |
2589 | lec_arp_remove(priv, prev); | 2603 | lec_arp_remove(priv, prev); |
2590 | kfree(prev); | 2604 | kfree(prev); |
2591 | } | 2605 | } |
2592 | lec_arp_add(priv, entry); | 2606 | lec_arp_add(priv, entry); |
2593 | out: | 2607 | out: |
2594 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2608 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2595 | } | 2609 | } |
2610 | |||
2596 | MODULE_LICENSE("GPL"); | 2611 | MODULE_LICENSE("GPL"); |