monitor: Enable kernel side timestamps and make them available

This commit is contained in:
Marcel Holtmann 2014-08-09 23:48:25 -07:00
parent 7a1bb1e953
commit 55bbf22edb
1 changed files with 40 additions and 23 deletions

View File

@ -99,7 +99,7 @@ do { \
print_indent(4 + (level) * 4, COLOR_OFF, "", "", color, \ print_indent(4 + (level) * 4, COLOR_OFF, "", "", color, \
fmt, ## args) fmt, ## args)
static void print_packet(struct timeval *tv, char ident, static void print_packet(const struct timeval *tv, char ident,
const char *color, const char *label, const char *color, const char *label,
const char *text, const char *extra) const char *text, const char *extra)
{ {
@ -931,9 +931,10 @@ static const struct {
{ } { }
}; };
static void print_message(enum msg_type type, uint16_t flags, int status, static void print_message(const struct timeval *tv, enum msg_type type,
uint8_t cmd, uint8_t version, uint16_t flags, int status,
const void *data, uint32_t len) uint8_t cmd, uint8_t version,
const void *data, uint32_t len)
{ {
char extra_str[64]; char extra_str[64];
const char *label = ""; const char *label = "";
@ -1038,11 +1039,15 @@ static bool nlmon_req_match(const void *a, const void *b)
return (req->seq == match->seq && req->pid == match->pid); return (req->seq == match->seq && req->pid == match->pid);
} }
static void store_message(struct nlmon *nlmon, const struct nlmsghdr *nlmsg) static void store_message(struct nlmon *nlmon, const struct timeval *tv,
const struct tpacket_auxdata *tp,
const struct nlmsghdr *nlmsg)
{ {
} }
static void nlmon_message(struct nlmon *nlmon, const struct nlmsghdr *nlmsg) static void nlmon_message(struct nlmon *nlmon, const struct timeval *tv,
const struct tpacket_auxdata *tp,
const struct nlmsghdr *nlmsg)
{ {
struct nlmon_req *req; struct nlmon_req *req;
@ -1073,8 +1078,8 @@ static void nlmon_message(struct nlmon *nlmon, const struct nlmsghdr *nlmsg)
return; return;
} }
store_message(nlmon, nlmsg); store_message(nlmon, tv, tp, nlmsg);
print_message(type, nlmsg->nlmsg_flags, status, print_message(tv, type, nlmsg->nlmsg_flags, status,
req->cmd, req->version, req->cmd, req->version,
NULL, sizeof(status)); NULL, sizeof(status));
nlmon_req_free(req); nlmon_req_free(req);
@ -1099,8 +1104,8 @@ static void nlmon_message(struct nlmon *nlmon, const struct nlmsghdr *nlmsg)
l_queue_push_tail(nlmon->req_list, req); l_queue_push_tail(nlmon->req_list, req);
store_message(nlmon, nlmsg); store_message(nlmon, tv, tp, nlmsg);
print_message(MSG_REQUEST, flags, 0, print_message(tv, MSG_REQUEST, flags, 0,
req->cmd, req->version, req->cmd, req->version,
NLMSG_DATA(nlmsg) + GENL_HDRLEN, NLMSG_DATA(nlmsg) + GENL_HDRLEN,
NLMSG_PAYLOAD(nlmsg, GENL_HDRLEN)); NLMSG_PAYLOAD(nlmsg, GENL_HDRLEN));
@ -1122,8 +1127,8 @@ static void nlmon_message(struct nlmon *nlmon, const struct nlmsghdr *nlmsg)
type = MSG_RESULT; type = MSG_RESULT;
} }
store_message(nlmon, nlmsg); store_message(nlmon, tv, tp, nlmsg);
print_message(type, nlmsg->nlmsg_flags, 0, print_message(tv, type, nlmsg->nlmsg_flags, 0,
genlmsg->cmd, genlmsg->version, genlmsg->cmd, genlmsg->version,
NLMSG_DATA(nlmsg) + GENL_HDRLEN, NLMSG_DATA(nlmsg) + GENL_HDRLEN,
NLMSG_PAYLOAD(nlmsg, GENL_HDRLEN)); NLMSG_PAYLOAD(nlmsg, GENL_HDRLEN));
@ -1200,7 +1205,7 @@ void nlmon_print_genl(struct nlmon *nlmon, const void *data, uint32_t size)
genl_ctrl(nlmon, NLMSG_DATA(nlmsg), genl_ctrl(nlmon, NLMSG_DATA(nlmsg),
NLMSG_PAYLOAD(nlmsg, 0)); NLMSG_PAYLOAD(nlmsg, 0));
else else
nlmon_message(nlmon, nlmsg); nlmon_message(nlmon, NULL, NULL, nlmsg);
} }
} }
@ -1212,6 +1217,10 @@ static bool nlmon_receive(struct l_io *io, void *user_data)
struct sockaddr_ll sll; struct sockaddr_ll sll;
struct iovec iov; struct iovec iov;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
struct timeval copy_tv;
struct tpacket_auxdata copy_tp;
const struct timeval *tv = NULL;
const struct tpacket_auxdata *tp = NULL;
unsigned char buf[8192]; unsigned char buf[8192];
unsigned char control[32]; unsigned char control[32];
ssize_t bytes_read; ssize_t bytes_read;
@ -1248,20 +1257,22 @@ static bool nlmon_receive(struct l_io *io, void *user_data)
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
cmsg = CMSG_NXTHDR(&msg, cmsg)) { cmsg = CMSG_NXTHDR(&msg, cmsg)) {
struct tpacket_auxdata tp; if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_TIMESTAMP) {
memcpy(&copy_tv, CMSG_DATA(cmsg), sizeof(copy_tv));
tv = &copy_tv;
}
if (cmsg->cmsg_level != SOL_PACKET) if (cmsg->cmsg_level == SOL_PACKET &&
continue; cmsg->cmsg_type != PACKET_AUXDATA) {
memcpy(&copy_tp, CMSG_DATA(cmsg), sizeof(copy_tp));
if (cmsg->cmsg_type != PACKET_AUXDATA) tp = &copy_tp;
continue; }
memcpy(&tp, CMSG_DATA(cmsg), sizeof(tp));
} }
for (nlmsg = iov.iov_base; NLMSG_OK(nlmsg, bytes_read); for (nlmsg = iov.iov_base; NLMSG_OK(nlmsg, bytes_read);
nlmsg = NLMSG_NEXT(nlmsg, bytes_read)) { nlmsg = NLMSG_NEXT(nlmsg, bytes_read)) {
nlmon_message(nlmon, nlmsg); nlmon_message(nlmon, tv, tp, nlmsg);
} }
return true; return true;
@ -1273,7 +1284,7 @@ static struct l_io *open_packet(const char *name)
struct sockaddr_ll sll; struct sockaddr_ll sll;
struct packet_mreq mr; struct packet_mreq mr;
struct ifreq ifr; struct ifreq ifr;
int fd; int fd, opt = 1;
fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (fd < 0) { if (fd < 0) {
@ -1311,6 +1322,12 @@ static struct l_io *open_packet(const char *name)
return NULL; return NULL;
} }
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {
perror("Failed to enable timestamps");
close(fd);
return NULL;
}
io = l_io_new(fd); io = l_io_new(fd);
l_io_set_close_on_destroy(io, true); l_io_set_close_on_destroy(io, true);