From 36a8c1dbdb6af0d11d233ba49c92d3733b3eac17 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Tue, 7 Jan 2014 15:20:04 +0100 Subject: [PATCH] Add a simple user space gateway for measuring routing latencies --- buildppc/ugw | 1 + ugw/Makefile | 14 ++++ ugw/Makefile.omk | 7 ++ ugw/ppc/S50ugw | 10 +++ ugw/ppc/boot | 6 ++ ugw/ppc/mkinitramfs | 23 ++++++ ugw/ppc/rootfs.cpio | 1 + ugw/ppc/shark-ryu.dtb | 1 + ugw/ppc/uImage | 1 + ugw/ppc/ugw | 1 + ugw/ugw.c | 182 ++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 247 insertions(+) create mode 120000 buildppc/ugw create mode 100644 ugw/Makefile create mode 100644 ugw/Makefile.omk create mode 100644 ugw/ppc/S50ugw create mode 100755 ugw/ppc/boot create mode 100755 ugw/ppc/mkinitramfs create mode 120000 ugw/ppc/rootfs.cpio create mode 120000 ugw/ppc/shark-ryu.dtb create mode 120000 ugw/ppc/uImage create mode 120000 ugw/ppc/ugw create mode 100644 ugw/ugw.c diff --git a/buildppc/ugw b/buildppc/ugw new file mode 120000 index 0000000..befd827 --- /dev/null +++ b/buildppc/ugw @@ -0,0 +1 @@ +../ugw \ No newline at end of file diff --git a/ugw/Makefile b/ugw/Makefile new file mode 100644 index 0000000..76b56fd --- /dev/null +++ b/ugw/Makefile @@ -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 index 0000000..7dbe753 --- /dev/null +++ b/ugw/Makefile.omk @@ -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 index 0000000..75d5fdf --- /dev/null +++ b/ugw/ppc/S50ugw @@ -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 index 0000000..ba0bc4c --- /dev/null +++ b/ugw/ppc/boot @@ -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 index 0000000..a44ad0c --- /dev/null +++ b/ugw/ppc/mkinitramfs @@ -0,0 +1,23 @@ +#!/bin/bash + +SRCDIR=${SRCDIR:-$(dirname $0)} + +function gen_cpio() { + cat $SRCDIR/rootfs.cpio + gen_init_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 index 0000000..fbd31c6 --- /dev/null +++ b/ugw/ppc/rootfs.cpio @@ -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 index 0000000..df8743b --- /dev/null +++ b/ugw/ppc/shark-ryu.dtb @@ -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 index 0000000..adfe471 --- /dev/null +++ b/ugw/ppc/uImage @@ -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 index 0000000..021d3a2 --- /dev/null +++ b/ugw/ppc/ugw @@ -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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} -- 2.39.2