Commit 09b75b7d authored by Alessandro Rubini's avatar Alessandro Rubini

test: removed altogether, as obsolete

There is another ohwr project for switch testing
parent 0fb59c56
This package is software and documentation about testing network switches,
with specific attention to White Rabbit switches.
doc/ includes the documentation, you need TeX and texinfo to compile
misc/ has simple test programs related to hw timestamping. They
are documented in doc/ (there is no README in misc/)
rfc/ hosts a copy of the relevant RFC documents
Enjoy
/alessandro
*.o
onestamp
ttstamp
\ No newline at end of file
CFLAGS = -Wall -O2 -ggdb
ALL = ttstamp onestamp
all: $(ALL)
ttstamp: ttstamp.o stamp-funcs.o
onestamp: onestamp.o stamp-funcs.o
clean:
rm -f $(ALL) *.o *~
\ No newline at end of file
/* Common stuff for these misc tools */
#include <sys/types.h>
#ifndef SO_TIMESTAMPING
# define SO_TIMESTAMPING 37
# define SCM_TIMESTAMPING SO_TIMESTAMPING
#endif
#ifndef SIOCSHWTSTAMP
# define SIOCSHWTSTAMP 0x89b0
#endif
#ifndef ETH_P_1588
# define ETH_P_1588 0x88F7
#endif
extern int make_stamping_socket(FILE *errchan, char *argv0, char *ifname,
int tx_type, int rx_filter, int bits,
unsigned char *macaddr);
extern ssize_t send_and_stamp(int sock, void *buf, size_t len, int flags);
extern ssize_t recv_and_stamp(int sock, void *buf, size_t len, int flags);
extern int print_stamp(FILE *out, char *prefix, FILE *err /* may be NULL */);
extern int get_stamp(struct timespec ts[4]);
/* Functions to make the difference between timevals and timespecs */
static inline int tvdiff(struct timeval *tv2, struct timeval *tv1)
{
return (tv2->tv_sec - tv1->tv_sec) * 1000 * 1000
+ tv2->tv_usec - tv1->tv_usec;
}
static inline int tsdiff(struct timespec *tv2, struct timespec *tv1)
{
return (tv2->tv_sec - tv1->tv_sec) * 1000 * 1000 * 1000
+ tv2->tv_nsec - tv1->tv_nsec;
}
/*
* Userspace API for hardware time stamping of network packets
*
* Copyright (C) 2008,2009 Intel Corporation
* Author: Patrick Ohly <patrick.ohly@intel.com>
*
*/
#ifndef _NET_TIMESTAMPING_H
#define _NET_TIMESTAMPING_H
#include <linux/socket.h> /* for SO_TIMESTAMPING */
/* SO_TIMESTAMPING gets an integer bit field comprised of these values */
enum {
SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),
SOF_TIMESTAMPING_TX_SOFTWARE = (1<<1),
SOF_TIMESTAMPING_RX_HARDWARE = (1<<2),
SOF_TIMESTAMPING_RX_SOFTWARE = (1<<3),
SOF_TIMESTAMPING_SOFTWARE = (1<<4),
SOF_TIMESTAMPING_SYS_HARDWARE = (1<<5),
SOF_TIMESTAMPING_RAW_HARDWARE = (1<<6),
SOF_TIMESTAMPING_MASK =
(SOF_TIMESTAMPING_RAW_HARDWARE - 1) |
SOF_TIMESTAMPING_RAW_HARDWARE
};
/**
* struct hwtstamp_config - %SIOCSHWTSTAMP parameter
*
* @flags: no flags defined right now, must be zero
* @tx_type: one of HWTSTAMP_TX_*
* @rx_type: one of one of HWTSTAMP_FILTER_*
*
* %SIOCSHWTSTAMP expects a &struct ifreq with a ifr_data pointer to
* this structure. dev_ifsioc() in the kernel takes care of the
* translation between 32 bit userspace and 64 bit kernel. The
* structure is intentionally chosen so that it has the same layout on
* 32 and 64 bit systems, don't break this!
*/
struct hwtstamp_config {
int flags;
int tx_type;
int rx_filter;
};
/* possible values for hwtstamp_config->tx_type */
enum {
/*
* No outgoing packet will need hardware time stamping;
* should a packet arrive which asks for it, no hardware
* time stamping will be done.
*/
HWTSTAMP_TX_OFF,
/*
* Enables hardware time stamping for outgoing packets;
* the sender of the packet decides which are to be
* time stamped by setting %SOF_TIMESTAMPING_TX_SOFTWARE
* before sending the packet.
*/
HWTSTAMP_TX_ON,
};
/* possible values for hwtstamp_config->rx_filter */
enum {
/* time stamp no incoming packet at all */
HWTSTAMP_FILTER_NONE,
/* time stamp any incoming packet */
HWTSTAMP_FILTER_ALL,
/* return value: time stamp all packets requested plus some others */
HWTSTAMP_FILTER_SOME,
/* PTP v1, UDP, any kind of event packet */
HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
/* PTP v1, UDP, Sync packet */
HWTSTAMP_FILTER_PTP_V1_L4_SYNC,
/* PTP v1, UDP, Delay_req packet */
HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ,
/* PTP v2, UDP, any kind of event packet */
HWTSTAMP_FILTER_PTP_V2_L4_EVENT,
/* PTP v2, UDP, Sync packet */
HWTSTAMP_FILTER_PTP_V2_L4_SYNC,
/* PTP v2, UDP, Delay_req packet */
HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ,
/* 802.AS1, Ethernet, any kind of event packet */
HWTSTAMP_FILTER_PTP_V2_L2_EVENT,
/* 802.AS1, Ethernet, Sync packet */
HWTSTAMP_FILTER_PTP_V2_L2_SYNC,
/* 802.AS1, Ethernet, Delay_req packet */
HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ,
/* PTP v2/802.AS1, any layer, any kind of event packet */
HWTSTAMP_FILTER_PTP_V2_EVENT,
/* PTP v2/802.AS1, any layer, Sync packet */
HWTSTAMP_FILTER_PTP_V2_SYNC,
/* PTP v2/802.AS1, any layer, Delay_req packet */
HWTSTAMP_FILTER_PTP_V2_DELAY_REQ,
};
#endif /* _NET_TIMESTAMPING_H */
/*
* A simple tool to timestamp one tx and one rx packet
* Alessandro Rubini 2011, GPL2 or later
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "net_tstamp.h"
#include "misc-common.h"
#define BSIZE 2048
char pkt[BSIZE];
int main(int argc, char **argv)
{
int sock;
unsigned char macaddr[6];
char *rest;
int howto;
if (argc != 3) {
fprintf(stderr, "%s: Use \"%s <ifname> <bitmask>\n", argv[0],
argv[0]);
exit(1);
}
howto = strtol(argv[2], &rest, 0);
if (rest && *rest) {
fprintf(stderr, "%s: \"%s\" is not a number\n", argv[0],
argv[2]);
exit(1);
}
/* From ./net_tstamp.h, these are the "howto" values
*
* SOF_TIMESTAMPING_TX_HARDWARE = 1,
* SOF_TIMESTAMPING_TX_SOFTWARE = 2
* SOF_TIMESTAMPING_RX_HARDWARE = 4,
* SOF_TIMESTAMPING_RX_SOFTWARE = 8,
* SOF_TIMESTAMPING_SOFTWARE = 16,
* SOF_TIMESTAMPING_SYS_HARDWARE = 32,
* SOF_TIMESTAMPING_RAW_HARDWARE = 64,
*/
printf("%s: Using interface %s, with %i as SO_TIMESTAMPING\n",
argv[0], argv[1], howto);
/* Create a socket to use for stamping, use the library code */
sock = make_stamping_socket(stderr, argv[0], argv[1],
HWTSTAMP_TX_ON, HWTSTAMP_FILTER_ALL,
howto, macaddr);
if (sock < 0) /* message already printed */
exit(1);
/* build a packet */
memcpy(pkt + 0, "\xff\xff\xff\xff\xff\xff", 6);
memcpy(pkt + 6, macaddr, 6);
memcpy(pkt + 12, "xx", 2);
if (send_and_stamp(sock, pkt, 64, 0) < 0) {
fprintf(stderr, "%s: send_and_stamp: %s\n", argv[0],
strerror(errno));
} else {
print_stamp(stdout, "tx", stderr);
}
if (recv_and_stamp(sock, pkt, sizeof(pkt), 0) < 0) {
fprintf(stderr, "%s: recv_and_stamp: %s\n", argv[0],
strerror(errno));
} else {
print_stamp(stdout, "rx", stderr);
}
exit(0);
}
/*
* This file is a "library" file which offers functions with the same
* Interface as send() and recv() but that handle stamping as well.
* The timestamp informazion is saved to global variables, so no
* concurrency is allowed and so on. In short: it's as crappy as
* possible, but not crappier.
*
* Alessandro Rubini 2011, GPL2 or later
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include "net_tstamp.h"
#include "misc-common.h"
/* This functions opens a socket and configures it for stamping */
int make_stamping_socket(FILE *errchan, char *argv0, char *ifname,
int tx_type, int rx_filter, int bits,
unsigned char *macaddr)
{
struct ifreq ifr;
struct sockaddr_ll addr;
struct hwtstamp_config hwconfig;
int sock, iindex, enable = 1;
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock < 0 && errchan)
fprintf(errchan, "%s: socket(): %s\n", argv0,
strerror(errno));
if (sock < 0)
return sock;
memset (&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, ifname);
/* hw interface information */
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
if (errchan)
fprintf(errchan, "%s: SIOCGIFINDEX(%s): %s\n", argv0,
ifname, strerror(errno));
close(sock);
return -1;
}
iindex = ifr.ifr_ifindex;
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
if (errchan)
fprintf(errchan, "%s: SIOCGIFHWADDR(%s): %s\n", argv0,
ifname, strerror(errno));
close(sock);
return -1;
}
memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6);
/* Also, enable stamping for the hw interface */
memset(&hwconfig, 0, sizeof(hwconfig));
hwconfig.tx_type = tx_type;
hwconfig.rx_filter = rx_filter;
ifr.ifr_data = (void *)&hwconfig;
if (ioctl(sock, SIOCSHWTSTAMP, &ifr) < 0) {
if (errchan)
fprintf(errchan, "%s: SIOCSHWSTAMP(%s): %s\n", argv0,
ifname, strerror(errno));
close(sock);
return -1;
}
/* bind and setsockopt */
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_ifindex = iindex;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
if (errchan)
fprintf(errchan, "%s: SIOCSHWSTAMP(%s): %s\n", argv0,
ifname, strerror(errno));
close(sock);
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
&enable, sizeof(enable)) < 0) {
if (errchan)
fprintf(errchan, "%s: setsockopt(TIMESTAMPNS): %s\n",
argv0, strerror(errno));
close(sock);
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
&bits, sizeof(bits)) < 0) {
if (errchan)
fprintf(errchan, "%s: setsockopt(TIMESTAMPING): %s\n",
argv0, strerror(errno));
close(sock);
return -1;
}
return sock;
}
/* This static data is used to collect stamping information */
static struct timespec __stamp_ns;
static struct timespec __stamp_hw_info[3];
static int __stamp_errno;
/* We can print such stamp info */
int print_stamp(FILE *out, char *prefix, FILE *err)
{
int i;
if (__stamp_errno) {
if (err)
fprintf(err, "get_timestamp: %s\n", strerror(errno));
errno = __stamp_errno;
return -1;
}
fprintf(out, "%s ns: %10li.%09li\n", prefix, __stamp_ns.tv_sec,
__stamp_ns.tv_nsec);
for (i = 0; i < 3; i++)
fprintf(out, "%s ns%i: %10li.%09li\n", prefix, i,
__stamp_hw_info[i].tv_sec,
__stamp_hw_info[i].tv_nsec);
fprintf(out, "\n");
return 0;
}
/* Or we can return it to the caller -- FIXME */
int get_stamp(struct timespec ts[4])
{
if (__stamp_errno) {
errno = __stamp_errno;
memset(ts, 0, 4 * sizeof(ts[0]));
return -1;
}
ts[0] = __stamp_ns;
memcpy(ts + 1, __stamp_hw_info, sizeof(__stamp_hw_info));
return 0;
}
/* This collecting of data is in common between send and recv */
static void __collect_data(struct msghdr *msgp)
{
struct cmsghdr *cmsg;
int i;
__stamp_errno = 0;
memset(&__stamp_ns, 0, sizeof(__stamp_ns));
memset(__stamp_hw_info, 0, sizeof(__stamp_hw_info));
/* Ok, got the tx stamp. Now collect stamp data */
for (cmsg = CMSG_FIRSTHDR(msgp); cmsg;
cmsg = CMSG_NXTHDR(msgp, cmsg)) {
struct timespec *stamp_ptr;
if (0) {
printf("level %i, type %i, len %i\n", cmsg->cmsg_level,
cmsg->cmsg_type, cmsg->cmsg_len);
}
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
stamp_ptr = (struct timespec *)CMSG_DATA(cmsg);
if (cmsg->cmsg_type == SO_TIMESTAMPNS)
__stamp_ns = *stamp_ptr;
if (cmsg->cmsg_type != SO_TIMESTAMPING)
continue;
for (i = 0; i < 3; i++, stamp_ptr++)
__stamp_hw_info[i] = *stamp_ptr;
}
}
/*
* These functions are like send/recv but handle stamping too.
*/
ssize_t send_and_stamp(int sock, void *buf, size_t len, int flags)
{
struct msghdr msg; /* this line and more from timestamping.c */
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[512];
} control;
char data[3*1024];
int i, j, ret;
ret = send(sock, buf, len, flags);
if (ret < 0)
return ret;
/* Then, get back from the error queue */
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = data;
entry.iov_len = sizeof(data);
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
j = 10; /* number of trials */
while ( (i = recvmsg(sock, &msg, MSG_ERRQUEUE)) < 0 && j--)
usleep(1000); /* retry... */
if (i < 0) {
__stamp_errno = ETIMEDOUT;
memset(&__stamp_ns, 0, sizeof(__stamp_ns));
memset(__stamp_hw_info, 0, sizeof(__stamp_hw_info));
return ret;
}
if (getenv("STAMP_VERBOSE")) {
int b;
printf("send %i =", i);
for (b = 0; b < i && b < 20; b++)
printf(" %02x", data[b] & 0xff);
putchar('\n');
}
__collect_data(&msg);
return ret;
}
ssize_t recv_and_stamp(int sock, void *buf, size_t len, int flags)
{
int ret;
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[512];
} control;
if (0) {
/* we can't really call recv, do it with cmsg alone */
ret = recv(sock, buf, len, flags);
} else {
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = buf;
entry.iov_len = len;
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
ret = recvmsg(sock, &msg, 0);
if (ret < 0)
return ret;
if (getenv("STAMP_VERBOSE")) {
int b;
printf("recv %i =", ret);
for (b = 0; b < ret && b < 20; b++)
printf(" %02x", ((char *)buf)[b] & 0xff);
putchar('\n');
}
__collect_data(&msg);
}
return ret;
}
/*
* A simple tool to test packet transmission, with or without hw stamping
* Alessandro Rubini 2011, GPL2 or later
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include "net_tstamp.h"
#include "misc-common.h"
#define BSIZE 2048 /* Packet buffer */
static int howto = 1;
static char pkt[2][BSIZE];
int main(int argc, char **argv)
{
int sock[2];
unsigned char macaddr[2][6];
int i, j, k, nloop=1000;
if (argc != 3) {
fprintf(stderr, "%s: Use: \"%s <ethname> <ethname>\"\n",
argv[0], argv[0]);
exit(1);
}
/* Extra arguments from environment */
if (getenv("STAMP_NLOOP"))
nloop = atoi(getenv("STAMP_NLOOP"));
if (getenv("STAMP_HOWTO"))
howto = atoi(getenv("STAMP_HOWTO"));
fprintf(stderr, "%s: working on %s and %s, %i loops, %02x stamp\n",
argv[0], argv[1], argv[2], nloop, howto);
/* Create two sockets */
sock[0] = make_stamping_socket(stderr, argv[0], argv[1],
HWTSTAMP_TX_ON, HWTSTAMP_FILTER_ALL,
howto, macaddr[0]);
if (sock[0] < 0)
exit(1);
sock[1] = make_stamping_socket(stderr, argv[0], argv[2],
HWTSTAMP_TX_ON, HWTSTAMP_FILTER_ALL,
howto, macaddr[1]);
if (sock[1] < 0)
exit(1);
/* Build the packet */
memcpy(pkt[0]+0, macaddr[1], 6);
memcpy(pkt[0]+6, macaddr[0], 6);
pkt[0][12] = ETH_P_1588 >> 8;
pkt[0][13] = ETH_P_1588 & 0xff;
for (i = 64; i < 1500; i += 64) {
/* there are 4 timespecs to consider */
unsigned long min[4], avg[4], max[4];
unsigned long long tot[4];
for (k = 0; k < 4; k++) {
max[k] = 0; avg[k] = 0; min[k] = ~0L;
}
for (j = 0; j < nloop; j++) {
long diff;
struct timespec ts0[4], ts1[4];
if (send_and_stamp(sock[0], pkt, i, 0) < 0) {
fprintf(stderr, "%s: send: %s\n", argv[0],
strerror(errno));
exit(1);
}
if (get_stamp(ts0) < 0) {
fprintf(stderr, "%s: getstamp(send): %s\n",
argv[0], strerror(errno));
continue;
}
if (recv_and_stamp(sock[1], pkt, sizeof(pkt), 0) < 0) {
fprintf(stderr, "%s: recv: %s\n", argv[0],
strerror(errno));
exit(1);
}
get_stamp(ts1);
for (k = 0; 0 && k < 4; k++) {
printf("%i: %10li.%09li %10li.%09li\n", k,
ts0[k].tv_sec, ts0[k].tv_nsec,
ts1[k].tv_sec, ts1[k].tv_nsec);
}
/* collect differences for all 4 values*/
for (k = 0; k < 4; k++) {
diff = tsdiff(ts1 + k, ts0 + k);
tot[k] += diff;
if (diff < min[k]) min[k] = diff;
if (diff > max[k]) max[k] = diff;
if (0)
printf("%li%c", diff,
k == 3 ? '\n' : ' ');
}
}
for (k = 0; k < 4; k++) {
avg[k] = tot[k] / nloop;
printf("size %4i ts %i: %7li %7li %7li\n", i, k,
min[k], avg[k], max[k]);
}
}
exit(0);
}
From d3b127b9ecd60a6bff64269708b9099fe902c198 Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Sat, 18 Dec 2010 17:01:30 +0100
Subject: [PATCH] r8169: added timestamp ioctl
This is a tool to fake hw timestamping on the 8169 gigabit ethernet.
The patch makes no actual stamping, which is added later.
Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
---
drivers/net/r8169.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index cdc6a5c..4b4cca0 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
+#include <linux/net_tstamp.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -511,6 +512,9 @@ struct rtl8169_private {
struct mii_if_info mii;
struct rtl8169_counters counters;
u32 saved_wolopts;
+ int hwtstamp; /* hack -- ARub */
+#define TSTAMP_TX 1
+#define TSTAMP_RX 2
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -2880,11 +2884,54 @@ static int rtl_set_mac_address(struct net_device *dev, void *p)
return 0;
}
+/* This copied from gianfar -- ARub */
+static int rtl8169_tstamp_ioctl(struct net_device *netdev,
+ struct ifreq *ifr, int cmd)
+{
+ struct hwtstamp_config config;
+ struct rtl8169_private *priv = netdev_priv(netdev);
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (config.flags)
+ return -EINVAL;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ priv->hwtstamp &= ~TSTAMP_TX;
+ break;
+ case HWTSTAMP_TX_ON:
+ priv->hwtstamp |= TSTAMP_TX;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ priv->hwtstamp &= ~TSTAMP_RX;
+ break;
+ default:
+ priv->hwtstamp |= TSTAMP_RX;
+ break;
+ }
+ printk("%s: stamp is %i\n", __func__, priv->hwtstamp);
+
+ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+ -EFAULT : 0;
+}
+
static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
+ if (cmd == SIOCSHWTSTAMP) {
+ return rtl8169_tstamp_ioctl(dev, ifr, cmd);
+ }
+
return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
}
--
1.5.6.5
From f68d43fbd71a12a31da21fe825987f87179c125b Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Sat, 18 Dec 2010 17:35:08 +0100
Subject: [PATCH] r8169: added tx timestamp (possibly too late)
This adds actual stamping in the tx-done interrupt, for the fake
hw-timestap in the RTL8169 device. The stamp is taken with
getnstimeofday, keeping only the last 4 digits and 2 digits of the
seconds field.
Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
---
drivers/net/r8169.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 4b4cca0..2a85588 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -4447,6 +4447,25 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
+static inline void __tstamp_tx(struct sk_buff *skb)
+{
+ union skb_shared_tx *shtx;
+ struct timespec ts;
+
+ getnstimeofday(&ts);
+ shtx = skb_tx(skb);
+ if (unlikely(shtx->hardware)) {
+ struct skb_shared_hwtstamps shhwtstamps;
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ ts.tv_sec %=10000; /* sys tstamp different from sw one */
+ shhwtstamps.syststamp = timespec_to_ktime(ts);
+ ts.tv_sec %=100; /* and hw tstamp is still different */
+ shhwtstamps.hwtstamp = timespec_to_ktime(ts);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ }
+}
+
static void rtl8169_tx_interrupt(struct net_device *dev,
struct rtl8169_private *tp,
void __iomem *ioaddr)
@@ -4474,6 +4493,9 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
if (status & LastFrag) {
+ /* We may need to tx-timestamp. FIXME: too late? */
+ if (unlikely(tp->hwtstamp & TSTAMP_TX))
+ __tstamp_tx(tx_skb->skb);
dev_kfree_skb(tx_skb->skb);
tx_skb->skb = NULL;
}
--
1.5.6.5
From e4aa9cf635afdfbe604c5fa61c3801653404713b Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Sat, 18 Dec 2010 17:45:41 +0100
Subject: [PATCH] r8169: added rx timestamp
Like the previous patch, this adds fake hw-timestamp to the RTL8169 device.
Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
---
drivers/net/r8169.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 2a85588..9b37f02 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -4563,6 +4563,20 @@ out:
return done;
}
+static inline void __tstamp_rx(struct sk_buff *skb)
+{
+ struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+ struct timespec ts;
+
+ getnstimeofday(&ts);
+
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ ts.tv_sec %=10000; /* sys tstamp different from sw one */
+ shhwtstamps->syststamp = timespec_to_ktime(ts);
+ ts.tv_sec %=100; /* and hw tstamp is still different */
+ shhwtstamps->hwtstamp = timespec_to_ktime(ts);
+}
+
/*
* Warning : rtl8169_rx_interrupt() might be called :
* 1) from NAPI (softirq) context
@@ -4639,6 +4653,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
skb->protocol = eth_type_trans(skb, dev);
if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
+ if (unlikely(tp->hwtstamp & TSTAMP_RX))
+ __tstamp_rx(skb);
if (likely(polling))
netif_receive_skb(skb);
else
--
1.5.6.5
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
CFLAGS = -Wall -O2 -ggdb
ALL = swflood multidump
all: $(ALL)
swflood: main.o parse.o commands.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
# build commands.o by various cmd-*.c using a linker script
CMD_C := $(wildcard cmd-*.c)
CMD_O := $(CMD_C:.c=.o)
commands.o: $(CMD_O)
$(LD) -r -T commands.lds $^ -o $@
clean:
rm -f $(ALL) *.o *~ core
repeat df r
repeat 1000 50
repeat 100 f
repeat 50 a
endr x
iface eth1 eth2 eth3 eth4
verbose 9 /dev/tty
send 0 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 1 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 2 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 3 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
repeat A 10
send 1 50 00:00 22:00:10:00:00:00
send 1 50 00:00 ff:ff:ff:ff:ff:ff
flush
endr A
#-*-shell-script-*-
flush
verbose 9 /dev/stdout
### I run this test with a 4-cable octopus
iface eth1 eth2 eth3 eth4
echo testing from 32 different senders plus another
send 0 32 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 32 32 32
send 1 32 00:00 22:00:10:00:00:00 +1
expect 32 0 0 0
echo testing from 64 different senders plus another
send 0 64 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 64 64 64
send 1 64 00:00 22:00:10:00:00:00 +1
expect 64 0 0 0
echo testing from 128 different senders plus another
send 0 128 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 128 128 128
send 1 128 00:00 22:00:10:00:00:00 +1
expect 128 0 0 0
echo testing from 256 different senders plus another
send 0 256 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 256 256 256
send 1 256 00:00 22:00:10:00:00:00 +1
expect 256 0 0 0
echo testing from 512 different senders plus another
send 0 512 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 512 512 512
send 1 512 00:00 22:00:10:00:00:00 +1
expect 512 0 0 0
echo testing from 1024 different senders plus another
send 0 1024 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 1024 1024 1024
send 1 1024 00:00 22:00:10:00:00:00 +1
expect 1024 0 0 0
echo testing from 2048 different senders plus another
send 0 2048 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 2048 2048 2048
send 1 2048 00:00 22:00:10:00:00:00 +1
expect 2048 0 0 0
echo testing from 4096 different senders plus another
send 0 4096 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 4096 4096 4096
send 1 4096 00:00 22:00:10:00:00:00 +1
expect 4096 0 0 0
echo testing from 8192 different senders plus another
send 0 8192 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 8192 8192 8192
send 1 8192 00:00 22:00:10:00:00:00 +1
expect 8192 0 0 0
echo testing from 16384 different senders plus another
send 0 16384 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 16384 16384 16384
send 1 16384 00:00 22:00:10:00:00:00 +1
expect 16384 0 0 0
iface br0 tap0 tap1 tap2 tap3
verbose 9 /dev/stdout
send 0 5 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 1 5 00:02 +0 ff:ff:ff:ff:ff:ff
flush
send 2 5 00:00 +0 ff:ff:ff:ff:ff:ff
flush
send 3 5 00:00 +0 ff:ff:ff:ff:ff:ff
flush
echo now repeating 10 times
repeat A 2
echo loop
send 1 5 00:00 22:00:10:00:00:00
flush
send 1 1 00:00 ff:ff:ff:ff:ff:ff
flush
send 2 5 00:20 22:00:11:00:00:00
flush
endr A
send 1 5 00:ff 22:00:12:00:00:20
flush
echo foreign
send 0 20 00:66 00:01:02:00:00:00 +1
flush
\ No newline at end of file
#-*-shell-script-*-
flush
verbose 9 /dev/stdout
### I run this test with a 4-cable octopus
iface tap1 tap2 tap3 tap4
echo testing from 32 different senders plus another
send 0 32 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 32 32 32
send 1 32 00:00 22:00:10:00:00:00 +1
expect 32 0 0 0
echo testing from 64 different senders plus another
send 0 64 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 64 64 64
send 1 64 00:00 22:00:10:00:00:00 +1
expect 64 0 0 0
echo testing from 128 different senders plus another
send 0 128 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 128 128 128
send 1 128 00:00 22:00:10:00:00:00 +1
expect 128 0 0 0
echo testing from 256 different senders plus another
send 0 256 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 256 256 256
send 1 256 00:00 22:00:10:00:00:00 +1
expect 256 0 0 0
echo testing from 512 different senders plus another
send 0 512 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 512 512 512
send 1 512 00:00 22:00:10:00:00:00 +1
expect 512 0 0 0
echo testing from 1024 different senders plus another
send 0 1024 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 1024 1024 1024
send 1 1024 00:00 22:00:10:00:00:00 +1
expect 1024 0 0 0
echo testing from 2048 different senders plus another
send 0 2048 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 2048 2048 2048
send 1 2048 00:00 22:00:10:00:00:00 +1
expect 2048 0 0 0
echo testing from 4096 different senders plus another
send 0 4096 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 4096 4096 4096
send 1 4096 00:00 22:00:10:00:00:00 +1
expect 4096 0 0 0
echo testing from 8192 different senders plus another
send 0 8192 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 8192 8192 8192
send 1 8192 00:00 22:00:10:00:00:00 +1
expect 8192 0 0 0
echo testing from 16384 different senders plus another
send 0 16384 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 16384 16384 16384
send 1 16384 00:00 22:00:10:00:00:00 +1
expect 16384 0 0 0
echo tsting repeat, expect 10 "loop" messages
repeat x 5
repeat y 2
repeat a 10000
endr a
echo loop
endr y
endr x
\ No newline at end of file
echo sleep 2s
sleep 2
echo sleep 2s
sleep 0 2000
repeat x 10
echo sleep .5s
sleep 0 500
endr x
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
SECTIONS
{
.data : {
. = ALIGN(4);
__cmd_start = .;
*(.commands);
__cmd_end = .;
}
}
This diff is collapsed.
This diff is collapsed.
/* Alessandro Rubini for CERN and White Rabbit, 2011 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "swflood.h"
#define MAXARG 15 /* lazy me */
/*
* This can write to stderr and to the newly-allocated line.
* It returns -ENODATA if the line is empty, 0 on success, or
* other negative errors
*/
int swf_parse(char *s, struct swf_line *line)
{
int i;
struct swf_command **cmdp;
/* First trim any leading and trailing whitespace */
while (isspace(*s))
s++;
i = strlen(s);
while(i && isspace(s[i-1]))
s[--i] = '\0';
/* Now, if it's empty we are done */
if (!s[0] || s[0] == '#')
return -ENODATA;
/* Make a local copy for our argv, and allocate it */
s = strdup(s);
line->argv = malloc(sizeof(*line->argv) * (MAXARG + 1));
if (!s || !line->argv) {
free(s);
free(line->argv);
return -ENOMEM;
}
/* fill the argv */
i = 0;
while (1) {
line->argv[i++] = s;
while (*s && !isspace(*s))
s++;
if (!*s)
break;
*(s++) = '\0';
}
line->argc = i;
/* find the command */
for (cmdp = __cmd_start; cmdp < __cmd_end; cmdp++)
if (!strcmp(line->argv[0], (*cmdp)->name))
break;
if (cmdp == __cmd_end) {
fprintf(stderr, " invalid command \"%s\"\n",
line->argv[0]);
return -EINVAL;
}
/* and verify it */
line->cmd = *cmdp;
return line->cmd->verify(line);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment