Commit d70a3f887a38cb0acc7233a1d05f15c2b6e0be2b
Committed by
David S. Miller
1 parent
93a306aef5
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
doc: packet: simplify tpacket example code
This patch simplifies the tpacket_v3 example code a bit by getting rid of unecessary macro wrappers, removing some debugging code so that it is more to the point, and also adds a header comment. Now this example code is the very minimum one needs to start from when dealing with tpacket_v3 and ~100 lines smaller than before. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 28 additions and 105 deletions Side-by-side Diff
Documentation/networking/packet_mmap.txt
... | ... | @@ -704,6 +704,12 @@ |
704 | 704 | Minimal example code by Daniel Borkmann based on Chetan Loke's lolpcap (compile |
705 | 705 | it with gcc -Wall -O2 blob.c, and try things like "./a.out eth0", etc.): |
706 | 706 | |
707 | +/* Written from scratch, but kernel-to-user space API usage | |
708 | + * dissected from lolpcap: | |
709 | + * Copyright 2011, Chetan Loke <loke.chetan@gmail.com> | |
710 | + * License: GPL, version 2.0 | |
711 | + */ | |
712 | + | |
707 | 713 | #include <stdio.h> |
708 | 714 | #include <stdlib.h> |
709 | 715 | #include <stdint.h> |
... | ... | @@ -722,27 +728,6 @@ |
722 | 728 | #include <linux/if_ether.h> |
723 | 729 | #include <linux/ip.h> |
724 | 730 | |
725 | -#define BLOCK_SIZE (1 << 22) | |
726 | -#define FRAME_SIZE 2048 | |
727 | - | |
728 | -#define NUM_BLOCKS 64 | |
729 | -#define NUM_FRAMES ((BLOCK_SIZE * NUM_BLOCKS) / FRAME_SIZE) | |
730 | - | |
731 | -#define BLOCK_RETIRE_TOV_IN_MS 64 | |
732 | -#define BLOCK_PRIV_AREA_SZ 13 | |
733 | - | |
734 | -#define ALIGN_8(x) (((x) + 8 - 1) & ~(8 - 1)) | |
735 | - | |
736 | -#define BLOCK_STATUS(x) ((x)->h1.block_status) | |
737 | -#define BLOCK_NUM_PKTS(x) ((x)->h1.num_pkts) | |
738 | -#define BLOCK_O2FP(x) ((x)->h1.offset_to_first_pkt) | |
739 | -#define BLOCK_LEN(x) ((x)->h1.blk_len) | |
740 | -#define BLOCK_SNUM(x) ((x)->h1.seq_num) | |
741 | -#define BLOCK_O2PRIV(x) ((x)->offset_to_priv) | |
742 | -#define BLOCK_PRIV(x) ((void *) ((uint8_t *) (x) + BLOCK_O2PRIV(x))) | |
743 | -#define BLOCK_HDR_LEN (ALIGN_8(sizeof(struct block_desc))) | |
744 | -#define BLOCK_PLUS_PRIV(sz_pri) (BLOCK_HDR_LEN + ALIGN_8((sz_pri))) | |
745 | - | |
746 | 731 | #ifndef likely |
747 | 732 | # define likely(x) __builtin_expect(!!(x), 1) |
748 | 733 | #endif |
... | ... | @@ -765,7 +750,7 @@ |
765 | 750 | static unsigned long packets_total = 0, bytes_total = 0; |
766 | 751 | static sig_atomic_t sigint = 0; |
767 | 752 | |
768 | -void sighandler(int num) | |
753 | +static void sighandler(int num) | |
769 | 754 | { |
770 | 755 | sigint = 1; |
771 | 756 | } |
... | ... | @@ -774,6 +759,8 @@ |
774 | 759 | { |
775 | 760 | int err, i, fd, v = TPACKET_V3; |
776 | 761 | struct sockaddr_ll ll; |
762 | + unsigned int blocksiz = 1 << 22, framesiz = 1 << 11; | |
763 | + unsigned int blocknum = 64; | |
777 | 764 | |
778 | 765 | fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); |
779 | 766 | if (fd < 0) { |
... | ... | @@ -788,13 +775,12 @@ |
788 | 775 | } |
789 | 776 | |
790 | 777 | memset(&ring->req, 0, sizeof(ring->req)); |
791 | - ring->req.tp_block_size = BLOCK_SIZE; | |
792 | - ring->req.tp_frame_size = FRAME_SIZE; | |
793 | - ring->req.tp_block_nr = NUM_BLOCKS; | |
794 | - ring->req.tp_frame_nr = NUM_FRAMES; | |
795 | - ring->req.tp_retire_blk_tov = BLOCK_RETIRE_TOV_IN_MS; | |
796 | - ring->req.tp_sizeof_priv = BLOCK_PRIV_AREA_SZ; | |
797 | - ring->req.tp_feature_req_word |= TP_FT_REQ_FILL_RXHASH; | |
778 | + ring->req.tp_block_size = blocksiz; | |
779 | + ring->req.tp_frame_size = framesiz; | |
780 | + ring->req.tp_block_nr = blocknum; | |
781 | + ring->req.tp_frame_nr = (blocksiz * blocknum) / framesiz; | |
782 | + ring->req.tp_retire_blk_tov = 60; | |
783 | + ring->req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; | |
798 | 784 | |
799 | 785 | err = setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &ring->req, |
800 | 786 | sizeof(ring->req)); |
... | ... | @@ -804,8 +790,7 @@ |
804 | 790 | } |
805 | 791 | |
806 | 792 | ring->map = mmap(NULL, ring->req.tp_block_size * ring->req.tp_block_nr, |
807 | - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, | |
808 | - fd, 0); | |
793 | + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); | |
809 | 794 | if (ring->map == MAP_FAILED) { |
810 | 795 | perror("mmap"); |
811 | 796 | exit(1); |
... | ... | @@ -835,58 +820,6 @@ |
835 | 820 | return fd; |
836 | 821 | } |
837 | 822 | |
838 | -#ifdef __checked | |
839 | -static uint64_t prev_block_seq_num = 0; | |
840 | - | |
841 | -void assert_block_seq_num(struct block_desc *pbd) | |
842 | -{ | |
843 | - if (unlikely(prev_block_seq_num + 1 != BLOCK_SNUM(pbd))) { | |
844 | - printf("prev_block_seq_num:%"PRIu64", expected seq:%"PRIu64" != " | |
845 | - "actual seq:%"PRIu64"\n", prev_block_seq_num, | |
846 | - prev_block_seq_num + 1, (uint64_t) BLOCK_SNUM(pbd)); | |
847 | - exit(1); | |
848 | - } | |
849 | - | |
850 | - prev_block_seq_num = BLOCK_SNUM(pbd); | |
851 | -} | |
852 | - | |
853 | -static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) | |
854 | -{ | |
855 | - if (BLOCK_NUM_PKTS(pbd)) { | |
856 | - if (unlikely(bytes != BLOCK_LEN(pbd))) { | |
857 | - printf("block:%u with %upackets, expected len:%u != actual len:%u\n", | |
858 | - block_num, BLOCK_NUM_PKTS(pbd), bytes, BLOCK_LEN(pbd)); | |
859 | - exit(1); | |
860 | - } | |
861 | - } else { | |
862 | - if (unlikely(BLOCK_LEN(pbd) != BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ))) { | |
863 | - printf("block:%u, expected len:%lu != actual len:%u\n", | |
864 | - block_num, BLOCK_HDR_LEN, BLOCK_LEN(pbd)); | |
865 | - exit(1); | |
866 | - } | |
867 | - } | |
868 | -} | |
869 | - | |
870 | -static void assert_block_header(struct block_desc *pbd, const int block_num) | |
871 | -{ | |
872 | - uint32_t block_status = BLOCK_STATUS(pbd); | |
873 | - | |
874 | - if (unlikely((block_status & TP_STATUS_USER) == 0)) { | |
875 | - printf("block:%u, not in TP_STATUS_USER\n", block_num); | |
876 | - exit(1); | |
877 | - } | |
878 | - | |
879 | - assert_block_seq_num(pbd); | |
880 | -} | |
881 | -#else | |
882 | -static inline void assert_block_header(struct block_desc *pbd, const int block_num) | |
883 | -{ | |
884 | -} | |
885 | -static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) | |
886 | -{ | |
887 | -} | |
888 | -#endif | |
889 | - | |
890 | 823 | static void display(struct tpacket3_hdr *ppd) |
891 | 824 | { |
892 | 825 | struct ethhdr *eth = (struct ethhdr *) ((uint8_t *) ppd + ppd->tp_mac); |
893 | 826 | |
894 | 827 | |
895 | 828 | |
896 | 829 | |
897 | 830 | |
898 | 831 | |
899 | 832 | |
... | ... | @@ -916,37 +849,27 @@ |
916 | 849 | |
917 | 850 | static void walk_block(struct block_desc *pbd, const int block_num) |
918 | 851 | { |
919 | - int num_pkts = BLOCK_NUM_PKTS(pbd), i; | |
852 | + int num_pkts = pbd->h1.num_pkts, i; | |
920 | 853 | unsigned long bytes = 0; |
921 | - unsigned long bytes_with_padding = BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ); | |
922 | 854 | struct tpacket3_hdr *ppd; |
923 | 855 | |
924 | - assert_block_header(pbd, block_num); | |
925 | - | |
926 | - ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + BLOCK_O2FP(pbd)); | |
856 | + ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + | |
857 | + pbd->h1.offset_to_first_pkt); | |
927 | 858 | for (i = 0; i < num_pkts; ++i) { |
928 | 859 | bytes += ppd->tp_snaplen; |
929 | - if (ppd->tp_next_offset) | |
930 | - bytes_with_padding += ppd->tp_next_offset; | |
931 | - else | |
932 | - bytes_with_padding += ALIGN_8(ppd->tp_snaplen + ppd->tp_mac); | |
933 | - | |
934 | 860 | display(ppd); |
935 | 861 | |
936 | - ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + ppd->tp_next_offset); | |
937 | - __sync_synchronize(); | |
862 | + ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + | |
863 | + ppd->tp_next_offset); | |
938 | 864 | } |
939 | 865 | |
940 | - assert_block_len(pbd, bytes_with_padding, block_num); | |
941 | - | |
942 | 866 | packets_total += num_pkts; |
943 | 867 | bytes_total += bytes; |
944 | 868 | } |
945 | 869 | |
946 | -void flush_block(struct block_desc *pbd) | |
870 | +static void flush_block(struct block_desc *pbd) | |
947 | 871 | { |
948 | - BLOCK_STATUS(pbd) = TP_STATUS_KERNEL; | |
949 | - __sync_synchronize(); | |
872 | + pbd->h1.block_status = TP_STATUS_KERNEL; | |
950 | 873 | } |
951 | 874 | |
952 | 875 | static void teardown_socket(struct ring *ring, int fd) |
... | ... | @@ -962,7 +885,7 @@ |
962 | 885 | socklen_t len; |
963 | 886 | struct ring ring; |
964 | 887 | struct pollfd pfd; |
965 | - unsigned int block_num = 0; | |
888 | + unsigned int block_num = 0, blocks = 64; | |
966 | 889 | struct block_desc *pbd; |
967 | 890 | struct tpacket_stats_v3 stats; |
968 | 891 | |
969 | 892 | |
970 | 893 | |
... | ... | @@ -984,15 +907,15 @@ |
984 | 907 | |
985 | 908 | while (likely(!sigint)) { |
986 | 909 | pbd = (struct block_desc *) ring.rd[block_num].iov_base; |
987 | -retry_block: | |
988 | - if ((BLOCK_STATUS(pbd) & TP_STATUS_USER) == 0) { | |
910 | + | |
911 | + if ((pbd->h1.block_status & TP_STATUS_USER) == 0) { | |
989 | 912 | poll(&pfd, 1, -1); |
990 | - goto retry_block; | |
913 | + continue; | |
991 | 914 | } |
992 | 915 | |
993 | 916 | walk_block(pbd, block_num); |
994 | 917 | flush_block(pbd); |
995 | - block_num = (block_num + 1) % NUM_BLOCKS; | |
918 | + block_num = (block_num + 1) % blocks; | |
996 | 919 | } |
997 | 920 | |
998 | 921 | len = sizeof(stats); |