Created
December 2, 2015 18:04
-
-
Save any1/7062000f8c02b9b27bf6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/ioctl.h> | |
#include <net/if.h> | |
#include <linux/can.h> | |
#include <unistd.h> | |
#include <assert.h> | |
#define FTRACE_PATH "/sys/kernel/debug/tracing" | |
#define ftrace_mark(fmt, ...) fprintf(trace_marker_, fmt, ## __VA_ARGS__) | |
const char* iface; | |
static int fd_; | |
static unsigned long burst_rate; | |
static unsigned long burst_length; | |
static unsigned long can_id; | |
static uint8_t frame_number_ = 0; | |
static FILE* trace_marker_; | |
static inline int open_trace_marker(void) | |
{ | |
trace_marker_ = fopen(FTRACE_PATH "/trace_marker", "w"); | |
if (!trace_marker_) | |
return -1; | |
setvbuf(trace_marker_, NULL, _IONBF, 0); | |
return 0; | |
} | |
static inline int fix_sndbuf(int fd) | |
{ | |
int s = 0; | |
return setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &s, sizeof(s)); | |
} | |
static int open_socket(const char* iface) | |
{ | |
int fd; | |
struct sockaddr_can addr; | |
struct ifreq ifreq; | |
fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); | |
if (fd < 0) | |
return -1; | |
memset(&ifreq, 0, sizeof(ifreq)); | |
strcpy(ifreq.ifr_name, iface); | |
if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0) | |
goto failure; | |
memset(&addr, 0, sizeof(addr)); | |
addr.can_family = AF_CAN; | |
addr.can_ifindex = ifreq.ifr_ifindex; | |
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) | |
goto failure; | |
if (fix_sndbuf(fd) < 0) | |
goto failure; | |
return fd; | |
failure: | |
close(fd); | |
return -1; | |
} | |
static void send_frame(unsigned long id, uint8_t i) | |
{ | |
static struct can_frame cf; | |
cf.can_id = id; | |
cf.can_dlc = sizeof(i); | |
uint8_t* d = (uint8_t*)cf.data; | |
*d = i; | |
ftrace_mark("start send frame %u", i); | |
ssize_t rc = write(fd_, &cf, sizeof(cf)); | |
assert(rc == sizeof(cf)); | |
ftrace_mark("end send frame %u", i); | |
} | |
static void send_burst(void) | |
{ | |
unsigned long id = can_id; | |
for (unsigned long i = 0; i < burst_length; ++i) | |
send_frame(can_id, frame_number_++); | |
} | |
static int burst_test(void) | |
{ | |
open_trace_marker(); | |
fd_ = open_socket(iface); | |
if (fd_ < 0) | |
return 1; | |
while (1) { | |
send_burst(); | |
usleep(burst_rate); | |
} | |
return 0; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
iface = argv[1]; | |
burst_rate = strtoul(argv[2], NULL, 0); | |
burst_length = strtoul(argv[3], NULL, 0); | |
can_id = strtoul(argv[4], NULL, 0); | |
return burst_test(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/ioctl.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <net/if.h> | |
#include <linux/can.h> | |
#include <unistd.h> | |
#include <assert.h> | |
#define FTRACE_PATH "/sys/kernel/debug/tracing" | |
#define ftrace_mark(fmt, ...) fprintf(trace_marker_, fmt, ## __VA_ARGS__) | |
const char* iface; | |
static unsigned long can_id_; | |
static int fd_; | |
static FILE* trace_marker_; | |
static int tracing_on_; | |
static uint8_t sequence_ = 0; | |
static int open_trace_marker(void) | |
{ | |
trace_marker_ = fopen(FTRACE_PATH "/trace_marker", "w"); | |
if (!trace_marker_) | |
return -1; | |
setvbuf(trace_marker_, NULL, _IONBF, 0); | |
return 0; | |
} | |
static inline int open_tracing_on(void) | |
{ | |
tracing_on_ = open(FTRACE_PATH "/tracing_on", O_WRONLY); | |
if (tracing_on_ < 0) | |
return -1; | |
return 0; | |
} | |
static inline void tracing_on(void) | |
{ | |
write(tracing_on_, "1", 1); | |
} | |
static inline void tracing_off(void) | |
{ | |
write(tracing_on_, "0", 1); | |
} | |
static inline int fix_sndbuf(int fd) | |
{ | |
int s = 0; | |
return setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &s, sizeof(s)); | |
} | |
static int open_socket(const char* iface) | |
{ | |
int fd; | |
struct sockaddr_can addr; | |
struct ifreq ifreq; | |
fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); | |
if (fd < 0) | |
return -1; | |
memset(&ifreq, 0, sizeof(ifreq)); | |
strcpy(ifreq.ifr_name, iface); | |
if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0) | |
goto failure; | |
memset(&addr, 0, sizeof(addr)); | |
addr.can_family = AF_CAN; | |
addr.can_ifindex = ifreq.ifr_ifindex; | |
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) | |
goto failure; | |
if (fix_sndbuf(fd) < 0) | |
goto failure; | |
return fd; | |
failure: | |
close(fd); | |
return -1; | |
} | |
static uint8_t read_sequence_frame(void) | |
{ | |
struct can_frame cf; | |
uint8_t* s; | |
ssize_t rsize; | |
do { | |
rsize = read(fd_, &cf, sizeof(cf)); | |
assert(rsize == sizeof(cf)); | |
} while (cf.can_id != can_id_); | |
s = (uint8_t*)cf.data; | |
return *s; | |
} | |
static void read_first_frame(void) | |
{ | |
sequence_ = read_sequence_frame(); | |
} | |
static void report_error(void) | |
{ | |
tracing_off(); | |
printf("frame %u dropped. tracing turned off.\n", sequence_ + 1); | |
ftrace_mark("frame %u dropped\n", sequence_ + 1); | |
} | |
static void read_frame(void) | |
{ | |
uint8_t new_seq = read_sequence_frame(); | |
if (new_seq != ((sequence_ + 1) & 0xff)) | |
report_error(); | |
sequence_ = new_seq; | |
} | |
static int detect_missing(void) | |
{ | |
open_trace_marker(); | |
open_tracing_on(); | |
fd_ = open_socket(iface); | |
if (fd_ < 0) | |
return 1; | |
tracing_on(); | |
read_first_frame(); | |
while (1) | |
read_frame(); | |
return 0; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
iface = argv[1]; | |
can_id_ = strtoul(argv[2], NULL, 0); | |
return detect_missing(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment