aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJP Abgrall2013-01-28 18:50:44 -0600
committerArve Hjønnevåg2013-02-19 19:56:18 -0600
commit795297ef2a8480403722baae248c2bb180da917d (patch)
tree10434dcb380ac53584912f3920323394bbdc0d7f
parent4373bbc2bb1cc94c4e5711148bd134fe4cebd34a (diff)
downloadkernel-common-795297ef2a8480403722baae248c2bb180da917d.tar.gz
kernel-common-795297ef2a8480403722baae248c2bb180da917d.tar.xz
kernel-common-795297ef2a8480403722baae248c2bb180da917d.zip
netfilter: xt_qtaguid: extend iface stat to report protocols
In the past the iface_stat_fmt would only show global bytes/packets for the skb-based numbers. For stall detection in userspace, distinguishing tcp vs other protocols makes it easier. Now we report ifname total_skb_rx_bytes total_skb_rx_packets total_skb_tx_bytes total_skb_tx_packets {rx,tx}_{tcp,udp,ohter}_{bytes,packets} Bug: 6818637 Signed-off-by: JP Abgrall <jpa@google.com>
-rw-r--r--net/netfilter/xt_qtaguid.c90
-rw-r--r--net/netfilter/xt_qtaguid_internal.h21
-rw-r--r--net/netfilter/xt_qtaguid_print.c14
3 files changed, 82 insertions, 43 deletions
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index 923f1bdd02e..92e5f80bd8f 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -268,24 +268,6 @@ static inline void dc_add_byte_packets(struct data_counters *counters, int set,
268 counters->bpc[set][direction][ifs_proto].packets += packets; 268 counters->bpc[set][direction][ifs_proto].packets += packets;
269} 269}
270 270
271static inline uint64_t dc_sum_bytes(struct data_counters *counters,
272 int set,
273 enum ifs_tx_rx direction)
274{
275 return counters->bpc[set][direction][IFS_TCP].bytes
276 + counters->bpc[set][direction][IFS_UDP].bytes
277 + counters->bpc[set][direction][IFS_PROTO_OTHER].bytes;
278}
279
280static inline uint64_t dc_sum_packets(struct data_counters *counters,
281 int set,
282 enum ifs_tx_rx direction)
283{
284 return counters->bpc[set][direction][IFS_TCP].packets
285 + counters->bpc[set][direction][IFS_UDP].packets
286 + counters->bpc[set][direction][IFS_PROTO_OTHER].packets;
287}
288
289static struct tag_node *tag_node_tree_search(struct rb_root *root, tag_t tag) 271static struct tag_node *tag_node_tree_search(struct rb_root *root, tag_t tag)
290{ 272{
291 struct rb_node *node = root->rb_node; 273 struct rb_node *node = root->rb_node;
@@ -787,6 +769,53 @@ done:
787 return iface_entry; 769 return iface_entry;
788} 770}
789 771
772/* This is for fmt2 only */
773static int pp_iface_stat_line(bool header, char *outp,
774 int char_count, struct iface_stat *iface_entry)
775{
776 int len;
777 if (header) {
778 len = snprintf(outp, char_count,
779 "ifname "
780 "total_skb_rx_bytes total_skb_rx_packets "
781 "total_skb_tx_bytes total_skb_tx_packets "
782 "rx_tcp_bytes rx_tcp_packets "
783 "rx_udp_bytes rx_udp_packets "
784 "rx_other_bytes rx_other_packets "
785 "tx_tcp_bytes tx_tcp_packets "
786 "tx_udp_bytes tx_udp_packets "
787 "tx_other_bytes tx_other_packets\n"
788 );
789 } else {
790 struct data_counters *cnts;
791 int cnt_set = 0; /* We only use one set for the device */
792 cnts = &iface_entry->totals_via_skb;
793 len = snprintf(
794 outp, char_count,
795 "%s "
796 "%llu %llu %llu %llu %llu %llu %llu %llu "
797 "%llu %llu %llu %llu %llu %llu %llu %llu\n",
798 iface_entry->ifname,
799 dc_sum_bytes(cnts, cnt_set, IFS_RX),
800 dc_sum_packets(cnts, cnt_set, IFS_RX),
801 dc_sum_bytes(cnts, cnt_set, IFS_TX),
802 dc_sum_packets(cnts, cnt_set, IFS_TX),
803 cnts->bpc[cnt_set][IFS_RX][IFS_TCP].bytes,
804 cnts->bpc[cnt_set][IFS_RX][IFS_TCP].packets,
805 cnts->bpc[cnt_set][IFS_RX][IFS_UDP].bytes,
806 cnts->bpc[cnt_set][IFS_RX][IFS_UDP].packets,
807 cnts->bpc[cnt_set][IFS_RX][IFS_PROTO_OTHER].bytes,
808 cnts->bpc[cnt_set][IFS_RX][IFS_PROTO_OTHER].packets,
809 cnts->bpc[cnt_set][IFS_TX][IFS_TCP].bytes,
810 cnts->bpc[cnt_set][IFS_TX][IFS_TCP].packets,
811 cnts->bpc[cnt_set][IFS_TX][IFS_UDP].bytes,
812 cnts->bpc[cnt_set][IFS_TX][IFS_UDP].packets,
813 cnts->bpc[cnt_set][IFS_TX][IFS_PROTO_OTHER].bytes,
814 cnts->bpc[cnt_set][IFS_TX][IFS_PROTO_OTHER].packets);
815 }
816 return len;
817}
818
790static int iface_stat_fmt_proc_read(char *page, char **num_items_returned, 819static int iface_stat_fmt_proc_read(char *page, char **num_items_returned,
791 off_t items_to_skip, int char_count, 820 off_t items_to_skip, int char_count,
792 int *eof, void *data) 821 int *eof, void *data)
@@ -816,11 +845,7 @@ static int iface_stat_fmt_proc_read(char *page, char **num_items_returned,
816 return 0; 845 return 0;
817 846
818 if (fmt == 2 && item_index++ >= items_to_skip) { 847 if (fmt == 2 && item_index++ >= items_to_skip) {
819 len = snprintf(outp, char_count, 848 len = pp_iface_stat_line(true, outp, char_count, NULL);
820 "ifname "
821 "total_skb_rx_bytes total_skb_rx_packets "
822 "total_skb_tx_bytes total_skb_tx_packets\n"
823 );
824 if (len >= char_count) { 849 if (len >= char_count) {
825 *outp = '\0'; 850 *outp = '\0';
826 return outp - page; 851 return outp - page;
@@ -865,16 +890,8 @@ static int iface_stat_fmt_proc_read(char *page, char **num_items_returned,
865 stats->tx_bytes, stats->tx_packets 890 stats->tx_bytes, stats->tx_packets
866 ); 891 );
867 } else { 892 } else {
868 len = snprintf( 893 len = pp_iface_stat_line(false, outp, char_count,
869 outp, char_count, 894 iface_entry);
870 "%s "
871 "%llu %llu %llu %llu\n",
872 iface_entry->ifname,
873 iface_entry->totals_via_skb[IFS_RX].bytes,
874 iface_entry->totals_via_skb[IFS_RX].packets,
875 iface_entry->totals_via_skb[IFS_TX].bytes,
876 iface_entry->totals_via_skb[IFS_TX].packets
877 );
878 } 895 }
879 if (len >= char_count) { 896 if (len >= char_count) {
880 spin_unlock_bh(&iface_stat_list_lock); 897 spin_unlock_bh(&iface_stat_list_lock);
@@ -1304,6 +1321,7 @@ static void iface_stat_update_from_skb(const struct sk_buff *skb,
1304 const struct net_device *el_dev; 1321 const struct net_device *el_dev;
1305 enum ifs_tx_rx direction = par->in ? IFS_RX : IFS_TX; 1322 enum ifs_tx_rx direction = par->in ? IFS_RX : IFS_TX;
1306 int bytes = skb->len; 1323 int bytes = skb->len;
1324 int proto;
1307 1325
1308 if (!skb->dev) { 1326 if (!skb->dev) {
1309 MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum); 1327 MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum);
@@ -1329,7 +1347,7 @@ static void iface_stat_update_from_skb(const struct sk_buff *skb,
1329 par->hooknum, __func__); 1347 par->hooknum, __func__);
1330 BUG(); 1348 BUG();
1331 } else { 1349 } else {
1332 int proto = ipx_proto(skb, par); 1350 proto = ipx_proto(skb, par);
1333 MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n", 1351 MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n",
1334 par->hooknum, el_dev->name, el_dev->type, 1352 par->hooknum, el_dev->name, el_dev->type,
1335 par->family, proto); 1353 par->family, proto);
@@ -1347,8 +1365,8 @@ static void iface_stat_update_from_skb(const struct sk_buff *skb,
1347 IF_DEBUG("qtaguid: %s(%s): entry=%p\n", __func__, 1365 IF_DEBUG("qtaguid: %s(%s): entry=%p\n", __func__,
1348 el_dev->name, entry); 1366 el_dev->name, entry);
1349 1367
1350 entry->totals_via_skb[direction].bytes += bytes; 1368 data_counters_update(&entry->totals_via_skb, 0, direction, proto,
1351 entry->totals_via_skb[direction].packets++; 1369 bytes);
1352 spin_unlock_bh(&iface_stat_list_lock); 1370 spin_unlock_bh(&iface_stat_list_lock);
1353} 1371}
1354 1372
diff --git a/net/netfilter/xt_qtaguid_internal.h b/net/netfilter/xt_qtaguid_internal.h
index d79f8383abf..6dc14a9c688 100644
--- a/net/netfilter/xt_qtaguid_internal.h
+++ b/net/netfilter/xt_qtaguid_internal.h
@@ -179,6 +179,25 @@ struct data_counters {
179 struct byte_packet_counters bpc[IFS_MAX_COUNTER_SETS][IFS_MAX_DIRECTIONS][IFS_MAX_PROTOS]; 179 struct byte_packet_counters bpc[IFS_MAX_COUNTER_SETS][IFS_MAX_DIRECTIONS][IFS_MAX_PROTOS];
180}; 180};
181 181
182static inline uint64_t dc_sum_bytes(struct data_counters *counters,
183 int set,
184 enum ifs_tx_rx direction)
185{
186 return counters->bpc[set][direction][IFS_TCP].bytes
187 + counters->bpc[set][direction][IFS_UDP].bytes
188 + counters->bpc[set][direction][IFS_PROTO_OTHER].bytes;
189}
190
191static inline uint64_t dc_sum_packets(struct data_counters *counters,
192 int set,
193 enum ifs_tx_rx direction)
194{
195 return counters->bpc[set][direction][IFS_TCP].packets
196 + counters->bpc[set][direction][IFS_UDP].packets
197 + counters->bpc[set][direction][IFS_PROTO_OTHER].packets;
198}
199
200
182/* Generic X based nodes used as a base for rb_tree ops */ 201/* Generic X based nodes used as a base for rb_tree ops */
183struct tag_node { 202struct tag_node {
184 struct rb_node node; 203 struct rb_node node;
@@ -203,7 +222,7 @@ struct iface_stat {
203 struct net_device *net_dev; 222 struct net_device *net_dev;
204 223
205 struct byte_packet_counters totals_via_dev[IFS_MAX_DIRECTIONS]; 224 struct byte_packet_counters totals_via_dev[IFS_MAX_DIRECTIONS];
206 struct byte_packet_counters totals_via_skb[IFS_MAX_DIRECTIONS]; 225 struct data_counters totals_via_skb;
207 /* 226 /*
208 * We keep the last_known, because some devices reset their counters 227 * We keep the last_known, because some devices reset their counters
209 * just before NETDEV_UP, while some will reset just before 228 * just before NETDEV_UP, while some will reset just before
diff --git a/net/netfilter/xt_qtaguid_print.c b/net/netfilter/xt_qtaguid_print.c
index 8cbd8e42bcc..f6a00a3520e 100644
--- a/net/netfilter/xt_qtaguid_print.c
+++ b/net/netfilter/xt_qtaguid_print.c
@@ -177,9 +177,10 @@ char *pp_tag_stat(struct tag_stat *ts)
177char *pp_iface_stat(struct iface_stat *is) 177char *pp_iface_stat(struct iface_stat *is)
178{ 178{
179 char *res; 179 char *res;
180 if (!is) 180 if (!is) {
181 res = kasprintf(GFP_ATOMIC, "iface_stat@null{}"); 181 res = kasprintf(GFP_ATOMIC, "iface_stat@null{}");
182 else 182 } else {
183 struct data_counters *cnts = &is->totals_via_skb;
183 res = kasprintf(GFP_ATOMIC, "iface_stat@%p{" 184 res = kasprintf(GFP_ATOMIC, "iface_stat@%p{"
184 "list=list_head{...}, " 185 "list=list_head{...}, "
185 "ifname=%s, " 186 "ifname=%s, "
@@ -206,10 +207,10 @@ char *pp_iface_stat(struct iface_stat *is)
206 is->totals_via_dev[IFS_RX].packets, 207 is->totals_via_dev[IFS_RX].packets,
207 is->totals_via_dev[IFS_TX].bytes, 208 is->totals_via_dev[IFS_TX].bytes,
208 is->totals_via_dev[IFS_TX].packets, 209 is->totals_via_dev[IFS_TX].packets,
209 is->totals_via_skb[IFS_RX].bytes, 210 dc_sum_bytes(cnts, 0, IFS_RX),
210 is->totals_via_skb[IFS_RX].packets, 211 dc_sum_packets(cnts, 0, IFS_RX),
211 is->totals_via_skb[IFS_TX].bytes, 212 dc_sum_bytes(cnts, 0, IFS_TX),
212 is->totals_via_skb[IFS_TX].packets, 213 dc_sum_packets(cnts, 0, IFS_TX),
213 is->last_known_valid, 214 is->last_known_valid,
214 is->last_known[IFS_RX].bytes, 215 is->last_known[IFS_RX].bytes,
215 is->last_known[IFS_RX].packets, 216 is->last_known[IFS_RX].packets,
@@ -218,6 +219,7 @@ char *pp_iface_stat(struct iface_stat *is)
218 is->active, 219 is->active,
219 is->net_dev, 220 is->net_dev,
220 is->proc_ptr); 221 is->proc_ptr);
222 }
221 _bug_on_err_or_null(res); 223 _bug_on_err_or_null(res);
222 return res; 224 return res;
223} 225}