first session work on project phase
This commit is contained in:
parent
508151e215
commit
59deb6302b
4 changed files with 176 additions and 0 deletions
1
project/.gitignore
vendored
Normal file
1
project/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
netem
|
17
project/Makefile
Normal file
17
project/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
TARGET = netem
|
||||
|
||||
OBJS = main.o probe.o
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -g -lrt
|
||||
|
||||
all: $(TARGET) Makefile
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
rm -f *.o *~
|
||||
|
||||
.PHONY: all clean
|
98
project/main.c
Normal file
98
project/main.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define VERSION "0.1"
|
||||
|
||||
int running = 1;
|
||||
|
||||
void quit(int sig, siginfo_t *si, void *ptr)
|
||||
{
|
||||
printf("Goodbye!\n");
|
||||
running = 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Options */
|
||||
int mark;
|
||||
int interval;
|
||||
int rate;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("usage: %s CMD [OPTIONS]\n", argv[0]);
|
||||
printf(" CMD can be one of:\n");
|
||||
printf(" live \n");
|
||||
printf(" probe \n");
|
||||
printf(" emulate \n");
|
||||
|
||||
/*
|
||||
-m --mark N apply emulation only to packet buffers with mark N
|
||||
-i --interval N update the emulation parameters every N seconds
|
||||
-r --rate the packet rate used for measurements
|
||||
*/
|
||||
|
||||
printf("\n");
|
||||
printf("netem util %s (built on %s %s)\n",
|
||||
VERSION, __DATE__, __TIME__);
|
||||
printf(" Copyright 2015, Steffen Vogel <post@steffenvogel.de>\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *cmd = argv[1];
|
||||
|
||||
/* Setup signals */
|
||||
struct sigaction sa_quit = {
|
||||
.sa_flags = SA_SIGINFO,
|
||||
.sa_sigaction = quit
|
||||
};
|
||||
|
||||
sigemptyset(&sa_quit.sa_mask);
|
||||
sigaction(SIGTERM, &sa_quit, NULL);
|
||||
sigaction(SIGINT, &sa_quit, NULL);
|
||||
|
||||
/* Parse Arguments */
|
||||
char c, *endptr;
|
||||
while ((c = getopt (argc-1, argv+1, "h:m:i:")) != -1) {
|
||||
switch (c) {
|
||||
case 'm':
|
||||
mark = strtoul(optarg, &endptr, 10);
|
||||
goto check;
|
||||
case 'i':
|
||||
interval = strtoul(optarg, &endptr, 10);
|
||||
goto check;
|
||||
case 'r':
|
||||
rate = strtoul(optarg, &endptr, 10);
|
||||
goto check;
|
||||
|
||||
case '?':
|
||||
if (optopt == 'c')
|
||||
error(-1, 0, "Option -%c requires an argument.", optopt);
|
||||
else if (isprint(optopt))
|
||||
error(-1, 0, "Unknown option '-%c'.", optopt);
|
||||
else
|
||||
error(-1, 0, "Unknown option character '\\x%x'.", optopt);
|
||||
exit(EXIT_FAILURE);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
continue;
|
||||
check:
|
||||
if (optarg == endptr)
|
||||
error(-1, 0, "Failed to parse parse option argument '-%c %s'", c, optarg);
|
||||
}
|
||||
|
||||
if (!strcmp(cmd, "probe"))
|
||||
return probe();
|
||||
else
|
||||
error(-1, 0, "Unknown command: %s", cmd);
|
||||
|
||||
return 0;
|
||||
}
|
60
project/probe.c
Normal file
60
project/probe.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int probe()
|
||||
{
|
||||
int val;
|
||||
|
||||
printf("Start probing\n");
|
||||
|
||||
/* Create RAW socket */
|
||||
int sd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
|
||||
|
||||
/* Enable kernel / hw timestamping */
|
||||
val = SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RX_SOFTWARE; /* Enable RX timestamps */
|
||||
val |= SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_TX_SOFTWARE; /* Enable TX timestamps */
|
||||
|
||||
val |= SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RAW_HARDWARE; /* Report SW and HW timestamps */
|
||||
|
||||
val |= SOF_TIMESTAMPING_OPT_TSONLY; /* Only return timestamp in cmsg */
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, (void *) val, &val))
|
||||
error(-1, errno, "Failed to set SO_TIMESTAMPING");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probe_read_ts(int sd)
|
||||
{
|
||||
char cmsg[1024];
|
||||
struct msghdr msgh = {
|
||||
.msg_name = NULL, .msg_namelen = 0,
|
||||
.msg_iov = NULL, .msg_iovlen = 0,
|
||||
.msg_control = &cmsg, .msg_controllen = sizeof(cmsg)
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
struct timespec *ts;
|
||||
|
||||
if (recvmsg(sd, &msgh, 0) == -1)
|
||||
error(-1, errno, "Failed to get control messages");
|
||||
|
||||
/* Receive auxiliary data in msgh */
|
||||
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh,cmsg)) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMPING) {
|
||||
ts = (struct timespec*) CMSG_DATA(cmsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmsg == NULL)
|
||||
error(-1, 0, "SO_TIMESTAMPING not enabled or small buffer or I/O error.");
|
||||
|
||||
if (ts) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
print_ts(&ts[i]);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue