Skip to content

Instantly share code, notes, and snippets.

@any1
Created December 2, 2015 18:04
Show Gist options
  • Save any1/7062000f8c02b9b27bf6 to your computer and use it in GitHub Desktop.
Save any1/7062000f8c02b9b27bf6 to your computer and use it in GitHub Desktop.
#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();
}
#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