@@ -65,6 +65,68 @@ static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
65
65
static enum hrtimer_restart cdc_ncm_tx_timer_cb (struct hrtimer * hr_timer );
66
66
static struct usb_driver cdc_ncm_driver ;
67
67
68
+ struct cdc_ncm_stats {
69
+ char stat_string [ETH_GSTRING_LEN ];
70
+ int sizeof_stat ;
71
+ int stat_offset ;
72
+ };
73
+
74
+ #define CDC_NCM_STAT (str , m ) { \
75
+ .stat_string = str, \
76
+ .sizeof_stat = sizeof(((struct cdc_ncm_ctx *)0)->m), \
77
+ .stat_offset = offsetof(struct cdc_ncm_ctx, m) }
78
+ #define CDC_NCM_SIMPLE_STAT (m ) CDC_NCM_STAT(__stringify(m), m)
79
+
80
+ static const struct cdc_ncm_stats cdc_ncm_gstrings_stats [] = {
81
+ CDC_NCM_SIMPLE_STAT (tx_reason_ntb_full ),
82
+ CDC_NCM_SIMPLE_STAT (tx_reason_ndp_full ),
83
+ CDC_NCM_SIMPLE_STAT (tx_reason_timeout ),
84
+ CDC_NCM_SIMPLE_STAT (tx_reason_max_datagram ),
85
+ CDC_NCM_SIMPLE_STAT (tx_overhead ),
86
+ CDC_NCM_SIMPLE_STAT (tx_ntbs ),
87
+ CDC_NCM_SIMPLE_STAT (rx_overhead ),
88
+ CDC_NCM_SIMPLE_STAT (rx_ntbs ),
89
+ };
90
+
91
+ static int cdc_ncm_get_sset_count (struct net_device __always_unused * netdev , int sset )
92
+ {
93
+ switch (sset ) {
94
+ case ETH_SS_STATS :
95
+ return ARRAY_SIZE (cdc_ncm_gstrings_stats );
96
+ default :
97
+ return - EOPNOTSUPP ;
98
+ }
99
+ }
100
+
101
+ static void cdc_ncm_get_ethtool_stats (struct net_device * netdev ,
102
+ struct ethtool_stats __always_unused * stats ,
103
+ u64 * data )
104
+ {
105
+ struct usbnet * dev = netdev_priv (netdev );
106
+ struct cdc_ncm_ctx * ctx = (struct cdc_ncm_ctx * )dev -> data [0 ];
107
+ int i ;
108
+ char * p = NULL ;
109
+
110
+ for (i = 0 ; i < ARRAY_SIZE (cdc_ncm_gstrings_stats ); i ++ ) {
111
+ p = (char * )ctx + cdc_ncm_gstrings_stats [i ].stat_offset ;
112
+ data [i ] = (cdc_ncm_gstrings_stats [i ].sizeof_stat == sizeof (u64 )) ? * (u64 * )p : * (u32 * )p ;
113
+ }
114
+ }
115
+
116
+ static void cdc_ncm_get_strings (struct net_device __always_unused * netdev , u32 stringset , u8 * data )
117
+ {
118
+ u8 * p = data ;
119
+ int i ;
120
+
121
+ switch (stringset ) {
122
+ case ETH_SS_STATS :
123
+ for (i = 0 ; i < ARRAY_SIZE (cdc_ncm_gstrings_stats ); i ++ ) {
124
+ memcpy (p , cdc_ncm_gstrings_stats [i ].stat_string , ETH_GSTRING_LEN );
125
+ p += ETH_GSTRING_LEN ;
126
+ }
127
+ }
128
+ }
129
+
68
130
static int cdc_ncm_get_coalesce (struct net_device * netdev ,
69
131
struct ethtool_coalesce * ec )
70
132
{
@@ -122,6 +184,9 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
122
184
.get_msglevel = usbnet_get_msglevel ,
123
185
.set_msglevel = usbnet_set_msglevel ,
124
186
.get_ts_info = ethtool_op_get_ts_info ,
187
+ .get_sset_count = cdc_ncm_get_sset_count ,
188
+ .get_strings = cdc_ncm_get_strings ,
189
+ .get_ethtool_stats = cdc_ncm_get_ethtool_stats ,
125
190
.get_coalesce = cdc_ncm_get_coalesce ,
126
191
.set_coalesce = cdc_ncm_set_coalesce ,
127
192
};
@@ -862,6 +927,9 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
862
927
863
928
/* count total number of frames in this NTB */
864
929
ctx -> tx_curr_frame_num = 0 ;
930
+
931
+ /* recent payload counter for this skb_out */
932
+ ctx -> tx_curr_frame_payload = 0 ;
865
933
}
866
934
867
935
for (n = ctx -> tx_curr_frame_num ; n < ctx -> tx_max_datagrams ; n ++ ) {
@@ -899,6 +967,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
899
967
ctx -> tx_rem_sign = sign ;
900
968
skb = NULL ;
901
969
ready2send = 1 ;
970
+ ctx -> tx_reason_ntb_full ++ ; /* count reason for transmitting */
902
971
}
903
972
break ;
904
973
}
@@ -912,12 +981,14 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
912
981
ndp16 -> dpe16 [index ].wDatagramIndex = cpu_to_le16 (skb_out -> len );
913
982
ndp16 -> wLength = cpu_to_le16 (ndplen + sizeof (struct usb_cdc_ncm_dpe16 ));
914
983
memcpy (skb_put (skb_out , skb -> len ), skb -> data , skb -> len );
984
+ ctx -> tx_curr_frame_payload += skb -> len ; /* count real tx payload data */
915
985
dev_kfree_skb_any (skb );
916
986
skb = NULL ;
917
987
918
988
/* send now if this NDP is full */
919
989
if (index >= CDC_NCM_DPT_DATAGRAMS_MAX ) {
920
990
ready2send = 1 ;
991
+ ctx -> tx_reason_ndp_full ++ ; /* count reason for transmitting */
921
992
break ;
922
993
}
923
994
}
@@ -947,6 +1018,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
947
1018
goto exit_no_skb ;
948
1019
949
1020
} else {
1021
+ if (n == ctx -> tx_max_datagrams )
1022
+ ctx -> tx_reason_max_datagram ++ ; /* count reason for transmitting */
950
1023
/* frame goes out */
951
1024
/* variables will be reset at next call */
952
1025
}
@@ -974,6 +1047,17 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
974
1047
/* return skb */
975
1048
ctx -> tx_curr_skb = NULL ;
976
1049
dev -> net -> stats .tx_packets += ctx -> tx_curr_frame_num ;
1050
+
1051
+ /* keep private stats: framing overhead and number of NTBs */
1052
+ ctx -> tx_overhead += skb_out -> len - ctx -> tx_curr_frame_payload ;
1053
+ ctx -> tx_ntbs ++ ;
1054
+
1055
+ /* usbnet has already counted all the framing overhead.
1056
+ * Adjust the stats so that the tx_bytes counter show real
1057
+ * payload data instead.
1058
+ */
1059
+ dev -> net -> stats .tx_bytes -= skb_out -> len - ctx -> tx_curr_frame_payload ;
1060
+
977
1061
return skb_out ;
978
1062
979
1063
exit_no_skb :
@@ -1014,6 +1098,7 @@ static void cdc_ncm_txpath_bh(unsigned long param)
1014
1098
cdc_ncm_tx_timeout_start (ctx );
1015
1099
spin_unlock_bh (& ctx -> mtx );
1016
1100
} else if (dev -> net != NULL ) {
1101
+ ctx -> tx_reason_timeout ++ ; /* count reason for transmitting */
1017
1102
spin_unlock_bh (& ctx -> mtx );
1018
1103
netif_tx_lock_bh (dev -> net );
1019
1104
usbnet_start_xmit (NULL , dev -> net );
@@ -1149,6 +1234,7 @@ int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1149
1234
struct usb_cdc_ncm_dpe16 * dpe16 ;
1150
1235
int ndpoffset ;
1151
1236
int loopcount = 50 ; /* arbitrary max preventing infinite loop */
1237
+ u32 payload = 0 ;
1152
1238
1153
1239
ndpoffset = cdc_ncm_rx_verify_nth16 (ctx , skb_in );
1154
1240
if (ndpoffset < 0 )
@@ -1201,6 +1287,7 @@ int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1201
1287
skb -> data = ((u8 * )skb_in -> data ) + offset ;
1202
1288
skb_set_tail_pointer (skb , len );
1203
1289
usbnet_skb_return (dev , skb );
1290
+ payload += len ; /* count payload bytes in this NTB */
1204
1291
}
1205
1292
}
1206
1293
err_ndp :
@@ -1209,6 +1296,10 @@ int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1209
1296
if (ndpoffset && loopcount -- )
1210
1297
goto next_ndp ;
1211
1298
1299
+ /* update stats */
1300
+ ctx -> rx_overhead += skb_in -> len - payload ;
1301
+ ctx -> rx_ntbs ++ ;
1302
+
1212
1303
return 1 ;
1213
1304
error :
1214
1305
return 0 ;
0 commit comments