Commit 4d91e4f1 authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'for-2.6.39' of /home/shemminger/iproute2-net-next

Conflicts:
	include/linux/xfrm.h
	ip/iplink.c
parents 21cfb5e1 242b8da7
......@@ -33,11 +33,10 @@ CCOPTS = -D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall
CFLAGS = $(CCOPTS) -I../include $(DEFINES)
YACCFLAGS = -d -t -v
LDLIBS += -L../lib -lnetlink -lutil
SUBDIRS=lib ip tc misc netem genl
LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
LDLIBS += $(LIBNETLINK)
all: Config
@set -e; \
......
Primary site is:
http://developer.osdl.org/dev/iproute2
This is a set of utilities for Linux networking.
Original FTP site is:
ftp://ftp.inr.ac.ru/ip-routing/
Information:
http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
Download:
http://devresources.linuxfoundation.org/dev/iproute2/download
Repository:
git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
How to compile this.
--------------------
1. Look at start of Makefile and set correct values for:
KERNEL_INCLUDE should point to correct linux kernel include directory.
Default (/usr/src/linux/include) is right as rule.
1. libdbm
arpd needs to have the db4 development libraries. For debian
users this is the package with a name like libdb4.x-dev.
......@@ -29,8 +31,13 @@ contains whether or not ATM is available, etc.
and make there. It assumes, that latex, dvips and psnup
are in your path.
4. This package includes matching sanitized kernel headers because
the build environment may not have up to date versions. See Makefile
if you have special requirements and need to point at different
kernel include files.
Stephen Hemminger
shemminger@osdl.org
shemminger@linux-foundation.org
Alexey Kuznetsov
kuznet@ms2.inr.ac.ru
Iproute2 development is closely tied to Linux kernel networking
development. Most new features require a kernel and a utility component.
Please submit both the the Linux networking mailing list
<netdev@vger.kernel.org>
The current source is in the git repository:
git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
The master branch contains the source corresponding to the current
code in the mainline Linux kernel (ie follows Linus). The net-next
branch is a temporary branch that tracks the code intended for the
next release; it corresponds with networking development branch in
the kernel.
......@@ -15,6 +15,7 @@ PAGESPERPAGE=2
HTMLFILES=$(subst .sgml,.html,$(shell echo *.sgml))
DVIFILES=$(subst .ps,.dvi,$(PSFILES))
PDFFILES=$(subst .ps,.pdf,$(PSFILES))
all: pstwocol
......@@ -25,6 +26,8 @@ html: $(HTMLFILES)
dvi: $(DVIFILES)
pdf: $(PDFFILES)
print: $(PSFILES)
$(LPR) $(PSFILES)
......@@ -41,6 +44,11 @@ print: $(PSFILES)
echo "Re-running LaTeX $<, $${pass}d pass"; pass=$$[$$pass + 1]; \
done
#%.pdf: %.tex
# pdflatex $<
%.pdf: %.ps
ps2pdf $<
%.ps: %.dvi
$(DVIPS) $< -o $@
......
......@@ -3,6 +3,8 @@ GENLOBJ=genl.o
include ../Config
SHARED_LIBS ?= y
CFLAGS += -fno-strict-aliasing
GENLMODULES :=
GENLMODULES += ctrl.o
......
......@@ -151,5 +151,6 @@ extern int makeargs(char *line, char *argv[], int maxargs);
struct iplink_req;
int iplink_parse(int argc, char **argv, struct iplink_req *req,
char **name, char **type, char **link, char **dev);
char **name, char **type, char **link, char **dev,
int *group);
#endif /* __UTILS_H__ */
......@@ -262,8 +262,11 @@ static int do_tunnels_list(struct ip6_tnl_parm *p)
}
/* skip two lines at the begenning of the file */
fgets(buf, sizeof(buf), fp);
fgets(buf, sizeof(buf), fp);
if (!fgets(buf, sizeof(buf), fp) ||
!fgets(buf, sizeof(buf), fp)) {
fprintf(stderr, "/proc/net/dev read error\n");
return -1;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
char name[IFNAMSIZ];
......
......@@ -278,12 +278,10 @@ int print_linkinfo(const struct sockaddr_nl *who,
fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
if (tb[IFLA_QDISC])
fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
#ifdef IFLA_MASTER
if (tb[IFLA_MASTER]) {
SPRINT_BUF(b1);
fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
}
#endif
if (tb[IFLA_OPERSTATE])
print_operstate(fp, *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE]));
......
......@@ -51,7 +51,7 @@ void iplink_usage(void)
fprintf(stderr, " type TYPE [ ARGS ]\n");
fprintf(stderr, " ip link delete DEV type TYPE [ ARGS ]\n");
fprintf(stderr, "\n");
fprintf(stderr, " ip link set DEVICE [ { up | down } ]\n");
fprintf(stderr, " ip link set { dev DEVICE | group DEVGROUP } [ { up | down } ]\n");
} else
fprintf(stderr, "Usage: ip link set DEVICE [ { up | down } ]\n");
......@@ -71,6 +71,8 @@ void iplink_usage(void)
fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n");
fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] ]\n");
fprintf(stderr, " [ rate TXRATE ] ] \n");
fprintf(stderr, " [ master DEVICE ]\n");
fprintf(stderr, " [ nomaster ]\n");
fprintf(stderr, " ip link show [ DEVICE | group GROUP ]\n");
if (iplink_have_newlink()) {
......@@ -244,7 +246,7 @@ int iplink_parse_vf(int vf, int *argcp, char ***argvp,
int iplink_parse(int argc, char **argv, struct iplink_req *req,
char **name, char **type, char **link, char **dev)
char **name, char **type, char **link, char **dev, int *group)
{
int ret, len;
char abuf[32];
......@@ -253,6 +255,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
int netns = -1;
int vf = -1;
*group = -1;
ret = argc;
while (argc > 0) {
......@@ -361,7 +364,18 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
if (len < 0)
return -1;
addattr_nest_end(&req->n, vflist);
#ifdef IFF_DYNAMIC
} else if (matches(*argv, "master") == 0) {
int ifindex;
NEXT_ARG();
ifindex = ll_name_to_index(*argv);
if (!ifindex)
invarg("Device does not exist\n", *argv);
addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
&ifindex, 4);
} else if (matches(*argv, "nomaster") == 0) {
int ifindex = 0;
addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
&ifindex, 4);
} else if (matches(*argv, "dynamic") == 0) {
NEXT_ARG();
req->i.ifi_change |= IFF_DYNAMIC;
......@@ -371,7 +385,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
req->i.ifi_flags &= ~IFF_DYNAMIC;
} else
return on_off("dynamic");
#endif
} else if (matches(*argv, "type") == 0) {
NEXT_ARG();
*type = *argv;
......@@ -383,6 +396,12 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
*argv, strlen(*argv));
argc--; argv++;
break;
} else if (strcmp(*argv, "group") == 0) {
NEXT_ARG();
if (*group != -1)
duparg("group", *argv);
if (rtnl_group_a2n(group, *argv))
invarg("Invalid \"group\" value\n", *argv);
} else {
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
......@@ -406,6 +425,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
char *name = NULL;
char *link = NULL;
char *type = NULL;
int group;
struct link_util *lu = NULL;
struct iplink_req req;
int ret;
......@@ -417,12 +437,38 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
req.n.nlmsg_type = cmd;
req.i.ifi_family = preferred_family;
ret = iplink_parse(argc, argv, &req, &name, &type, &link, &dev);
ret = iplink_parse(argc, argv, &req, &name, &type, &link, &dev, &group);
if (ret < 0)
return ret;
argc -= ret;
argv += ret;
if (group != -1) {
if (dev)
addattr_l(&req.n, sizeof(req), IFLA_GROUP,
&group, sizeof(group));
else {
if (argc) {
fprintf(stderr, "Garbage instead of arguments "
"\"%s ...\". Try \"ip link "
"help\".\n", *argv);
return -1;
}
if (flags & NLM_F_CREATE) {
fprintf(stderr, "group cannot be used when "
"creating devices.\n");
return -1;
}
req.i.ifi_index = 0;
addattr32(&req.n, sizeof(req), IFLA_GROUP, group);
if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
exit(2);
return 0;
}
}
ll_init_map(&rth);
if (type) {
......@@ -779,7 +825,6 @@ static int do_set(int argc, char **argv)
flags |= IFF_NOARP;
} else
return on_off("noarp");
#ifdef IFF_DYNAMIC
} else if (matches(*argv, "dynamic") == 0) {
NEXT_ARG();
mask |= IFF_DYNAMIC;
......@@ -789,7 +834,6 @@ static int do_set(int argc, char **argv)
flags &= ~IFF_DYNAMIC;
} else
return on_off("dynamic");
#endif
} else {
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
......
......@@ -128,14 +128,15 @@ void read_igmp(struct ma_info **result_p)
if (!fp)
return;
memset(&m, 0, sizeof(m));
fgets(buf, sizeof(buf), fp);
if (!fgets(buf, sizeof(buf), fp))
return;
m.addr.family = AF_INET;
m.addr.bitlen = 32;
m.addr.bytelen = 4;
while (fgets(buf, sizeof(buf), fp)) {
struct ma_info *ma = malloc(sizeof(m));
struct ma_info *ma;
if (buf[0] != '\t') {
sscanf(buf, "%d%s", &m.index, m.name);
......
......@@ -58,7 +58,8 @@ static void read_viftable(void)
if (!fp)
return;
fgets(buf, sizeof(buf), fp);
if (!fgets(buf, sizeof(buf), fp))
return;
while (fgets(buf, sizeof(buf), fp)) {
int vifi;
......@@ -83,7 +84,8 @@ static void read_mroute_list(FILE *ofp)
if (!fp)
return;
fgets(buf, sizeof(buf), fp);
if (!fgets(buf, sizeof(buf), fp))
return;
while (fgets(buf, sizeof(buf), fp)) {
inet_prefix maddr, msrc;
......
......@@ -277,12 +277,10 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
ci->ndm_confirmed/hz, ci->ndm_updated/hz);
}
#ifdef NDA_PROBES
if (tb[NDA_PROBES] && show_stats) {
__u32 p = *(__u32 *) RTA_DATA(tb[NDA_PROBES]);
fprintf(fp, " probes %u", p);
}
#endif
if (r->ndm_state) {
int nud = r->ndm_state;
......
......@@ -478,12 +478,11 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (ci->rta_lastuse != 0)
fprintf(fp, " age %dsec", ci->rta_lastuse/hz);
}
#ifdef RTNETLINK_HAVE_PEERINFO
if (ci->rta_id)
fprintf(fp, " ipid 0x%04x", ci->rta_id);
if (ci->rta_ts || ci->rta_tsage)
fprintf(fp, " ts 0x%x tsage %dsec", ci->rta_ts, ci->rta_tsage);
#endif
fprintf(fp, " ts 0x%x tsage %dsec",
ci->rta_ts, ci->rta_tsage);
}
} else if (r->rtm_family == AF_INET6) {
struct rta_cacheinfo *ci = NULL;
......@@ -792,7 +791,6 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
if (get_unsigned(&mtu, *argv, 0))
invarg("\"mtu\" value is invalid\n", *argv);
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
#ifdef RTAX_HOPLIMIT
} else if (strcmp(*argv, "hoplimit") == 0) {
unsigned hoplimit;
NEXT_ARG();
......@@ -803,8 +801,6 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
if (get_unsigned(&hoplimit, *argv, 0))
invarg("\"hoplimit\" value is invalid\n", *argv);
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit);
#endif
#ifdef RTAX_ADVMSS
} else if (strcmp(*argv, "advmss") == 0) {
unsigned mss;
NEXT_ARG();
......@@ -815,8 +811,6 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
if (get_unsigned(&mss, *argv, 0))
invarg("\"mss\" value is invalid\n", *argv);
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_ADVMSS, mss);
#endif
#ifdef RTAX_REORDERING
} else if (matches(*argv, "reordering") == 0) {
unsigned reord;
NEXT_ARG();
......@@ -827,7 +821,6 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
if (get_unsigned(&reord, *argv, 0))
invarg("\"reordering\" value is invalid\n", *argv);
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord);
#endif
} else if (strcmp(*argv, "rtt") == 0) {
unsigned rtt;
NEXT_ARG();
......
......@@ -407,8 +407,12 @@ static int do_tunnels_list(struct ip_tunnel_parm *p)
return -1;
}
fgets(buf, sizeof(buf), fp);
fgets(buf, sizeof(buf), fp);
/* skip header lines */
if (!fgets(buf, sizeof(buf), fp) ||
!fgets(buf, sizeof(buf), fp)) {
fprintf(stderr, "/proc/net/dev read error\n");
return -1;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
int index, type;
......
......@@ -854,6 +854,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_WILDRECV, "wildrecv");
XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_ICMP, "icmp");
XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_AF_UNSPEC, "af-unspec");
XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_ALIGN4, "align4");
if (flags)
fprintf(fp, "%x", flags);
}
......@@ -980,6 +981,7 @@ void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo,
fprintf(fp, "flag ");
XFRM_FLAG_PRINT(fp, flags, XFRM_POLICY_LOCALOK, "localok");
XFRM_FLAG_PRINT(fp, flags, XFRM_POLICY_ICMP, "icmp");
if (flags)
fprintf(fp, "%x", flags);
}
......
......@@ -30,6 +30,7 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
char *name, *type, *link, *dev;
int err, len;
struct rtattr * data;
int group;
if (strcmp(argv[0], "peer") != 0) {
usage();
......@@ -42,7 +43,7 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
hdr->nlmsg_len += sizeof(struct ifinfomsg);
err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr,
&name, &type, &link, &dev);
&name, &type, &link, &dev, &group);
if (err < 0)
return err;
......
......@@ -77,7 +77,7 @@ static void usage(void)
//fprintf(stderr, "PRIORITY - priority value(default=0)\n");
fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
fprintf(stderr, "FLAG := [ localok ]\n");
fprintf(stderr, "FLAG := [ localok | icmp ]\n");
fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] | [ limit LIMIT ]\n");
fprintf(stderr, "LIMIT := [ [time-soft|time-hard|time-use-soft|time-use-hard] SECONDS ] |\n");
......@@ -156,6 +156,8 @@ static int xfrm_policy_flag_parse(__u8 *flags, int *argcp, char ***argvp)
while (1) {
if (strcmp(*argv, "localok") == 0)
*flags |= XFRM_POLICY_LOCALOK;
else if (strcmp(*argv, "icmp") == 0)
*flags |= XFRM_POLICY_ICMP;
else {
PREV_ARG(); /* back track */
break;
......
......@@ -84,7 +84,7 @@ static void usage(void)
//fprintf(stderr, "REQID - number(default=0)\n");
fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
fprintf(stderr, "FLAG := [ noecn | decap-dscp | nopmtudisc | wildrecv | icmp | af-unspec ]\n");
fprintf(stderr, "FLAG := [ noecn | decap-dscp | nopmtudisc | wildrecv | icmp | af-unspec | align4 ]\n");
fprintf(stderr, "ENCAP := ENCAP-TYPE SPORT DPORT OADDR\n");
fprintf(stderr, "ENCAP-TYPE := espinudp | espinudp-nonike\n");
......@@ -216,6 +216,8 @@ static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
*flags |= XFRM_STATE_ICMP;
else if (strcmp(*argv, "af-unspec") == 0)
*flags |= XFRM_STATE_AF_UNSPEC;
else if (strcmp(*argv, "align4") == 0)
*flags |= XFRM_STATE_ALIGN4;
else {
PREV_ARG(); /* back track */
break;
......
......@@ -36,19 +36,13 @@ static struct {
} llproto_names[] = {
__PF(LOOP,loop)
__PF(PUP,pup)
#ifdef ETH_P_PUPAT
__PF(PUPAT,pupat)
#endif
__PF(IP,ip)
__PF(X25,x25)
__PF(ARP,arp)
__PF(BPQ,bpq)
#ifdef ETH_P_IEEEPUP
__PF(IEEEPUP,ieeepup)
#endif
#ifdef ETH_P_IEEEPUPAT
__PF(IEEEPUPAT,ieeepupat)
#endif
__PF(DEC,dec)
__PF(DNA_DL,dna_dl)
__PF(DNA_RC,dna_rc)
......@@ -62,19 +56,10 @@ __PF(ATALK,atalk)
__PF(AARP,aarp)
__PF(IPX,ipx)
__PF(IPV6,ipv6)
#ifdef ETH_P_PPP_DISC
__PF(PPP_DISC,ppp_disc)
#endif
#ifdef ETH_P_PPP_SES
__PF(PPP_SES,ppp_ses)
#endif
#ifdef ETH_P_ATMMPOA
__PF(ATMMPOA,atmmpoa)
#endif
#ifdef ETH_P_ATMFATE
__PF(ATMFATE,atmfate)
#endif
__PF(802_3,802_3)
__PF(AX25,ax25)
__PF(ALL,all)
......@@ -90,9 +75,7 @@ __PF(TR_802_2,tr_802_2)
__PF(MOBITEX,mobitex)
__PF(CONTROL,control)
__PF(IRDA,irda)
#ifdef ETH_P_ECONET
__PF(ECONET,econet)
#endif
__PF(TIPC,tipc)
__PF(AOE,aoe)
......
......@@ -55,8 +55,10 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
.RI "[ " ARGS " ]"
.ti -8
.BI "ip link set " DEVICE
.RB "{ " up " | " down " | " arp " { " on " | " off " } |"
.BR "ip link set " {
.IR DEVICE " | "
.BI "group " GROUP
.RB "} { " up " | " down " | " arp " { " on " | " off " } |"
.br
.BR promisc " { " on " | " off " } |"
.br
......@@ -95,7 +97,12 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
.B qos
.IR VLAN-QOS " ] ] ["
.B rate
.IR TXRATE " ]"
.IR TXRATE " ] |"
.br
.B master
.IR DEVICE
.br
.B nomaster
.ti -8
.B ip link show
......@@ -929,6 +936,13 @@ specifies network device to operate on. When configuring SR-IOV Virtual Fuction
(VF) devices, this keyword should specify the associated Physical Function (PF)
device.
.TP
.BI group " GROUP "
.I GROUP
has a dual role: If both group and dev are present, then move the device to the
specified group. If only a group is specified, then the command operates on
all devices in that group.
.TP
.BR up " and " down
change the state of the device to
......@@ -995,6 +1009,12 @@ move the device to the network namespace associated with the process
.BI alias " NAME"
give the device a symbolic name for easy reference.
.TP
.BI group " GROUP"
specify the group the device belongs to.
The available groups are listed in file
.BR "/etc/iproute2/group" .
.TP
.BI vf " NUM"
specify a Virtual Function device to be configured. The associated PF device
......@@ -1040,6 +1060,14 @@ Setting this parameter to 0 disables rate limiting. The
parameter must be specified.
.in -8
.TP
.BI master " DEVICE"
set master device of the device (enslave device).
.TP
.BI nomaster
unset master device of the device (release device).
.PP
.B Warning:
If multiple parameter changes are requested,
......
......@@ -535,7 +535,7 @@ int main(int argc, char *argv[])
}
if (getenv("RTACCT_HISTORY"))
snprintf(hist_name, sizeof(hist_name), getenv("RTACCT_HISTORY"));
snprintf(hist_name, sizeof(hist_name), "%s", getenv("RTACCT_HISTORY"));
else
sprintf(hist_name, "/tmp/.rtacct.u%d", getuid());
......@@ -563,7 +563,10 @@ int main(int argc, char *argv[])
exit(-1);
}
if (stb.st_size != sizeof(*hist_db))
write(fd, kern_db, sizeof(*hist_db));
if (write(fd, kern_db, sizeof(*hist_db)) < 0) {
perror("rtacct: write history file");
exit(-1);
}
hist_db = mmap(NULL, sizeof(*hist_db),
PROT_READ|PROT_WRITE,
......
......@@ -15,6 +15,8 @@ TCMODULES += q_cbq.o
TCMODULES += q_rr.o
TCMODULES += q_multiq.o
TCMODULES += q_netem.o
TCMODULES += q_choke.o
TCMODULES += q_sfb.o
TCMODULES += f_rsvp.o
TCMODULES += f_u32.o
TCMODULES += f_route.o
......@@ -43,6 +45,7 @@ TCMODULES += em_nbyte.o
TCMODULES += em_cmp.o
TCMODULES += em_u32.o
TCMODULES += em_meta.o
TCMODULES += q_mqprio.o
TCSO :=
ifeq ($(TC_CONFIG_ATM),y)
......
......@@ -432,7 +432,8 @@ static int parse_ip6_class(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
key = htonl(key);
mask = htonl(mask);
if (res = pack_key(sel, key, mask, off, offmask) < 0)
res = pack_key(sel, key, mask, off, offmask);
if (res < 0)
return -1;
*argc_p = argc;
......
/*
* q_choke.c CHOKE.
*
* 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.
*
* Authors: Stephen Hemminger <shemminger@vyatta.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "utils.h"
#include "tc_util.h"
#include "tc_red.h"
static void explain(void)
{
fprintf(stderr, "Usage: ... choke limit PACKETS bandwidth KBPS [ecn]\n");
fprintf(stderr, " [ min PACKETS ] [ max PACKETS ] [ burst PACKETS ]\n");
}
static int choke_parse_opt(struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n)
{
struct tc_red_qopt opt;
unsigned burst = 0;
unsigned avpkt = 1000;
double probability = 0.02;
unsigned rate = 0;
int ecn_ok = 0;
int wlog;
__u8 sbuf[256];
struct rtattr *tail;
memset(&opt, 0, sizeof(opt));
while (argc > 0) {
if (strcmp(*argv, "limit") == 0) {
NEXT_ARG();
if (get_unsigned(&opt.limit, *argv, 0)) {
fprintf(stderr, "Illegal \"limit\"\n");
return -1;
}
} else if (strcmp(*argv, "bandwidth") == 0) {
NEXT_ARG();
if (get_rate(&rate, *argv)) {
fprintf(stderr, "Illegal \"bandwidth\"\n");
return -1;
}
} else if (strcmp(*argv, "ecn") == 0) {
ecn_ok = 1;
} else if (strcmp(*argv, "min") == 0) {
NEXT_ARG();
if (get_unsigned(&opt.qth_min, *argv, 0)) {
fprintf(stderr, "Illegal \"min\"\n");
return -1;
}
} else if (strcmp(*argv, "max") == 0) {
NEXT_ARG();
if (get_unsigned(&opt.qth_max, *argv, 0)) {
fprintf(stderr, "Illegal \"max\"\n");
return -1;
}
} else if (strcmp(*argv, "burst") == 0) {
NEXT_ARG();
if (get_unsigned(&burst, *argv, 0)) {
fprintf(stderr, "Illegal \"burst\"\n");
return -1;
}
} else if (strcmp(*argv, "avpkt") == 0) {
NEXT_ARG();
if (get_size(&avpkt, *argv)) {
fprintf(stderr, "Illegal \"avpkt\"\n");
return -1;
}
} else if (strcmp(*argv, "probability") == 0) {
NEXT_ARG();
if (sscanf(*argv, "%lg", &probability) != 1) {
fprintf(stderr, "Illegal \"probability\"\n");
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
explain();
return -1;
}
argc--; argv++;
}
if (!rate || !opt.limit) {
fprintf(stderr, "Required parameter (bandwidth, limit) is missing\n");
return -1;
}
/* Compute default min/max thresholds based on
Sally Floyd's recommendations:
http://www.icir.org/floyd/REDparameters.txt
*/
if (!opt.qth_max)
opt.qth_max = opt.limit / 4;
if (!opt.qth_min)
opt.qth_min = opt.qth_max / 3;
if (!burst)
burst = (2 * opt.qth_min + opt.qth_max) / 3;
if (opt.qth_max > opt.limit) {
fprintf(stderr, "\"max\" is larger than \"limit\"\n");
return -1;
}
if (opt.qth_min > opt.qth_min) {
fprintf(stderr, "\"min\" is not smaller than \"max\"\n");
return -1;
}
wlog = tc_red_eval_ewma(opt.qth_min*avpkt, burst, avpkt);
if (wlog < 0) {
fprintf(stderr, "CHOKE: failed to calculate EWMA constant.\n");
return -1;
}
if (wlog >= 10)
fprintf(stderr, "CHOKE: WARNING. Burst %d seems to be to large.\n", burst);
opt.Wlog = wlog;
wlog = tc_red_eval_P(opt.qth_min*avpkt, opt.qth_max*avpkt, probability);
if (wlog < 0) {
fprintf(stderr, "CHOKE: failed to calculate probability.\n");
return -1;
}
opt.Plog = wlog;
wlog = tc_red_eval_idle_damping(opt.Wlog, avpkt, rate, sbuf);
if (wlog < 0) {
fprintf(stderr, "CHOKE: failed to calculate idle damping table.\n");
return -1;
}
opt.Scell_log = wlog;
if (ecn_ok)
opt.flags |= TC_RED_ECN;
tail = NLMSG_TAIL(n);
addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
addattr_l(n, 1024, TCA_CHOKE_PARMS, &opt, sizeof(opt));
addattr_l(n, 1024, TCA_CHOKE_STAB, sbuf, 256);
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
return 0;
}
static int choke_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
struct rtattr *tb[TCA_CHOKE_STAB+1];
const struct tc_red_qopt *qopt;
if (opt == NULL)
return 0;
parse_rtattr_nested(tb, TCA_CHOKE_STAB, opt);
if (tb[TCA_CHOKE_PARMS] == NULL)
return -1;
qopt = RTA_DATA(tb[TCA_CHOKE_PARMS]);
if (RTA_PAYLOAD(tb[TCA_CHOKE_PARMS]) < sizeof(*qopt))
return -1;
fprintf(f, "limit %up min %up max %up ",
qopt->limit, qopt->qth_min, qopt->qth_max);
if (qopt->flags & TC_RED_ECN)
fprintf(f, "ecn ");
if (show_details) {
fprintf(f, "ewma %u Plog %u Scell_log %u",
qopt->Wlog, qopt->Plog, qopt->Scell_log);
}
return 0;
}
static int choke_print_xstats(struct qdisc_util *qu, FILE *f,
struct rtattr *xstats)
{
struct tc_choke_xstats *st;
if (xstats == NULL)
return 0;
if (RTA_PAYLOAD(xstats) < sizeof(*st))
return -1;
st = RTA_DATA(xstats);
fprintf(f, " marked %u early %u pdrop %u other %u matched %u",
st->marked, st->early, st->pdrop, st->other, st->matched);
return 0;
}
struct qdisc_util choke_qdisc_util = {
.id = "choke",
.parse_qopt = choke_parse_opt,
.print_qopt = choke_print_opt,
.print_xstats = choke_print_xstats,
};
/*
* q_mqprio.c MQ prio qdisc
*
* 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.
*
* Author: John Fastabend, <john.r.fastabend@intel.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "utils.h"
#include "tc_util.h"
static void explain(void)
{
fprintf(stderr, "Usage: ... mqprio [num_tc NUMBER] [map P0 P1 ...]\n");
fprintf(stderr, " [offset txq0 txq1 ...] ");
fprintf(stderr, "[count cnt0,cnt1 ...] [hw 1|0]\n");
}
static int mqprio_parse_opt(struct qdisc_util *qu, int argc,
char **argv, struct nlmsghdr *n)
{
int idx;
struct tc_mqprio_qopt opt = {
8,
{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 1, 3, 3, 3, 3},
1,
};
while (argc > 0) {
idx = 0;
if (strcmp(*argv, "num_tc") == 0) {
NEXT_ARG();
if (get_u8(&opt.num_tc, *argv, 10)) {
fprintf(stderr, "Illegal \"num_tc\"\n");
return -1;
}
} else if (strcmp(*argv, "map") == 0) {
while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) {
NEXT_ARG();
if (get_u8(&opt.prio_tc_map[idx], *argv, 10)) {
PREV_ARG();
break;
}
idx++;
}
for ( ; idx < TC_QOPT_MAX_QUEUE; idx++)
opt.prio_tc_map[idx] = 0;
} else if (strcmp(*argv, "offset") == 0) {
while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) {
NEXT_ARG();
if (get_u16(&opt.offset[idx], *argv, 10)) {
PREV_ARG();
break;
}
idx++;
}
} else if (strcmp(*argv, "count") == 0) {
while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) {
NEXT_ARG();
if (get_u16(&opt.count[idx], *argv, 10)) {
PREV_ARG();
break;
}
idx++;
}
} else if (strcmp(*argv, "hw") == 0) {
NEXT_ARG();
if (get_u8(&opt.hw, *argv, 10)) {
fprintf(stderr, "Illegal \"hw\"\n");
return -1;
}
idx++;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "Unknown argument\n");
return -1;
}
argc--; argv++;
}
addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
return 0;
}
int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
int i;
struct tc_mqprio_qopt *qopt;
if (opt == NULL)
return 0;
qopt = RTA_DATA(opt);
fprintf(f, " tc %u map ", qopt->num_tc);
for (i = 0; i <= TC_PRIO_MAX; i++)
fprintf(f, "%d ", qopt->prio_tc_map[i]);
fprintf(f, "\n queues:");
for (i = 0; i < qopt->num_tc; i++)
fprintf(f, "(%i:%i) ", qopt->offset[i],
qopt->offset[i] + qopt->count[i] - 1);
return 0;
}
struct qdisc_util mqprio_qdisc_util = {
.id = "mqprio",
.parse_qopt = mqprio_parse_opt,
.print_qopt = mqprio_print_opt,
};
......@@ -6,7 +6,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Authors: Stephen Hemminger <shemminger@osdl.org>
* Authors: Stephen Hemminger <shemminger@linux-foundation.org>
*
*/
......
/*
* q_sfb.c Stochastic Fair Blue.
*
* 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.
*
* Authors: Juliusz Chroboczek <jch@pps.jussieu.fr>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "utils.h"
#include "tc_util.h"
static void explain(void)
{
fprintf(stderr,
"Usage: ... sfb [ rehash SECS ] [ db SECS ]\n"
" [ limit PACKETS ] [ max PACKETS ] [ target PACKETS ]\n"
" [ increment FLOAT ] [ decrement FLOAT ]\n"
" [ penalty_rate PPS ] [ penalty_burst PACKETS ]\n");
}
static int get_prob(__u32 *val, const char *arg)
{
double d;
char *ptr;
if (!arg || !*arg)
return -1;
d = strtod(arg, &ptr);
if (!ptr || ptr == arg || d < 0.0 || d > 1.0)
return -1;
*val = (__u32)(d * SFB_MAX_PROB + 0.5);
return 0;
}
static int sfb_parse_opt(struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n)
{
struct tc_sfb_qopt opt;
struct rtattr *tail;
memset(&opt, 0, sizeof(opt));
opt.rehash_interval = 600*1000;
opt.warmup_time = 60*1000;
opt.penalty_rate = 10;
opt.penalty_burst = 20;
opt.increment = (SFB_MAX_PROB + 1000) / 2000;
opt.decrement = (SFB_MAX_PROB + 10000) / 20000;
while (argc > 0) {
if (strcmp(*argv, "rehash") == 0) {
NEXT_ARG();
if (get_u32(&opt.rehash_interval, *argv, 0)) {
fprintf(stderr, "Illegal \"rehash\"\n");
return -1;
}
} else if (strcmp(*argv, "db") == 0) {
NEXT_ARG();
if (get_u32(&opt.warmup_time, *argv, 0)) {
fprintf(stderr, "Illegal \"db\"\n");
return -1;
}
} else if (strcmp(*argv, "limit") == 0) {
NEXT_ARG();
if (get_u32(&opt.limit, *argv, 0)) {
fprintf(stderr, "Illegal \"limit\"\n");
return -1;
}
} else if (strcmp(*argv, "max") == 0) {
NEXT_ARG();
if (get_u32(&opt.max, *argv, 0)) {
fprintf(stderr, "Illegal \"max\"\n");
return -1;
}
} else if (strcmp(*argv, "target") == 0) {
NEXT_ARG();
if (get_u32(&opt.bin_size, *argv, 0)) {
fprintf(stderr, "Illegal \"target\"\n");
return -1;
}
} else if (strcmp(*argv, "increment") == 0) {
NEXT_ARG();
if (get_prob(&opt.increment, *argv)) {
fprintf(stderr, "Illegal \"increment\"\n");
return -1;
}
} else if (strcmp(*argv, "decrement") == 0) {
NEXT_ARG();
if (get_prob(&opt.decrement, *argv)) {
fprintf(stderr, "Illegal \"decrement\"\n");
return -1;
}
} else if (strcmp(*argv, "penalty_rate") == 0) {
NEXT_ARG();
if (get_u32(&opt.penalty_rate, *argv, 0)) {
fprintf(stderr, "Illegal \"penalty_rate\"\n");
return -1;
}
} else if (strcmp(*argv, "penalty_burst") == 0) {
NEXT_ARG();
if (get_u32(&opt.penalty_burst, *argv, 0)) {
fprintf(stderr, "Illegal \"penalty_burst\"\n");
return -1;
}
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
explain();
return -1;
}
argc--; argv++;
}
if (opt.max == 0) {
if (opt.bin_size >= 1)
opt.max = (opt.bin_size * 5 + 1) / 4;
else
opt.max = 25;
}
if (opt.bin_size == 0)
opt.bin_size = (opt.max * 4 + 3) / 5;
tail = NLMSG_TAIL(n);
addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
addattr_l(n, 1024, TCA_SFB_PARMS, &opt, sizeof(opt));
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
return 0;
}
static int sfb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
struct rtattr *tb[__TCA_SFB_MAX];
struct tc_sfb_qopt *qopt;
if (opt == NULL)
return 0;
parse_rtattr_nested(tb, TCA_SFB_MAX, opt);
if (tb[TCA_SFB_PARMS] == NULL)
return -1;
qopt = RTA_DATA(tb[TCA_SFB_PARMS]);
if (RTA_PAYLOAD(tb[TCA_SFB_PARMS]) < sizeof(*qopt))
return -1;
fprintf(f,
"limit %d max %d target %d\n"
" increment %.5f decrement %.5f penalty rate %d burst %d "
"(%ums %ums)",
qopt->limit, qopt->max, qopt->bin_size,
(double)qopt->increment / SFB_MAX_PROB,
(double)qopt->decrement / SFB_MAX_PROB,
qopt->penalty_rate, qopt->penalty_burst,
qopt->rehash_interval, qopt->warmup_time);
return 0;
}
static int sfb_print_xstats(struct qdisc_util *qu, FILE *f,
struct rtattr *xstats)
{
struct tc_sfb_xstats *st;
if (xstats == NULL)
return 0;
if (RTA_PAYLOAD(xstats) < sizeof(*st))
return -1;
st = RTA_DATA(xstats);
fprintf(f,
" earlydrop %u penaltydrop %u bucketdrop %u queuedrop %u childdrop %u marked %u\n"
" maxqlen %u maxprob %.5f avgprob %.5f ",
st->earlydrop, st->penaltydrop, st->bucketdrop, st->queuedrop, st->childdrop,
st->marked,
st->maxqlen, (double)st->maxprob / SFB_MAX_PROB,
(double)st->avgprob / SFB_MAX_PROB);
return 0;
}
struct qdisc_util sfb_qdisc_util = {
.id = "sfb",
.parse_qopt = sfb_parse_opt,
.print_qopt = sfb_print_opt,
.print_xstats = sfb_print_xstats,
};
......@@ -26,6 +26,7 @@
static void explain(void)
{
fprintf(stderr, "Usage: ... sfq [ limit NUMBER ] [ perturb SECS ] [ quantum BYTES ]\n");
fprintf(stderr, " [ divisor NUMBER ]\n");
}
static int sfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
......@@ -61,6 +62,13 @@ static int sfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
return -1;
}
ok++;
} else if (strcmp(*argv, "divisor") == 0) {
NEXT_ARG();
if (get_u32(&opt.divisor, *argv, 0)) {
fprintf(stderr, "Illegal \"divisor\"\n");
return -1;
}
ok++;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
......@@ -93,6 +101,7 @@ static int sfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (show_details) {
fprintf(f, "flows %u/%u ", qopt->flows, qopt->divisor);
}
fprintf(f, "divisor %u ", qopt->divisor);
if (qopt->perturb_period)
fprintf(f, "perturb %dsec ", qopt->perturb_period);
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