mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-17 17:59:38 +00:00
Merge branch 'for-2.6.39' of /home/shemminger/iproute2-net-next
Conflicts: include/linux/xfrm.h ip/iplink.c
This commit is contained in:
commit
4d91e4f168
3
Makefile
3
Makefile
@ -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; \
|
||||
|
25
README
25
README
@ -1,15 +1,17 @@
|
||||
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
|
||||
|
15
README.devel
Normal file
15
README.devel
Normal file
@ -0,0 +1,15 @@
|
||||
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]));
|
||||
|
||||
|
58
ip/iplink.c
58
ip/iplink.c
@ -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;
|
||||
|
11
ip/iproute.c
11
ip/iproute.c
@ -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;
|
||||
|
215
tc/q_choke.c
Normal file
215
tc/q_choke.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* 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,
|
||||
};
|
124
tc/q_mqprio.c
Normal file
124
tc/q_mqprio.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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>
|
||||
*
|
||||
*/
|
||||
|
||||
|
200
tc/q_sfb.c
Normal file
200
tc/q_sfb.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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;
|
||||
|
Loading…
Reference in New Issue
Block a user