loopback.c (b65b34895437915f411882dd40d704eb0863ffb0) | loopback.c (6b10de38f0ef4e921a1f6e5cba2b6c92d6b46ecd) |
---|---|
1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Pseudo-driver for the loopback interface. 7 * 8 * Version: @(#)loopback.c 1.0.4b 08/16/93 --- 46 unchanged lines hidden (view full) --- 55#include <linux/if_ether.h> /* For the statistics structure. */ 56#include <linux/if_arp.h> /* For ARPHRD_ETHER */ 57#include <linux/ip.h> 58#include <linux/tcp.h> 59#include <linux/percpu.h> 60#include <net/net_namespace.h> 61 62struct pcpu_lstats { | 1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Pseudo-driver for the loopback interface. 7 * 8 * Version: @(#)loopback.c 1.0.4b 08/16/93 --- 46 unchanged lines hidden (view full) --- 55#include <linux/if_ether.h> /* For the statistics structure. */ 56#include <linux/if_arp.h> /* For ARPHRD_ETHER */ 57#include <linux/ip.h> 58#include <linux/tcp.h> 59#include <linux/percpu.h> 60#include <net/net_namespace.h> 61 62struct pcpu_lstats { |
63 unsigned long packets; 64 unsigned long bytes; | 63 u64 packets; 64 u64 bytes; 65#if BITS_PER_LONG==32 && defined(CONFIG_SMP) 66 seqcount_t seq; 67#endif |
65 unsigned long drops; 66}; 67 | 68 unsigned long drops; 69}; 70 |
71#if BITS_PER_LONG==32 && defined(CONFIG_SMP) 72static void inline lstats_update_begin(struct pcpu_lstats *lstats) 73{ 74 write_seqcount_begin(&lstats->seq); 75} 76static void inline lstats_update_end(struct pcpu_lstats *lstats) 77{ 78 write_seqcount_end(&lstats->seq); 79} 80static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats) 81{ 82 u64 tpackets, tbytes; 83 unsigned int seq; 84 85 do { 86 seq = read_seqcount_begin(&lstats->seq); 87 tpackets = lstats->packets; 88 tbytes = lstats->bytes; 89 } while (read_seqcount_retry(&lstats->seq, seq)); 90 91 *packets += tpackets; 92 *bytes += tbytes; 93} 94#else 95static void inline lstats_update_begin(struct pcpu_lstats *lstats) 96{ 97} 98static void inline lstats_update_end(struct pcpu_lstats *lstats) 99{ 100} 101static void inline lstats_fetch_and_add(u64 *packets, u64 *bytes, const struct pcpu_lstats *lstats) 102{ 103 *packets += lstats->packets; 104 *bytes += lstats->bytes; 105} 106#endif 107 |
|
68/* 69 * The higher levels take care of making this non-reentrant (it's 70 * called with bh's disabled). 71 */ 72static netdev_tx_t loopback_xmit(struct sk_buff *skb, 73 struct net_device *dev) 74{ 75 struct pcpu_lstats __percpu *pcpu_lstats; --- 5 unchanged lines hidden (view full) --- 81 skb->protocol = eth_type_trans(skb, dev); 82 83 /* it's OK to use per_cpu_ptr() because BHs are off */ 84 pcpu_lstats = (void __percpu __force *)dev->ml_priv; 85 lb_stats = this_cpu_ptr(pcpu_lstats); 86 87 len = skb->len; 88 if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { | 108/* 109 * The higher levels take care of making this non-reentrant (it's 110 * called with bh's disabled). 111 */ 112static netdev_tx_t loopback_xmit(struct sk_buff *skb, 113 struct net_device *dev) 114{ 115 struct pcpu_lstats __percpu *pcpu_lstats; --- 5 unchanged lines hidden (view full) --- 121 skb->protocol = eth_type_trans(skb, dev); 122 123 /* it's OK to use per_cpu_ptr() because BHs are off */ 124 pcpu_lstats = (void __percpu __force *)dev->ml_priv; 125 lb_stats = this_cpu_ptr(pcpu_lstats); 126 127 len = skb->len; 128 if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { |
129 lstats_update_begin(lb_stats); |
|
89 lb_stats->bytes += len; 90 lb_stats->packets++; | 130 lb_stats->bytes += len; 131 lb_stats->packets++; |
132 lstats_update_end(lb_stats); |
|
91 } else 92 lb_stats->drops++; 93 94 return NETDEV_TX_OK; 95} 96 | 133 } else 134 lb_stats->drops++; 135 136 return NETDEV_TX_OK; 137} 138 |
97static struct net_device_stats *loopback_get_stats(struct net_device *dev) | 139static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev) |
98{ 99 const struct pcpu_lstats __percpu *pcpu_lstats; | 140{ 141 const struct pcpu_lstats __percpu *pcpu_lstats; |
100 struct net_device_stats *stats = &dev->stats; 101 unsigned long bytes = 0; 102 unsigned long packets = 0; 103 unsigned long drops = 0; | 142 struct rtnl_link_stats64 *stats = &dev->stats64; 143 u64 bytes = 0; 144 u64 packets = 0; 145 u64 drops = 0; |
104 int i; 105 106 pcpu_lstats = (void __percpu __force *)dev->ml_priv; 107 for_each_possible_cpu(i) { 108 const struct pcpu_lstats *lb_stats; 109 110 lb_stats = per_cpu_ptr(pcpu_lstats, i); | 146 int i; 147 148 pcpu_lstats = (void __percpu __force *)dev->ml_priv; 149 for_each_possible_cpu(i) { 150 const struct pcpu_lstats *lb_stats; 151 152 lb_stats = per_cpu_ptr(pcpu_lstats, i); |
111 bytes += lb_stats->bytes; 112 packets += lb_stats->packets; | 153 lstats_fetch_and_add(&packets, &bytes, lb_stats); |
113 drops += lb_stats->drops; 114 } 115 stats->rx_packets = packets; 116 stats->tx_packets = packets; 117 stats->rx_dropped = drops; 118 stats->rx_errors = drops; 119 stats->rx_bytes = bytes; 120 stats->tx_bytes = bytes; --- 32 unchanged lines hidden (view full) --- 153 154 free_percpu(lstats); 155 free_netdev(dev); 156} 157 158static const struct net_device_ops loopback_ops = { 159 .ndo_init = loopback_dev_init, 160 .ndo_start_xmit= loopback_xmit, | 154 drops += lb_stats->drops; 155 } 156 stats->rx_packets = packets; 157 stats->tx_packets = packets; 158 stats->rx_dropped = drops; 159 stats->rx_errors = drops; 160 stats->rx_bytes = bytes; 161 stats->tx_bytes = bytes; --- 32 unchanged lines hidden (view full) --- 194 195 free_percpu(lstats); 196 free_netdev(dev); 197} 198 199static const struct net_device_ops loopback_ops = { 200 .ndo_init = loopback_dev_init, 201 .ndo_start_xmit= loopback_xmit, |
161 .ndo_get_stats = loopback_get_stats, | 202 .ndo_get_stats64 = loopback_get_stats64, |
162}; 163 164/* 165 * The loopback device is special. There is only one instance 166 * per network namespace. 167 */ 168static void loopback_setup(struct net_device *dev) 169{ --- 51 unchanged lines hidden --- | 203}; 204 205/* 206 * The loopback device is special. There is only one instance 207 * per network namespace. 208 */ 209static void loopback_setup(struct net_device *dev) 210{ --- 51 unchanged lines hidden --- |