- Timestamp:
- 11/28/12 09:13:11 (9 years ago)
- Branches:
- 4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
- Children:
- 17dc71c
- Parents:
- 0a8eb88
- Location:
- lib
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/format_linux.c
r0a8eb88 rd500159 7 7 * Authors: Daniel Lawson 8 8 * Perry Lorier 9 * Shane Alcock 9 * Shane Alcock 10 * Richard Sanger 10 11 * 11 12 * All rights reserved. … … 58 59 #include <assert.h> 59 60 61 #include <poll.h> 62 #include <sys/mman.h> 63 60 64 /* This format module deals with using the Linux Native capture format. 61 65 * … … 79 83 80 84 typedef enum { TS_NONE, TS_TIMEVAL, TS_TIMESPEC } timestamptype_t; 85 86 /* linux/if_packet.h defines. They are here rather than including the header 87 * this means that we can interpret a ring frame on a kernel that doesn't 88 * support the format directly. 89 */ 90 #define PACKET_RX_RING 5 91 #define PACKET_VERSION 10 92 #define PACKET_HDRLEN 11 93 #define PACKET_TX_RING 13 94 #define TP_STATUS_USER 0x1 95 #define TP_STATUS_SEND_REQUEST 0x1 96 #define TP_STATUS_AVAILABLE 0x0 97 #define TO_TP_HDR(x) ((struct tpacket2_hdr *) (x)) 98 #define TPACKET_ALIGNMENT 16 99 #define TPACKET_ALIGN(x) (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1)) 100 #define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) 101 102 enum tpacket_versions { 103 TPACKET_V1, 104 TPACKET_V2 105 }; 106 107 struct tpacket2_hdr { 108 /* Frame status - in use by kernel or libtrace etc. */ 109 __u32 tp_status; 110 /* Wire length */ 111 __u32 tp_len; 112 /* Captured length */ 113 __u32 tp_snaplen; 114 /* Offset in bytes from frame start to the mac (link layer) header */ 115 __u16 tp_mac; 116 /* Offset in bytes from frame start to the net (network layer) header */ 117 __u16 tp_net; 118 /* Timestamp */ 119 __u32 tp_sec; 120 __u32 tp_nsec; 121 /* Not used VLAN tag control information */ 122 __u16 tp_vlan_tci; 123 __u16 tp_padding; 124 }; 125 126 struct tpacket_req { 127 unsigned int tp_block_size; /* Minimal size of contiguous block */ 128 unsigned int tp_block_nr; /* Number of blocks */ 129 unsigned int tp_frame_size; /* Size of frame */ 130 unsigned int tp_frame_nr; /* Total number of frames */ 131 }; 81 132 82 133 struct linux_format_data_t { … … 96 147 /* Flag indicating whether the statistics are current or not */ 97 148 int stats_valid; 149 /* The rx ring mmap location*/ 150 char * rx_ring; 151 /* The current frame number within the rx ring */ 152 int rxring_offset; 153 /* The format this trace is using linuxring or linuxnative */ 154 libtrace_rt_types_t format; 155 /* The current ring buffer layout */ 156 struct tpacket_req req; 98 157 }; 99 158 … … 129 188 /* The file descriptor used to write the packets */ 130 189 int fd; 190 /* The tx ring mmap location */ 191 char * tx_ring; 192 /* The current frame number within the tx ring */ 193 int txring_offset; 194 /* The current ring buffer layout */ 195 struct tpacket_req req; 196 /* Our sockaddr structure, here so we can cache the interface number */ 197 struct sockaddr_ll sock_hdr; 198 /* The (maximum) number of packets that haven't been written */ 199 int queue; 200 /* The format this trace is using linuxring or linuxnative */ 201 libtrace_rt_types_t format; 131 202 }; 203 204 /* MAX_ORDER is defined in linux/mmzone.h. 10 is default for 2.4 kernel. 205 * max_order will be decreased by one if the ring buffer fails to allocate. 206 * Used to get correct sized buffers from the kernel. 207 */ 208 #define MAX_ORDER 10 209 static unsigned int max_order = MAX_ORDER; 210 211 /* Cached page size, the page size shoudn't be changing */ 212 static int pagesize = 0; 213 214 /* Number of frames in the ring used by both TX and TR rings. More frames 215 * hopefully means less packet loss, especially if traffic comes in bursts. 216 */ 217 #define CONF_RING_FRAMES 0x100 218 219 /* The maximum frames allowed to be waiting in the TX_RING before the kernel is 220 * notified to write them out. Make sure this is less than CONF_RING_FRAMES. 221 * Performance doesn't seem to increase any more when setting this above 10. 222 */ 223 #define TX_MAX_QUEUE 10 224 225 /* Get the start of the captured data. I'm not sure if tp_mac (link layer) is 226 * always guaranteed. If it's not there then just use tp_net. 227 */ 228 #define TP_TRACE_START(mac, net, hdrend) \ 229 ((mac) > (hdrend) && (mac) < (net) ? (mac) : (net)) 230 231 /* Get current frame in the ring buffer*/ 232 #define GET_CURRENT_BUFFER(libtrace) ((void *) FORMAT(libtrace->format_data)->rx_ring + \ 233 (FORMAT(libtrace->format_data)->rxring_offset * FORMAT(libtrace->format_data)->req.tp_frame_size)) 234 235 /* Get the sockaddr_ll structure from a frame */ 236 #define GET_SOCKADDR_HDR(x) ((struct sockaddr_ll *) (((char *) (x))\ 237 + TPACKET_ALIGN(sizeof(struct tpacket2_hdr)))) 238 239 #define TPACKET_HDRLEN TPACKET2_HDRLEN 132 240 133 241 #define FORMAT(x) ((struct linux_format_data_t*)(x)) 134 242 #define DATAOUT(x) ((struct linux_output_format_data_t*)((x)->format_data)) 135 243 244 245 /* 246 * Try figure out the best sizes for the ring buffer. Ensure that: 247 * - max(Block_size) == page_size << max_order 248 * - Frame_size == page_size << x (so that block_size%frame_size == 0) 249 * This means that there will be no wasted space between blocks 250 * - Frame_size < block_size 251 * - Frame_size is as close as possible to LIBTRACE_PACKET_BUFSIZE, but not 252 * bigger 253 * - Frame_nr = Block_nr * (frames per block) 254 * - CONF_RING_FRAMES is used a minimum number of frames to hold 255 * - Calculates based on max_order and buf_min 256 */ 257 static void calculate_buffers(struct tpacket_req * req, int fd, char * uri){ 258 259 struct ifreq ifr; 260 unsigned mtu = LIBTRACE_PACKET_BUFSIZE; 261 pagesize = getpagesize(); 262 263 /* Don't bother trying to set frame size above mtu linux will drop 264 * these anyway 265 */ 266 strcpy(ifr.ifr_name, uri); 267 if (ioctl(fd, SIOCGIFMTU, (caddr_t) &ifr) >= 0) 268 mtu = ifr.ifr_mtu; 269 if(mtu > LIBTRACE_PACKET_BUFSIZE) 270 mtu = LIBTRACE_PACKET_BUFSIZE; 271 272 /* Calculate frame size */ 273 req->tp_frame_size = pagesize; 274 do { 275 req->tp_frame_size <<= 1; 276 } while(req->tp_frame_size < mtu && req->tp_frame_size < LIBTRACE_PACKET_BUFSIZE); 277 if(req->tp_frame_size > LIBTRACE_PACKET_BUFSIZE) 278 req->tp_frame_size >>= 1; 279 280 /* Calculate block size */ 281 req->tp_block_size = pagesize << max_order; 282 do{ 283 req->tp_block_size >>= 1; 284 } while((CONF_RING_FRAMES * req->tp_frame_size) < req->tp_block_size); 285 req->tp_block_size <<= 1; 286 287 /* Calculate number of blocks */ 288 req->tp_block_nr = (CONF_RING_FRAMES * req->tp_frame_size) 289 / req->tp_block_size; 290 if((CONF_RING_FRAMES * req->tp_frame_size) % req->tp_block_size != 0) 291 req->tp_block_nr++; 292 293 /* Calculate packets such that we use all the space we have to allocated */ 294 req->tp_frame_nr = req->tp_block_nr * 295 (req->tp_block_size / req->tp_frame_size); 296 297 printf("MaxO 0x%x BS 0x%x BN 0x%x FS 0x%x FN 0x%x\n", 298 max_order, 299 req->tp_block_size, 300 req->tp_block_nr, 301 req->tp_frame_size, 302 req->tp_frame_nr); 303 304 /* In case we have some silly values*/ 305 assert(req->tp_block_size); 306 assert(req->tp_block_nr); 307 assert(req->tp_frame_size); 308 assert(req->tp_frame_nr); 309 assert(req->tp_block_size % req->tp_frame_size == 0); 310 } 311 136 312 static int linuxnative_probe_filename(const char *filename) 137 313 { … … 140 316 } 141 317 142 static int linuxnative_init_input(libtrace_t *libtrace) 143 { 318 static inline void init_input(libtrace_t *libtrace){ 144 319 libtrace->format_data = (struct linux_format_data_t *) 145 320 malloc(sizeof(struct linux_format_data_t)); … … 149 324 FORMAT(libtrace->format_data)->filter = NULL; 150 325 FORMAT(libtrace->format_data)->stats_valid = 0; 151 326 FORMAT(libtrace->format_data)->rx_ring = NULL; 327 FORMAT(libtrace->format_data)->rxring_offset = 0; 328 } 329 static int linuxring_init_input(libtrace_t *libtrace) 330 { 331 init_input(libtrace); 332 FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_RING; 152 333 return 0; 153 334 } 154 155 static int linuxnative_init_output(libtrace_out_t *libtrace) 335 static int linuxnative_init_input(libtrace_t *libtrace) 336 { 337 init_input(libtrace); 338 FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_NATIVE; 339 return 0; 340 } 341 342 static inline void init_output(libtrace_out_t *libtrace) 156 343 { 157 344 libtrace->format_data = (struct linux_output_format_data_t*) 158 345 malloc(sizeof(struct linux_output_format_data_t)); 159 346 DATAOUT(libtrace)->fd = -1; 160 347 DATAOUT(libtrace)->tx_ring = NULL; 348 DATAOUT(libtrace)->txring_offset = 0; 349 DATAOUT(libtrace)->queue = 0; 350 } 351 static int linuxnative_init_output(libtrace_out_t *libtrace) 352 { 353 init_output(libtrace); 354 DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_NATIVE; 355 return 0; 356 } 357 static int linuxring_init_output(libtrace_out_t *libtrace) 358 { 359 init_output(libtrace); 360 DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_RING; 161 361 return 0; 162 362 } … … 284 484 return 0; 285 485 } 486 static inline int socket_to_packetmmap(char * uridata, int ring_type, 487 int fd, 488 struct tpacket_req * req, 489 char ** ring_location){ 490 socklen_t len; 491 int val; 492 493 /* Switch to TPACKET header version 2, we only try support v2 because v1 had problems */ 494 val = TPACKET_V2; 495 len = sizeof(val); 496 if(getsockopt(fd, 497 SOL_PACKET, 498 PACKET_HDRLEN, 499 &val, 500 &len) == -1){ 501 return -1; 502 } 503 504 val = TPACKET_V2; 505 if (setsockopt(fd, 506 SOL_PACKET, 507 PACKET_VERSION, 508 &val, 509 sizeof(val)) == -1){ 510 return -1; 511 } 512 513 /* Try switch to a ring buffer. If it fails we assume the the kernel 514 * cannot allocate a block of that size, so decrease max_block and retry. 515 */ 516 while(1) { 517 if (max_order <= 0) { 518 return -1; 519 } 520 calculate_buffers(req, fd, uridata); 521 if (setsockopt(fd, 522 SOL_PACKET, 523 ring_type, 524 req, 525 sizeof(struct tpacket_req)) == -1) { 526 if(errno == ENOMEM){ 527 max_order--; 528 } else { 529 return -1; 530 } 531 532 } else break; 533 } 534 535 /* Map the ring buffer into userspace */ 536 *ring_location = mmap(NULL, 537 req->tp_block_size * req->tp_block_nr, 538 PROT_READ | PROT_WRITE, 539 MAP_SHARED, 540 fd, 0); 541 if(*ring_location == MAP_FAILED){ 542 return -1; 543 } 544 return 0; 545 } 546 static int linuxring_start_input(libtrace_t *libtrace){ 547 548 549 /* We set the socket up the same and then convert it to PACKET_MMAP */ 550 if(linuxnative_start_input(libtrace) != 0) 551 return -1; 552 553 /* Make it a packetmmap */ 554 if(socket_to_packetmmap(libtrace->uridata, PACKET_RX_RING, FORMAT(libtrace->format_data)->fd, 555 &FORMAT(libtrace->format_data)->req, &FORMAT(libtrace->format_data)->rx_ring) != 0){ 556 trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, 557 "TPACKET2 not supported or ring buffer is too large"); 558 close(DATAOUT(libtrace)->fd); 559 free(libtrace->format_data); 560 return -1; 561 } 562 563 return 0; 564 } 286 565 287 566 static int linuxnative_start_output(libtrace_out_t *libtrace) … … 291 570 free(DATAOUT(libtrace)); 292 571 return -1; 293 } 572 } 573 574 return 0; 575 } 576 577 static int linuxring_start_output(libtrace_out_t *libtrace) 578 { 579 /* We set the socket up the same and then convert it to PACKET_MMAP */ 580 if(linuxnative_start_output(libtrace) != 0) 581 return -1; 582 583 /* Make it a packetmmap */ 584 if(socket_to_packetmmap(libtrace->uridata, PACKET_TX_RING, DATAOUT(libtrace)->fd, 585 &DATAOUT(libtrace)->req, &DATAOUT(libtrace)->tx_ring) != 0){ 586 trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, 587 "TPACKET2 not supported or ring buffer is too large"); 588 close(DATAOUT(libtrace)->fd); 589 free(libtrace->format_data); 590 return -1; 591 } 592 593 DATAOUT(libtrace)->sock_hdr.sll_family = AF_PACKET; 594 DATAOUT(libtrace)->sock_hdr.sll_protocol = 0; 595 DATAOUT(libtrace)->sock_hdr.sll_ifindex = 596 if_nametoindex(libtrace->uridata); 597 DATAOUT(libtrace)->sock_hdr.sll_hatype = 0; 598 DATAOUT(libtrace)->sock_hdr.sll_pkttype = 0; 599 DATAOUT(libtrace)->sock_hdr.sll_halen = 0; 600 DATAOUT(libtrace)->queue = 0; 294 601 295 602 return 0; … … 302 609 303 610 return 0; 611 } 612 static int linuxring_pause_input(libtrace_t *libtrace) 613 { 614 munmap(FORMAT(libtrace->format_data)->rx_ring, 615 FORMAT(libtrace->format_data)->req.tp_block_size * 616 FORMAT(libtrace->format_data)->req.tp_block_nr); 617 FORMAT(libtrace->format_data)->rx_ring = NULL; 618 return linuxnative_pause_input(libtrace); 304 619 } 305 620 … … 321 636 free(libtrace->format_data); 322 637 return 0; 638 } 639 static int linuxring_fin_output(libtrace_out_t *libtrace) 640 { 641 /* Make sure any remaining frames get sent */ 642 sendto(DATAOUT(libtrace)->fd, 643 NULL, 644 0, 645 0, 646 (void *) &DATAOUT(libtrace)->sock_hdr, 647 sizeof(DATAOUT(libtrace)->sock_hdr)); 648 649 /* Unmap our data area */ 650 munmap(DATAOUT(libtrace)->tx_ring, 651 DATAOUT(libtrace)->req.tp_block_size * 652 DATAOUT(libtrace)->req.tp_block_nr); 653 654 return linuxnative_fin_output(libtrace); 323 655 } 324 656 … … 446 778 } 447 779 780 static int linuxring_prepare_packet(libtrace_t *libtrace, 781 libtrace_packet_t *packet, void *buffer, 782 libtrace_rt_types_t rt_type, uint32_t flags) { 783 784 if (packet->buffer != buffer && 785 packet->buf_control == TRACE_CTRL_PACKET) { 786 free(packet->buffer); 787 } 788 789 if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) { 790 packet->buf_control = TRACE_CTRL_PACKET; 791 } else 792 packet->buf_control = TRACE_CTRL_EXTERNAL; 793 794 795 packet->buffer = buffer; 796 packet->header = buffer; 797 packet->payload = (char *)buffer + 798 TP_TRACE_START( 799 TO_TP_HDR(packet->header)->tp_mac, 800 TO_TP_HDR(packet->header)->tp_net, 801 TPACKET2_HDRLEN); 802 packet->type = rt_type; 803 804 if (libtrace->format_data == NULL) { 805 if (linuxnative_init_input(libtrace)) 806 return -1; 807 } 808 return 0; 809 810 } 811 448 812 #define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b)) 449 813 … … 565 929 } 566 930 931 #define LIBTRACE_BETWEEN(test,a,b) ((test) >= (a) && (test) < (b)) 932 static int linuxring_get_capture_length(const libtrace_packet_t *packet); 933 static int linuxring_get_framing_length(const libtrace_packet_t *packet); 934 935 static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) { 936 937 struct tpacket2_hdr *header; 938 struct pollfd pollset; 939 int ret; 940 941 /* Free the old packet */ 942 if(packet->buf_control == TRACE_CTRL_PACKET){ 943 free(packet->buffer); 944 } 945 if(packet->buf_control == TRACE_CTRL_EXTERNAL) { 946 struct linux_format_data_t *ftd = FORMAT(libtrace->format_data); 947 948 /* Check it's within our buffer first */ 949 if(LIBTRACE_BETWEEN((char *) packet->buffer, 950 (char *) ftd->rx_ring, 951 ftd->rx_ring 952 + ftd->req.tp_block_size * ftd->req.tp_block_nr)){ 953 TO_TP_HDR(packet->buffer)->tp_status = 0; 954 packet->buffer = NULL; 955 } 956 } 957 958 packet->buf_control = TRACE_CTRL_EXTERNAL; 959 packet->type = TRACE_RT_DATA_LINUX_RING; 960 961 /* Fetch the current frame */ 962 header = GET_CURRENT_BUFFER(libtrace); 963 assert((((unsigned long) header) & (pagesize - 1)) == 0); 964 965 /* TP_STATUS_USER means that we can use the frame. 966 * When a slot does not have this flag set, the frame is not 967 * ready for consumption. 968 */ 969 while (!(header->tp_status & TP_STATUS_USER)) { 970 pollset.fd = FORMAT(libtrace->format_data)->fd; 971 pollset.events = POLLIN; 972 pollset.revents = 0; 973 /* Wait for more data */ 974 ret = poll(&pollset, 1, -1); 975 if (ret < 0) { 976 if (errno != EINTR) 977 trace_set_err(libtrace,errno,"poll()"); 978 return -1; 979 } 980 } 981 982 packet->buffer = header; 983 984 /* Move to next buffer */ 985 FORMAT(libtrace->format_data)->rxring_offset++; 986 FORMAT(libtrace->format_data)->rxring_offset %= FORMAT(libtrace->format_data)->req.tp_frame_nr; 987 988 /* We just need to get prepare_packet to set all our packet pointers 989 * appropriately */ 990 if (linuxring_prepare_packet(libtrace, packet, packet->buffer, 991 packet->type, 0)) 992 return -1; 993 return linuxring_get_framing_length(packet) + 994 linuxring_get_capture_length(packet); 995 996 } 997 998 567 999 static int linuxnative_write_packet(libtrace_out_t *trace, 568 1000 libtrace_packet_t *packet) … … 590 1022 591 1023 } 592 593 static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) { 594 int linktype=(((struct libtrace_linuxnative_header*)(packet->buffer)) 595 ->hdr.sll_hatype); 1024 static int linuxring_write_packet(libtrace_out_t *trace, 1025 libtrace_packet_t *packet) 1026 { 1027 struct tpacket2_hdr *header; 1028 struct pollfd pollset; 1029 struct socket_addr; 1030 int ret; 1031 unsigned max_size; 1032 void * off; 1033 1034 if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA) 1035 return 0; 1036 1037 max_size = DATAOUT(trace)->req.tp_frame_size - 1038 - TPACKET_HDRLEN + sizeof(struct sockaddr_ll); 1039 1040 header = (void *) DATAOUT(trace)->tx_ring + 1041 (DATAOUT(trace)->txring_offset * DATAOUT(trace)->req.tp_frame_size); 1042 1043 while(header->tp_status != TP_STATUS_AVAILABLE){ 1044 /* if none available: wait on more data */ 1045 pollset.fd = DATAOUT(trace)->fd; 1046 pollset.events = POLLOUT; 1047 pollset.revents = 0; 1048 ret = poll(&pollset, 1, 1000); 1049 if (ret < 0 && errno != EINTR) { 1050 perror("poll"); 1051 return -1; 1052 } 1053 if(ret == 0) 1054 /* Timeout something has gone wrong - maybe the queue is 1055 * to large so try issue another send command 1056 */ 1057 sendto(DATAOUT(trace)->fd, 1058 NULL, 1059 0, 1060 0, 1061 (void *) &DATAOUT(trace)->sock_hdr, 1062 sizeof(DATAOUT(trace)->sock_hdr)); 1063 } 1064 1065 header->tp_len = trace_get_capture_length(packet); 1066 1067 /* We cannot write the whole packet so just write part of it */ 1068 if (header->tp_len > max_size) 1069 header->tp_len = max_size; 1070 1071 /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */ 1072 off = ((void *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll)); 1073 memcpy(off, 1074 (char *) packet->payload, 1075 header->tp_len); 1076 1077 /* 'Send it' and increase ring pointer to the next frame */ 1078 header->tp_status = TP_STATUS_SEND_REQUEST; 1079 DATAOUT(trace)->txring_offset = (DATAOUT(trace)->txring_offset + 1) % 1080 DATAOUT(trace)->req.tp_frame_nr; 1081 1082 /* Notify kernel there are frames to send */ 1083 DATAOUT(trace)->queue = (++DATAOUT(trace)->queue) % TX_MAX_QUEUE; 1084 if(DATAOUT(trace)->queue == 0){ 1085 sendto(DATAOUT(trace)->fd, 1086 NULL, 1087 0, 1088 MSG_DONTWAIT, 1089 (void *) &DATAOUT(trace)->sock_hdr, 1090 sizeof(DATAOUT(trace)->sock_hdr)); 1091 } 1092 return header->tp_len; 1093 1094 } 1095 1096 static inline libtrace_linktype_t get_libtrace_link_type(int linktype){ 596 1097 /* Convert the ARPHRD type into an appropriate libtrace link type */ 597 598 1098 switch (linktype) { 599 1099 case ARPHRD_ETHER: … … 614 1114 } 615 1115 } 616 617 static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) { 618 switch (((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype) { 1116 static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) { 1117 int linktype=(((struct libtrace_linuxnative_header*)(packet->buffer)) 1118 ->hdr.sll_hatype); 1119 return get_libtrace_link_type(linktype); 1120 } 1121 static libtrace_linktype_t linuxring_get_link_type(const struct libtrace_packet_t *packet) { 1122 int linktype= GET_SOCKADDR_HDR(packet->buffer)->sll_hatype; 1123 return get_libtrace_link_type(linktype); 1124 } 1125 1126 static inline libtrace_direction_t get_libtrace_direction(int pkttype){ 1127 switch (pkttype) { 619 1128 case PACKET_OUTGOING: 620 1129 case PACKET_LOOPBACK: … … 624 1133 } 625 1134 } 626 1135 static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) { 1136 return get_libtrace_link_type(((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype); 1137 } 1138 static libtrace_direction_t linuxring_get_direction(const struct libtrace_packet_t *packet) { 1139 return get_libtrace_link_type(GET_SOCKADDR_HDR(packet->buffer)->sll_pkttype); 1140 } 1141 1142 static libtrace_direction_t set_direction(struct sockaddr_ll * skadr, libtrace_direction_t direction){ 1143 switch (direction) { 1144 case TRACE_DIR_OUTGOING: 1145 skadr->sll_pkttype = PACKET_OUTGOING; 1146 return TRACE_DIR_OUTGOING; 1147 case TRACE_DIR_INCOMING: 1148 skadr->sll_pkttype = PACKET_HOST; 1149 return TRACE_DIR_INCOMING; 1150 default: 1151 return -1; 1152 } 1153 } 627 1154 static libtrace_direction_t linuxnative_set_direction( 628 1155 libtrace_packet_t *packet, 629 1156 libtrace_direction_t direction) { 630 631 switch (direction) { 632 case TRACE_DIR_OUTGOING: 633 ((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype = PACKET_OUTGOING; 634 return TRACE_DIR_OUTGOING; 635 case TRACE_DIR_INCOMING: 636 ((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype = PACKET_HOST; 637 return TRACE_DIR_INCOMING; 638 default: 639 return -1; 640 } 1157 return set_direction(&((struct libtrace_linuxnative_header*)(packet->buffer))->hdr, direction); 1158 } 1159 static libtrace_direction_t linuxring_set_direction( 1160 libtrace_packet_t *packet, 1161 libtrace_direction_t direction) { 1162 return set_direction(GET_SOCKADDR_HDR(packet->buffer), direction); 641 1163 } 642 1164 … … 659 1181 } 660 1182 } 1183 static struct timespec linuxring_get_timespec(const libtrace_packet_t *packet) 1184 { 1185 struct timespec ts; 1186 ts.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec; 1187 ts.tv_nsec = TO_TP_HDR(packet->buffer)->tp_nsec; 1188 return ts; 1189 } 1190 661 1191 662 1192 static struct timeval linuxnative_get_timeval(const libtrace_packet_t *packet) … … 678 1208 } 679 1209 } 1210 static struct timeval linuxring_get_timeval(const libtrace_packet_t *packet) 1211 { 1212 struct timeval tv; 1213 tv.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec; 1214 tv.tv_usec = TO_TP_HDR(packet->buffer)->tp_nsec / 1000; 1215 return tv; 1216 } 680 1217 681 1218 static int linuxnative_get_capture_length(const libtrace_packet_t *packet) 682 1219 { 683 1220 return ((struct libtrace_linuxnative_header*)(packet->buffer))->caplen; 1221 } 1222 1223 static int linuxring_get_capture_length(const libtrace_packet_t *packet) 1224 { 1225 return TO_TP_HDR(packet->buffer)->tp_snaplen; 684 1226 } 685 1227 … … 696 1238 } 697 1239 1240 static int linuxring_get_wire_length(const libtrace_packet_t *packet) 1241 { 1242 int wirelen = TO_TP_HDR(packet->buffer)->tp_len; 1243 1244 /* Include the missing FCS */ 1245 if (trace_get_link_type(packet) == TRACE_TYPE_ETH) 1246 wirelen += 4; 1247 1248 return wirelen; 1249 } 1250 698 1251 static int linuxnative_get_framing_length(UNUSED 699 1252 const libtrace_packet_t *packet) 700 1253 { 701 1254 return sizeof(struct libtrace_linuxnative_header); 1255 } 1256 1257 static int linuxring_get_framing_length(const libtrace_packet_t *packet) 1258 { 1259 /* 1260 * Need to make frame_length + capture_length = compelete capture length 1261 * so include alligment whitespace. So reverse calculate from packet. 1262 */ 1263 return (char *) packet->payload - (char *) packet->buffer; 702 1264 } 703 1265 … … 717 1279 linux_hdr = (struct libtrace_linuxnative_header *)packet->header; 718 1280 linux_hdr->caplen = size; 1281 return trace_get_capture_length(packet); 1282 } 1283 1284 static size_t linuxring_set_capture_length(libtrace_packet_t *packet, 1285 size_t size) { 1286 assert(packet); 1287 if (size > trace_get_capture_length(packet)) { 1288 /* We should avoid making a packet larger */ 1289 return trace_get_capture_length(packet); 1290 } 1291 1292 /* Reset the cached capture length */ 1293 packet->capture_length = -1; 1294 1295 TO_TP_HDR(packet->buffer)->tp_len = size; 1296 719 1297 return trace_get_capture_length(packet); 720 1298 } … … 797 1375 return; 798 1376 } 1377 1378 static void linuxring_help(void) { 1379 printf("linuxring format module: $Revision$\n"); 1380 printf("Supported input URIs:\n"); 1381 printf("\tring:eth0\n"); 1382 printf("\n"); 1383 printf("Supported output URIs:\n"); 1384 printf("\tring:eth0\n"); 1385 printf("\n"); 1386 return; 1387 } 1388 799 1389 static struct libtrace_format_t linuxnative = { 800 1390 "int", … … 840 1430 }; 841 1431 1432 static struct libtrace_format_t linuxring = { 1433 "ring", 1434 "$Id$", 1435 TRACE_FORMAT_LINUX_RING, 1436 linuxnative_probe_filename, /* probe filename */ 1437 NULL, /* probe magic */ 1438 linuxring_init_input, /* init_input */ 1439 linuxnative_config_input, /* config_input */ 1440 linuxring_start_input, /* start_input */ 1441 linuxring_pause_input, /* pause_input */ 1442 linuxring_init_output, /* init_output */ 1443 NULL, /* config_output */ 1444 linuxring_start_output, /* start_ouput */ 1445 linuxnative_fin_input, /* fin_input */ 1446 linuxring_fin_output, /* fin_output */ 1447 linuxring_read_packet, /* read_packet */ 1448 linuxring_prepare_packet, /* prepare_packet */ 1449 NULL, /* fin_packet */ 1450 linuxring_write_packet, /* write_packet */ 1451 linuxring_get_link_type, /* get_link_type */ 1452 linuxring_get_direction, /* get_direction */ 1453 linuxring_set_direction, /* set_direction */ 1454 NULL, /* get_erf_timestamp */ 1455 linuxring_get_timeval, /* get_timeval */ 1456 linuxring_get_timespec, /* get_timespec */ 1457 NULL, /* get_seconds */ 1458 NULL, /* seek_erf */ 1459 NULL, /* seek_timeval */ 1460 NULL, /* seek_seconds */ 1461 linuxring_get_capture_length, /* get_capture_length */ 1462 linuxring_get_wire_length, /* get_wire_length */ 1463 linuxring_get_framing_length, /* get_framing_length */ 1464 linuxring_set_capture_length, /* set_capture_length */ 1465 NULL, /* get_received_packets */ 1466 linuxnative_get_filtered_packets,/* get_filtered_packets */ 1467 linuxnative_get_dropped_packets,/* get_dropped_packets */ 1468 linuxnative_get_captured_packets,/* get_captured_packets */ 1469 linuxnative_get_fd, /* get_fd */ 1470 trace_event_device, /* trace_event */ 1471 linuxring_help, /* help */ 1472 NULL 1473 }; 1474 842 1475 void linuxnative_constructor(void) { 843 1476 register_format(&linuxnative); 844 } 1477 register_format(&linuxring); 1478 } -
lib/libtrace.h.in
r64d4398 rd500159 302 302 TRACE_FORMAT_TSH =12, /**< TSH trace format */ 303 303 TRACE_FORMAT_ATMHDR =13, /**< Legacy ATM header capture */ 304 TRACE_FORMAT_LEGACY_NZIX =14 /**< Legacy format used for NZIX traces */ 304 TRACE_FORMAT_LEGACY_NZIX =14, /**< Legacy format used for NZIX traces */ 305 TRACE_FORMAT_LINUX_RING =15 /**< Linux native interface capture PACKET_MMAP */ 305 306 }; 306 307 … … 351 352 /** RT is encapsulating a Legacy NZIX capture record */ 352 353 TRACE_RT_DATA_LEGACY_NZIX=TRACE_RT_DATA_SIMPLE + TRACE_FORMAT_LEGACY_NZIX, 354 /** RT is encapsulating a Linux native PACKET_MMAP capture record */ 355 TRACE_RT_DATA_LINUX_RING=TRACE_RT_DATA_SIMPLE+TRACE_FORMAT_LINUX_RING, 353 356 354 357 /** As PCAP does not store the linktype with the packet, we need to
Note: See TracChangeset
for help on using the changeset viewer.