Commit a3075628 authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch 'greg-throttling'

Add a tool to control Rx bandwidth throttling of the traffic that goes
from WR ports to Linux. It configures the FPGA module with a maximum allowed
bandwidth in KB/s. Throttling can be enabled to prevent Linux using 100% of
the processing power to receive Ethernet frames coming from WR ports to the
CPU.
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents 41227d23 3341a8a7
......@@ -754,7 +754,22 @@ config WRSAUXCLK_PPSHIFT
should be re-calibrated. Otherwise, 1-PPS output will be shifted
from the WR timescale by <steps>*150ps.
endmenu
menu "NIC throttling configuration"
config NIC_THROTTLING_ENABLED
bool "Enable NIC throttling"
default n
help
Limit bandwith on NIC
config NIC_THROTTLING_VAL
int "NIC throttling value"
depends on NIC_THROTTLING_ENABLED
default "4000"
range 1 65535
help
Value to which bandwith should be limited
endmenu
......
......@@ -1283,6 +1283,13 @@ The following tools and scripts are provided:
transactions. The race can cause errors while reading SFPs memory,
wrong notification of LEDs, the false insert/remove SFP notifications.
@item wrs_throttling
The tool is used to control Rx bandwidth throttling of the traffic that goes
from WR ports to Linux. It configures the FPGA module with a maximum allowed
bandwidth in KB/s. Throttling can be enabled to prevent Linux using 100% of
the processing power to receive Ethernet frames coming from WR ports to the
CPU.
@c FIXME: document lm32-vuart rtu_stat spll_dbg_proxy
@c FIXME: document wrs_pstats
@end table
......
This diff is collapsed.
This diff is collapsed.
......@@ -139,7 +139,7 @@ static int wrn_probe(struct platform_device *pdev)
wrn->ppsg_regs = wrn->bases[WRN_FB_PPSG];
wrn->txd = ((void *)wrn->regs) + 0x80; /* was: TX1_D1 */
wrn->rxd = ((void *)wrn->regs) + 0x100; /* was: RX1_D1 */
wrn->databuf = (void *)wrn->regs + offsetof(struct NIC_WB, MEM);
wrn->databuf = (void *)wrn->regs + NIC_MEM_BASE;
tasklet_init(&wrn->rx_tlet, wrn_rx_interrupt, (unsigned long)wrn);
if (0)
printk("regs %p, txd %p, rxd %p, buffer %p\n",
......
......@@ -11,6 +11,9 @@
#include "wr-nic.h"
#include <asm/unaligned.h>
#define NIC_MEM_BASE 0x8000 /* byte addressing of wb_in.adr(13) that in HDL
* selects between WB registers and nic_buffer */
/* Descriptor direction, used to locate descriptror data memory */
enum wrn_ddir {
WRN_DDIR_RX,
......
......@@ -38,6 +38,9 @@
/* Endpoint */
#define FPGA_BASE_EP0 0x30000
/* NIC */
#define FPGA_BASE_NIC 0x20000
extern volatile uint8_t *_fpga_base_virt; /* libwr/fpga_io.c */
#define FPGA_BASE_ADDR _fpga_base_virt
......
#!/bin/sh
# this script shall be called before enabling the switching
dotconfig=/wr/etc/dot-config
set -o pipefail
start() {
if [ -f $dotconfig ]; then
. $dotconfig
else
echo "$0 unable to start wrs_throttling, unable to source " \
"dot-config ($dotconfig)!"
exit 1
fi
WRS_LOG=$CONFIG_WRS_LOG_OTHER
# if empty turn it to /dev/null
if [ -z $WRS_LOG ]; then
WRS_LOG="/dev/null";
fi
# if a pathname, use it
if echo "$WRS_LOG" | grep / > /dev/null; then
eval LOGPIPE=\" \> $WRS_LOG 2\>\&1 \";
else
# not a pathname: use verbatim
eval LOGPIPE=\" 2\>\&1 \| logger -t wr-switch -p $WRS_LOG\"
fi
echo -n "Starting wrs_throttling: "
if [ "$CONFIG_NIC_THROTTLING_ENABLED" = "y" ] \
&& [ ! -z "$CONFIG_NIC_THROTTLING_VAL" ] ; then
eval /wr/bin/wrs_throttling -t "$CONFIG_NIC_THROTTLING_VAL" $LOGPIPE
ret=$?
if [ $ret -eq 0 ]; then
echo "OK"
else
echo "Failed"
fi
else
echo "throttling disabled"
fi
}
stop() {
echo -n "Stopping wrs_throttling: "
eval /wr/bin/wrs_throttling -d $LOGPIPE
ret=$?
if [ $ret -eq 0 ]; then
echo "OK"
else
echo "Failed"
fi
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
restart
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
;;
esac
../init.d/wrs_throttling.sh
\ No newline at end of file
......@@ -24,3 +24,4 @@ mkpasswd
wrs_status_led
wrs_sfp_dump
wrs_pps_control
wrs_throttling
......@@ -9,6 +9,7 @@ TOOLS += wrs_checkcfg
TOOLS += wrs_status_led
TOOLS += mkpasswd
TOOLS += wrs_sfp_dump
TOOLS += wrs_throttling
PPSI_CONFIG = ../ppsi/include/generated/autoconf.h
WR_INSTALL_ROOT ?= /usr/lib/white-rabbit
......
/*
* Copyright (c) 2016, CERN
*
* Author: Grzegorz Daniluk <grzegorz.daniluk@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <getopt.h>
#include <inttypes.h>
#include <stddef.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <libwr/switch_hw.h>
#include <libwr/wrs-msg.h>
#include <fpga_io.h>
#include <regs/nic-regs.h>
#define nic_write(reg, val) \
_fpga_writel(FPGA_BASE_NIC + offsetof(struct NIC_WB, reg), val)
#define nic_read(reg) \
_fpga_readl(FPGA_BASE_NIC + offsetof(struct NIC_WB, reg))
#define MAX_THR 65535 /* b/w thr in HDL is 16-bit value in KB/s */
#define MIN_THR 2
static char *prgname;
void enable_throttling(int en)
{
uint32_t val;
val = nic_read(CR);
if (en) {
val |= NIC_CR_RXTHR_EN;
printf("NIC bandwidth throttling enabled\n");
} else {
val &= (~NIC_CR_RXTHR_EN);
printf("NIC bandwidth throttling disabled\n");
}
nic_write(CR, val);
}
void print_bw(int print_bps)
{
uint32_t bw;
/* first we read the b/w in Bytes/s */
bw = nic_read(RXBW);
if (print_bps)
printf("NIC Rx bandwidth: %u B/s\n", bw);
else
printf("NIC Rx bandwidth: %.3f KB/s\n", bw/1024.0);
}
int set_thr(unsigned thr)
{
if (thr > MAX_THR || thr < MIN_THR)
return -1;
printf("Setting NIC Rx bandwidth threshold: %u KB/s\n", thr);
nic_write(MAXRXBW, thr);
return 0;
}
void print_settings(void)
{
uint32_t en;
en = nic_read(CR) & NIC_CR_RXTHR_EN;
printf("Current settings:\n");
printf("Throttling: %s\n", en ? "enabled" : "disabled");
printf("Max bandwidth: %u KB/s\n", nic_read(MAXRXBW));
}
void print_help(char *prgname)
{
printf("wrs_throttling. Commit %s, built on " __DATE__ "\n",
__GIT_VER__);
printf("usage: %s <options>\n", prgname);
printf(" -h Show this help message\n"
" -b Print current b/w in B/s (KB/s by default)\n"
" -l Endless loop mode. Prints the current b/w "
"every 1 s\n"
" -t <KB/s> Set maximum NIC Rx bandwidth to <KB/s>\n"
" -d Disable b/w throttling in NIC\n"
" -s Print current settings of the throttling\n");
}
int main(int argc, char *argv[])
{
int c = 0;
int print_bps = 0; /* print current b/w in Bytes/s */
int loop_mode = 0; /* prints current b/w every 1s */
prgname = argv[0];
wrs_msg_init(argc, argv);
if (shw_fpga_mmap_init() < 0) {
pr_error("%s: Can't access device memory\n", prgname);
exit(1);
}
while ((c = getopt(argc, argv, "hbt:lds")) != -1) {
switch (c) {
case 'b':
/* print current b/w in B/s */
print_bps = 1;
break;
case 't':
/* set b/w threshold */
if (set_thr(atoi(optarg)) != -1) {
enable_throttling(1);
} else {
pr_error("Threshold outside allowed range "
"<%d; %d>\n", MIN_THR, MAX_THR);
}
break;
case 'd':
/* disable b/w throttling */
enable_throttling(0);
break;
case 'l':
loop_mode = 1;
break;
case 's':
print_settings();
break;
case 'h':
default:
print_help(prgname);
exit(1);
}
}
/* do actual printing */
print_bw(print_bps);
while (loop_mode) {
sleep(1);
print_bw(print_bps);
}
return 0;
}
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