diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/hv/bondvf.sh | 193 | ||||
-rw-r--r-- | tools/perf/scripts/python/netdev-times.py | 11 | ||||
-rw-r--r-- | tools/virtio/ringtest/Makefile | 5 | ||||
-rw-r--r-- | tools/virtio/ringtest/ptr_ring.c | 197 |
4 files changed, 401 insertions, 5 deletions
diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh new file mode 100755 index 000000000000..8e960234013d --- /dev/null +++ b/tools/hv/bondvf.sh @@ -0,0 +1,193 @@ +#!/bin/bash + +# This example script creates bonding network devices based on synthetic NIC +# (the virtual network adapter usually provided by Hyper-V) and the matching +# VF NIC (SRIOV virtual function). So the synthetic NIC and VF NIC can +# function as one network device, and fail over to the synthetic NIC if VF is +# down. +# +# Usage: +# - After configured vSwitch and vNIC with SRIOV, start Linux virtual +# machine (VM) +# - Run this scripts on the VM. It will create configuration files in +# distro specific directory. +# - Reboot the VM, so that the bonding config are enabled. +# +# The config files are DHCP by default. You may edit them if you need to change +# to Static IP or change other settings. +# + +sysdir=/sys/class/net +netvsc_cls={f8615163-df3e-46c5-913f-f2d2f965ed0e} +bondcnt=0 + +# Detect Distro +if [ -f /etc/redhat-release ]; +then + cfgdir=/etc/sysconfig/network-scripts + distro=redhat +elif grep -q 'Ubuntu' /etc/issue +then + cfgdir=/etc/network + distro=ubuntu +elif grep -q 'SUSE' /etc/issue +then + cfgdir=/etc/sysconfig/network + distro=suse +else + echo "Unsupported Distro" + exit 1 +fi + +echo Detected Distro: $distro, or compatible + +# Get a list of ethernet names +list_eth=(`cd $sysdir && ls -d */ | cut -d/ -f1 | grep -v bond`) +eth_cnt=${#list_eth[@]} + +echo List of net devices: + +# Get the MAC addresses +for (( i=0; i < $eth_cnt; i++ )) +do + list_mac[$i]=`cat $sysdir/${list_eth[$i]}/address` + echo ${list_eth[$i]}, ${list_mac[$i]} +done + +# Find NIC with matching MAC +for (( i=0; i < $eth_cnt-1; i++ )) +do + for (( j=i+1; j < $eth_cnt; j++ )) + do + if [ "${list_mac[$i]}" = "${list_mac[$j]}" ] + then + list_match[$i]=${list_eth[$j]} + break + fi + done +done + +function create_eth_cfg_redhat { + local fn=$cfgdir/ifcfg-$1 + + rm -f $fn + echo DEVICE=$1 >>$fn + echo TYPE=Ethernet >>$fn + echo BOOTPROTO=none >>$fn + echo ONBOOT=yes >>$fn + echo NM_CONTROLLED=no >>$fn + echo PEERDNS=yes >>$fn + echo IPV6INIT=yes >>$fn + echo MASTER=$2 >>$fn + echo SLAVE=yes >>$fn +} + +function create_eth_cfg_pri_redhat { + create_eth_cfg_redhat $1 $2 +} + +function create_bond_cfg_redhat { + local fn=$cfgdir/ifcfg-$1 + + rm -f $fn + echo DEVICE=$1 >>$fn + echo TYPE=Bond >>$fn + echo BOOTPROTO=dhcp >>$fn + echo ONBOOT=yes >>$fn + echo NM_CONTROLLED=no >>$fn + echo PEERDNS=yes >>$fn + echo IPV6INIT=yes >>$fn + echo BONDING_MASTER=yes >>$fn + echo BONDING_OPTS=\"mode=active-backup miimon=100 primary=$2\" >>$fn +} + +function create_eth_cfg_ubuntu { + local fn=$cfgdir/interfaces + + echo $'\n'auto $1 >>$fn + echo iface $1 inet manual >>$fn + echo bond-master $2 >>$fn +} + +function create_eth_cfg_pri_ubuntu { + local fn=$cfgdir/interfaces + + create_eth_cfg_ubuntu $1 $2 + echo bond-primary $1 >>$fn +} + +function create_bond_cfg_ubuntu { + local fn=$cfgdir/interfaces + + echo $'\n'auto $1 >>$fn + echo iface $1 inet dhcp >>$fn + echo bond-mode active-backup >>$fn + echo bond-miimon 100 >>$fn + echo bond-slaves none >>$fn +} + +function create_eth_cfg_suse { + local fn=$cfgdir/ifcfg-$1 + + rm -f $fn + echo BOOTPROTO=none >>$fn + echo STARTMODE=auto >>$fn +} + +function create_eth_cfg_pri_suse { + create_eth_cfg_suse $1 +} + +function create_bond_cfg_suse { + local fn=$cfgdir/ifcfg-$1 + + rm -f $fn + echo BOOTPROTO=dhcp >>$fn + echo STARTMODE=auto >>$fn + echo BONDING_MASTER=yes >>$fn + echo BONDING_SLAVE_0=$2 >>$fn + echo BONDING_SLAVE_1=$3 >>$fn + echo BONDING_MODULE_OPTS=\'mode=active-backup miimon=100 primary=$2\' >>$fn +} + +function create_bond { + local bondname=bond$bondcnt + local primary + local secondary + + local class_id1=`cat $sysdir/$1/device/class_id 2>/dev/null` + local class_id2=`cat $sysdir/$2/device/class_id 2>/dev/null` + + if [ "$class_id1" = "$netvsc_cls" ] + then + primary=$2 + secondary=$1 + elif [ "$class_id2" = "$netvsc_cls" ] + then + primary=$1 + secondary=$2 + else + return 0 + fi + + echo $'\nBond name:' $bondname + + echo configuring $primary + create_eth_cfg_pri_$distro $primary $bondname + + echo configuring $secondary + create_eth_cfg_$distro $secondary $bondname + + echo creating: $bondname with primary slave: $primary + create_bond_cfg_$distro $bondname $primary $secondary + + let bondcnt=bondcnt+1 +} + +for (( i=0; i < $eth_cnt-1; i++ )) +do + if [ -n "${list_match[$i]}" ] + then + create_bond ${list_eth[$i]} ${list_match[$i]} + fi +done diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py index 4d21ef2d601d..4c6f09ac7d12 100644 --- a/tools/perf/scripts/python/netdev-times.py +++ b/tools/perf/scripts/python/netdev-times.py @@ -252,9 +252,10 @@ def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, i event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) all_event_list.append(event_info) -def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name): +def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, + dev_name, work=None, budget=None): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, - napi, dev_name) + napi, dev_name, work, budget) all_event_list.append(event_info) def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, @@ -354,11 +355,13 @@ def handle_irq_softirq_exit(event_info): receive_hunk_list.append(rec_data) def handle_napi_poll(event_info): - (name, context, cpu, time, pid, comm, napi, dev_name) = event_info + (name, context, cpu, time, pid, comm, napi, dev_name, + work, budget) = event_info if cpu in net_rx_dic.keys(): event_list = net_rx_dic[cpu]['event_list'] rec_data = {'event_name':'napi_poll', - 'dev':dev_name, 'event_t':time} + 'dev':dev_name, 'event_t':time, + 'work':work, 'budget':budget} event_list.append(rec_data) def handle_netif_rx(event_info): diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile index 6173adae9f08..877a8a4721b6 100644 --- a/tools/virtio/ringtest/Makefile +++ b/tools/virtio/ringtest/Makefile @@ -1,6 +1,6 @@ all: -all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder noring +all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring CFLAGS += -Wall CFLAGS += -pthread -O2 -ggdb @@ -8,6 +8,7 @@ LDFLAGS += -pthread -O2 -ggdb main.o: main.c main.h ring.o: ring.c main.h +ptr_ring.o: ptr_ring.c main.h ../../../include/linux/ptr_ring.h virtio_ring_0_9.o: virtio_ring_0_9.c main.h virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h @@ -15,6 +16,7 @@ ring: ring.o main.o virtio_ring_0_9: virtio_ring_0_9.o main.o virtio_ring_poll: virtio_ring_poll.o main.o virtio_ring_inorder: virtio_ring_inorder.o main.o +ptr_ring: ptr_ring.o main.o noring: noring.o main.o clean: -rm main.o @@ -22,6 +24,7 @@ clean: -rm virtio_ring_0_9.o virtio_ring_0_9 -rm virtio_ring_poll.o virtio_ring_poll -rm virtio_ring_inorder.o virtio_ring_inorder + -rm ptr_ring.o ptr_ring -rm noring.o noring .PHONY: all clean diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c new file mode 100644 index 000000000000..68e4f9f0da3a --- /dev/null +++ b/tools/virtio/ringtest/ptr_ring.c @@ -0,0 +1,197 @@ +#define _GNU_SOURCE +#include "main.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <pthread.h> +#include <malloc.h> +#include <assert.h> +#include <errno.h> +#include <limits.h> + +#define SMP_CACHE_BYTES 64 +#define cache_line_size() SMP_CACHE_BYTES +#define ____cacheline_aligned_in_smp __attribute__ ((aligned (SMP_CACHE_BYTES))) +#define unlikely(x) (__builtin_expect(!!(x), 0)) +#define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a)) +typedef pthread_spinlock_t spinlock_t; + +typedef int gfp_t; +static void *kmalloc(unsigned size, gfp_t gfp) +{ + return memalign(64, size); +} + +static void *kzalloc(unsigned size, gfp_t gfp) +{ + void *p = memalign(64, size); + if (!p) + return p; + memset(p, 0, size); + + return p; +} + +static void kfree(void *p) +{ + if (p) + free(p); +} + +static void spin_lock_init(spinlock_t *lock) +{ + int r = pthread_spin_init(lock, 0); + assert(!r); +} + +static void spin_lock(spinlock_t *lock) +{ + int ret = pthread_spin_lock(lock); + assert(!ret); +} + +static void spin_unlock(spinlock_t *lock) +{ + int ret = pthread_spin_unlock(lock); + assert(!ret); +} + +static void spin_lock_bh(spinlock_t *lock) +{ + spin_lock(lock); +} + +static void spin_unlock_bh(spinlock_t *lock) +{ + spin_unlock(lock); +} + +static void spin_lock_irq(spinlock_t *lock) +{ + spin_lock(lock); +} + +static void spin_unlock_irq(spinlock_t *lock) +{ + spin_unlock(lock); +} + +static void spin_lock_irqsave(spinlock_t *lock, unsigned long f) +{ + spin_lock(lock); +} + +static void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f) +{ + spin_unlock(lock); +} + +#include "../../../include/linux/ptr_ring.h" + +static unsigned long long headcnt, tailcnt; +static struct ptr_ring array ____cacheline_aligned_in_smp; + +/* implemented by ring */ +void alloc_ring(void) +{ + int ret = ptr_ring_init(&array, ring_size, 0); + assert(!ret); +} + +/* guest side */ +int add_inbuf(unsigned len, void *buf, void *datap) +{ + int ret; + + ret = __ptr_ring_produce(&array, buf); + if (ret >= 0) { + ret = 0; + headcnt++; + } + + return ret; +} + +/* + * ptr_ring API provides no way for producer to find out whether a given + * buffer was consumed. Our tests merely require that a successful get_buf + * implies that add_inbuf succeed in the past, and that add_inbuf will succeed, + * fake it accordingly. + */ +void *get_buf(unsigned *lenp, void **bufp) +{ + void *datap; + + if (tailcnt == headcnt || __ptr_ring_full(&array)) + datap = NULL; + else { + datap = "Buffer\n"; + ++tailcnt; + } + + return datap; +} + +void poll_used(void) +{ + void *b; + + do { + if (tailcnt == headcnt || __ptr_ring_full(&array)) { + b = NULL; + barrier(); + } else { + b = "Buffer\n"; + } + } while (!b); +} + +void disable_call() +{ + assert(0); +} + +bool enable_call() +{ + assert(0); +} + +void kick_available(void) +{ + assert(0); +} + +/* host side */ +void disable_kick() +{ + assert(0); +} + +bool enable_kick() +{ + assert(0); +} + +void poll_avail(void) +{ + void *b; + + do { + barrier(); + b = __ptr_ring_peek(&array); + } while (!b); +} + +bool use_buf(unsigned *lenp, void **bufp) +{ + void *ptr; + + ptr = __ptr_ring_consume(&array); + + return ptr; +} + +void call_used(void) +{ + assert(0); +} |