Add a simple user space gateway for measuring routing latencies
authorMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 7 Jan 2014 14:20:04 +0000 (15:20 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 7 Jan 2014 14:20:19 +0000 (15:20 +0100)
buildppc/ugw [new symlink]
ugw/Makefile [new file with mode: 0644]
ugw/Makefile.omk [new file with mode: 0644]
ugw/ppc/S50ugw [new file with mode: 0644]
ugw/ppc/boot [new file with mode: 0755]
ugw/ppc/mkinitramfs [new file with mode: 0755]
ugw/ppc/rootfs.cpio [new symlink]
ugw/ppc/shark-ryu.dtb [new symlink]
ugw/ppc/uImage [new symlink]
ugw/ppc/ugw [new symlink]
ugw/ugw.c [new file with mode: 0644]

diff --git a/buildppc/ugw b/buildppc/ugw
new file mode 120000 (symlink)
index 0000000..befd827
--- /dev/null
@@ -0,0 +1 @@
+../ugw
\ No newline at end of file
diff --git a/ugw/Makefile b/ugw/Makefile
new file mode 100644 (file)
index 0000000..76b56fd
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or parent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/ugw/Makefile.omk b/ugw/Makefile.omk
new file mode 100644 (file)
index 0000000..7dbe753
--- /dev/null
@@ -0,0 +1,7 @@
+# -*- makefile -*-
+
+bin_PROGRAMS += ugw
+ugw_SOURCES = ugw.c
+ugw_LIBS = rt #pthread m #talloc popt #ulut
+
+# OMK_CFLAGS = -DSO_RXQ_OVFL=40 -DPF_CAN=29 -DAF_CAN=PF_CAN
diff --git a/ugw/ppc/S50ugw b/ugw/ppc/S50ugw
new file mode 100644 (file)
index 0000000..75d5fdf
--- /dev/null
@@ -0,0 +1,10 @@
+echo Setting up CAN interfaces
+
+ip link set can0 type can bitrate 1000000
+ip link set up dev can0
+ip link set can1 type can bitrate 1000000
+ip link set up dev can1
+
+echo Starting UGW
+
+ugw
diff --git a/ugw/ppc/boot b/ugw/ppc/boot
new file mode 100755 (executable)
index 0000000..ba0bc4c
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/env novaboot
+# -*-sh-*-
+EXITON=UGW started
+uImage console=ttyPSC0,115200
+shark-ryu.dtb
+rootfs2.uImage < $SRCDIR/mkinitramfs
diff --git a/ugw/ppc/mkinitramfs b/ugw/ppc/mkinitramfs
new file mode 100755 (executable)
index 0000000..a44ad0c
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+SRCDIR=${SRCDIR:-$(dirname $0)}
+
+function gen_cpio() {
+    cat $SRCDIR/rootfs.cpio
+    gen_init_cpio - <<EOF
+dir /etc 0755 0 0
+dir /etc/init.d 0755 0 0
+file /etc/init.d/S50ugw S50ugw 0755 0 0
+dir /bin 0755 0 0
+file /bin/ugw ugw 0755 0 0
+EOF
+}
+
+tmp=$(mktemp)
+gen_cpio > $tmp
+
+uimage=$(mktemp)
+mkimage -T ramdisk -A powerpc -O linux -d $tmp $uimage >&2
+cat $uimage
+
+rm $tmp $uimage
diff --git a/ugw/ppc/rootfs.cpio b/ugw/ppc/rootfs.cpio
new file mode 120000 (symlink)
index 0000000..fbd31c6
--- /dev/null
@@ -0,0 +1 @@
+../../rootfs/build/images/rootfs.cpio
\ No newline at end of file
diff --git a/ugw/ppc/shark-ryu.dtb b/ugw/ppc/shark-ryu.dtb
new file mode 120000 (symlink)
index 0000000..df8743b
--- /dev/null
@@ -0,0 +1 @@
+../../kernel/build/shark/3.12/arch/powerpc/boot/shark-ryu.dtb
\ No newline at end of file
diff --git a/ugw/ppc/uImage b/ugw/ppc/uImage
new file mode 120000 (symlink)
index 0000000..adfe471
--- /dev/null
@@ -0,0 +1 @@
+../../kernel/build/shark/3.12/arch/powerpc/boot/uImage
\ No newline at end of file
diff --git a/ugw/ppc/ugw b/ugw/ppc/ugw
new file mode 120000 (symlink)
index 0000000..021d3a2
--- /dev/null
@@ -0,0 +1 @@
+../../buildppc/_compiled/bin/ugw
\ No newline at end of file
diff --git a/ugw/ugw.c b/ugw/ugw.c
new file mode 100644 (file)
index 0000000..a3395c3
--- /dev/null
+++ b/ugw/ugw.c
@@ -0,0 +1,182 @@
+/**************************************************************************/
+/* CAN user space gateway for performance benchmarks                     */
+/* Copyright (C) 2013, 2014 Michal Sojka, DCE, FEE, CTU Prague           */
+/* License: GPLv2                                                        */
+/**************************************************************************/
+
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <linux/can.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdbool.h>
+
+#define STRINGIFY(val) #val
+#define TOSTRING(val) STRINGIFY(val)
+#define CHECK(cmd) ({ int ret = (cmd); if (ret == -1) { perror(#cmd " line " TOSTRING(__LINE__)); exit(1); }; ret; })
+
+char *devin = "can0";
+char *devout = "can1";
+enum { READ, RECVMMSG } in_method = READ;
+enum { WRITE }                out_method = WRITE;
+bool quiet = false;
+
+#define VERBOSE(format, ...) do { if (!quiet) fprintf(stderr, format, ##__VA_ARGS__); } while (0)
+
+struct in_ctx {
+       int s;
+       int for_out;
+       int (*in_fn)(struct in_ctx *ctx, struct can_frame *cf);
+};
+
+struct out_ctx {
+       int s;
+       int from_in;
+       int (*out_fn)(struct out_ctx *ctx, struct can_frame *cf);
+};
+
+int in_read(struct in_ctx *ctx, struct can_frame *cf)
+{
+       int ret = read(ctx->s, cf, sizeof(*cf));
+       if (ret != sizeof(*cf)) {
+               perror("read");
+               exit(1);
+       }
+       return 0;
+}
+
+void init_read(struct in_ctx *ctx)
+{
+       int s;
+       struct sockaddr_can addr;
+       struct ifreq ifr;
+
+       s = CHECK(socket(PF_CAN, SOCK_RAW, CAN_RAW));
+
+       strcpy(ifr.ifr_name, devin);
+       if (-1 == ioctl(s, SIOCGIFINDEX, &ifr)) {
+               perror(devin);
+               exit(1);
+       }
+
+       addr.can_family = AF_CAN;
+       addr.can_ifindex = ifr.ifr_ifindex;
+
+       CHECK(bind(s, (struct sockaddr *)&addr, sizeof(addr)));
+
+       ctx->s = s;
+       ctx->in_fn = in_read;
+}
+
+int out_write(struct out_ctx *ctx, struct can_frame *cf)
+{
+       int ret = write(ctx->s, cf, sizeof(*cf));
+       if (ret != sizeof(*cf)) {
+               perror("write");
+               exit(1);
+       }
+       return 0;
+}
+
+void init_write(struct out_ctx *ctx)
+{
+       int s;
+       struct sockaddr_can addr;
+       struct ifreq ifr;
+
+       s = CHECK(socket(PF_CAN, SOCK_RAW, CAN_RAW));
+
+       strcpy(ifr.ifr_name, devout);
+       if (-1 == ioctl(s, SIOCGIFINDEX, &ifr)) {
+               perror(devout);
+               exit(1);
+       }
+
+       addr.can_family = AF_CAN;
+       addr.can_ifindex = ifr.ifr_ifindex;
+
+       CHECK(bind(s, (struct sockaddr *)&addr, sizeof(addr)));
+
+       ctx->s = s;
+       ctx->out_fn = out_write;
+}
+
+void init_in(struct in_ctx *in)
+{
+       switch (in_method) {
+       case READ: init_read(in); break;
+       default:
+               fprintf(stderr, "Unknown \"in method\" %d\n", in_method);
+               exit(1);
+       }
+}
+
+int in(struct in_ctx *ctx, struct can_frame *cf)
+{
+       return ctx->in_fn(ctx, cf);
+}
+
+void init_out(struct out_ctx *out)
+{
+       switch (out_method) {
+       case WRITE: init_write(out); break;
+       default:
+               fprintf(stderr, "Unknown \"out method\" %d\n", out_method);
+               exit(1);
+       }
+}
+
+int out(struct out_ctx *ctx, struct can_frame *cf)
+{
+       return ctx->out_fn(ctx, cf);
+}
+
+void gw()
+{
+       struct in_ctx    ic;
+       struct out_ctx   oc;
+       struct can_frame cf;
+
+       init_in(&ic);
+       init_out(&oc);
+
+       VERBOSE("UGW started");
+
+       while (1) {
+               in(&ic, &cf);
+               oc.from_in = ic.for_out;
+               out(&oc, &cf);
+       }
+}
+
+
+int main(int argc, char *argv[])
+{
+       int opt;
+
+       while ((opt = getopt(argc, argv, "q")) != -1) {
+               switch (opt) {
+               case 'q':
+                       quiet = true;
+                       break;
+               default: /* '?' */
+                       fprintf(stderr, "Usage: %s [in_interface out_interface]\n",
+                               argv[0]);
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       if (optind < argc)
+               devin  = argv[optind];
+       if (optind+1 < argc)
+               devout = argv[optind+1];
+
+       gw();
+
+       return 0;
+}