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 ---