diff options
| author | Steve French <sfrench@us.ibm.com> | 2007-07-18 20:38:57 -0400 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2007-07-18 20:38:57 -0400 |
| commit | 1ff8392c32a2645d2665ca779ecb91bb29361c13 (patch) | |
| tree | 860b95e9a499ade4060848740fc6ce1fbb4e4e8d /net/core | |
| parent | 70b315b0dd3879cb3ab8aadffb14f10b2d19b9c3 (diff) | |
| parent | 5bae7ac9feba925fd0099057f6b23d7be80b7b41 (diff) | |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
fs/cifs/export.c
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 433 | ||||
| -rw-r--r-- | net/core/dev_mcast.c | 200 | ||||
| -rw-r--r-- | net/core/ethtool.c | 12 | ||||
| -rw-r--r-- | net/core/gen_estimator.c | 82 | ||||
| -rw-r--r-- | net/core/netevent.c | 1 | ||||
| -rw-r--r-- | net/core/netpoll.c | 36 | ||||
| -rw-r--r-- | net/core/pktgen.c | 251 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 470 | ||||
| -rw-r--r-- | net/core/scm.c | 3 | ||||
| -rw-r--r-- | net/core/skbuff.c | 21 | ||||
| -rw-r--r-- | net/core/sock.c | 42 |
11 files changed, 1204 insertions, 347 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 26090621ea6b..6357f54c8ff7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
| 99 | #include <linux/stat.h> | 99 | #include <linux/stat.h> |
| 100 | #include <linux/if_bridge.h> | 100 | #include <linux/if_bridge.h> |
| 101 | #include <linux/if_macvlan.h> | ||
| 101 | #include <net/dst.h> | 102 | #include <net/dst.h> |
| 102 | #include <net/pkt_sched.h> | 103 | #include <net/pkt_sched.h> |
| 103 | #include <net/checksum.h> | 104 | #include <net/checksum.h> |
| @@ -151,9 +152,22 @@ static struct list_head ptype_base[16] __read_mostly; /* 16 way hashed list */ | |||
| 151 | static struct list_head ptype_all __read_mostly; /* Taps */ | 152 | static struct list_head ptype_all __read_mostly; /* Taps */ |
| 152 | 153 | ||
| 153 | #ifdef CONFIG_NET_DMA | 154 | #ifdef CONFIG_NET_DMA |
| 154 | static struct dma_client *net_dma_client; | 155 | struct net_dma { |
| 155 | static unsigned int net_dma_count; | 156 | struct dma_client client; |
| 156 | static spinlock_t net_dma_event_lock; | 157 | spinlock_t lock; |
| 158 | cpumask_t channel_mask; | ||
| 159 | struct dma_chan *channels[NR_CPUS]; | ||
| 160 | }; | ||
| 161 | |||
| 162 | static enum dma_state_client | ||
| 163 | netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | ||
| 164 | enum dma_state state); | ||
| 165 | |||
| 166 | static struct net_dma net_dma = { | ||
| 167 | .client = { | ||
| 168 | .event_callback = netdev_dma_event, | ||
| 169 | }, | ||
| 170 | }; | ||
| 157 | #endif | 171 | #endif |
| 158 | 172 | ||
| 159 | /* | 173 | /* |
| @@ -942,7 +956,7 @@ int dev_open(struct net_device *dev) | |||
| 942 | /* | 956 | /* |
| 943 | * Initialize multicasting status | 957 | * Initialize multicasting status |
| 944 | */ | 958 | */ |
| 945 | dev_mc_upload(dev); | 959 | dev_set_rx_mode(dev); |
| 946 | 960 | ||
| 947 | /* | 961 | /* |
| 948 | * Wakeup transmit queue engine | 962 | * Wakeup transmit queue engine |
| @@ -1429,7 +1443,9 @@ gso: | |||
| 1429 | skb->next = nskb; | 1443 | skb->next = nskb; |
| 1430 | return rc; | 1444 | return rc; |
| 1431 | } | 1445 | } |
| 1432 | if (unlikely(netif_queue_stopped(dev) && skb->next)) | 1446 | if (unlikely((netif_queue_stopped(dev) || |
| 1447 | netif_subqueue_stopped(dev, skb->queue_mapping)) && | ||
| 1448 | skb->next)) | ||
| 1433 | return NETDEV_TX_BUSY; | 1449 | return NETDEV_TX_BUSY; |
| 1434 | } while (skb->next); | 1450 | } while (skb->next); |
| 1435 | 1451 | ||
| @@ -1510,8 +1526,10 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
| 1510 | skb_headroom(skb)); | 1526 | skb_headroom(skb)); |
| 1511 | 1527 | ||
| 1512 | if (!(dev->features & NETIF_F_GEN_CSUM) && | 1528 | if (!(dev->features & NETIF_F_GEN_CSUM) && |
| 1513 | (!(dev->features & NETIF_F_IP_CSUM) || | 1529 | !((dev->features & NETIF_F_IP_CSUM) && |
| 1514 | skb->protocol != htons(ETH_P_IP))) | 1530 | skb->protocol == htons(ETH_P_IP)) && |
| 1531 | !((dev->features & NETIF_F_IPV6_CSUM) && | ||
| 1532 | skb->protocol == htons(ETH_P_IPV6))) | ||
| 1515 | if (skb_checksum_help(skb)) | 1533 | if (skb_checksum_help(skb)) |
| 1516 | goto out_kfree_skb; | 1534 | goto out_kfree_skb; |
| 1517 | } | 1535 | } |
| @@ -1545,6 +1563,8 @@ gso: | |||
| 1545 | spin_lock(&dev->queue_lock); | 1563 | spin_lock(&dev->queue_lock); |
| 1546 | q = dev->qdisc; | 1564 | q = dev->qdisc; |
| 1547 | if (q->enqueue) { | 1565 | if (q->enqueue) { |
| 1566 | /* reset queue_mapping to zero */ | ||
| 1567 | skb->queue_mapping = 0; | ||
| 1548 | rc = q->enqueue(skb, q); | 1568 | rc = q->enqueue(skb, q); |
| 1549 | qdisc_run(dev); | 1569 | qdisc_run(dev); |
| 1550 | spin_unlock(&dev->queue_lock); | 1570 | spin_unlock(&dev->queue_lock); |
| @@ -1574,7 +1594,8 @@ gso: | |||
| 1574 | 1594 | ||
| 1575 | HARD_TX_LOCK(dev, cpu); | 1595 | HARD_TX_LOCK(dev, cpu); |
| 1576 | 1596 | ||
| 1577 | if (!netif_queue_stopped(dev)) { | 1597 | if (!netif_queue_stopped(dev) && |
| 1598 | !netif_subqueue_stopped(dev, skb->queue_mapping)) { | ||
| 1578 | rc = 0; | 1599 | rc = 0; |
| 1579 | if (!dev_hard_start_xmit(skb, dev)) { | 1600 | if (!dev_hard_start_xmit(skb, dev)) { |
| 1580 | HARD_TX_UNLOCK(dev); | 1601 | HARD_TX_UNLOCK(dev); |
| @@ -1793,6 +1814,28 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb, | |||
| 1793 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) | 1814 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) |
| 1794 | #endif | 1815 | #endif |
| 1795 | 1816 | ||
| 1817 | #if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) | ||
| 1818 | struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly; | ||
| 1819 | EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); | ||
| 1820 | |||
| 1821 | static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, | ||
| 1822 | struct packet_type **pt_prev, | ||
| 1823 | int *ret, | ||
| 1824 | struct net_device *orig_dev) | ||
| 1825 | { | ||
| 1826 | if (skb->dev->macvlan_port == NULL) | ||
| 1827 | return skb; | ||
| 1828 | |||
| 1829 | if (*pt_prev) { | ||
| 1830 | *ret = deliver_skb(skb, *pt_prev, orig_dev); | ||
| 1831 | *pt_prev = NULL; | ||
| 1832 | } | ||
| 1833 | return macvlan_handle_frame_hook(skb); | ||
| 1834 | } | ||
| 1835 | #else | ||
| 1836 | #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) | ||
| 1837 | #endif | ||
| 1838 | |||
| 1796 | #ifdef CONFIG_NET_CLS_ACT | 1839 | #ifdef CONFIG_NET_CLS_ACT |
| 1797 | /* TODO: Maybe we should just force sch_ingress to be compiled in | 1840 | /* TODO: Maybe we should just force sch_ingress to be compiled in |
| 1798 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions | 1841 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions |
| @@ -1900,6 +1943,9 @@ ncls: | |||
| 1900 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); | 1943 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); |
| 1901 | if (!skb) | 1944 | if (!skb) |
| 1902 | goto out; | 1945 | goto out; |
| 1946 | skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); | ||
| 1947 | if (!skb) | ||
| 1948 | goto out; | ||
| 1903 | 1949 | ||
| 1904 | type = skb->protocol; | 1950 | type = skb->protocol; |
| 1905 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { | 1951 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { |
| @@ -2009,20 +2055,21 @@ static void net_rx_action(struct softirq_action *h) | |||
| 2009 | } | 2055 | } |
| 2010 | } | 2056 | } |
| 2011 | out: | 2057 | out: |
| 2058 | local_irq_enable(); | ||
| 2012 | #ifdef CONFIG_NET_DMA | 2059 | #ifdef CONFIG_NET_DMA |
| 2013 | /* | 2060 | /* |
| 2014 | * There may not be any more sk_buffs coming right now, so push | 2061 | * There may not be any more sk_buffs coming right now, so push |
| 2015 | * any pending DMA copies to hardware | 2062 | * any pending DMA copies to hardware |
| 2016 | */ | 2063 | */ |
| 2017 | if (net_dma_client) { | 2064 | if (!cpus_empty(net_dma.channel_mask)) { |
| 2018 | struct dma_chan *chan; | 2065 | int chan_idx; |
| 2019 | rcu_read_lock(); | 2066 | for_each_cpu_mask(chan_idx, net_dma.channel_mask) { |
| 2020 | list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node) | 2067 | struct dma_chan *chan = net_dma.channels[chan_idx]; |
| 2021 | dma_async_memcpy_issue_pending(chan); | 2068 | if (chan) |
| 2022 | rcu_read_unlock(); | 2069 | dma_async_memcpy_issue_pending(chan); |
| 2070 | } | ||
| 2023 | } | 2071 | } |
| 2024 | #endif | 2072 | #endif |
| 2025 | local_irq_enable(); | ||
| 2026 | return; | 2073 | return; |
| 2027 | 2074 | ||
| 2028 | softnet_break: | 2075 | softnet_break: |
| @@ -2496,26 +2543,17 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) | |||
| 2496 | return 0; | 2543 | return 0; |
| 2497 | } | 2544 | } |
| 2498 | 2545 | ||
| 2499 | /** | 2546 | static void __dev_set_promiscuity(struct net_device *dev, int inc) |
| 2500 | * dev_set_promiscuity - update promiscuity count on a device | ||
| 2501 | * @dev: device | ||
| 2502 | * @inc: modifier | ||
| 2503 | * | ||
| 2504 | * Add or remove promiscuity from a device. While the count in the device | ||
| 2505 | * remains above zero the interface remains promiscuous. Once it hits zero | ||
| 2506 | * the device reverts back to normal filtering operation. A negative inc | ||
| 2507 | * value is used to drop promiscuity on the device. | ||
| 2508 | */ | ||
| 2509 | void dev_set_promiscuity(struct net_device *dev, int inc) | ||
| 2510 | { | 2547 | { |
| 2511 | unsigned short old_flags = dev->flags; | 2548 | unsigned short old_flags = dev->flags; |
| 2512 | 2549 | ||
| 2550 | ASSERT_RTNL(); | ||
| 2551 | |||
| 2513 | if ((dev->promiscuity += inc) == 0) | 2552 | if ((dev->promiscuity += inc) == 0) |
| 2514 | dev->flags &= ~IFF_PROMISC; | 2553 | dev->flags &= ~IFF_PROMISC; |
| 2515 | else | 2554 | else |
| 2516 | dev->flags |= IFF_PROMISC; | 2555 | dev->flags |= IFF_PROMISC; |
| 2517 | if (dev->flags != old_flags) { | 2556 | if (dev->flags != old_flags) { |
| 2518 | dev_mc_upload(dev); | ||
| 2519 | printk(KERN_INFO "device %s %s promiscuous mode\n", | 2557 | printk(KERN_INFO "device %s %s promiscuous mode\n", |
| 2520 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : | 2558 | dev->name, (dev->flags & IFF_PROMISC) ? "entered" : |
| 2521 | "left"); | 2559 | "left"); |
| @@ -2525,10 +2563,32 @@ void dev_set_promiscuity(struct net_device *dev, int inc) | |||
| 2525 | dev->name, (dev->flags & IFF_PROMISC), | 2563 | dev->name, (dev->flags & IFF_PROMISC), |
| 2526 | (old_flags & IFF_PROMISC), | 2564 | (old_flags & IFF_PROMISC), |
| 2527 | audit_get_loginuid(current->audit_context)); | 2565 | audit_get_loginuid(current->audit_context)); |
| 2566 | |||
| 2567 | if (dev->change_rx_flags) | ||
| 2568 | dev->change_rx_flags(dev, IFF_PROMISC); | ||
| 2528 | } | 2569 | } |
| 2529 | } | 2570 | } |
| 2530 | 2571 | ||
| 2531 | /** | 2572 | /** |
| 2573 | * dev_set_promiscuity - update promiscuity count on a device | ||
| 2574 | * @dev: device | ||
| 2575 | * @inc: modifier | ||
| 2576 | * | ||
| 2577 | * Add or remove promiscuity from a device. While the count in the device | ||
| 2578 | * remains above zero the interface remains promiscuous. Once it hits zero | ||
| 2579 | * the device reverts back to normal filtering operation. A negative inc | ||
| 2580 | * value is used to drop promiscuity on the device. | ||
| 2581 | */ | ||
| 2582 | void dev_set_promiscuity(struct net_device *dev, int inc) | ||
| 2583 | { | ||
| 2584 | unsigned short old_flags = dev->flags; | ||
| 2585 | |||
| 2586 | __dev_set_promiscuity(dev, inc); | ||
| 2587 | if (dev->flags != old_flags) | ||
| 2588 | dev_set_rx_mode(dev); | ||
| 2589 | } | ||
| 2590 | |||
| 2591 | /** | ||
| 2532 | * dev_set_allmulti - update allmulti count on a device | 2592 | * dev_set_allmulti - update allmulti count on a device |
| 2533 | * @dev: device | 2593 | * @dev: device |
| 2534 | * @inc: modifier | 2594 | * @inc: modifier |
| @@ -2544,11 +2604,190 @@ void dev_set_allmulti(struct net_device *dev, int inc) | |||
| 2544 | { | 2604 | { |
| 2545 | unsigned short old_flags = dev->flags; | 2605 | unsigned short old_flags = dev->flags; |
| 2546 | 2606 | ||
| 2607 | ASSERT_RTNL(); | ||
| 2608 | |||
| 2547 | dev->flags |= IFF_ALLMULTI; | 2609 | dev->flags |= IFF_ALLMULTI; |
| 2548 | if ((dev->allmulti += inc) == 0) | 2610 | if ((dev->allmulti += inc) == 0) |
| 2549 | dev->flags &= ~IFF_ALLMULTI; | 2611 | dev->flags &= ~IFF_ALLMULTI; |
| 2550 | if (dev->flags ^ old_flags) | 2612 | if (dev->flags ^ old_flags) { |
| 2551 | dev_mc_upload(dev); | 2613 | if (dev->change_rx_flags) |
| 2614 | dev->change_rx_flags(dev, IFF_ALLMULTI); | ||
| 2615 | dev_set_rx_mode(dev); | ||
| 2616 | } | ||
| 2617 | } | ||
| 2618 | |||
| 2619 | /* | ||
| 2620 | * Upload unicast and multicast address lists to device and | ||
| 2621 | * configure RX filtering. When the device doesn't support unicast | ||
| 2622 | * filtering it is put in promiscous mode while unicast addresses | ||
| 2623 | * are present. | ||
| 2624 | */ | ||
| 2625 | void __dev_set_rx_mode(struct net_device *dev) | ||
| 2626 | { | ||
| 2627 | /* dev_open will call this function so the list will stay sane. */ | ||
| 2628 | if (!(dev->flags&IFF_UP)) | ||
| 2629 | return; | ||
| 2630 | |||
| 2631 | if (!netif_device_present(dev)) | ||
| 2632 | return; | ||
| 2633 | |||
| 2634 | if (dev->set_rx_mode) | ||
| 2635 | dev->set_rx_mode(dev); | ||
| 2636 | else { | ||
| 2637 | /* Unicast addresses changes may only happen under the rtnl, | ||
| 2638 | * therefore calling __dev_set_promiscuity here is safe. | ||
| 2639 | */ | ||
| 2640 | if (dev->uc_count > 0 && !dev->uc_promisc) { | ||
| 2641 | __dev_set_promiscuity(dev, 1); | ||
| 2642 | dev->uc_promisc = 1; | ||
| 2643 | } else if (dev->uc_count == 0 && dev->uc_promisc) { | ||
| 2644 | __dev_set_promiscuity(dev, -1); | ||
| 2645 | dev->uc_promisc = 0; | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | if (dev->set_multicast_list) | ||
| 2649 | dev->set_multicast_list(dev); | ||
| 2650 | } | ||
| 2651 | } | ||
| 2652 | |||
| 2653 | void dev_set_rx_mode(struct net_device *dev) | ||
| 2654 | { | ||
| 2655 | netif_tx_lock_bh(dev); | ||
| 2656 | __dev_set_rx_mode(dev); | ||
| 2657 | netif_tx_unlock_bh(dev); | ||
| 2658 | } | ||
| 2659 | |||
| 2660 | int __dev_addr_delete(struct dev_addr_list **list, int *count, | ||
| 2661 | void *addr, int alen, int glbl) | ||
| 2662 | { | ||
| 2663 | struct dev_addr_list *da; | ||
| 2664 | |||
| 2665 | for (; (da = *list) != NULL; list = &da->next) { | ||
| 2666 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
| 2667 | alen == da->da_addrlen) { | ||
| 2668 | if (glbl) { | ||
| 2669 | int old_glbl = da->da_gusers; | ||
| 2670 | da->da_gusers = 0; | ||
| 2671 | if (old_glbl == 0) | ||
| 2672 | break; | ||
| 2673 | } | ||
| 2674 | if (--da->da_users) | ||
| 2675 | return 0; | ||
| 2676 | |||
| 2677 | *list = da->next; | ||
| 2678 | kfree(da); | ||
| 2679 | (*count)--; | ||
| 2680 | return 0; | ||
| 2681 | } | ||
| 2682 | } | ||
| 2683 | return -ENOENT; | ||
| 2684 | } | ||
| 2685 | |||
| 2686 | int __dev_addr_add(struct dev_addr_list **list, int *count, | ||
| 2687 | void *addr, int alen, int glbl) | ||
| 2688 | { | ||
| 2689 | struct dev_addr_list *da; | ||
| 2690 | |||
| 2691 | for (da = *list; da != NULL; da = da->next) { | ||
| 2692 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
| 2693 | da->da_addrlen == alen) { | ||
| 2694 | if (glbl) { | ||
| 2695 | int old_glbl = da->da_gusers; | ||
| 2696 | da->da_gusers = 1; | ||
| 2697 | if (old_glbl) | ||
| 2698 | return 0; | ||
| 2699 | } | ||
| 2700 | da->da_users++; | ||
| 2701 | return 0; | ||
| 2702 | } | ||
| 2703 | } | ||
| 2704 | |||
| 2705 | da = kmalloc(sizeof(*da), GFP_ATOMIC); | ||
| 2706 | if (da == NULL) | ||
| 2707 | return -ENOMEM; | ||
| 2708 | memcpy(da->da_addr, addr, alen); | ||
| 2709 | da->da_addrlen = alen; | ||
| 2710 | da->da_users = 1; | ||
| 2711 | da->da_gusers = glbl ? 1 : 0; | ||
| 2712 | da->next = *list; | ||
| 2713 | *list = da; | ||
| 2714 | (*count)++; | ||
| 2715 | return 0; | ||
| 2716 | } | ||
| 2717 | |||
| 2718 | /** | ||
| 2719 | * dev_unicast_delete - Release secondary unicast address. | ||
| 2720 | * @dev: device | ||
| 2721 | * | ||
| 2722 | * Release reference to a secondary unicast address and remove it | ||
| 2723 | * from the device if the reference count drop to zero. | ||
| 2724 | * | ||
| 2725 | * The caller must hold the rtnl_mutex. | ||
| 2726 | */ | ||
| 2727 | int dev_unicast_delete(struct net_device *dev, void *addr, int alen) | ||
| 2728 | { | ||
| 2729 | int err; | ||
| 2730 | |||
| 2731 | ASSERT_RTNL(); | ||
| 2732 | |||
| 2733 | netif_tx_lock_bh(dev); | ||
| 2734 | err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0); | ||
| 2735 | if (!err) | ||
| 2736 | __dev_set_rx_mode(dev); | ||
| 2737 | netif_tx_unlock_bh(dev); | ||
| 2738 | return err; | ||
| 2739 | } | ||
| 2740 | EXPORT_SYMBOL(dev_unicast_delete); | ||
| 2741 | |||
| 2742 | /** | ||
| 2743 | * dev_unicast_add - add a secondary unicast address | ||
| 2744 | * @dev: device | ||
| 2745 | * | ||
| 2746 | * Add a secondary unicast address to the device or increase | ||
| 2747 | * the reference count if it already exists. | ||
| 2748 | * | ||
| 2749 | * The caller must hold the rtnl_mutex. | ||
| 2750 | */ | ||
| 2751 | int dev_unicast_add(struct net_device *dev, void *addr, int alen) | ||
| 2752 | { | ||
| 2753 | int err; | ||
| 2754 | |||
| 2755 | ASSERT_RTNL(); | ||
| 2756 | |||
| 2757 | netif_tx_lock_bh(dev); | ||
| 2758 | err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0); | ||
| 2759 | if (!err) | ||
| 2760 | __dev_set_rx_mode(dev); | ||
| 2761 | netif_tx_unlock_bh(dev); | ||
| 2762 | return err; | ||
| 2763 | } | ||
| 2764 | EXPORT_SYMBOL(dev_unicast_add); | ||
| 2765 | |||
| 2766 | static void __dev_addr_discard(struct dev_addr_list **list) | ||
| 2767 | { | ||
| 2768 | struct dev_addr_list *tmp; | ||
| 2769 | |||
| 2770 | while (*list != NULL) { | ||
| 2771 | tmp = *list; | ||
| 2772 | *list = tmp->next; | ||
| 2773 | if (tmp->da_users > tmp->da_gusers) | ||
| 2774 | printk("__dev_addr_discard: address leakage! " | ||
| 2775 | "da_users=%d\n", tmp->da_users); | ||
| 2776 | kfree(tmp); | ||
| 2777 | } | ||
| 2778 | } | ||
| 2779 | |||
| 2780 | static void dev_addr_discard(struct net_device *dev) | ||
| 2781 | { | ||
| 2782 | netif_tx_lock_bh(dev); | ||
| 2783 | |||
| 2784 | __dev_addr_discard(&dev->uc_list); | ||
| 2785 | dev->uc_count = 0; | ||
| 2786 | |||
| 2787 | __dev_addr_discard(&dev->mc_list); | ||
| 2788 | dev->mc_count = 0; | ||
| 2789 | |||
| 2790 | netif_tx_unlock_bh(dev); | ||
| 2552 | } | 2791 | } |
| 2553 | 2792 | ||
| 2554 | unsigned dev_get_flags(const struct net_device *dev) | 2793 | unsigned dev_get_flags(const struct net_device *dev) |
| @@ -2580,6 +2819,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
| 2580 | int ret, changes; | 2819 | int ret, changes; |
| 2581 | int old_flags = dev->flags; | 2820 | int old_flags = dev->flags; |
| 2582 | 2821 | ||
| 2822 | ASSERT_RTNL(); | ||
| 2823 | |||
| 2583 | /* | 2824 | /* |
| 2584 | * Set the flags on our device. | 2825 | * Set the flags on our device. |
| 2585 | */ | 2826 | */ |
| @@ -2594,7 +2835,10 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
| 2594 | * Load in the correct multicast list now the flags have changed. | 2835 | * Load in the correct multicast list now the flags have changed. |
| 2595 | */ | 2836 | */ |
| 2596 | 2837 | ||
| 2597 | dev_mc_upload(dev); | 2838 | if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST) |
| 2839 | dev->change_rx_flags(dev, IFF_MULTICAST); | ||
| 2840 | |||
| 2841 | dev_set_rx_mode(dev); | ||
| 2598 | 2842 | ||
| 2599 | /* | 2843 | /* |
| 2600 | * Have we downed the interface. We handle IFF_UP ourselves | 2844 | * Have we downed the interface. We handle IFF_UP ourselves |
| @@ -2607,7 +2851,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
| 2607 | ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev); | 2851 | ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev); |
| 2608 | 2852 | ||
| 2609 | if (!ret) | 2853 | if (!ret) |
| 2610 | dev_mc_upload(dev); | 2854 | dev_set_rx_mode(dev); |
| 2611 | } | 2855 | } |
| 2612 | 2856 | ||
| 2613 | if (dev->flags & IFF_UP && | 2857 | if (dev->flags & IFF_UP && |
| @@ -3107,6 +3351,22 @@ int register_netdevice(struct net_device *dev) | |||
| 3107 | } | 3351 | } |
| 3108 | } | 3352 | } |
| 3109 | 3353 | ||
| 3354 | /* Fix illegal checksum combinations */ | ||
| 3355 | if ((dev->features & NETIF_F_HW_CSUM) && | ||
| 3356 | (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | ||
| 3357 | printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n", | ||
| 3358 | dev->name); | ||
| 3359 | dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); | ||
| 3360 | } | ||
| 3361 | |||
| 3362 | if ((dev->features & NETIF_F_NO_CSUM) && | ||
| 3363 | (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | ||
| 3364 | printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n", | ||
| 3365 | dev->name); | ||
| 3366 | dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); | ||
| 3367 | } | ||
| 3368 | |||
| 3369 | |||
| 3110 | /* Fix illegal SG+CSUM combinations. */ | 3370 | /* Fix illegal SG+CSUM combinations. */ |
| 3111 | if ((dev->features & NETIF_F_SG) && | 3371 | if ((dev->features & NETIF_F_SG) && |
| 3112 | !(dev->features & NETIF_F_ALL_CSUM)) { | 3372 | !(dev->features & NETIF_F_ALL_CSUM)) { |
| @@ -3343,16 +3603,18 @@ static struct net_device_stats *internal_stats(struct net_device *dev) | |||
| 3343 | } | 3603 | } |
| 3344 | 3604 | ||
| 3345 | /** | 3605 | /** |
| 3346 | * alloc_netdev - allocate network device | 3606 | * alloc_netdev_mq - allocate network device |
| 3347 | * @sizeof_priv: size of private data to allocate space for | 3607 | * @sizeof_priv: size of private data to allocate space for |
| 3348 | * @name: device name format string | 3608 | * @name: device name format string |
| 3349 | * @setup: callback to initialize device | 3609 | * @setup: callback to initialize device |
| 3610 | * @queue_count: the number of subqueues to allocate | ||
| 3350 | * | 3611 | * |
| 3351 | * Allocates a struct net_device with private data area for driver use | 3612 | * Allocates a struct net_device with private data area for driver use |
| 3352 | * and performs basic initialization. | 3613 | * and performs basic initialization. Also allocates subquue structs |
| 3614 | * for each queue on the device at the end of the netdevice. | ||
| 3353 | */ | 3615 | */ |
| 3354 | struct net_device *alloc_netdev(int sizeof_priv, const char *name, | 3616 | struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, |
| 3355 | void (*setup)(struct net_device *)) | 3617 | void (*setup)(struct net_device *), unsigned int queue_count) |
| 3356 | { | 3618 | { |
| 3357 | void *p; | 3619 | void *p; |
| 3358 | struct net_device *dev; | 3620 | struct net_device *dev; |
| @@ -3361,7 +3623,9 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, | |||
| 3361 | BUG_ON(strlen(name) >= sizeof(dev->name)); | 3623 | BUG_ON(strlen(name) >= sizeof(dev->name)); |
| 3362 | 3624 | ||
| 3363 | /* ensure 32-byte alignment of both the device and private area */ | 3625 | /* ensure 32-byte alignment of both the device and private area */ |
| 3364 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; | 3626 | alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST + |
| 3627 | (sizeof(struct net_device_subqueue) * queue_count)) & | ||
| 3628 | ~NETDEV_ALIGN_CONST; | ||
| 3365 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; | 3629 | alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; |
| 3366 | 3630 | ||
| 3367 | p = kzalloc(alloc_size, GFP_KERNEL); | 3631 | p = kzalloc(alloc_size, GFP_KERNEL); |
| @@ -3374,15 +3638,22 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, | |||
| 3374 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 3638 | (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
| 3375 | dev->padded = (char *)dev - (char *)p; | 3639 | dev->padded = (char *)dev - (char *)p; |
| 3376 | 3640 | ||
| 3377 | if (sizeof_priv) | 3641 | if (sizeof_priv) { |
| 3378 | dev->priv = netdev_priv(dev); | 3642 | dev->priv = ((char *)dev + |
| 3643 | ((sizeof(struct net_device) + | ||
| 3644 | (sizeof(struct net_device_subqueue) * | ||
| 3645 | queue_count) + NETDEV_ALIGN_CONST) | ||
| 3646 | & ~NETDEV_ALIGN_CONST)); | ||
| 3647 | } | ||
| 3648 | |||
| 3649 | dev->egress_subqueue_count = queue_count; | ||
| 3379 | 3650 | ||
| 3380 | dev->get_stats = internal_stats; | 3651 | dev->get_stats = internal_stats; |
| 3381 | setup(dev); | 3652 | setup(dev); |
| 3382 | strcpy(dev->name, name); | 3653 | strcpy(dev->name, name); |
| 3383 | return dev; | 3654 | return dev; |
| 3384 | } | 3655 | } |
| 3385 | EXPORT_SYMBOL(alloc_netdev); | 3656 | EXPORT_SYMBOL(alloc_netdev_mq); |
| 3386 | 3657 | ||
| 3387 | /** | 3658 | /** |
| 3388 | * free_netdev - free network device | 3659 | * free_netdev - free network device |
| @@ -3471,9 +3742,9 @@ void unregister_netdevice(struct net_device *dev) | |||
| 3471 | raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); | 3742 | raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); |
| 3472 | 3743 | ||
| 3473 | /* | 3744 | /* |
| 3474 | * Flush the multicast chain | 3745 | * Flush the unicast and multicast chains |
| 3475 | */ | 3746 | */ |
| 3476 | dev_mc_discard(dev); | 3747 | dev_addr_discard(dev); |
| 3477 | 3748 | ||
| 3478 | if (dev->uninit) | 3749 | if (dev->uninit) |
| 3479 | dev->uninit(dev); | 3750 | dev->uninit(dev); |
| @@ -3563,12 +3834,13 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 3563 | * This is called when the number of channels allocated to the net_dma_client | 3834 | * This is called when the number of channels allocated to the net_dma_client |
| 3564 | * changes. The net_dma_client tries to have one DMA channel per CPU. | 3835 | * changes. The net_dma_client tries to have one DMA channel per CPU. |
| 3565 | */ | 3836 | */ |
| 3566 | static void net_dma_rebalance(void) | 3837 | |
| 3838 | static void net_dma_rebalance(struct net_dma *net_dma) | ||
| 3567 | { | 3839 | { |
| 3568 | unsigned int cpu, i, n; | 3840 | unsigned int cpu, i, n, chan_idx; |
| 3569 | struct dma_chan *chan; | 3841 | struct dma_chan *chan; |
| 3570 | 3842 | ||
| 3571 | if (net_dma_count == 0) { | 3843 | if (cpus_empty(net_dma->channel_mask)) { |
| 3572 | for_each_online_cpu(cpu) | 3844 | for_each_online_cpu(cpu) |
| 3573 | rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); | 3845 | rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); |
| 3574 | return; | 3846 | return; |
| @@ -3577,10 +3849,12 @@ static void net_dma_rebalance(void) | |||
| 3577 | i = 0; | 3849 | i = 0; |
| 3578 | cpu = first_cpu(cpu_online_map); | 3850 | cpu = first_cpu(cpu_online_map); |
| 3579 | 3851 | ||
| 3580 | rcu_read_lock(); | 3852 | for_each_cpu_mask(chan_idx, net_dma->channel_mask) { |
| 3581 | list_for_each_entry(chan, &net_dma_client->channels, client_node) { | 3853 | chan = net_dma->channels[chan_idx]; |
| 3582 | n = ((num_online_cpus() / net_dma_count) | 3854 | |
| 3583 | + (i < (num_online_cpus() % net_dma_count) ? 1 : 0)); | 3855 | n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask)) |
| 3856 | + (i < (num_online_cpus() % | ||
| 3857 | cpus_weight(net_dma->channel_mask)) ? 1 : 0)); | ||
| 3584 | 3858 | ||
| 3585 | while(n) { | 3859 | while(n) { |
| 3586 | per_cpu(softnet_data, cpu).net_dma = chan; | 3860 | per_cpu(softnet_data, cpu).net_dma = chan; |
| @@ -3589,7 +3863,6 @@ static void net_dma_rebalance(void) | |||
| 3589 | } | 3863 | } |
| 3590 | i++; | 3864 | i++; |
| 3591 | } | 3865 | } |
| 3592 | rcu_read_unlock(); | ||
| 3593 | } | 3866 | } |
| 3594 | 3867 | ||
| 3595 | /** | 3868 | /** |
| @@ -3598,23 +3871,53 @@ static void net_dma_rebalance(void) | |||
| 3598 | * @chan: DMA channel for the event | 3871 | * @chan: DMA channel for the event |
| 3599 | * @event: event type | 3872 | * @event: event type |
| 3600 | */ | 3873 | */ |
| 3601 | static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | 3874 | static enum dma_state_client |
| 3602 | enum dma_event event) | 3875 | netdev_dma_event(struct dma_client *client, struct dma_chan *chan, |
| 3603 | { | 3876 | enum dma_state state) |
| 3604 | spin_lock(&net_dma_event_lock); | 3877 | { |
| 3605 | switch (event) { | 3878 | int i, found = 0, pos = -1; |
| 3606 | case DMA_RESOURCE_ADDED: | 3879 | struct net_dma *net_dma = |
| 3607 | net_dma_count++; | 3880 | container_of(client, struct net_dma, client); |
| 3608 | net_dma_rebalance(); | 3881 | enum dma_state_client ack = DMA_DUP; /* default: take no action */ |
| 3882 | |||
| 3883 | spin_lock(&net_dma->lock); | ||
| 3884 | switch (state) { | ||
| 3885 | case DMA_RESOURCE_AVAILABLE: | ||
| 3886 | for (i = 0; i < NR_CPUS; i++) | ||
| 3887 | if (net_dma->channels[i] == chan) { | ||
| 3888 | found = 1; | ||
| 3889 | break; | ||
| 3890 | } else if (net_dma->channels[i] == NULL && pos < 0) | ||
| 3891 | pos = i; | ||
| 3892 | |||
| 3893 | if (!found && pos >= 0) { | ||
| 3894 | ack = DMA_ACK; | ||
| 3895 | net_dma->channels[pos] = chan; | ||
| 3896 | cpu_set(pos, net_dma->channel_mask); | ||
| 3897 | net_dma_rebalance(net_dma); | ||
| 3898 | } | ||
| 3609 | break; | 3899 | break; |
| 3610 | case DMA_RESOURCE_REMOVED: | 3900 | case DMA_RESOURCE_REMOVED: |
| 3611 | net_dma_count--; | 3901 | for (i = 0; i < NR_CPUS; i++) |
| 3612 | net_dma_rebalance(); | 3902 | if (net_dma->channels[i] == chan) { |
| 3903 | found = 1; | ||
| 3904 | pos = i; | ||
| 3905 | break; | ||
| 3906 | } | ||
| 3907 | |||
| 3908 | if (found) { | ||
| 3909 | ack = DMA_ACK; | ||
| 3910 | cpu_clear(pos, net_dma->channel_mask); | ||
| 3911 | net_dma->channels[i] = NULL; | ||
| 3912 | net_dma_rebalance(net_dma); | ||
| 3913 | } | ||
| 3613 | break; | 3914 | break; |
| 3614 | default: | 3915 | default: |
| 3615 | break; | 3916 | break; |
| 3616 | } | 3917 | } |
| 3617 | spin_unlock(&net_dma_event_lock); | 3918 | spin_unlock(&net_dma->lock); |
| 3919 | |||
| 3920 | return ack; | ||
| 3618 | } | 3921 | } |
| 3619 | 3922 | ||
| 3620 | /** | 3923 | /** |
| @@ -3622,12 +3925,10 @@ static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | |||
| 3622 | */ | 3925 | */ |
| 3623 | static int __init netdev_dma_register(void) | 3926 | static int __init netdev_dma_register(void) |
| 3624 | { | 3927 | { |
| 3625 | spin_lock_init(&net_dma_event_lock); | 3928 | spin_lock_init(&net_dma.lock); |
| 3626 | net_dma_client = dma_async_client_register(netdev_dma_event); | 3929 | dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask); |
| 3627 | if (net_dma_client == NULL) | 3930 | dma_async_client_register(&net_dma.client); |
| 3628 | return -ENOMEM; | 3931 | dma_async_client_chan_request(&net_dma.client); |
| 3629 | |||
| 3630 | dma_async_client_chan_request(net_dma_client, num_online_cpus()); | ||
| 3631 | return 0; | 3932 | return 0; |
| 3632 | } | 3933 | } |
| 3633 | 3934 | ||
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 5a54053386c8..99aece1aeccf 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
| @@ -64,85 +64,24 @@ | |||
| 64 | */ | 64 | */ |
| 65 | 65 | ||
| 66 | /* | 66 | /* |
| 67 | * Update the multicast list into the physical NIC controller. | ||
| 68 | */ | ||
| 69 | |||
| 70 | static void __dev_mc_upload(struct net_device *dev) | ||
| 71 | { | ||
| 72 | /* Don't do anything till we up the interface | ||
| 73 | * [dev_open will call this function so the list will | ||
| 74 | * stay sane] | ||
| 75 | */ | ||
| 76 | |||
| 77 | if (!(dev->flags&IFF_UP)) | ||
| 78 | return; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Devices with no set multicast or which have been | ||
| 82 | * detached don't get set. | ||
| 83 | */ | ||
| 84 | |||
| 85 | if (dev->set_multicast_list == NULL || | ||
| 86 | !netif_device_present(dev)) | ||
| 87 | return; | ||
| 88 | |||
| 89 | dev->set_multicast_list(dev); | ||
| 90 | } | ||
| 91 | |||
| 92 | void dev_mc_upload(struct net_device *dev) | ||
| 93 | { | ||
| 94 | netif_tx_lock_bh(dev); | ||
| 95 | __dev_mc_upload(dev); | ||
| 96 | netif_tx_unlock_bh(dev); | ||
| 97 | } | ||
| 98 | |||
| 99 | /* | ||
| 100 | * Delete a device level multicast | 67 | * Delete a device level multicast |
| 101 | */ | 68 | */ |
| 102 | 69 | ||
| 103 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | 70 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) |
| 104 | { | 71 | { |
| 105 | int err = 0; | 72 | int err; |
| 106 | struct dev_mc_list *dmi, **dmip; | ||
| 107 | 73 | ||
| 108 | netif_tx_lock_bh(dev); | 74 | netif_tx_lock_bh(dev); |
| 109 | 75 | err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, | |
| 110 | for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) { | 76 | addr, alen, glbl); |
| 77 | if (!err) { | ||
| 111 | /* | 78 | /* |
| 112 | * Find the entry we want to delete. The device could | 79 | * We have altered the list, so the card |
| 113 | * have variable length entries so check these too. | 80 | * loaded filter is now wrong. Fix it |
| 114 | */ | 81 | */ |
| 115 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && | 82 | |
| 116 | alen == dmi->dmi_addrlen) { | 83 | __dev_set_rx_mode(dev); |
| 117 | if (glbl) { | ||
| 118 | int old_glbl = dmi->dmi_gusers; | ||
| 119 | dmi->dmi_gusers = 0; | ||
| 120 | if (old_glbl == 0) | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | if (--dmi->dmi_users) | ||
| 124 | goto done; | ||
| 125 | |||
| 126 | /* | ||
| 127 | * Last user. So delete the entry. | ||
| 128 | */ | ||
| 129 | *dmip = dmi->next; | ||
| 130 | dev->mc_count--; | ||
| 131 | |||
| 132 | kfree(dmi); | ||
| 133 | |||
| 134 | /* | ||
| 135 | * We have altered the list, so the card | ||
| 136 | * loaded filter is now wrong. Fix it | ||
| 137 | */ | ||
| 138 | __dev_mc_upload(dev); | ||
| 139 | |||
| 140 | netif_tx_unlock_bh(dev); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | } | 84 | } |
| 144 | err = -ENOENT; | ||
| 145 | done: | ||
| 146 | netif_tx_unlock_bh(dev); | 85 | netif_tx_unlock_bh(dev); |
| 147 | return err; | 86 | return err; |
| 148 | } | 87 | } |
| @@ -153,68 +92,90 @@ done: | |||
| 153 | 92 | ||
| 154 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | 93 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) |
| 155 | { | 94 | { |
| 156 | int err = 0; | 95 | int err; |
| 157 | struct dev_mc_list *dmi, *dmi1; | ||
| 158 | |||
| 159 | dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC); | ||
| 160 | 96 | ||
| 161 | netif_tx_lock_bh(dev); | 97 | netif_tx_lock_bh(dev); |
| 162 | for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { | 98 | err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); |
| 163 | if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 && | 99 | if (!err) |
| 164 | dmi->dmi_addrlen == alen) { | 100 | __dev_set_rx_mode(dev); |
| 165 | if (glbl) { | 101 | netif_tx_unlock_bh(dev); |
| 166 | int old_glbl = dmi->dmi_gusers; | 102 | return err; |
| 167 | dmi->dmi_gusers = 1; | 103 | } |
| 168 | if (old_glbl) | ||
| 169 | goto done; | ||
| 170 | } | ||
| 171 | dmi->dmi_users++; | ||
| 172 | goto done; | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | if ((dmi = dmi1) == NULL) { | ||
| 177 | netif_tx_unlock_bh(dev); | ||
| 178 | return -ENOMEM; | ||
| 179 | } | ||
| 180 | memcpy(dmi->dmi_addr, addr, alen); | ||
| 181 | dmi->dmi_addrlen = alen; | ||
| 182 | dmi->next = dev->mc_list; | ||
| 183 | dmi->dmi_users = 1; | ||
| 184 | dmi->dmi_gusers = glbl ? 1 : 0; | ||
| 185 | dev->mc_list = dmi; | ||
| 186 | dev->mc_count++; | ||
| 187 | 104 | ||
| 188 | __dev_mc_upload(dev); | 105 | /** |
| 106 | * dev_mc_sync - Synchronize device's multicast list to another device | ||
| 107 | * @to: destination device | ||
| 108 | * @from: source device | ||
| 109 | * | ||
| 110 | * Add newly added addresses to the destination device and release | ||
| 111 | * addresses that have no users left. The source device must be | ||
| 112 | * locked by netif_tx_lock_bh. | ||
| 113 | * | ||
| 114 | * This function is intended to be called from the dev->set_multicast_list | ||
| 115 | * function of layered software devices. | ||
| 116 | */ | ||
| 117 | int dev_mc_sync(struct net_device *to, struct net_device *from) | ||
| 118 | { | ||
| 119 | struct dev_addr_list *da; | ||
| 120 | int err = 0; | ||
| 189 | 121 | ||
| 190 | netif_tx_unlock_bh(dev); | 122 | netif_tx_lock_bh(to); |
| 191 | return 0; | 123 | for (da = from->mc_list; da != NULL; da = da->next) { |
| 124 | if (!da->da_synced) { | ||
| 125 | err = __dev_addr_add(&to->mc_list, &to->mc_count, | ||
| 126 | da->da_addr, da->da_addrlen, 0); | ||
| 127 | if (err < 0) | ||
| 128 | break; | ||
| 129 | da->da_synced = 1; | ||
| 130 | da->da_users++; | ||
| 131 | } else if (da->da_users == 1) { | ||
| 132 | __dev_addr_delete(&to->mc_list, &to->mc_count, | ||
| 133 | da->da_addr, da->da_addrlen, 0); | ||
| 134 | __dev_addr_delete(&from->mc_list, &from->mc_count, | ||
| 135 | da->da_addr, da->da_addrlen, 0); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | if (!err) | ||
| 139 | __dev_set_rx_mode(to); | ||
| 140 | netif_tx_unlock_bh(to); | ||
| 192 | 141 | ||
| 193 | done: | ||
| 194 | netif_tx_unlock_bh(dev); | ||
| 195 | kfree(dmi1); | ||
| 196 | return err; | 142 | return err; |
| 197 | } | 143 | } |
| 144 | EXPORT_SYMBOL(dev_mc_sync); | ||
| 198 | 145 | ||
| 199 | /* | ||
| 200 | * Discard multicast list when a device is downed | ||
| 201 | */ | ||
| 202 | 146 | ||
| 203 | void dev_mc_discard(struct net_device *dev) | 147 | /** |
| 148 | * dev_mc_unsync - Remove synchronized addresses from the destination | ||
| 149 | * device | ||
| 150 | * @to: destination device | ||
| 151 | * @from: source device | ||
| 152 | * | ||
| 153 | * Remove all addresses that were added to the destination device by | ||
| 154 | * dev_mc_sync(). This function is intended to be called from the | ||
| 155 | * dev->stop function of layered software devices. | ||
| 156 | */ | ||
| 157 | void dev_mc_unsync(struct net_device *to, struct net_device *from) | ||
| 204 | { | 158 | { |
| 205 | netif_tx_lock_bh(dev); | 159 | struct dev_addr_list *da; |
| 206 | 160 | ||
| 207 | while (dev->mc_list != NULL) { | 161 | netif_tx_lock_bh(from); |
| 208 | struct dev_mc_list *tmp = dev->mc_list; | 162 | netif_tx_lock_bh(to); |
| 209 | dev->mc_list = tmp->next; | 163 | |
| 210 | if (tmp->dmi_users > tmp->dmi_gusers) | 164 | for (da = from->mc_list; da != NULL; da = da->next) { |
| 211 | printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users); | 165 | if (!da->da_synced) |
| 212 | kfree(tmp); | 166 | continue; |
| 167 | __dev_addr_delete(&to->mc_list, &to->mc_count, | ||
| 168 | da->da_addr, da->da_addrlen, 0); | ||
| 169 | da->da_synced = 0; | ||
| 170 | __dev_addr_delete(&from->mc_list, &from->mc_count, | ||
| 171 | da->da_addr, da->da_addrlen, 0); | ||
| 213 | } | 172 | } |
| 214 | dev->mc_count = 0; | 173 | __dev_set_rx_mode(to); |
| 215 | 174 | ||
| 216 | netif_tx_unlock_bh(dev); | 175 | netif_tx_unlock_bh(to); |
| 176 | netif_tx_unlock_bh(from); | ||
| 217 | } | 177 | } |
| 178 | EXPORT_SYMBOL(dev_mc_unsync); | ||
| 218 | 179 | ||
| 219 | #ifdef CONFIG_PROC_FS | 180 | #ifdef CONFIG_PROC_FS |
| 220 | static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos) | 181 | static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos) |
| @@ -244,7 +205,7 @@ static void dev_mc_seq_stop(struct seq_file *seq, void *v) | |||
| 244 | 205 | ||
| 245 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | 206 | static int dev_mc_seq_show(struct seq_file *seq, void *v) |
| 246 | { | 207 | { |
| 247 | struct dev_mc_list *m; | 208 | struct dev_addr_list *m; |
| 248 | struct net_device *dev = v; | 209 | struct net_device *dev = v; |
| 249 | 210 | ||
| 250 | netif_tx_lock_bh(dev); | 211 | netif_tx_lock_bh(dev); |
| @@ -292,4 +253,3 @@ void __init dev_mcast_init(void) | |||
| 292 | 253 | ||
| 293 | EXPORT_SYMBOL(dev_mc_add); | 254 | EXPORT_SYMBOL(dev_mc_add); |
| 294 | EXPORT_SYMBOL(dev_mc_delete); | 255 | EXPORT_SYMBOL(dev_mc_delete); |
| 295 | EXPORT_SYMBOL(dev_mc_upload); | ||
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 8d5e5a09b576..0b531e98ec33 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -52,6 +52,17 @@ int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) | |||
| 52 | 52 | ||
| 53 | return 0; | 53 | return 0; |
| 54 | } | 54 | } |
| 55 | |||
| 56 | int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) | ||
| 57 | { | ||
| 58 | if (data) | ||
| 59 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; | ||
| 60 | else | ||
| 61 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 55 | u32 ethtool_op_get_sg(struct net_device *dev) | 66 | u32 ethtool_op_get_sg(struct net_device *dev) |
| 56 | { | 67 | { |
| 57 | return (dev->features & NETIF_F_SG) != 0; | 68 | return (dev->features & NETIF_F_SG) != 0; |
| @@ -980,5 +991,6 @@ EXPORT_SYMBOL(ethtool_op_set_sg); | |||
| 980 | EXPORT_SYMBOL(ethtool_op_set_tso); | 991 | EXPORT_SYMBOL(ethtool_op_set_tso); |
| 981 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | 992 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); |
| 982 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | 993 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); |
| 994 | EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); | ||
| 983 | EXPORT_SYMBOL(ethtool_op_set_ufo); | 995 | EXPORT_SYMBOL(ethtool_op_set_ufo); |
| 984 | EXPORT_SYMBOL(ethtool_op_get_ufo); | 996 | EXPORT_SYMBOL(ethtool_op_get_ufo); |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 17daf4c9f793..590a767b029c 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
| @@ -79,27 +79,27 @@ | |||
| 79 | 79 | ||
| 80 | struct gen_estimator | 80 | struct gen_estimator |
| 81 | { | 81 | { |
| 82 | struct gen_estimator *next; | 82 | struct list_head list; |
| 83 | struct gnet_stats_basic *bstats; | 83 | struct gnet_stats_basic *bstats; |
| 84 | struct gnet_stats_rate_est *rate_est; | 84 | struct gnet_stats_rate_est *rate_est; |
| 85 | spinlock_t *stats_lock; | 85 | spinlock_t *stats_lock; |
| 86 | unsigned interval; | ||
| 87 | int ewma_log; | 86 | int ewma_log; |
| 88 | u64 last_bytes; | 87 | u64 last_bytes; |
| 89 | u32 last_packets; | 88 | u32 last_packets; |
| 90 | u32 avpps; | 89 | u32 avpps; |
| 91 | u32 avbps; | 90 | u32 avbps; |
| 91 | struct rcu_head e_rcu; | ||
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | struct gen_estimator_head | 94 | struct gen_estimator_head |
| 95 | { | 95 | { |
| 96 | struct timer_list timer; | 96 | struct timer_list timer; |
| 97 | struct gen_estimator *list; | 97 | struct list_head list; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | static struct gen_estimator_head elist[EST_MAX_INTERVAL+1]; | 100 | static struct gen_estimator_head elist[EST_MAX_INTERVAL+1]; |
| 101 | 101 | ||
| 102 | /* Estimator array lock */ | 102 | /* Protects against NULL dereference */ |
| 103 | static DEFINE_RWLOCK(est_lock); | 103 | static DEFINE_RWLOCK(est_lock); |
| 104 | 104 | ||
| 105 | static void est_timer(unsigned long arg) | 105 | static void est_timer(unsigned long arg) |
| @@ -107,13 +107,17 @@ static void est_timer(unsigned long arg) | |||
| 107 | int idx = (int)arg; | 107 | int idx = (int)arg; |
| 108 | struct gen_estimator *e; | 108 | struct gen_estimator *e; |
| 109 | 109 | ||
| 110 | read_lock(&est_lock); | 110 | rcu_read_lock(); |
| 111 | for (e = elist[idx].list; e; e = e->next) { | 111 | list_for_each_entry_rcu(e, &elist[idx].list, list) { |
| 112 | u64 nbytes; | 112 | u64 nbytes; |
| 113 | u32 npackets; | 113 | u32 npackets; |
| 114 | u32 rate; | 114 | u32 rate; |
| 115 | 115 | ||
| 116 | spin_lock(e->stats_lock); | 116 | spin_lock(e->stats_lock); |
| 117 | read_lock(&est_lock); | ||
| 118 | if (e->bstats == NULL) | ||
| 119 | goto skip; | ||
| 120 | |||
| 117 | nbytes = e->bstats->bytes; | 121 | nbytes = e->bstats->bytes; |
| 118 | npackets = e->bstats->packets; | 122 | npackets = e->bstats->packets; |
| 119 | rate = (nbytes - e->last_bytes)<<(7 - idx); | 123 | rate = (nbytes - e->last_bytes)<<(7 - idx); |
| @@ -125,11 +129,14 @@ static void est_timer(unsigned long arg) | |||
| 125 | e->last_packets = npackets; | 129 | e->last_packets = npackets; |
| 126 | e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log; | 130 | e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log; |
| 127 | e->rate_est->pps = (e->avpps+0x1FF)>>10; | 131 | e->rate_est->pps = (e->avpps+0x1FF)>>10; |
| 132 | skip: | ||
| 133 | read_unlock(&est_lock); | ||
| 128 | spin_unlock(e->stats_lock); | 134 | spin_unlock(e->stats_lock); |
| 129 | } | 135 | } |
| 130 | 136 | ||
| 131 | mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4)); | 137 | if (!list_empty(&elist[idx].list)) |
| 132 | read_unlock(&est_lock); | 138 | mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4)); |
| 139 | rcu_read_unlock(); | ||
| 133 | } | 140 | } |
| 134 | 141 | ||
| 135 | /** | 142 | /** |
| @@ -146,12 +153,17 @@ static void est_timer(unsigned long arg) | |||
| 146 | * &rate_est with the statistics lock grabed during this period. | 153 | * &rate_est with the statistics lock grabed during this period. |
| 147 | * | 154 | * |
| 148 | * Returns 0 on success or a negative error code. | 155 | * Returns 0 on success or a negative error code. |
| 156 | * | ||
| 157 | * NOTE: Called under rtnl_mutex | ||
| 149 | */ | 158 | */ |
| 150 | int gen_new_estimator(struct gnet_stats_basic *bstats, | 159 | int gen_new_estimator(struct gnet_stats_basic *bstats, |
| 151 | struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct rtattr *opt) | 160 | struct gnet_stats_rate_est *rate_est, |
| 161 | spinlock_t *stats_lock, | ||
| 162 | struct rtattr *opt) | ||
| 152 | { | 163 | { |
| 153 | struct gen_estimator *est; | 164 | struct gen_estimator *est; |
| 154 | struct gnet_estimator *parm = RTA_DATA(opt); | 165 | struct gnet_estimator *parm = RTA_DATA(opt); |
| 166 | int idx; | ||
| 155 | 167 | ||
| 156 | if (RTA_PAYLOAD(opt) < sizeof(*parm)) | 168 | if (RTA_PAYLOAD(opt) < sizeof(*parm)) |
| 157 | return -EINVAL; | 169 | return -EINVAL; |
| @@ -163,7 +175,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, | |||
| 163 | if (est == NULL) | 175 | if (est == NULL) |
| 164 | return -ENOBUFS; | 176 | return -ENOBUFS; |
| 165 | 177 | ||
| 166 | est->interval = parm->interval + 2; | 178 | idx = parm->interval + 2; |
| 167 | est->bstats = bstats; | 179 | est->bstats = bstats; |
| 168 | est->rate_est = rate_est; | 180 | est->rate_est = rate_est; |
| 169 | est->stats_lock = stats_lock; | 181 | est->stats_lock = stats_lock; |
| @@ -173,20 +185,25 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, | |||
| 173 | est->last_packets = bstats->packets; | 185 | est->last_packets = bstats->packets; |
| 174 | est->avpps = rate_est->pps<<10; | 186 | est->avpps = rate_est->pps<<10; |
| 175 | 187 | ||
| 176 | est->next = elist[est->interval].list; | 188 | if (!elist[idx].timer.function) { |
| 177 | if (est->next == NULL) { | 189 | INIT_LIST_HEAD(&elist[idx].list); |
| 178 | init_timer(&elist[est->interval].timer); | 190 | setup_timer(&elist[idx].timer, est_timer, idx); |
| 179 | elist[est->interval].timer.data = est->interval; | ||
| 180 | elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4); | ||
| 181 | elist[est->interval].timer.function = est_timer; | ||
| 182 | add_timer(&elist[est->interval].timer); | ||
| 183 | } | 191 | } |
| 184 | write_lock_bh(&est_lock); | 192 | |
| 185 | elist[est->interval].list = est; | 193 | if (list_empty(&elist[idx].list)) |
| 186 | write_unlock_bh(&est_lock); | 194 | mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4)); |
| 195 | |||
| 196 | list_add_rcu(&est->list, &elist[idx].list); | ||
| 187 | return 0; | 197 | return 0; |
| 188 | } | 198 | } |
| 189 | 199 | ||
| 200 | static void __gen_kill_estimator(struct rcu_head *head) | ||
| 201 | { | ||
| 202 | struct gen_estimator *e = container_of(head, | ||
| 203 | struct gen_estimator, e_rcu); | ||
| 204 | kfree(e); | ||
| 205 | } | ||
| 206 | |||
| 190 | /** | 207 | /** |
| 191 | * gen_kill_estimator - remove a rate estimator | 208 | * gen_kill_estimator - remove a rate estimator |
| 192 | * @bstats: basic statistics | 209 | * @bstats: basic statistics |
| @@ -194,31 +211,32 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, | |||
| 194 | * | 211 | * |
| 195 | * Removes the rate estimator specified by &bstats and &rate_est | 212 | * Removes the rate estimator specified by &bstats and &rate_est |
| 196 | * and deletes the timer. | 213 | * and deletes the timer. |
| 214 | * | ||
| 215 | * NOTE: Called under rtnl_mutex | ||
| 197 | */ | 216 | */ |
| 198 | void gen_kill_estimator(struct gnet_stats_basic *bstats, | 217 | void gen_kill_estimator(struct gnet_stats_basic *bstats, |
| 199 | struct gnet_stats_rate_est *rate_est) | 218 | struct gnet_stats_rate_est *rate_est) |
| 200 | { | 219 | { |
| 201 | int idx; | 220 | int idx; |
| 202 | struct gen_estimator *est, **pest; | 221 | struct gen_estimator *e, *n; |
| 203 | 222 | ||
| 204 | for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { | 223 | for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { |
| 205 | int killed = 0; | 224 | |
| 206 | pest = &elist[idx].list; | 225 | /* Skip non initialized indexes */ |
| 207 | while ((est=*pest) != NULL) { | 226 | if (!elist[idx].timer.function) |
| 208 | if (est->rate_est != rate_est || est->bstats != bstats) { | 227 | continue; |
| 209 | pest = &est->next; | 228 | |
| 229 | list_for_each_entry_safe(e, n, &elist[idx].list, list) { | ||
| 230 | if (e->rate_est != rate_est || e->bstats != bstats) | ||
| 210 | continue; | 231 | continue; |
| 211 | } | ||
| 212 | 232 | ||
| 213 | write_lock_bh(&est_lock); | 233 | write_lock_bh(&est_lock); |
| 214 | *pest = est->next; | 234 | e->bstats = NULL; |
| 215 | write_unlock_bh(&est_lock); | 235 | write_unlock_bh(&est_lock); |
| 216 | 236 | ||
| 217 | kfree(est); | 237 | list_del_rcu(&e->list); |
| 218 | killed++; | 238 | call_rcu(&e->e_rcu, __gen_kill_estimator); |
| 219 | } | 239 | } |
| 220 | if (killed && elist[idx].list == NULL) | ||
| 221 | del_timer(&elist[idx].timer); | ||
| 222 | } | 240 | } |
| 223 | } | 241 | } |
| 224 | 242 | ||
diff --git a/net/core/netevent.c b/net/core/netevent.c index 35d02c38554e..95f81de87502 100644 --- a/net/core/netevent.c +++ b/net/core/netevent.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
| 17 | #include <linux/notifier.h> | 17 | #include <linux/notifier.h> |
| 18 | #include <net/netevent.h> | ||
| 18 | 19 | ||
| 19 | static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain); | 20 | static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain); |
| 20 | 21 | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 758dafe284c0..de1b26aa5720 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -66,8 +66,9 @@ static void queue_process(struct work_struct *work) | |||
| 66 | 66 | ||
| 67 | local_irq_save(flags); | 67 | local_irq_save(flags); |
| 68 | netif_tx_lock(dev); | 68 | netif_tx_lock(dev); |
| 69 | if (netif_queue_stopped(dev) || | 69 | if ((netif_queue_stopped(dev) || |
| 70 | dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) { | 70 | netif_subqueue_stopped(dev, skb->queue_mapping)) || |
| 71 | dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) { | ||
| 71 | skb_queue_head(&npinfo->txq, skb); | 72 | skb_queue_head(&npinfo->txq, skb); |
| 72 | netif_tx_unlock(dev); | 73 | netif_tx_unlock(dev); |
| 73 | local_irq_restore(flags); | 74 | local_irq_restore(flags); |
| @@ -250,22 +251,24 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
| 250 | unsigned long flags; | 251 | unsigned long flags; |
| 251 | 252 | ||
| 252 | local_irq_save(flags); | 253 | local_irq_save(flags); |
| 253 | if (netif_tx_trylock(dev)) { | 254 | /* try until next clock tick */ |
| 254 | /* try until next clock tick */ | 255 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; |
| 255 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; | 256 | tries > 0; --tries) { |
| 256 | tries > 0; --tries) { | 257 | if (netif_tx_trylock(dev)) { |
| 257 | if (!netif_queue_stopped(dev)) | 258 | if (!netif_queue_stopped(dev) && |
| 259 | !netif_subqueue_stopped(dev, skb->queue_mapping)) | ||
| 258 | status = dev->hard_start_xmit(skb, dev); | 260 | status = dev->hard_start_xmit(skb, dev); |
| 261 | netif_tx_unlock(dev); | ||
| 259 | 262 | ||
| 260 | if (status == NETDEV_TX_OK) | 263 | if (status == NETDEV_TX_OK) |
| 261 | break; | 264 | break; |
| 262 | 265 | ||
| 263 | /* tickle device maybe there is some cleanup */ | ||
| 264 | netpoll_poll(np); | ||
| 265 | |||
| 266 | udelay(USEC_PER_POLL); | ||
| 267 | } | 266 | } |
| 268 | netif_tx_unlock(dev); | 267 | |
| 268 | /* tickle device maybe there is some cleanup */ | ||
| 269 | netpoll_poll(np); | ||
| 270 | |||
| 271 | udelay(USEC_PER_POLL); | ||
| 269 | } | 272 | } |
| 270 | local_irq_restore(flags); | 273 | local_irq_restore(flags); |
| 271 | } | 274 | } |
| @@ -780,14 +783,19 @@ void netpoll_cleanup(struct netpoll *np) | |||
| 780 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 783 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
| 781 | } | 784 | } |
| 782 | 785 | ||
| 783 | np->dev->npinfo = NULL; | ||
| 784 | if (atomic_dec_and_test(&npinfo->refcnt)) { | 786 | if (atomic_dec_and_test(&npinfo->refcnt)) { |
| 785 | skb_queue_purge(&npinfo->arp_tx); | 787 | skb_queue_purge(&npinfo->arp_tx); |
| 786 | skb_queue_purge(&npinfo->txq); | 788 | skb_queue_purge(&npinfo->txq); |
| 787 | cancel_rearming_delayed_work(&npinfo->tx_work); | 789 | cancel_rearming_delayed_work(&npinfo->tx_work); |
| 788 | flush_scheduled_work(); | ||
| 789 | 790 | ||
| 791 | /* clean after last, unfinished work */ | ||
| 792 | if (!skb_queue_empty(&npinfo->txq)) { | ||
| 793 | struct sk_buff *skb; | ||
| 794 | skb = __skb_dequeue(&npinfo->txq); | ||
| 795 | kfree_skb(skb); | ||
| 796 | } | ||
| 790 | kfree(npinfo); | 797 | kfree(npinfo); |
| 798 | np->dev->npinfo = NULL; | ||
| 791 | } | 799 | } |
| 792 | } | 800 | } |
| 793 | 801 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 9cd3a1cb60ef..bca787fdbc51 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
| @@ -152,6 +152,9 @@ | |||
| 152 | #include <net/checksum.h> | 152 | #include <net/checksum.h> |
| 153 | #include <net/ipv6.h> | 153 | #include <net/ipv6.h> |
| 154 | #include <net/addrconf.h> | 154 | #include <net/addrconf.h> |
| 155 | #ifdef CONFIG_XFRM | ||
| 156 | #include <net/xfrm.h> | ||
| 157 | #endif | ||
| 155 | #include <asm/byteorder.h> | 158 | #include <asm/byteorder.h> |
| 156 | #include <linux/rcupdate.h> | 159 | #include <linux/rcupdate.h> |
| 157 | #include <asm/bitops.h> | 160 | #include <asm/bitops.h> |
| @@ -181,6 +184,8 @@ | |||
| 181 | #define F_MPLS_RND (1<<8) /* Random MPLS labels */ | 184 | #define F_MPLS_RND (1<<8) /* Random MPLS labels */ |
| 182 | #define F_VID_RND (1<<9) /* Random VLAN ID */ | 185 | #define F_VID_RND (1<<9) /* Random VLAN ID */ |
| 183 | #define F_SVID_RND (1<<10) /* Random SVLAN ID */ | 186 | #define F_SVID_RND (1<<10) /* Random SVLAN ID */ |
| 187 | #define F_FLOW_SEQ (1<<11) /* Sequential flows */ | ||
| 188 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ | ||
| 184 | 189 | ||
| 185 | /* Thread control flag bits */ | 190 | /* Thread control flag bits */ |
| 186 | #define T_TERMINATE (1<<0) | 191 | #define T_TERMINATE (1<<0) |
| @@ -207,8 +212,15 @@ static struct proc_dir_entry *pg_proc_dir = NULL; | |||
| 207 | struct flow_state { | 212 | struct flow_state { |
| 208 | __be32 cur_daddr; | 213 | __be32 cur_daddr; |
| 209 | int count; | 214 | int count; |
| 215 | #ifdef CONFIG_XFRM | ||
| 216 | struct xfrm_state *x; | ||
| 217 | #endif | ||
| 218 | __u32 flags; | ||
| 210 | }; | 219 | }; |
| 211 | 220 | ||
| 221 | /* flow flag bits */ | ||
| 222 | #define F_INIT (1<<0) /* flow has been initialized */ | ||
| 223 | |||
| 212 | struct pktgen_dev { | 224 | struct pktgen_dev { |
| 213 | /* | 225 | /* |
| 214 | * Try to keep frequent/infrequent used vars. separated. | 226 | * Try to keep frequent/infrequent used vars. separated. |
| @@ -228,6 +240,7 @@ struct pktgen_dev { | |||
| 228 | 240 | ||
| 229 | int min_pkt_size; /* = ETH_ZLEN; */ | 241 | int min_pkt_size; /* = ETH_ZLEN; */ |
| 230 | int max_pkt_size; /* = ETH_ZLEN; */ | 242 | int max_pkt_size; /* = ETH_ZLEN; */ |
| 243 | int pkt_overhead; /* overhead for MPLS, VLANs, IPSEC etc */ | ||
| 231 | int nfrags; | 244 | int nfrags; |
| 232 | __u32 delay_us; /* Default delay */ | 245 | __u32 delay_us; /* Default delay */ |
| 233 | __u32 delay_ns; | 246 | __u32 delay_ns; |
| @@ -341,7 +354,11 @@ struct pktgen_dev { | |||
| 341 | unsigned cflows; /* Concurrent flows (config) */ | 354 | unsigned cflows; /* Concurrent flows (config) */ |
| 342 | unsigned lflow; /* Flow length (config) */ | 355 | unsigned lflow; /* Flow length (config) */ |
| 343 | unsigned nflows; /* accumulated flows (stats) */ | 356 | unsigned nflows; /* accumulated flows (stats) */ |
| 344 | 357 | unsigned curfl; /* current sequenced flow (state)*/ | |
| 358 | #ifdef CONFIG_XFRM | ||
| 359 | __u8 ipsmode; /* IPSEC mode (config) */ | ||
| 360 | __u8 ipsproto; /* IPSEC type (config) */ | ||
| 361 | #endif | ||
| 345 | char result[512]; | 362 | char result[512]; |
| 346 | }; | 363 | }; |
| 347 | 364 | ||
| @@ -690,6 +707,18 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
| 690 | if (pkt_dev->flags & F_MPLS_RND) | 707 | if (pkt_dev->flags & F_MPLS_RND) |
| 691 | seq_printf(seq, "MPLS_RND "); | 708 | seq_printf(seq, "MPLS_RND "); |
| 692 | 709 | ||
| 710 | if (pkt_dev->cflows) { | ||
| 711 | if (pkt_dev->flags & F_FLOW_SEQ) | ||
| 712 | seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/ | ||
| 713 | else | ||
| 714 | seq_printf(seq, "FLOW_RND "); | ||
| 715 | } | ||
| 716 | |||
| 717 | #ifdef CONFIG_XFRM | ||
| 718 | if (pkt_dev->flags & F_IPSEC_ON) | ||
| 719 | seq_printf(seq, "IPSEC "); | ||
| 720 | #endif | ||
| 721 | |||
| 693 | if (pkt_dev->flags & F_MACSRC_RND) | 722 | if (pkt_dev->flags & F_MACSRC_RND) |
| 694 | seq_printf(seq, "MACSRC_RND "); | 723 | seq_printf(seq, "MACSRC_RND "); |
| 695 | 724 | ||
| @@ -1181,6 +1210,14 @@ static ssize_t pktgen_if_write(struct file *file, | |||
| 1181 | else if (strcmp(f, "!SVID_RND") == 0) | 1210 | else if (strcmp(f, "!SVID_RND") == 0) |
| 1182 | pkt_dev->flags &= ~F_SVID_RND; | 1211 | pkt_dev->flags &= ~F_SVID_RND; |
| 1183 | 1212 | ||
| 1213 | else if (strcmp(f, "FLOW_SEQ") == 0) | ||
| 1214 | pkt_dev->flags |= F_FLOW_SEQ; | ||
| 1215 | |||
| 1216 | #ifdef CONFIG_XFRM | ||
| 1217 | else if (strcmp(f, "IPSEC") == 0) | ||
| 1218 | pkt_dev->flags |= F_IPSEC_ON; | ||
| 1219 | #endif | ||
| 1220 | |||
| 1184 | else if (strcmp(f, "!IPV6") == 0) | 1221 | else if (strcmp(f, "!IPV6") == 0) |
| 1185 | pkt_dev->flags &= ~F_IPV6; | 1222 | pkt_dev->flags &= ~F_IPV6; |
| 1186 | 1223 | ||
| @@ -1189,7 +1226,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
| 1189 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", | 1226 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", |
| 1190 | f, | 1227 | f, |
| 1191 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " | 1228 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " |
| 1192 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n"); | 1229 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n"); |
| 1193 | return count; | 1230 | return count; |
| 1194 | } | 1231 | } |
| 1195 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); | 1232 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); |
| @@ -2075,6 +2112,70 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us) | |||
| 2075 | pkt_dev->idle_acc += now - start; | 2112 | pkt_dev->idle_acc += now - start; |
| 2076 | } | 2113 | } |
| 2077 | 2114 | ||
| 2115 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) | ||
| 2116 | { | ||
| 2117 | pkt_dev->pkt_overhead = 0; | ||
| 2118 | pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32); | ||
| 2119 | pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev); | ||
| 2120 | pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev); | ||
| 2121 | } | ||
| 2122 | |||
| 2123 | static inline int f_seen(struct pktgen_dev *pkt_dev, int flow) | ||
| 2124 | { | ||
| 2125 | |||
| 2126 | if (pkt_dev->flows[flow].flags & F_INIT) | ||
| 2127 | return 1; | ||
| 2128 | else | ||
| 2129 | return 0; | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | static inline int f_pick(struct pktgen_dev *pkt_dev) | ||
| 2133 | { | ||
| 2134 | int flow = pkt_dev->curfl; | ||
| 2135 | |||
| 2136 | if (pkt_dev->flags & F_FLOW_SEQ) { | ||
| 2137 | if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { | ||
| 2138 | /* reset time */ | ||
| 2139 | pkt_dev->flows[flow].count = 0; | ||
| 2140 | pkt_dev->curfl += 1; | ||
| 2141 | if (pkt_dev->curfl >= pkt_dev->cflows) | ||
| 2142 | pkt_dev->curfl = 0; /*reset */ | ||
| 2143 | } | ||
| 2144 | } else { | ||
| 2145 | flow = random32() % pkt_dev->cflows; | ||
| 2146 | |||
| 2147 | if (pkt_dev->flows[flow].count > pkt_dev->lflow) | ||
| 2148 | pkt_dev->flows[flow].count = 0; | ||
| 2149 | } | ||
| 2150 | |||
| 2151 | return pkt_dev->curfl; | ||
| 2152 | } | ||
| 2153 | |||
| 2154 | |||
| 2155 | #ifdef CONFIG_XFRM | ||
| 2156 | /* If there was already an IPSEC SA, we keep it as is, else | ||
| 2157 | * we go look for it ... | ||
| 2158 | */ | ||
| 2159 | inline | ||
| 2160 | void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow) | ||
| 2161 | { | ||
| 2162 | struct xfrm_state *x = pkt_dev->flows[flow].x; | ||
| 2163 | if (!x) { | ||
| 2164 | /*slow path: we dont already have xfrm_state*/ | ||
| 2165 | x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr, | ||
| 2166 | (xfrm_address_t *)&pkt_dev->cur_saddr, | ||
| 2167 | AF_INET, | ||
| 2168 | pkt_dev->ipsmode, | ||
| 2169 | pkt_dev->ipsproto, 0); | ||
| 2170 | if (x) { | ||
| 2171 | pkt_dev->flows[flow].x = x; | ||
| 2172 | set_pkt_overhead(pkt_dev); | ||
| 2173 | pkt_dev->pkt_overhead+=x->props.header_len; | ||
| 2174 | } | ||
| 2175 | |||
| 2176 | } | ||
| 2177 | } | ||
| 2178 | #endif | ||
| 2078 | /* Increment/randomize headers according to flags and current values | 2179 | /* Increment/randomize headers according to flags and current values |
| 2079 | * for IP src/dest, UDP src/dst port, MAC-Addr src/dst | 2180 | * for IP src/dest, UDP src/dst port, MAC-Addr src/dst |
| 2080 | */ | 2181 | */ |
| @@ -2084,12 +2185,8 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
| 2084 | __u32 imx; | 2185 | __u32 imx; |
| 2085 | int flow = 0; | 2186 | int flow = 0; |
| 2086 | 2187 | ||
| 2087 | if (pkt_dev->cflows) { | 2188 | if (pkt_dev->cflows) |
| 2088 | flow = random32() % pkt_dev->cflows; | 2189 | flow = f_pick(pkt_dev); |
| 2089 | |||
| 2090 | if (pkt_dev->flows[flow].count > pkt_dev->lflow) | ||
| 2091 | pkt_dev->flows[flow].count = 0; | ||
| 2092 | } | ||
| 2093 | 2190 | ||
| 2094 | /* Deal with source MAC */ | 2191 | /* Deal with source MAC */ |
| 2095 | if (pkt_dev->src_mac_count > 1) { | 2192 | if (pkt_dev->src_mac_count > 1) { |
| @@ -2205,7 +2302,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
| 2205 | pkt_dev->cur_saddr = htonl(t); | 2302 | pkt_dev->cur_saddr = htonl(t); |
| 2206 | } | 2303 | } |
| 2207 | 2304 | ||
| 2208 | if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) { | 2305 | if (pkt_dev->cflows && f_seen(pkt_dev, flow)) { |
| 2209 | pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; | 2306 | pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; |
| 2210 | } else { | 2307 | } else { |
| 2211 | imn = ntohl(pkt_dev->daddr_min); | 2308 | imn = ntohl(pkt_dev->daddr_min); |
| @@ -2235,8 +2332,13 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
| 2235 | } | 2332 | } |
| 2236 | } | 2333 | } |
| 2237 | if (pkt_dev->cflows) { | 2334 | if (pkt_dev->cflows) { |
| 2335 | pkt_dev->flows[flow].flags |= F_INIT; | ||
| 2238 | pkt_dev->flows[flow].cur_daddr = | 2336 | pkt_dev->flows[flow].cur_daddr = |
| 2239 | pkt_dev->cur_daddr; | 2337 | pkt_dev->cur_daddr; |
| 2338 | #ifdef CONFIG_XFRM | ||
| 2339 | if (pkt_dev->flags & F_IPSEC_ON) | ||
| 2340 | get_ipsec_sa(pkt_dev, flow); | ||
| 2341 | #endif | ||
| 2240 | pkt_dev->nflows++; | 2342 | pkt_dev->nflows++; |
| 2241 | } | 2343 | } |
| 2242 | } | 2344 | } |
| @@ -2277,6 +2379,91 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) | |||
| 2277 | pkt_dev->flows[flow].count++; | 2379 | pkt_dev->flows[flow].count++; |
| 2278 | } | 2380 | } |
| 2279 | 2381 | ||
| 2382 | |||
| 2383 | #ifdef CONFIG_XFRM | ||
| 2384 | static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) | ||
| 2385 | { | ||
| 2386 | struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; | ||
| 2387 | int err = 0; | ||
| 2388 | struct iphdr *iph; | ||
| 2389 | |||
| 2390 | if (!x) | ||
| 2391 | return 0; | ||
| 2392 | /* XXX: we dont support tunnel mode for now until | ||
| 2393 | * we resolve the dst issue */ | ||
| 2394 | if (x->props.mode != XFRM_MODE_TRANSPORT) | ||
| 2395 | return 0; | ||
| 2396 | |||
| 2397 | spin_lock(&x->lock); | ||
| 2398 | iph = ip_hdr(skb); | ||
| 2399 | |||
| 2400 | err = x->mode->output(x, skb); | ||
| 2401 | if (err) | ||
| 2402 | goto error; | ||
| 2403 | err = x->type->output(x, skb); | ||
| 2404 | if (err) | ||
| 2405 | goto error; | ||
| 2406 | |||
| 2407 | x->curlft.bytes +=skb->len; | ||
| 2408 | x->curlft.packets++; | ||
| 2409 | spin_unlock(&x->lock); | ||
| 2410 | |||
| 2411 | error: | ||
| 2412 | spin_unlock(&x->lock); | ||
| 2413 | return err; | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | static inline void free_SAs(struct pktgen_dev *pkt_dev) | ||
| 2417 | { | ||
| 2418 | if (pkt_dev->cflows) { | ||
| 2419 | /* let go of the SAs if we have them */ | ||
| 2420 | int i = 0; | ||
| 2421 | for (; i < pkt_dev->nflows; i++){ | ||
| 2422 | struct xfrm_state *x = pkt_dev->flows[i].x; | ||
| 2423 | if (x) { | ||
| 2424 | xfrm_state_put(x); | ||
| 2425 | pkt_dev->flows[i].x = NULL; | ||
| 2426 | } | ||
| 2427 | } | ||
| 2428 | } | ||
| 2429 | } | ||
| 2430 | |||
| 2431 | static inline int process_ipsec(struct pktgen_dev *pkt_dev, | ||
| 2432 | struct sk_buff *skb, __be16 protocol) | ||
| 2433 | { | ||
| 2434 | if (pkt_dev->flags & F_IPSEC_ON) { | ||
| 2435 | struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; | ||
| 2436 | int nhead = 0; | ||
| 2437 | if (x) { | ||
| 2438 | int ret; | ||
| 2439 | __u8 *eth; | ||
| 2440 | nhead = x->props.header_len - skb_headroom(skb); | ||
| 2441 | if (nhead >0) { | ||
| 2442 | ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); | ||
| 2443 | if (ret < 0) { | ||
| 2444 | printk("Error expanding ipsec packet %d\n",ret); | ||
| 2445 | return 0; | ||
| 2446 | } | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | /* ipsec is not expecting ll header */ | ||
| 2450 | skb_pull(skb, ETH_HLEN); | ||
| 2451 | ret = pktgen_output_ipsec(skb, pkt_dev); | ||
| 2452 | if (ret) { | ||
| 2453 | printk("Error creating ipsec packet %d\n",ret); | ||
| 2454 | kfree_skb(skb); | ||
| 2455 | return 0; | ||
| 2456 | } | ||
| 2457 | /* restore ll */ | ||
| 2458 | eth = (__u8 *) skb_push(skb, ETH_HLEN); | ||
| 2459 | memcpy(eth, pkt_dev->hh, 12); | ||
| 2460 | *(u16 *) & eth[12] = protocol; | ||
| 2461 | } | ||
| 2462 | } | ||
| 2463 | return 1; | ||
| 2464 | } | ||
| 2465 | #endif | ||
| 2466 | |||
| 2280 | static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev) | 2467 | static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev) |
| 2281 | { | 2468 | { |
| 2282 | unsigned i; | 2469 | unsigned i; |
| @@ -2323,9 +2510,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
| 2323 | 2510 | ||
| 2324 | datalen = (odev->hard_header_len + 16) & ~0xf; | 2511 | datalen = (odev->hard_header_len + 16) & ~0xf; |
| 2325 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen + | 2512 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen + |
| 2326 | pkt_dev->nr_labels*sizeof(u32) + | 2513 | pkt_dev->pkt_overhead, GFP_ATOMIC); |
| 2327 | VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev), | ||
| 2328 | GFP_ATOMIC); | ||
| 2329 | if (!skb) { | 2514 | if (!skb) { |
| 2330 | sprintf(pkt_dev->result, "No memory"); | 2515 | sprintf(pkt_dev->result, "No memory"); |
| 2331 | return NULL; | 2516 | return NULL; |
| @@ -2368,7 +2553,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
| 2368 | 2553 | ||
| 2369 | /* Eth + IPh + UDPh + mpls */ | 2554 | /* Eth + IPh + UDPh + mpls */ |
| 2370 | datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - | 2555 | datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - |
| 2371 | pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev); | 2556 | pkt_dev->pkt_overhead; |
| 2372 | if (datalen < sizeof(struct pktgen_hdr)) | 2557 | if (datalen < sizeof(struct pktgen_hdr)) |
| 2373 | datalen = sizeof(struct pktgen_hdr); | 2558 | datalen = sizeof(struct pktgen_hdr); |
| 2374 | 2559 | ||
| @@ -2391,8 +2576,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
| 2391 | iph->check = ip_fast_csum((void *)iph, iph->ihl); | 2576 | iph->check = ip_fast_csum((void *)iph, iph->ihl); |
| 2392 | skb->protocol = protocol; | 2577 | skb->protocol = protocol; |
| 2393 | skb->mac_header = (skb->network_header - ETH_HLEN - | 2578 | skb->mac_header = (skb->network_header - ETH_HLEN - |
| 2394 | pkt_dev->nr_labels * sizeof(u32) - | 2579 | pkt_dev->pkt_overhead); |
| 2395 | VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev)); | ||
| 2396 | skb->dev = odev; | 2580 | skb->dev = odev; |
| 2397 | skb->pkt_type = PACKET_HOST; | 2581 | skb->pkt_type = PACKET_HOST; |
| 2398 | 2582 | ||
| @@ -2463,6 +2647,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
| 2463 | pgh->tv_usec = htonl(timestamp.tv_usec); | 2647 | pgh->tv_usec = htonl(timestamp.tv_usec); |
| 2464 | } | 2648 | } |
| 2465 | 2649 | ||
| 2650 | #ifdef CONFIG_XFRM | ||
| 2651 | if (!process_ipsec(pkt_dev, skb, protocol)) | ||
| 2652 | return NULL; | ||
| 2653 | #endif | ||
| 2654 | |||
| 2466 | return skb; | 2655 | return skb; |
| 2467 | } | 2656 | } |
| 2468 | 2657 | ||
| @@ -2662,9 +2851,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
| 2662 | mod_cur_headers(pkt_dev); | 2851 | mod_cur_headers(pkt_dev); |
| 2663 | 2852 | ||
| 2664 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 + | 2853 | skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 + |
| 2665 | pkt_dev->nr_labels*sizeof(u32) + | 2854 | pkt_dev->pkt_overhead, GFP_ATOMIC); |
| 2666 | VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev), | ||
| 2667 | GFP_ATOMIC); | ||
| 2668 | if (!skb) { | 2855 | if (!skb) { |
| 2669 | sprintf(pkt_dev->result, "No memory"); | 2856 | sprintf(pkt_dev->result, "No memory"); |
| 2670 | return NULL; | 2857 | return NULL; |
| @@ -2708,7 +2895,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
| 2708 | /* Eth + IPh + UDPh + mpls */ | 2895 | /* Eth + IPh + UDPh + mpls */ |
| 2709 | datalen = pkt_dev->cur_pkt_size - 14 - | 2896 | datalen = pkt_dev->cur_pkt_size - 14 - |
| 2710 | sizeof(struct ipv6hdr) - sizeof(struct udphdr) - | 2897 | sizeof(struct ipv6hdr) - sizeof(struct udphdr) - |
| 2711 | pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev); | 2898 | pkt_dev->pkt_overhead; |
| 2712 | 2899 | ||
| 2713 | if (datalen < sizeof(struct pktgen_hdr)) { | 2900 | if (datalen < sizeof(struct pktgen_hdr)) { |
| 2714 | datalen = sizeof(struct pktgen_hdr); | 2901 | datalen = sizeof(struct pktgen_hdr); |
| @@ -2738,8 +2925,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
| 2738 | ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); | 2925 | ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr); |
| 2739 | 2926 | ||
| 2740 | skb->mac_header = (skb->network_header - ETH_HLEN - | 2927 | skb->mac_header = (skb->network_header - ETH_HLEN - |
| 2741 | pkt_dev->nr_labels * sizeof(u32) - | 2928 | pkt_dev->pkt_overhead); |
| 2742 | VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev)); | ||
| 2743 | skb->protocol = protocol; | 2929 | skb->protocol = protocol; |
| 2744 | skb->dev = odev; | 2930 | skb->dev = odev; |
| 2745 | skb->pkt_type = PACKET_HOST; | 2931 | skb->pkt_type = PACKET_HOST; |
| @@ -2857,6 +3043,7 @@ static void pktgen_run(struct pktgen_thread *t) | |||
| 2857 | pkt_dev->started_at = getCurUs(); | 3043 | pkt_dev->started_at = getCurUs(); |
| 2858 | pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */ | 3044 | pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */ |
| 2859 | pkt_dev->next_tx_ns = 0; | 3045 | pkt_dev->next_tx_ns = 0; |
| 3046 | set_pkt_overhead(pkt_dev); | ||
| 2860 | 3047 | ||
| 2861 | strcpy(pkt_dev->result, "Starting"); | 3048 | strcpy(pkt_dev->result, "Starting"); |
| 2862 | started++; | 3049 | started++; |
| @@ -3139,7 +3326,9 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
| 3139 | } | 3326 | } |
| 3140 | } | 3327 | } |
| 3141 | 3328 | ||
| 3142 | if (netif_queue_stopped(odev) || need_resched()) { | 3329 | if ((netif_queue_stopped(odev) || |
| 3330 | netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) || | ||
| 3331 | need_resched()) { | ||
| 3143 | idle_start = getCurUs(); | 3332 | idle_start = getCurUs(); |
| 3144 | 3333 | ||
| 3145 | if (!netif_running(odev)) { | 3334 | if (!netif_running(odev)) { |
| @@ -3154,7 +3343,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
| 3154 | 3343 | ||
| 3155 | pkt_dev->idle_acc += getCurUs() - idle_start; | 3344 | pkt_dev->idle_acc += getCurUs() - idle_start; |
| 3156 | 3345 | ||
| 3157 | if (netif_queue_stopped(odev)) { | 3346 | if (netif_queue_stopped(odev) || |
| 3347 | netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) { | ||
| 3158 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ | 3348 | pkt_dev->next_tx_us = getCurUs(); /* TODO */ |
| 3159 | pkt_dev->next_tx_ns = 0; | 3349 | pkt_dev->next_tx_ns = 0; |
| 3160 | goto out; /* Try the next interface */ | 3350 | goto out; /* Try the next interface */ |
| @@ -3181,7 +3371,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
| 3181 | } | 3371 | } |
| 3182 | 3372 | ||
| 3183 | netif_tx_lock_bh(odev); | 3373 | netif_tx_lock_bh(odev); |
| 3184 | if (!netif_queue_stopped(odev)) { | 3374 | if (!netif_queue_stopped(odev) && |
| 3375 | !netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) { | ||
| 3185 | 3376 | ||
| 3186 | atomic_inc(&(pkt_dev->skb->users)); | 3377 | atomic_inc(&(pkt_dev->skb->users)); |
| 3187 | retry_now: | 3378 | retry_now: |
| @@ -3274,6 +3465,8 @@ static int pktgen_thread_worker(void *arg) | |||
| 3274 | 3465 | ||
| 3275 | set_current_state(TASK_INTERRUPTIBLE); | 3466 | set_current_state(TASK_INTERRUPTIBLE); |
| 3276 | 3467 | ||
| 3468 | set_freezable(); | ||
| 3469 | |||
| 3277 | while (!kthread_should_stop()) { | 3470 | while (!kthread_should_stop()) { |
| 3278 | pkt_dev = next_to_run(t); | 3471 | pkt_dev = next_to_run(t); |
| 3279 | 3472 | ||
| @@ -3446,11 +3639,18 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
| 3446 | } | 3639 | } |
| 3447 | pkt_dev->entry->proc_fops = &pktgen_if_fops; | 3640 | pkt_dev->entry->proc_fops = &pktgen_if_fops; |
| 3448 | pkt_dev->entry->data = pkt_dev; | 3641 | pkt_dev->entry->data = pkt_dev; |
| 3642 | #ifdef CONFIG_XFRM | ||
| 3643 | pkt_dev->ipsmode = XFRM_MODE_TRANSPORT; | ||
| 3644 | pkt_dev->ipsproto = IPPROTO_ESP; | ||
| 3645 | #endif | ||
| 3449 | 3646 | ||
| 3450 | return add_dev_to_thread(t, pkt_dev); | 3647 | return add_dev_to_thread(t, pkt_dev); |
| 3451 | out2: | 3648 | out2: |
| 3452 | dev_put(pkt_dev->odev); | 3649 | dev_put(pkt_dev->odev); |
| 3453 | out1: | 3650 | out1: |
| 3651 | #ifdef CONFIG_XFRM | ||
| 3652 | free_SAs(pkt_dev); | ||
| 3653 | #endif | ||
| 3454 | if (pkt_dev->flows) | 3654 | if (pkt_dev->flows) |
| 3455 | vfree(pkt_dev->flows); | 3655 | vfree(pkt_dev->flows); |
| 3456 | kfree(pkt_dev); | 3656 | kfree(pkt_dev); |
| @@ -3545,6 +3745,9 @@ static int pktgen_remove_device(struct pktgen_thread *t, | |||
| 3545 | if (pkt_dev->entry) | 3745 | if (pkt_dev->entry) |
| 3546 | remove_proc_entry(pkt_dev->entry->name, pg_proc_dir); | 3746 | remove_proc_entry(pkt_dev->entry->name, pg_proc_dir); |
| 3547 | 3747 | ||
| 3748 | #ifdef CONFIG_XFRM | ||
| 3749 | free_SAs(pkt_dev); | ||
| 3750 | #endif | ||
| 3548 | if (pkt_dev->flows) | 3751 | if (pkt_dev->flows) |
| 3549 | vfree(pkt_dev->flows); | 3752 | vfree(pkt_dev->flows); |
| 3550 | kfree(pkt_dev); | 3753 | kfree(pkt_dev); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 02e8bf084277..864cbdf31ed7 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -97,6 +97,19 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) | |||
| 97 | return 0; | 97 | return 0; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr, | ||
| 101 | struct rtattr *rta, int len) | ||
| 102 | { | ||
| 103 | if (RTA_PAYLOAD(rta) < len) | ||
| 104 | return -1; | ||
| 105 | if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) { | ||
| 106 | rta = RTA_DATA(rta) + RTA_ALIGN(len); | ||
| 107 | return rtattr_parse_nested(tb, maxattr, rta); | ||
| 108 | } | ||
| 109 | memset(tb, 0, sizeof(struct rtattr *) * maxattr); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 100 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; | 113 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; |
| 101 | 114 | ||
| 102 | static inline int rtm_msgindex(int msgtype) | 115 | static inline int rtm_msgindex(int msgtype) |
| @@ -243,6 +256,150 @@ void rtnl_unregister_all(int protocol) | |||
| 243 | 256 | ||
| 244 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); | 257 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); |
| 245 | 258 | ||
| 259 | static LIST_HEAD(link_ops); | ||
| 260 | |||
| 261 | /** | ||
| 262 | * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. | ||
| 263 | * @ops: struct rtnl_link_ops * to register | ||
| 264 | * | ||
| 265 | * The caller must hold the rtnl_mutex. This function should be used | ||
| 266 | * by drivers that create devices during module initialization. It | ||
| 267 | * must be called before registering the devices. | ||
| 268 | * | ||
| 269 | * Returns 0 on success or a negative error code. | ||
| 270 | */ | ||
| 271 | int __rtnl_link_register(struct rtnl_link_ops *ops) | ||
| 272 | { | ||
| 273 | if (!ops->dellink) | ||
| 274 | ops->dellink = unregister_netdevice; | ||
| 275 | |||
| 276 | list_add_tail(&ops->list, &link_ops); | ||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | EXPORT_SYMBOL_GPL(__rtnl_link_register); | ||
| 281 | |||
| 282 | /** | ||
| 283 | * rtnl_link_register - Register rtnl_link_ops with rtnetlink. | ||
| 284 | * @ops: struct rtnl_link_ops * to register | ||
| 285 | * | ||
| 286 | * Returns 0 on success or a negative error code. | ||
| 287 | */ | ||
| 288 | int rtnl_link_register(struct rtnl_link_ops *ops) | ||
| 289 | { | ||
| 290 | int err; | ||
| 291 | |||
| 292 | rtnl_lock(); | ||
| 293 | err = __rtnl_link_register(ops); | ||
| 294 | rtnl_unlock(); | ||
| 295 | return err; | ||
| 296 | } | ||
| 297 | |||
| 298 | EXPORT_SYMBOL_GPL(rtnl_link_register); | ||
| 299 | |||
| 300 | /** | ||
| 301 | * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | ||
| 302 | * @ops: struct rtnl_link_ops * to unregister | ||
| 303 | * | ||
| 304 | * The caller must hold the rtnl_mutex. | ||
| 305 | */ | ||
| 306 | void __rtnl_link_unregister(struct rtnl_link_ops *ops) | ||
| 307 | { | ||
| 308 | struct net_device *dev, *n; | ||
| 309 | |||
| 310 | for_each_netdev_safe(dev, n) { | ||
| 311 | if (dev->rtnl_link_ops == ops) | ||
| 312 | ops->dellink(dev); | ||
| 313 | } | ||
| 314 | list_del(&ops->list); | ||
| 315 | } | ||
| 316 | |||
| 317 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | ||
| 318 | |||
| 319 | /** | ||
| 320 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | ||
| 321 | * @ops: struct rtnl_link_ops * to unregister | ||
| 322 | */ | ||
| 323 | void rtnl_link_unregister(struct rtnl_link_ops *ops) | ||
| 324 | { | ||
| 325 | rtnl_lock(); | ||
| 326 | __rtnl_link_unregister(ops); | ||
| 327 | rtnl_unlock(); | ||
| 328 | } | ||
| 329 | |||
| 330 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | ||
| 331 | |||
| 332 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) | ||
| 333 | { | ||
| 334 | const struct rtnl_link_ops *ops; | ||
| 335 | |||
| 336 | list_for_each_entry(ops, &link_ops, list) { | ||
| 337 | if (!strcmp(ops->kind, kind)) | ||
| 338 | return ops; | ||
| 339 | } | ||
| 340 | return NULL; | ||
| 341 | } | ||
| 342 | |||
| 343 | static size_t rtnl_link_get_size(const struct net_device *dev) | ||
| 344 | { | ||
| 345 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; | ||
| 346 | size_t size; | ||
| 347 | |||
| 348 | if (!ops) | ||
| 349 | return 0; | ||
| 350 | |||
| 351 | size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */ | ||
| 352 | nlmsg_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_KIND */ | ||
| 353 | |||
| 354 | if (ops->get_size) | ||
| 355 | /* IFLA_INFO_DATA + nested data */ | ||
| 356 | size += nlmsg_total_size(sizeof(struct nlattr)) + | ||
| 357 | ops->get_size(dev); | ||
| 358 | |||
| 359 | if (ops->get_xstats_size) | ||
| 360 | size += ops->get_xstats_size(dev); /* IFLA_INFO_XSTATS */ | ||
| 361 | |||
| 362 | return size; | ||
| 363 | } | ||
| 364 | |||
| 365 | static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev) | ||
| 366 | { | ||
| 367 | const struct rtnl_link_ops *ops = dev->rtnl_link_ops; | ||
| 368 | struct nlattr *linkinfo, *data; | ||
| 369 | int err = -EMSGSIZE; | ||
| 370 | |||
| 371 | linkinfo = nla_nest_start(skb, IFLA_LINKINFO); | ||
| 372 | if (linkinfo == NULL) | ||
| 373 | goto out; | ||
| 374 | |||
| 375 | if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0) | ||
| 376 | goto err_cancel_link; | ||
| 377 | if (ops->fill_xstats) { | ||
| 378 | err = ops->fill_xstats(skb, dev); | ||
| 379 | if (err < 0) | ||
| 380 | goto err_cancel_link; | ||
| 381 | } | ||
| 382 | if (ops->fill_info) { | ||
| 383 | data = nla_nest_start(skb, IFLA_INFO_DATA); | ||
| 384 | if (data == NULL) | ||
| 385 | goto err_cancel_link; | ||
| 386 | err = ops->fill_info(skb, dev); | ||
| 387 | if (err < 0) | ||
| 388 | goto err_cancel_data; | ||
| 389 | nla_nest_end(skb, data); | ||
| 390 | } | ||
| 391 | |||
| 392 | nla_nest_end(skb, linkinfo); | ||
| 393 | return 0; | ||
| 394 | |||
| 395 | err_cancel_data: | ||
| 396 | nla_nest_cancel(skb, data); | ||
| 397 | err_cancel_link: | ||
| 398 | nla_nest_cancel(skb, linkinfo); | ||
| 399 | out: | ||
| 400 | return err; | ||
| 401 | } | ||
| 402 | |||
| 246 | static const int rtm_min[RTM_NR_FAMILIES] = | 403 | static const int rtm_min[RTM_NR_FAMILIES] = |
| 247 | { | 404 | { |
| 248 | [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), | 405 | [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), |
| @@ -437,7 +594,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
| 437 | a->tx_compressed = b->tx_compressed; | 594 | a->tx_compressed = b->tx_compressed; |
| 438 | }; | 595 | }; |
| 439 | 596 | ||
| 440 | static inline size_t if_nlmsg_size(void) | 597 | static inline size_t if_nlmsg_size(const struct net_device *dev) |
| 441 | { | 598 | { |
| 442 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 599 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
| 443 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ | 600 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ |
| @@ -452,7 +609,8 @@ static inline size_t if_nlmsg_size(void) | |||
| 452 | + nla_total_size(4) /* IFLA_LINK */ | 609 | + nla_total_size(4) /* IFLA_LINK */ |
| 453 | + nla_total_size(4) /* IFLA_MASTER */ | 610 | + nla_total_size(4) /* IFLA_MASTER */ |
| 454 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 611 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
| 455 | + nla_total_size(1); /* IFLA_LINKMODE */ | 612 | + nla_total_size(1) /* IFLA_LINKMODE */ |
| 613 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | ||
| 456 | } | 614 | } |
| 457 | 615 | ||
| 458 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | 616 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
| @@ -522,6 +680,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
| 522 | } | 680 | } |
| 523 | } | 681 | } |
| 524 | 682 | ||
| 683 | if (dev->rtnl_link_ops) { | ||
| 684 | if (rtnl_link_fill(skb, dev) < 0) | ||
| 685 | goto nla_put_failure; | ||
| 686 | } | ||
| 687 | |||
| 525 | return nlmsg_end(skb, nlh); | 688 | return nlmsg_end(skb, nlh); |
| 526 | 689 | ||
| 527 | nla_put_failure: | 690 | nla_put_failure: |
| @@ -553,6 +716,8 @@ cont: | |||
| 553 | 716 | ||
| 554 | static const struct nla_policy ifla_policy[IFLA_MAX+1] = { | 717 | static const struct nla_policy ifla_policy[IFLA_MAX+1] = { |
| 555 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, | 718 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, |
| 719 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | ||
| 720 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | ||
| 556 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, | 721 | [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, |
| 557 | [IFLA_MTU] = { .type = NLA_U32 }, | 722 | [IFLA_MTU] = { .type = NLA_U32 }, |
| 558 | [IFLA_TXQLEN] = { .type = NLA_U32 }, | 723 | [IFLA_TXQLEN] = { .type = NLA_U32 }, |
| @@ -561,44 +726,16 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
| 561 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 726 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
| 562 | }; | 727 | }; |
| 563 | 728 | ||
| 564 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 729 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
| 565 | { | 730 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, |
| 566 | struct ifinfomsg *ifm; | 731 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
| 567 | struct net_device *dev; | 732 | }; |
| 568 | int err, send_addr_notify = 0, modified = 0; | ||
| 569 | struct nlattr *tb[IFLA_MAX+1]; | ||
| 570 | char ifname[IFNAMSIZ]; | ||
| 571 | |||
| 572 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
| 573 | if (err < 0) | ||
| 574 | goto errout; | ||
| 575 | |||
| 576 | if (tb[IFLA_IFNAME]) | ||
| 577 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
| 578 | else | ||
| 579 | ifname[0] = '\0'; | ||
| 580 | |||
| 581 | err = -EINVAL; | ||
| 582 | ifm = nlmsg_data(nlh); | ||
| 583 | if (ifm->ifi_index > 0) | ||
| 584 | dev = dev_get_by_index(ifm->ifi_index); | ||
| 585 | else if (tb[IFLA_IFNAME]) | ||
| 586 | dev = dev_get_by_name(ifname); | ||
| 587 | else | ||
| 588 | goto errout; | ||
| 589 | |||
| 590 | if (dev == NULL) { | ||
| 591 | err = -ENODEV; | ||
| 592 | goto errout; | ||
| 593 | } | ||
| 594 | |||
| 595 | if (tb[IFLA_ADDRESS] && | ||
| 596 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
| 597 | goto errout_dev; | ||
| 598 | 733 | ||
| 599 | if (tb[IFLA_BROADCAST] && | 734 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
| 600 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | 735 | struct nlattr **tb, char *ifname, int modified) |
| 601 | goto errout_dev; | 736 | { |
| 737 | int send_addr_notify = 0; | ||
| 738 | int err; | ||
| 602 | 739 | ||
| 603 | if (tb[IFLA_MAP]) { | 740 | if (tb[IFLA_MAP]) { |
| 604 | struct rtnl_link_ifmap *u_map; | 741 | struct rtnl_link_ifmap *u_map; |
| @@ -606,12 +743,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 606 | 743 | ||
| 607 | if (!dev->set_config) { | 744 | if (!dev->set_config) { |
| 608 | err = -EOPNOTSUPP; | 745 | err = -EOPNOTSUPP; |
| 609 | goto errout_dev; | 746 | goto errout; |
| 610 | } | 747 | } |
| 611 | 748 | ||
| 612 | if (!netif_device_present(dev)) { | 749 | if (!netif_device_present(dev)) { |
| 613 | err = -ENODEV; | 750 | err = -ENODEV; |
| 614 | goto errout_dev; | 751 | goto errout; |
| 615 | } | 752 | } |
| 616 | 753 | ||
| 617 | u_map = nla_data(tb[IFLA_MAP]); | 754 | u_map = nla_data(tb[IFLA_MAP]); |
| @@ -624,7 +761,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 624 | 761 | ||
| 625 | err = dev->set_config(dev, &k_map); | 762 | err = dev->set_config(dev, &k_map); |
| 626 | if (err < 0) | 763 | if (err < 0) |
| 627 | goto errout_dev; | 764 | goto errout; |
| 628 | 765 | ||
| 629 | modified = 1; | 766 | modified = 1; |
| 630 | } | 767 | } |
| @@ -635,19 +772,19 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 635 | 772 | ||
| 636 | if (!dev->set_mac_address) { | 773 | if (!dev->set_mac_address) { |
| 637 | err = -EOPNOTSUPP; | 774 | err = -EOPNOTSUPP; |
| 638 | goto errout_dev; | 775 | goto errout; |
| 639 | } | 776 | } |
| 640 | 777 | ||
| 641 | if (!netif_device_present(dev)) { | 778 | if (!netif_device_present(dev)) { |
| 642 | err = -ENODEV; | 779 | err = -ENODEV; |
| 643 | goto errout_dev; | 780 | goto errout; |
| 644 | } | 781 | } |
| 645 | 782 | ||
| 646 | len = sizeof(sa_family_t) + dev->addr_len; | 783 | len = sizeof(sa_family_t) + dev->addr_len; |
| 647 | sa = kmalloc(len, GFP_KERNEL); | 784 | sa = kmalloc(len, GFP_KERNEL); |
| 648 | if (!sa) { | 785 | if (!sa) { |
| 649 | err = -ENOMEM; | 786 | err = -ENOMEM; |
| 650 | goto errout_dev; | 787 | goto errout; |
| 651 | } | 788 | } |
| 652 | sa->sa_family = dev->type; | 789 | sa->sa_family = dev->type; |
| 653 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), | 790 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), |
| @@ -655,7 +792,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 655 | err = dev->set_mac_address(dev, sa); | 792 | err = dev->set_mac_address(dev, sa); |
| 656 | kfree(sa); | 793 | kfree(sa); |
| 657 | if (err) | 794 | if (err) |
| 658 | goto errout_dev; | 795 | goto errout; |
| 659 | send_addr_notify = 1; | 796 | send_addr_notify = 1; |
| 660 | modified = 1; | 797 | modified = 1; |
| 661 | } | 798 | } |
| @@ -663,7 +800,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 663 | if (tb[IFLA_MTU]) { | 800 | if (tb[IFLA_MTU]) { |
| 664 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); | 801 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); |
| 665 | if (err < 0) | 802 | if (err < 0) |
| 666 | goto errout_dev; | 803 | goto errout; |
| 667 | modified = 1; | 804 | modified = 1; |
| 668 | } | 805 | } |
| 669 | 806 | ||
| @@ -675,7 +812,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 675 | if (ifm->ifi_index > 0 && ifname[0]) { | 812 | if (ifm->ifi_index > 0 && ifname[0]) { |
| 676 | err = dev_change_name(dev, ifname); | 813 | err = dev_change_name(dev, ifname); |
| 677 | if (err < 0) | 814 | if (err < 0) |
| 678 | goto errout_dev; | 815 | goto errout; |
| 679 | modified = 1; | 816 | modified = 1; |
| 680 | } | 817 | } |
| 681 | 818 | ||
| @@ -684,7 +821,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 684 | send_addr_notify = 1; | 821 | send_addr_notify = 1; |
| 685 | } | 822 | } |
| 686 | 823 | ||
| 687 | |||
| 688 | if (ifm->ifi_flags || ifm->ifi_change) { | 824 | if (ifm->ifi_flags || ifm->ifi_change) { |
| 689 | unsigned int flags = ifm->ifi_flags; | 825 | unsigned int flags = ifm->ifi_flags; |
| 690 | 826 | ||
| @@ -712,7 +848,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
| 712 | 848 | ||
| 713 | err = 0; | 849 | err = 0; |
| 714 | 850 | ||
| 715 | errout_dev: | 851 | errout: |
| 716 | if (err < 0 && modified && net_ratelimit()) | 852 | if (err < 0 && modified && net_ratelimit()) |
| 717 | printk(KERN_WARNING "A link change request failed with " | 853 | printk(KERN_WARNING "A link change request failed with " |
| 718 | "some changes comitted already. Interface %s may " | 854 | "some changes comitted already. Interface %s may " |
| @@ -721,12 +857,239 @@ errout_dev: | |||
| 721 | 857 | ||
| 722 | if (send_addr_notify) | 858 | if (send_addr_notify) |
| 723 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 859 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
| 860 | return err; | ||
| 861 | } | ||
| 862 | |||
| 863 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
| 864 | { | ||
| 865 | struct ifinfomsg *ifm; | ||
| 866 | struct net_device *dev; | ||
| 867 | int err; | ||
| 868 | struct nlattr *tb[IFLA_MAX+1]; | ||
| 869 | char ifname[IFNAMSIZ]; | ||
| 870 | |||
| 871 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
| 872 | if (err < 0) | ||
| 873 | goto errout; | ||
| 874 | |||
| 875 | if (tb[IFLA_IFNAME]) | ||
| 876 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
| 877 | else | ||
| 878 | ifname[0] = '\0'; | ||
| 879 | |||
| 880 | err = -EINVAL; | ||
| 881 | ifm = nlmsg_data(nlh); | ||
| 882 | if (ifm->ifi_index > 0) | ||
| 883 | dev = dev_get_by_index(ifm->ifi_index); | ||
| 884 | else if (tb[IFLA_IFNAME]) | ||
| 885 | dev = dev_get_by_name(ifname); | ||
| 886 | else | ||
| 887 | goto errout; | ||
| 888 | |||
| 889 | if (dev == NULL) { | ||
| 890 | err = -ENODEV; | ||
| 891 | goto errout; | ||
| 892 | } | ||
| 724 | 893 | ||
| 894 | if (tb[IFLA_ADDRESS] && | ||
| 895 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
| 896 | goto errout_dev; | ||
| 897 | |||
| 898 | if (tb[IFLA_BROADCAST] && | ||
| 899 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | ||
| 900 | goto errout_dev; | ||
| 901 | |||
| 902 | err = do_setlink(dev, ifm, tb, ifname, 0); | ||
| 903 | errout_dev: | ||
| 725 | dev_put(dev); | 904 | dev_put(dev); |
| 726 | errout: | 905 | errout: |
| 727 | return err; | 906 | return err; |
| 728 | } | 907 | } |
| 729 | 908 | ||
| 909 | static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
| 910 | { | ||
| 911 | const struct rtnl_link_ops *ops; | ||
| 912 | struct net_device *dev; | ||
| 913 | struct ifinfomsg *ifm; | ||
| 914 | char ifname[IFNAMSIZ]; | ||
| 915 | struct nlattr *tb[IFLA_MAX+1]; | ||
| 916 | int err; | ||
| 917 | |||
| 918 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
| 919 | if (err < 0) | ||
| 920 | return err; | ||
| 921 | |||
| 922 | if (tb[IFLA_IFNAME]) | ||
| 923 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
| 924 | |||
| 925 | ifm = nlmsg_data(nlh); | ||
| 926 | if (ifm->ifi_index > 0) | ||
| 927 | dev = __dev_get_by_index(ifm->ifi_index); | ||
| 928 | else if (tb[IFLA_IFNAME]) | ||
| 929 | dev = __dev_get_by_name(ifname); | ||
| 930 | else | ||
| 931 | return -EINVAL; | ||
| 932 | |||
| 933 | if (!dev) | ||
| 934 | return -ENODEV; | ||
| 935 | |||
| 936 | ops = dev->rtnl_link_ops; | ||
| 937 | if (!ops) | ||
| 938 | return -EOPNOTSUPP; | ||
| 939 | |||
| 940 | ops->dellink(dev); | ||
| 941 | return 0; | ||
| 942 | } | ||
| 943 | |||
| 944 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
| 945 | { | ||
| 946 | const struct rtnl_link_ops *ops; | ||
| 947 | struct net_device *dev; | ||
| 948 | struct ifinfomsg *ifm; | ||
| 949 | char kind[MODULE_NAME_LEN]; | ||
| 950 | char ifname[IFNAMSIZ]; | ||
| 951 | struct nlattr *tb[IFLA_MAX+1]; | ||
| 952 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; | ||
| 953 | int err; | ||
| 954 | |||
| 955 | replay: | ||
| 956 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
| 957 | if (err < 0) | ||
| 958 | return err; | ||
| 959 | |||
| 960 | if (tb[IFLA_IFNAME]) | ||
| 961 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
| 962 | else | ||
| 963 | ifname[0] = '\0'; | ||
| 964 | |||
| 965 | ifm = nlmsg_data(nlh); | ||
| 966 | if (ifm->ifi_index > 0) | ||
| 967 | dev = __dev_get_by_index(ifm->ifi_index); | ||
| 968 | else if (ifname[0]) | ||
| 969 | dev = __dev_get_by_name(ifname); | ||
| 970 | else | ||
| 971 | dev = NULL; | ||
| 972 | |||
| 973 | if (tb[IFLA_LINKINFO]) { | ||
| 974 | err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, | ||
| 975 | tb[IFLA_LINKINFO], ifla_info_policy); | ||
| 976 | if (err < 0) | ||
| 977 | return err; | ||
| 978 | } else | ||
| 979 | memset(linkinfo, 0, sizeof(linkinfo)); | ||
| 980 | |||
| 981 | if (linkinfo[IFLA_INFO_KIND]) { | ||
| 982 | nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind)); | ||
| 983 | ops = rtnl_link_ops_get(kind); | ||
| 984 | } else { | ||
| 985 | kind[0] = '\0'; | ||
| 986 | ops = NULL; | ||
| 987 | } | ||
| 988 | |||
| 989 | if (1) { | ||
| 990 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; | ||
| 991 | |||
| 992 | if (ops) { | ||
| 993 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { | ||
| 994 | err = nla_parse_nested(attr, ops->maxtype, | ||
| 995 | linkinfo[IFLA_INFO_DATA], | ||
| 996 | ops->policy); | ||
| 997 | if (err < 0) | ||
| 998 | return err; | ||
| 999 | data = attr; | ||
| 1000 | } | ||
| 1001 | if (ops->validate) { | ||
| 1002 | err = ops->validate(tb, data); | ||
| 1003 | if (err < 0) | ||
| 1004 | return err; | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | if (dev) { | ||
| 1009 | int modified = 0; | ||
| 1010 | |||
| 1011 | if (nlh->nlmsg_flags & NLM_F_EXCL) | ||
| 1012 | return -EEXIST; | ||
| 1013 | if (nlh->nlmsg_flags & NLM_F_REPLACE) | ||
| 1014 | return -EOPNOTSUPP; | ||
| 1015 | |||
| 1016 | if (linkinfo[IFLA_INFO_DATA]) { | ||
| 1017 | if (!ops || ops != dev->rtnl_link_ops || | ||
| 1018 | !ops->changelink) | ||
| 1019 | return -EOPNOTSUPP; | ||
| 1020 | |||
| 1021 | err = ops->changelink(dev, tb, data); | ||
| 1022 | if (err < 0) | ||
| 1023 | return err; | ||
| 1024 | modified = 1; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | return do_setlink(dev, ifm, tb, ifname, modified); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) | ||
| 1031 | return -ENODEV; | ||
| 1032 | |||
| 1033 | if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change) | ||
| 1034 | return -EOPNOTSUPP; | ||
| 1035 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) | ||
| 1036 | return -EOPNOTSUPP; | ||
| 1037 | |||
| 1038 | if (!ops) { | ||
| 1039 | #ifdef CONFIG_KMOD | ||
| 1040 | if (kind[0]) { | ||
| 1041 | __rtnl_unlock(); | ||
| 1042 | request_module("rtnl-link-%s", kind); | ||
| 1043 | rtnl_lock(); | ||
| 1044 | ops = rtnl_link_ops_get(kind); | ||
| 1045 | if (ops) | ||
| 1046 | goto replay; | ||
| 1047 | } | ||
| 1048 | #endif | ||
| 1049 | return -EOPNOTSUPP; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | if (!ifname[0]) | ||
| 1053 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | ||
| 1054 | dev = alloc_netdev(ops->priv_size, ifname, ops->setup); | ||
| 1055 | if (!dev) | ||
| 1056 | return -ENOMEM; | ||
| 1057 | |||
| 1058 | if (strchr(dev->name, '%')) { | ||
| 1059 | err = dev_alloc_name(dev, dev->name); | ||
| 1060 | if (err < 0) | ||
| 1061 | goto err_free; | ||
| 1062 | } | ||
| 1063 | dev->rtnl_link_ops = ops; | ||
| 1064 | |||
| 1065 | if (tb[IFLA_MTU]) | ||
| 1066 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | ||
| 1067 | if (tb[IFLA_ADDRESS]) | ||
| 1068 | memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), | ||
| 1069 | nla_len(tb[IFLA_ADDRESS])); | ||
| 1070 | if (tb[IFLA_BROADCAST]) | ||
| 1071 | memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), | ||
| 1072 | nla_len(tb[IFLA_BROADCAST])); | ||
| 1073 | if (tb[IFLA_TXQLEN]) | ||
| 1074 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | ||
| 1075 | if (tb[IFLA_WEIGHT]) | ||
| 1076 | dev->weight = nla_get_u32(tb[IFLA_WEIGHT]); | ||
| 1077 | if (tb[IFLA_OPERSTATE]) | ||
| 1078 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | ||
| 1079 | if (tb[IFLA_LINKMODE]) | ||
| 1080 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | ||
| 1081 | |||
| 1082 | if (ops->newlink) | ||
| 1083 | err = ops->newlink(dev, tb, data); | ||
| 1084 | else | ||
| 1085 | err = register_netdevice(dev); | ||
| 1086 | err_free: | ||
| 1087 | if (err < 0) | ||
| 1088 | free_netdev(dev); | ||
| 1089 | return err; | ||
| 1090 | } | ||
| 1091 | } | ||
| 1092 | |||
| 730 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 1093 | static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
| 731 | { | 1094 | { |
| 732 | struct ifinfomsg *ifm; | 1095 | struct ifinfomsg *ifm; |
| @@ -747,7 +1110,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
| 747 | } else | 1110 | } else |
| 748 | return -EINVAL; | 1111 | return -EINVAL; |
| 749 | 1112 | ||
| 750 | nskb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL); | 1113 | nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); |
| 751 | if (nskb == NULL) { | 1114 | if (nskb == NULL) { |
| 752 | err = -ENOBUFS; | 1115 | err = -ENOBUFS; |
| 753 | goto errout; | 1116 | goto errout; |
| @@ -797,7 +1160,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) | |||
| 797 | struct sk_buff *skb; | 1160 | struct sk_buff *skb; |
| 798 | int err = -ENOBUFS; | 1161 | int err = -ENOBUFS; |
| 799 | 1162 | ||
| 800 | skb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL); | 1163 | skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); |
| 801 | if (skb == NULL) | 1164 | if (skb == NULL) |
| 802 | goto errout; | 1165 | goto errout; |
| 803 | 1166 | ||
| @@ -952,6 +1315,8 @@ void __init rtnetlink_init(void) | |||
| 952 | 1315 | ||
| 953 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); | 1316 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); |
| 954 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); | 1317 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); |
| 1318 | rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL); | ||
| 1319 | rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL); | ||
| 955 | 1320 | ||
| 956 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); | 1321 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); |
| 957 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); | 1322 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); |
| @@ -960,6 +1325,7 @@ void __init rtnetlink_init(void) | |||
| 960 | EXPORT_SYMBOL(__rta_fill); | 1325 | EXPORT_SYMBOL(__rta_fill); |
| 961 | EXPORT_SYMBOL(rtattr_strlcpy); | 1326 | EXPORT_SYMBOL(rtattr_strlcpy); |
| 962 | EXPORT_SYMBOL(rtattr_parse); | 1327 | EXPORT_SYMBOL(rtattr_parse); |
| 1328 | EXPORT_SYMBOL(__rtattr_parse_nested_compat); | ||
| 963 | EXPORT_SYMBOL(rtnetlink_put_metrics); | 1329 | EXPORT_SYMBOL(rtnetlink_put_metrics); |
| 964 | EXPORT_SYMBOL(rtnl_lock); | 1330 | EXPORT_SYMBOL(rtnl_lock); |
| 965 | EXPORT_SYMBOL(rtnl_trylock); | 1331 | EXPORT_SYMBOL(rtnl_trylock); |
diff --git a/net/core/scm.c b/net/core/scm.c index 292ad8d5ad76..44c4ec2c8769 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
| @@ -228,7 +228,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
| 228 | err = security_file_receive(fp[i]); | 228 | err = security_file_receive(fp[i]); |
| 229 | if (err) | 229 | if (err) |
| 230 | break; | 230 | break; |
| 231 | err = get_unused_fd(); | 231 | err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags |
| 232 | ? O_CLOEXEC : 0); | ||
| 232 | if (err < 0) | 233 | if (err < 0) |
| 233 | break; | 234 | break; |
| 234 | new_fd = err; | 235 | new_fd = err; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 7c6a34e21eee..0583e8498f13 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -415,9 +415,11 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 415 | C(csum); | 415 | C(csum); |
| 416 | C(local_df); | 416 | C(local_df); |
| 417 | n->cloned = 1; | 417 | n->cloned = 1; |
| 418 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | ||
| 418 | n->nohdr = 0; | 419 | n->nohdr = 0; |
| 419 | C(pkt_type); | 420 | C(pkt_type); |
| 420 | C(ip_summed); | 421 | C(ip_summed); |
| 422 | skb_copy_queue_mapping(n, skb); | ||
| 421 | C(priority); | 423 | C(priority); |
| 422 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 424 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
| 423 | C(ipvs_property); | 425 | C(ipvs_property); |
| @@ -426,6 +428,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 426 | n->destructor = NULL; | 428 | n->destructor = NULL; |
| 427 | C(mark); | 429 | C(mark); |
| 428 | __nf_copy(n, skb); | 430 | __nf_copy(n, skb); |
| 431 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
| 432 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
| 433 | C(nf_trace); | ||
| 434 | #endif | ||
| 429 | #ifdef CONFIG_NET_SCHED | 435 | #ifdef CONFIG_NET_SCHED |
| 430 | C(tc_index); | 436 | C(tc_index); |
| 431 | #ifdef CONFIG_NET_CLS_ACT | 437 | #ifdef CONFIG_NET_CLS_ACT |
| @@ -434,8 +440,8 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 434 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | 440 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); |
| 435 | C(iif); | 441 | C(iif); |
| 436 | #endif | 442 | #endif |
| 437 | skb_copy_secmark(n, skb); | ||
| 438 | #endif | 443 | #endif |
| 444 | skb_copy_secmark(n, skb); | ||
| 439 | C(truesize); | 445 | C(truesize); |
| 440 | atomic_set(&n->users, 1); | 446 | atomic_set(&n->users, 1); |
| 441 | C(head); | 447 | C(head); |
| @@ -459,6 +465,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
| 459 | #endif | 465 | #endif |
| 460 | new->sk = NULL; | 466 | new->sk = NULL; |
| 461 | new->dev = old->dev; | 467 | new->dev = old->dev; |
| 468 | skb_copy_queue_mapping(new, old); | ||
| 462 | new->priority = old->priority; | 469 | new->priority = old->priority; |
| 463 | new->protocol = old->protocol; | 470 | new->protocol = old->protocol; |
| 464 | new->dst = dst_clone(old->dst); | 471 | new->dst = dst_clone(old->dst); |
| @@ -482,6 +489,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
| 482 | new->destructor = NULL; | 489 | new->destructor = NULL; |
| 483 | new->mark = old->mark; | 490 | new->mark = old->mark; |
| 484 | __nf_copy(new, old); | 491 | __nf_copy(new, old); |
| 492 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
| 493 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
| 494 | new->nf_trace = old->nf_trace; | ||
| 495 | #endif | ||
| 485 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 496 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
| 486 | new->ipvs_property = old->ipvs_property; | 497 | new->ipvs_property = old->ipvs_property; |
| 487 | #endif | 498 | #endif |
| @@ -676,6 +687,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
| 676 | skb->network_header += off; | 687 | skb->network_header += off; |
| 677 | skb->mac_header += off; | 688 | skb->mac_header += off; |
| 678 | skb->cloned = 0; | 689 | skb->cloned = 0; |
| 690 | skb->hdr_len = 0; | ||
| 679 | skb->nohdr = 0; | 691 | skb->nohdr = 0; |
| 680 | atomic_set(&skb_shinfo(skb)->dataref, 1); | 692 | atomic_set(&skb_shinfo(skb)->dataref, 1); |
| 681 | return 0; | 693 | return 0; |
| @@ -1706,6 +1718,11 @@ next_skb: | |||
| 1706 | st->stepped_offset += frag->size; | 1718 | st->stepped_offset += frag->size; |
| 1707 | } | 1719 | } |
| 1708 | 1720 | ||
| 1721 | if (st->frag_data) { | ||
| 1722 | kunmap_skb_frag(st->frag_data); | ||
| 1723 | st->frag_data = NULL; | ||
| 1724 | } | ||
| 1725 | |||
| 1709 | if (st->cur_skb->next) { | 1726 | if (st->cur_skb->next) { |
| 1710 | st->cur_skb = st->cur_skb->next; | 1727 | st->cur_skb = st->cur_skb->next; |
| 1711 | st->frag_idx = 0; | 1728 | st->frag_idx = 0; |
| @@ -1925,6 +1942,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
| 1925 | tail = nskb; | 1942 | tail = nskb; |
| 1926 | 1943 | ||
| 1927 | nskb->dev = skb->dev; | 1944 | nskb->dev = skb->dev; |
| 1945 | skb_copy_queue_mapping(nskb, skb); | ||
| 1928 | nskb->priority = skb->priority; | 1946 | nskb->priority = skb->priority; |
| 1929 | nskb->protocol = skb->protocol; | 1947 | nskb->protocol = skb->protocol; |
| 1930 | nskb->dst = dst_clone(skb->dst); | 1948 | nskb->dst = dst_clone(skb->dst); |
| @@ -2206,7 +2224,6 @@ EXPORT_SYMBOL(pskb_copy); | |||
| 2206 | EXPORT_SYMBOL(pskb_expand_head); | 2224 | EXPORT_SYMBOL(pskb_expand_head); |
| 2207 | EXPORT_SYMBOL(skb_checksum); | 2225 | EXPORT_SYMBOL(skb_checksum); |
| 2208 | EXPORT_SYMBOL(skb_clone); | 2226 | EXPORT_SYMBOL(skb_clone); |
| 2209 | EXPORT_SYMBOL(skb_clone_fraglist); | ||
| 2210 | EXPORT_SYMBOL(skb_copy); | 2227 | EXPORT_SYMBOL(skb_copy); |
| 2211 | EXPORT_SYMBOL(skb_copy_and_csum_bits); | 2228 | EXPORT_SYMBOL(skb_copy_and_csum_bits); |
| 2212 | EXPORT_SYMBOL(skb_copy_and_csum_dev); | 2229 | EXPORT_SYMBOL(skb_copy_and_csum_dev); |
diff --git a/net/core/sock.c b/net/core/sock.c index c14ce0198d25..091032a250c7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -210,7 +210,8 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) | |||
| 210 | return -EDOM; | 210 | return -EDOM; |
| 211 | 211 | ||
| 212 | if (tv.tv_sec < 0) { | 212 | if (tv.tv_sec < 0) { |
| 213 | static int warned = 0; | 213 | static int warned __read_mostly; |
| 214 | |||
| 214 | *timeo_p = 0; | 215 | *timeo_p = 0; |
| 215 | if (warned < 10 && net_ratelimit()) | 216 | if (warned < 10 && net_ratelimit()) |
| 216 | warned++; | 217 | warned++; |
| @@ -1851,46 +1852,15 @@ void proto_unregister(struct proto *prot) | |||
| 1851 | EXPORT_SYMBOL(proto_unregister); | 1852 | EXPORT_SYMBOL(proto_unregister); |
| 1852 | 1853 | ||
| 1853 | #ifdef CONFIG_PROC_FS | 1854 | #ifdef CONFIG_PROC_FS |
| 1854 | static inline struct proto *__proto_head(void) | ||
| 1855 | { | ||
| 1856 | return list_entry(proto_list.next, struct proto, node); | ||
| 1857 | } | ||
| 1858 | |||
| 1859 | static inline struct proto *proto_head(void) | ||
| 1860 | { | ||
| 1861 | return list_empty(&proto_list) ? NULL : __proto_head(); | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | static inline struct proto *proto_next(struct proto *proto) | ||
| 1865 | { | ||
| 1866 | return proto->node.next == &proto_list ? NULL : | ||
| 1867 | list_entry(proto->node.next, struct proto, node); | ||
| 1868 | } | ||
| 1869 | |||
| 1870 | static inline struct proto *proto_get_idx(loff_t pos) | ||
| 1871 | { | ||
| 1872 | struct proto *proto; | ||
| 1873 | loff_t i = 0; | ||
| 1874 | |||
| 1875 | list_for_each_entry(proto, &proto_list, node) | ||
| 1876 | if (i++ == pos) | ||
| 1877 | goto out; | ||
| 1878 | |||
| 1879 | proto = NULL; | ||
| 1880 | out: | ||
| 1881 | return proto; | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | static void *proto_seq_start(struct seq_file *seq, loff_t *pos) | 1855 | static void *proto_seq_start(struct seq_file *seq, loff_t *pos) |
| 1885 | { | 1856 | { |
| 1886 | read_lock(&proto_list_lock); | 1857 | read_lock(&proto_list_lock); |
| 1887 | return *pos ? proto_get_idx(*pos - 1) : SEQ_START_TOKEN; | 1858 | return seq_list_start_head(&proto_list, *pos); |
| 1888 | } | 1859 | } |
| 1889 | 1860 | ||
| 1890 | static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 1861 | static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
| 1891 | { | 1862 | { |
| 1892 | ++*pos; | 1863 | return seq_list_next(v, &proto_list, pos); |
| 1893 | return v == SEQ_START_TOKEN ? proto_head() : proto_next(v); | ||
| 1894 | } | 1864 | } |
| 1895 | 1865 | ||
| 1896 | static void proto_seq_stop(struct seq_file *seq, void *v) | 1866 | static void proto_seq_stop(struct seq_file *seq, void *v) |
| @@ -1938,7 +1908,7 @@ static void proto_seq_printf(struct seq_file *seq, struct proto *proto) | |||
| 1938 | 1908 | ||
| 1939 | static int proto_seq_show(struct seq_file *seq, void *v) | 1909 | static int proto_seq_show(struct seq_file *seq, void *v) |
| 1940 | { | 1910 | { |
| 1941 | if (v == SEQ_START_TOKEN) | 1911 | if (v == &proto_list) |
| 1942 | seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s", | 1912 | seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s", |
| 1943 | "protocol", | 1913 | "protocol", |
| 1944 | "size", | 1914 | "size", |
| @@ -1950,7 +1920,7 @@ static int proto_seq_show(struct seq_file *seq, void *v) | |||
| 1950 | "module", | 1920 | "module", |
| 1951 | "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n"); | 1921 | "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n"); |
| 1952 | else | 1922 | else |
| 1953 | proto_seq_printf(seq, v); | 1923 | proto_seq_printf(seq, list_entry(v, struct proto, node)); |
| 1954 | return 0; | 1924 | return 0; |
| 1955 | } | 1925 | } |
| 1956 | 1926 | ||
