@@ -42,6 +42,11 @@ struct l2tp_eth {
42
42
struct sock * tunnel_sock ;
43
43
struct l2tp_session * session ;
44
44
struct list_head list ;
45
+ atomic_long_t tx_bytes ;
46
+ atomic_long_t tx_packets ;
47
+ atomic_long_t rx_bytes ;
48
+ atomic_long_t rx_packets ;
49
+ atomic_long_t rx_errors ;
45
50
};
46
51
47
52
/* via l2tp_session_priv() */
@@ -88,24 +93,40 @@ static int l2tp_eth_dev_xmit(struct sk_buff *skb, struct net_device *dev)
88
93
struct l2tp_eth * priv = netdev_priv (dev );
89
94
struct l2tp_session * session = priv -> session ;
90
95
91
- dev -> stats . tx_bytes += skb -> len ;
92
- dev -> stats . tx_packets ++ ;
96
+ atomic_long_add ( skb -> len , & priv -> tx_bytes ) ;
97
+ atomic_long_inc ( & priv -> tx_packets ) ;
93
98
94
99
l2tp_xmit_skb (session , skb , session -> hdr_len );
95
100
96
101
return NETDEV_TX_OK ;
97
102
}
98
103
104
+ static struct rtnl_link_stats64 * l2tp_eth_get_stats64 (struct net_device * dev ,
105
+ struct rtnl_link_stats64 * stats )
106
+ {
107
+ struct l2tp_eth * priv = netdev_priv (dev );
108
+
109
+ stats -> tx_bytes = atomic_long_read (& priv -> tx_bytes );
110
+ stats -> tx_packets = atomic_long_read (& priv -> tx_packets );
111
+ stats -> rx_bytes = atomic_long_read (& priv -> rx_bytes );
112
+ stats -> rx_packets = atomic_long_read (& priv -> rx_packets );
113
+ stats -> rx_errors = atomic_long_read (& priv -> rx_errors );
114
+ return stats ;
115
+ }
116
+
117
+
99
118
static struct net_device_ops l2tp_eth_netdev_ops = {
100
119
.ndo_init = l2tp_eth_dev_init ,
101
120
.ndo_uninit = l2tp_eth_dev_uninit ,
102
121
.ndo_start_xmit = l2tp_eth_dev_xmit ,
122
+ .ndo_get_stats64 = l2tp_eth_get_stats64 ,
103
123
};
104
124
105
125
static void l2tp_eth_dev_setup (struct net_device * dev )
106
126
{
107
127
ether_setup (dev );
108
- dev -> priv_flags &= ~IFF_TX_SKB_SHARING ;
128
+ dev -> priv_flags &= ~IFF_TX_SKB_SHARING ;
129
+ dev -> features |= NETIF_F_LLTX ;
109
130
dev -> netdev_ops = & l2tp_eth_netdev_ops ;
110
131
dev -> destructor = free_netdev ;
111
132
}
@@ -114,17 +135,17 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
114
135
{
115
136
struct l2tp_eth_sess * spriv = l2tp_session_priv (session );
116
137
struct net_device * dev = spriv -> dev ;
138
+ struct l2tp_eth * priv = netdev_priv (dev );
117
139
118
140
if (session -> debug & L2TP_MSG_DATA ) {
119
141
unsigned int length ;
120
- u8 * ptr = skb -> data ;
121
142
122
143
length = min (32u , skb -> len );
123
144
if (!pskb_may_pull (skb , length ))
124
145
goto error ;
125
146
126
147
pr_debug ("%s: eth recv\n" , session -> name );
127
- print_hex_dump_bytes ("" , DUMP_PREFIX_OFFSET , ptr , length );
148
+ print_hex_dump_bytes ("" , DUMP_PREFIX_OFFSET , skb -> data , length );
128
149
}
129
150
130
151
if (!pskb_may_pull (skb , sizeof (ETH_HLEN )))
@@ -139,15 +160,15 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
139
160
nf_reset (skb );
140
161
141
162
if (dev_forward_skb (dev , skb ) == NET_RX_SUCCESS ) {
142
- dev -> stats . rx_packets ++ ;
143
- dev -> stats . rx_bytes += data_len ;
144
- } else
145
- dev -> stats . rx_errors ++ ;
146
-
163
+ atomic_long_inc ( & priv -> rx_packets ) ;
164
+ atomic_long_add ( data_len , & priv -> rx_bytes ) ;
165
+ } else {
166
+ atomic_long_inc ( & priv -> rx_errors ) ;
167
+ }
147
168
return ;
148
169
149
170
error :
150
- dev -> stats . rx_errors ++ ;
171
+ atomic_long_inc ( & priv -> rx_errors ) ;
151
172
kfree_skb (skb );
152
173
}
153
174
0 commit comments