Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2

This commit is contained in:
Stephen Hemminger 2008-04-08 09:58:50 -05:00
commit e2dc309e4f
15 changed files with 711 additions and 122 deletions

View File

@ -2,7 +2,7 @@
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.> <one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author> Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@ -313,7 +313,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this If the program is interactive, make it output a short notice like this
when it starts in an interactive mode: when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.

View File

@ -19,7 +19,7 @@
#define NF_VERDICT_QMASK 0xffff0000 #define NF_VERDICT_QMASK 0xffff0000
#define NF_VERDICT_QBITS 16 #define NF_VERDICT_QBITS 16
#define NF_QUEUE_NR(x) (((x << NF_VERDICT_QBITS) & NF_VERDICT_QMASK) | NF_QUEUE) #define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE)
/* only for userspace compatibility */ /* only for userspace compatibility */
/* Generic cache responses from hook functions. /* Generic cache responses from hook functions.
@ -37,7 +37,7 @@ enum nf_inet_hooks {
}; };
union nf_inet_addr { union nf_inet_addr {
u_int32_t all[4]; __u32 all[4];
__be32 ip; __be32 ip;
__be32 ip6[4]; __be32 ip6[4];
struct in_addr in; struct in_addr in;

View File

@ -201,8 +201,8 @@ enum
struct tc_u32_key struct tc_u32_key
{ {
__u32 mask; __be32 mask;
__u32 val; __be32 val;
int off; int off;
int offmask; int offmask;
}; };
@ -213,12 +213,12 @@ struct tc_u32_sel
unsigned char offshift; unsigned char offshift;
unsigned char nkeys; unsigned char nkeys;
__u16 offmask; __be16 offmask;
__u16 off; __u16 off;
short offoff; short offoff;
short hoff; short hoff;
__u32 hmask; __be32 hmask;
struct tc_u32_key keys[0]; struct tc_u32_key keys[0];
}; };

View File

@ -26,7 +26,7 @@ typedef __kernel_mqd_t mqd_t;
typedef __kernel_uid_t uid_t; typedef __kernel_uid_t uid_t;
typedef __kernel_gid_t gid_t; typedef __kernel_gid_t gid_t;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__GNUC__)
typedef __kernel_loff_t loff_t; typedef __kernel_loff_t loff_t;
#endif #endif
@ -92,7 +92,7 @@ typedef __u8 uint8_t;
typedef __u16 uint16_t; typedef __u16 uint16_t;
typedef __u32 uint32_t; typedef __u32 uint32_t;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__GNUC__)
typedef __u64 uint64_t; typedef __u64 uint64_t;
typedef __u64 u_int64_t; typedef __u64 u_int64_t;
typedef __s64 int64_t; typedef __s64 int64_t;
@ -154,7 +154,7 @@ typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16; typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32; typedef __u32 __bitwise __le32;
typedef __u32 __bitwise __be32; typedef __u32 __bitwise __be32;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__GNUC__)
typedef __u64 __bitwise __le64; typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64; typedef __u64 __bitwise __be64;
#endif #endif

View File

@ -17,7 +17,7 @@ ip: $(IPOBJ) $(LIBNETLINK) $(LIBUTIL)
rtmon: $(RTMONOBJ) $(LIBNETLINK) rtmon: $(RTMONOBJ) $(LIBNETLINK)
install: all install: all
install -m 0755 -s $(TARGETS) $(DESTDIR)$(SBINDIR) install -m 0755 $(TARGETS) $(DESTDIR)$(SBINDIR)
install -m 0755 $(SCRIPTS) $(DESTDIR)$(SBINDIR) install -m 0755 $(SCRIPTS) $(DESTDIR)$(SBINDIR)
clean: clean:

View File

@ -55,17 +55,17 @@ static void usage(void)
fprintf(stderr, " [ mode { ip6ip6 | ipip6 | any } ]\n"); fprintf(stderr, " [ mode { ip6ip6 | ipip6 | any } ]\n");
fprintf(stderr, " [ remote ADDR local ADDR ] [ dev PHYS_DEV ]\n"); fprintf(stderr, " [ remote ADDR local ADDR ] [ dev PHYS_DEV ]\n");
fprintf(stderr, " [ encaplimit ELIM ]\n"); fprintf(stderr, " [ encaplimit ELIM ]\n");
fprintf(stderr ," [ hoplimit HLIM ] [ tc TC ] [ fl FL ]\n"); fprintf(stderr ," [ hoplimit TTL ] [ tclass TCLASS ] [ flowlabel FLOWLABEL ]\n");
fprintf(stderr, " [ dscp inherit ]\n"); fprintf(stderr, " [ dscp inherit ]\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Where: NAME := STRING\n"); fprintf(stderr, "Where: NAME := STRING\n");
fprintf(stderr, " ADDR := IPV6_ADDRESS\n"); fprintf(stderr, " ADDR := IPV6_ADDRESS\n");
fprintf(stderr, " ELIM := { none | 0..255 }(default=%d)\n", fprintf(stderr, " ELIM := { none | 0..255 }(default=%d)\n",
IPV6_DEFAULT_TNL_ENCAP_LIMIT); IPV6_DEFAULT_TNL_ENCAP_LIMIT);
fprintf(stderr, " HLIM := 0..255 (default=%d)\n", fprintf(stderr, " TTL := 0..255 (default=%d)\n",
DEFAULT_TNL_HOP_LIMIT); DEFAULT_TNL_HOP_LIMIT);
fprintf(stderr, " TC := { 0x0..0xff | inherit }\n"); fprintf(stderr, " TOS := { 0x0..0xff | inherit }\n");
fprintf(stderr, " FL := { 0x0..0xfffff | inherit }\n"); fprintf(stderr, " FLOWLABEL := { 0x0..0xfffff | inherit }\n");
exit(-1); exit(-1);
} }
@ -93,16 +93,16 @@ static void print_tunnel(struct ip6_tnl_parm *p)
printf(" hoplimit %u", p->hop_limit); printf(" hoplimit %u", p->hop_limit);
if (p->flags & IP6_TNL_F_USE_ORIG_TCLASS) if (p->flags & IP6_TNL_F_USE_ORIG_TCLASS)
printf(" tc inherit"); printf(" tclass inherit");
else { else {
__u32 val = ntohl(p->flowinfo & IP6_FLOWINFO_TCLASS); __u32 val = ntohl(p->flowinfo & IP6_FLOWINFO_TCLASS);
printf(" tc 0x%02x", (__u8)(val >> 20)); printf(" tclass 0x%02x", (__u8)(val >> 20));
} }
if (p->flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) if (p->flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
printf(" fl inherit"); printf(" flowlabel inherit");
else else
printf(" fl 0x%05x", ntohl(p->flowinfo & IP6_FLOWINFO_FLOWLABEL)); printf(" flowlabel 0x%05x", ntohl(p->flowinfo & IP6_FLOWINFO_FLOWLABEL));
printf(" (flowinfo 0x%08x)", ntohl(p->flowinfo)); printf(" (flowinfo 0x%08x)", ntohl(p->flowinfo));
@ -161,33 +161,39 @@ static int parse_args(int argc, char **argv, struct ip6_tnl_parm *p)
invarg("invalid ELIM", *argv); invarg("invalid ELIM", *argv);
p->encap_limit = uval; p->encap_limit = uval;
} }
} else if (strcmp(*argv, "hoplimit") == 0) { } else if (strcmp(*argv, "hoplimit") == 0 ||
strcmp(*argv, "ttl") == 0 ||
strcmp(*argv, "hlim") == 0) {
__u8 uval; __u8 uval;
NEXT_ARG(); NEXT_ARG();
if (get_u8(&uval, *argv, 0)) if (get_u8(&uval, *argv, 0))
invarg("invalid HLIM", *argv); invarg("invalid TTL", *argv);
p->hop_limit = uval; p->hop_limit = uval;
} else if (strcmp(*argv, "tc") == 0) { } else if (strcmp(*argv, "tclass") == 0 ||
strcmp(*argv, "tc") == 0 ||
strcmp(*argv, "tos") == 0 ||
matches(*argv, "dsfield") == 0) {
__u8 uval; __u8 uval;
NEXT_ARG(); NEXT_ARG();
if (strcmp(*argv, "inherit") == 0) if (strcmp(*argv, "inherit") == 0)
p->flags |= IP6_TNL_F_USE_ORIG_TCLASS; p->flags |= IP6_TNL_F_USE_ORIG_TCLASS;
else { else {
if (get_u8(&uval, *argv, 16)) if (get_u8(&uval, *argv, 16))
invarg("invalid TC", *argv); invarg("invalid TClass", *argv);
p->flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; p->flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS;
p->flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; p->flags &= ~IP6_TNL_F_USE_ORIG_TCLASS;
} }
} else if (strcmp(*argv, "fl") == 0) { } else if (strcmp(*argv, "flowlabel") == 0 ||
strcmp(*argv, "fl") == 0) {
__u32 uval; __u32 uval;
NEXT_ARG(); NEXT_ARG();
if (strcmp(*argv, "inherit") == 0) if (strcmp(*argv, "inherit") == 0)
p->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; p->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
else { else {
if (get_u32(&uval, *argv, 16)) if (get_u32(&uval, *argv, 16))
invarg("invalid FL", *argv); invarg("invalid Flowlabel", *argv);
if (uval > 0xFFFFF) if (uval > 0xFFFFF)
invarg("invalid FL", *argv); invarg("invalid Flowlabel", *argv);
p->flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; p->flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL;
p->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; p->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
} }

View File

@ -20,6 +20,7 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/errno.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <string.h> #include <string.h>
@ -114,7 +115,20 @@ void print_link_flags(FILE *fp, unsigned flags, unsigned mdown)
fprintf(fp, "> "); fprintf(fp, "> ");
} }
void print_queuelen(char *name) static const char *oper_states[] = {
"UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN",
"TESTING", "DORMANT", "UP"
};
static void print_operstate(FILE *f, __u8 state)
{
if (state >= sizeof(oper_states)/sizeof(oper_states[0]))
fprintf(f, "state %#x ", state);
else
fprintf(f, "state %s ", oper_states[state]);
}
static void print_queuelen(FILE *f, const char *name)
{ {
struct ifreq ifr; struct ifreq ifr;
int s; int s;
@ -126,14 +140,14 @@ void print_queuelen(char *name)
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, name); strcpy(ifr.ifr_name, name);
if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) { if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) {
perror("SIOCGIFXQLEN"); fprintf(f, "ioctl(SIOCGIFXQLEN) failed: %s\n", strerror(errno));
close(s); close(s);
return; return;
} }
close(s); close(s);
if (ifr.ifr_qlen) if (ifr.ifr_qlen)
printf("qlen %d", ifr.ifr_qlen); fprintf(f, "qlen %d", ifr.ifr_qlen);
} }
static void print_linktype(FILE *fp, struct rtattr *tb) static void print_linktype(FILE *fp, struct rtattr *tb)
@ -233,8 +247,11 @@ int print_linkinfo(const struct sockaddr_nl *who,
fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
} }
#endif #endif
if (tb[IFLA_OPERSTATE])
print_operstate(fp, *(__u8 *)RTA_DATA(tb[IFLA_OPERSTATE]));
if (filter.showqueue) if (filter.showqueue)
print_queuelen((char*)RTA_DATA(tb[IFLA_IFNAME])); print_queuelen(fp, (char*)RTA_DATA(tb[IFLA_IFNAME]));
if (!filter.family || filter.family == AF_PACKET) { if (!filter.family || filter.family == AF_PACKET) {
SPRINT_BUF(b1); SPRINT_BUF(b1);
@ -514,7 +531,7 @@ struct nlmsg_list
struct nlmsghdr h; struct nlmsghdr h;
}; };
int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp) static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
{ {
for ( ;ainfo ; ainfo = ainfo->next) { for ( ;ainfo ; ainfo = ainfo->next) {
struct nlmsghdr *n = &ainfo->h; struct nlmsghdr *n = &ainfo->h;
@ -557,7 +574,7 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
return 0; return 0;
} }
int ipaddr_list_or_flush(int argc, char **argv, int flush) static int ipaddr_list_or_flush(int argc, char **argv, int flush)
{ {
struct nlmsg_list *linfo = NULL; struct nlmsg_list *linfo = NULL;
struct nlmsg_list *ainfo = NULL; struct nlmsg_list *ainfo = NULL;
@ -795,7 +812,7 @@ void ipaddr_reset_filter(int oneline)
filter.oneline = oneline; filter.oneline = oneline;
} }
int default_scope(inet_prefix *lcl) static int default_scope(inet_prefix *lcl)
{ {
if (lcl->family == AF_INET) { if (lcl->family == AF_INET) {
if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127) if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127)
@ -804,7 +821,7 @@ int default_scope(inet_prefix *lcl)
return 0; return 0;
} }
int ipaddr_modify(int cmd, int flags, int argc, char **argv) static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
{ {
struct { struct {
struct nlmsghdr n; struct nlmsghdr n;

View File

@ -171,7 +171,8 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
} else if (strcmp(*argv, "dev") == 0) { } else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG(); NEXT_ARG();
strncpy(medium, *argv, IFNAMSIZ-1); strncpy(medium, *argv, IFNAMSIZ-1);
} else if (strcmp(*argv, "ttl") == 0) { } else if (strcmp(*argv, "ttl") == 0 ||
strcmp(*argv, "hoplimit") == 0) {
unsigned uval; unsigned uval;
NEXT_ARG(); NEXT_ARG();
if (strcmp(*argv, "inherit") != 0) { if (strcmp(*argv, "inherit") != 0) {
@ -182,6 +183,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
p->iph.ttl = uval; p->iph.ttl = uval;
} }
} else if (strcmp(*argv, "tos") == 0 || } else if (strcmp(*argv, "tos") == 0 ||
strcmp(*argv, "tclass") == 0 ||
matches(*argv, "dsfield") == 0) { matches(*argv, "dsfield") == 0) {
__u32 uval; __u32 uval;
NEXT_ARG(); NEXT_ARG();

View File

@ -278,9 +278,9 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
.BR "ip tunnel" " { " add " | " change " | " del " | " show " }" .BR "ip tunnel" " { " add " | " change " | " del " | " show " }"
.RI "[ " NAME " ]" .RI "[ " NAME " ]"
.br .br
.RB "[ " mode " { " ipip " | " gre " | " sit " } ]" .RB "[ " mode
.br .IR MODE " ] [ "
.RB "[ " remote .B remote
.IR ADDR " ] [ " .IR ADDR " ] [ "
.B local .B local
.IR ADDR " ]" .IR ADDR " ]"
@ -289,14 +289,24 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
.IR KEY " ] [ " .IR KEY " ] [ "
.RB "[" i "|" o "]" csum " ] ]" .RB "[" i "|" o "]" csum " ] ]"
.br .br
.RB "[ " encaplimit
.IR ELIM " ]"
.RB "[ " ttl .RB "[ " ttl
.IR TTL " ] [ " .IR TTL " ]"
.B tos
.IR TOS " ] [ "
.RB "[" no "]" pmtudisc " ]"
.br .br
.RB "[ " tos
.IR TOS " ] [ "
.B flowlabel
.IR FLOWLABEL " ]"
.br
.RB "[ [" no "]" pmtudisc " ]"
.RB "[ " dev .RB "[ " dev
.IR PHYS_DEV " ]" .IR PHYS_DEV " ]"
.RB "[ " "dscp inherit" " ]"
.ti -8
.IR MODE " := "
.RB " { " ipip " | " gre " | " sit " | " isatap " | " ip6ip6 " | " ipip6 " | " any " }"
.ti -8 .ti -8
.IR ADDR " := { " IP_ADDRESS " |" .IR ADDR " := { " IP_ADDRESS " |"
@ -306,6 +316,12 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
.IR TOS " := { " NUMBER " |" .IR TOS " := { " NUMBER " |"
.BR inherit " }" .BR inherit " }"
.ti -8
.IR ELIM " := {
.BR none " | "
.IR 0 ".." 255 " }"
.ti -8
.ti -8 .ti -8
.IR TTL " := { " 1 ".." 255 " | " .IR TTL " := { " 1 ".." 255 " | "
.BR inherit " }" .BR inherit " }"
@ -335,6 +351,313 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
.ti -8 .ti -8
.BR "ip monitor" " [ " all " |" .BR "ip monitor" " [ " all " |"
.IR LISTofOBJECTS " ]" .IR LISTofOBJECTS " ]"
.ti -8
.BR "ip xfrm"
.IR XFRM_OBJECT " { " COMMAND " }"
.ti -8
.IR XFRM_OBJECT " := { " state " | " policy " | " monitor " } "
.ti -8
.BR "ip xfrm state " { " add " | " update " } "
.IR ID " [ "
.IR XFRM_OPT " ] "
.RB " [ " mode
.IR MODE " ] "
.br
.RB " [ " reqid
.IR REQID " ] "
.RB " [ " seq
.IR SEQ " ] "
.RB " [ " replay-window
.IR SIZE " ] "
.br
.RB " [ " flag
.IR FLAG-LIST " ] "
.RB " [ " encap
.IR ENCAP " ] "
.RB " [ " sel
.IR SELECTOR " ] "
.br
.RB " [ "
.IR LIMIT-LIST " ] "
.ti -8
.BR "ip xfrm state allocspi "
.IR ID
.RB " [ " mode
.IR MODE " ] "
.RB " [ " reqid
.IR REQID " ] "
.RB " [ " seq
.IR SEQ " ] "
.RB " [ " min
.IR SPI
.B max
.IR SPI " ] "
.ti -8
.BR "ip xfrm state" " { " delete " | " get " } "
.IR ID
.ti -8
.BR "ip xfrm state" " { " deleteall " | " list " } [ "
.IR ID " ] "
.RB " [ " mode
.IR MODE " ] "
.br
.RB " [ " reqid
.IR REQID " ] "
.RB " [ " flag
.IR FLAG_LIST " ] "
.ti -8
.BR "ip xfrm state flush" " [ " proto
.IR XFRM_PROTO " ] "
.ti -8
.BR "ip xfrm state count"
.ti -8
.IR ID " := "
.RB " [ " src
.IR ADDR " ] "
.RB " [ " dst
.IR ADDR " ] "
.RB " [ " proto
.IR XFRM_PROTO " ] "
.RB " [ " spi
.IR SPI " ] "
.ti -8
.IR XFRM_PROTO " := "
.RB " [ " esp " | " ah " | " comp " | " route2 " | " hao " ] "
.ti -8
.IR MODE " := "
.RB " [ " transport " | " tunnel " | " ro " | " beet " ] "
.b (default=transport)
.ti -8
.IR FLAG-LIST " := "
.RI " [ " FLAG-LIST " ] " FLAG
.ti -8
.IR FLAG " := "
.RB " [ " noecn " | " decap-dscp " | " wildrecv " ] "
.ti -8
.IR ENCAP " := " ENCAP-TYPE " " SPORT " " DPORT " " OADDR
.ti -8
.IR ENCAP-TYPE " := "
.B espinudp
.RB " | "
.B espinudp-nonike
.ti -8
.IR ALGO-LIST " := [ "
.IR ALGO-LIST " ] | [ "
.IR ALGO " ] "
.ti -8
.IR ALGO " := "
.IR ALGO_TYPE
.IR ALGO_NAME
.IR ALGO_KEY
.ti -8
.IR ALGO_TYPE " := "
.RB " [ " enc " | " auth " | " comp " ] "
.ti -8
.IR SELECTOR " := "
.B src
.IR ADDR "[/" PLEN "]"
.B dst
.IR ADDR "[/" PLEN "]"
.RI " [ " UPSPEC " ] "
.RB " [ " dev
.IR DEV " ] "
.ti -8
.IR UPSPEC " := "
.B proto
.IR PROTO " [[ "
.B sport
.IR PORT " ] "
.RB " [ " dport
.IR PORT " ] | "
.br
.RB " [ " type
.IR NUMBER " ] "
.RB " [ " code
.IR NUMBER " ]] "
.ti -8
.IR LIMIT-LIST " := [ " LIMIT-LIST " ] |"
.RB " [ "limit
.IR LIMIT " ] "
.ti -8
.IR LIMIT " := "
.RB " [ [" time-soft "|" time-hard "|" time-use-soft "|" time-use-hard "]"
.IR SECONDS " ] | "
.RB "[ ["byte-soft "|" byte-hard "]"
.IR SIZE " ] | "
.br
.RB " [ ["packet-soft "|" packet-hard "]"
.IR COUNT " ] "
.ti -8
.BR "ip xfrm policy" " { " add " | " update " } " " dir "
.IR DIR
.IR SELECTOR " [ "
.BR index
.IR INDEX " ] "
.br
.RB " [ " ptype
.IR PTYPE " ] "
.RB " [ " action
.IR ACTION " ] "
.RB " [ " priority
.IR PRIORITY " ] "
.br
.RI " [ " LIMIT-LIST " ] [ "
.IR TMPL-LIST " ] "
.ti -8
.BR "ip xfrm policy" " { " delete " | " get " } " " dir "
.IR DIR " [ " SELECTOR " | "
.BR index
.IR INDEX
.RB " ] "
.br
.RB " [ " ptype
.IR PTYPE " ] "
.ti -8
.BR "ip xfrm policy" " { " deleteall " | " list " } "
.RB " [ " dir
.IR DIR " ] [ "
.IR SELECTOR " ] "
.br
.RB " [ " index
.IR INDEX " ] "
.RB " [ " action
.IR ACTION " ] "
.RB " [ " priority
.IR PRIORITY " ] "
.ti -8
.B "ip xfrm policy flush"
.RB " [ " ptype
.IR PTYPE " ] "
.ti -8
.B "ip xfrm count"
.ti -8
.IR PTYPE " := "
.RB " [ " main " | " sub " ] "
.b (default=main)
.ti -8
.IR DIR " := "
.RB " [ " in " | " out " | " fwd " ] "
.ti -8
.IR SELECTOR " := "
.B src
.IR ADDR "[/" PLEN "]"
.B dst
.IR ADDR "[/" PLEN] " [ " UPSPEC
.RB " ] [ " dev
.IR DEV " ] "
.ti -8
.IR UPSPEC " := "
.B proto
.IR PROTO " [ "
.RB " [ " sport
.IR PORT " ] "
.RB " [ " dport
.IR PORT " ] | "
.br
.RB " [ " type
.IR NUMBER " ] "
.RB " [ " code
.IR NUMBER " ] ] "
.ti -8
.IR ACTION " := "
.RB " [ " allow " | " block " ]"
.b (default=allow)
.ti -8
.IR LIMIT-LIST " := "
.RB " [ "
.IR LIMIT-LIST " ] | "
.RB " [ " limit
.IR LIMIT " ] "
.ti -8
.IR LIMIT " := "
.RB " [ [" time-soft "|" time-hard "|" time-use-soft "|" time-use-hard "]"
.IR SECONDS " ] | "
.RB " [ [" byte-soft "|" byte-hard "]"
.IR SIZE " ] | "
.br [ "
.RB "[" packet-soft "|" packet-hard "]"
.IR NUMBER " ] "
.ti -8
.IR TMPL-LIST " := "
.b " [ "
.IR TMPL-LIST " ] | "
.RB " [ " tmpl
.IR TMPL " ] "
.ti -8
.IR TMPL " := "
.IR ID " [ "
.B mode
.IR MODE " ] "
.RB " [ " reqid
.IR REQID " ] "
.RB " [ " level
.IR LEVEL " ] "
.ti -8
.IR ID " := "
.RB " [ " src
.IR ADDR " ] "
.RB " [ " dst
.IR ADDR " ] "
.RB " [ " proto
.IR XFRM_PROTO " ] "
.RB " [ " spi
.IR SPI " ] "
.ti -8
.IR XFRM_PROTO " := "
.RB " [ " esp " | " ah " | " comp " | " route2 " | " hao " ] "
.ti -8
.IR MODE " := "
.RB " [ " transport " | " tunnel " | " beet " ] "
.b (default=transport)
.ti -8
.IR LEVEL " := "
.RB " [ " required " | " use " ] "
.b (default=required)
.ti -8
.BR "ip xfrm monitor" " [ " all " | "
.IR LISTofOBJECTS " ] "
.in -8 .in -8
.ad b .ad b
@ -444,6 +767,10 @@ host addresses.
.B tunnel .B tunnel
- tunnel over IP. - tunnel over IP.
.TP
.B xfrm
- framework for IPsec protocol.
.PP .PP
The names of all objects may be written in full or The names of all objects may be written in full or
abbreviated form, f.e. abbreviated form, f.e.
@ -1706,8 +2033,11 @@ the prefix selecting the IP source addresses of the multicast route.
.SH ip tunnel - tunnel configuration .SH ip tunnel - tunnel configuration
.B tunnel .B tunnel
objects are tunnels, encapsulating packets in IPv4 packets and then objects are tunnels, encapsulating packets in IP packets and then
sending them over the IP infrastructure. sending them over the IP infrastructure.
The encapulating (or outer) address family is specified by the
.B -f
option. The default is IPv4.
.SS ip tunnel add - add a new tunnel .SS ip tunnel add - add a new tunnel
.SS ip tunnel change - change an existing tunnel .SS ip tunnel change - change an existing tunnel
@ -1719,8 +2049,13 @@ select the tunnel device name.
.TP .TP
.BI mode " MODE" .BI mode " MODE"
set the tunnel mode. Three modes are currently available: set the tunnel mode. Available modes depend on the encapsulating address family.
.BR ipip ", " sit " and " gre "." .br
Modes for IPv4 encapsulation available:
.BR ipip ", " sit ", " isatap " and " gre "."
.br
Modes for IPv6 encapsulation available:
.BR ip6ip6 ", " ipip6 " and " any "."
.TP .TP
.BI remote " ADDRESS" .BI remote " ADDRESS"
@ -1739,14 +2074,19 @@ on tunneled packets.
.I N .I N
is a number in the range 1--255. 0 is a special value is a number in the range 1--255. 0 is a special value
meaning that packets inherit the TTL value. meaning that packets inherit the TTL value.
The default value is: The default value for IPv4 tunnels is:
.BR "inherit" . .BR "inherit" .
The default value for IPv6 tunnels is:
.BR "64" .
.TP .TP
.BI tos " T" .BI tos " T"
.TP .TP
.BI dsfield " T" .BI dsfield " T"
set a fixed TOS .TP
.BI tclass " T"
set a fixed TOS (or traffic class in IPv6)
.I T .I T
on tunneled packets. on tunneled packets.
The default value is: The default value is:
@ -1815,6 +2155,24 @@ flag is equivalent to the combination
.BR "iseq oseq" . .BR "iseq oseq" .
.B It isn't work. Don't use it. .B It isn't work. Don't use it.
.TP
.RP
.BI dscp inherit
.RB ( " only IPv6 tunnels " )
Inherit DS field between inner and outer header.
.TP
.RP
.BI encaplim " ELIM"
.RB ( " only IPv6 tunnels " )
set a fixed encapsulation limit. Default is 4.
.TP
.RP
.BI flowlabel " FLOWLABEL"
.RB ( " only IPv6 tunnels " )
set a fixed flowlabel.
.SS ip tunnel show - list tunnels .SS ip tunnel show - list tunnels
This command has no arguments. This command has no arguments.
@ -1868,6 +2226,169 @@ at any time.
It prepends the history with the state snapshot dumped at the moment It prepends the history with the state snapshot dumped at the moment
of starting. of starting.
.SH ip xfrm - setting xfrm
xfrm is an IP framework, which can transform format of the datagrams,
.br
i.e. encrypt the packets with some algorithm. xfrm policy and xfrm state
are associated through templates
.IR TMPL_LIST "."
This framework is used as a part of IPsec protocol.
.SS ip xfrm state add - add new state into xfrm
.SS ip xfrm state update - update existing xfrm state
.SS ip xfrm state allocspi - allocate SPI value
.TP
.I MODE
is set as default to
.BR transport ","
but it could be set to
.BR tunnel "," ro " or " beet "."
.TP
.I FLAG-LIST
contains one or more flags.
.TP
.I FLAG
could be set to
.BR noecn ", " decap-dscp " or " wildrecv "."
.TP
.I ENCAP
encapsulation is set to encapsulation type
.IR ENCAP-TYPE ", source port " SPORT ", destination port " DPORT " and " OADDR "."
.TP
.I ENCAP-TYPE
could be set to
.BR espinudp " or " espinudp-nonike "."
.TP
.I ALGO-LIST
contains one or more algorithms
.I ALGO
which depend on the type of algorithm set by
.IR ALGO_TYPE "."
It can be used these algoritms
.BR enc ", " auth " or " comp "."
.SS ip xfrm policy add - add a new policy
.SS ip xfrm policy update - update an existing policy
.SS ip xfrm policy delete - delete existing policy
.SS ip xfrm policy get - get existing policy
.SS ip xfrm policy deleteall - delete all existing xfrm policy
.SS ip xfrm policy list - print out the list of xfrm policy
.SS ip xfrm policy flush - flush policies
It can be flush
.BR all
policies or only those specified with
.BR ptype "."
.TP
.BI dir " DIR "
directory could be one of these:
.BR "inp", " out " or " fwd".
.TP
.IR SELECTOR
selects for which addresses will be set up the policy. The selector
is defined by source and destination address.
.TP
.IR UPSPEC
is defined by source port
.BR sport ", "
destination port
.BR dport ", " type
as number and
.B code
also number.
.TP
.BI dev " DEV "
specify network device.
.TP
.BI index " INDEX "
the number of indexed policy.
.TP
.BI ptype " PTYPE "
type is set as default on
.BR "main" ,
could be switch on
.BR "sub" .
.TP
.BI action " ACTION "
is set as default on
.BR "allow".
It could be switch on
.BR "block".
.TP
.BI priority " PRIORITY "
priority is a number. Default priority is set on zero.
.TP
.IR LIMIT-LIST
limits are set in seconds, bytes or numbers of packets.
.TP
.IR TMPL-LIST
template list is based on
.IR ID ","
.BR mode ", " reqid " and " level ". "
.TP
.IR ID
is specified by source address, destination address,
.I proto
and value of
.IR spi "."
.TP
.IR XFRM_PROTO
values:
.BR esp ", " ah ", " comp ", " route2 " or " hao "."
.TP
.IR MODE
is set as default on
.BR transport ","
but it could be set on
.BR tunnel " or " beet "."
.TP
.IR LEVEL
is set as default on
.BR required
and the other choice is
.BR use "."
.TP
.IR UPSPEC
is specified by
.BR sport ", "
.BR dport ", " type
and
.B code
(NUMBER).
.SS ip xfrm monitor - is used for listing all objects or defined group of them.
The
.B xfrm monitor
can monitor the policies for all objects or defined group of them.
.SH HISTORY .SH HISTORY
.B ip .B ip
was written by Alexey N. Kuznetsov and added in Linux 2.2. was written by Alexey N. Kuznetsov and added in Linux 2.2.

View File

@ -27,7 +27,7 @@ ssfilter.c: ssfilter.y
lnstat: $(LNSTATOBJ) lnstat: $(LNSTATOBJ)
install: all install: all
install -m 0755 -s $(TARGETS) $(DESTDIR)$(SBINDIR) install -m 0755 $(TARGETS) $(DESTDIR)$(SBINDIR)
ln -sf lnstat $(DESTDIR)$(SBINDIR)/rtstat ln -sf lnstat $(DESTDIR)$(SBINDIR)/rtstat
ln -sf lnstat $(DESTDIR)$(SBINDIR)/ctstat ln -sf lnstat $(DESTDIR)$(SBINDIR)/ctstat

View File

@ -1641,7 +1641,7 @@ static int tcp_show(struct filter *f, int socktype)
} }
if (f->families & (1<<AF_INET)) { if (f->families & (1<<AF_INET)) {
if ((fp = net_tcp_open()) < 0) if ((fp = net_tcp_open()) == NULL)
goto outerr; goto outerr;
setbuffer(fp, buf, bufsize); setbuffer(fp, buf, bufsize);
@ -1651,7 +1651,7 @@ static int tcp_show(struct filter *f, int socktype)
} }
if ((f->families & (1<<AF_INET6)) && if ((f->families & (1<<AF_INET6)) &&
(fp = net_tcp6_open()) >= 0) { (fp = net_tcp6_open()) != NULL) {
setbuffer(fp, buf, bufsize); setbuffer(fp, buf, bufsize);
if (generic_record_read(fp, tcp_show_line, f, AF_INET6)) if (generic_record_read(fp, tcp_show_line, f, AF_INET6))
goto outerr; goto outerr;
@ -1773,7 +1773,7 @@ int udp_show(struct filter *f)
dg_proto = UDP_PROTO; dg_proto = UDP_PROTO;
if (f->families&(1<<AF_INET)) { if (f->families&(1<<AF_INET)) {
if ((fp = net_udp_open()) < 0) if ((fp = net_udp_open()) == NULL)
goto outerr; goto outerr;
if (generic_record_read(fp, dgram_show_line, f, AF_INET)) if (generic_record_read(fp, dgram_show_line, f, AF_INET))
goto outerr; goto outerr;
@ -1781,7 +1781,7 @@ int udp_show(struct filter *f)
} }
if ((f->families&(1<<AF_INET6)) && if ((f->families&(1<<AF_INET6)) &&
(fp = net_udp6_open()) >= 0) { (fp = net_udp6_open()) != NULL) {
if (generic_record_read(fp, dgram_show_line, f, AF_INET6)) if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
goto outerr; goto outerr;
fclose(fp); fclose(fp);
@ -1805,7 +1805,7 @@ int raw_show(struct filter *f)
dg_proto = RAW_PROTO; dg_proto = RAW_PROTO;
if (f->families&(1<<AF_INET)) { if (f->families&(1<<AF_INET)) {
if ((fp = net_raw_open()) < 0) if ((fp = net_raw_open()) == NULL)
goto outerr; goto outerr;
if (generic_record_read(fp, dgram_show_line, f, AF_INET)) if (generic_record_read(fp, dgram_show_line, f, AF_INET))
goto outerr; goto outerr;
@ -1813,7 +1813,7 @@ int raw_show(struct filter *f)
} }
if ((f->families&(1<<AF_INET6)) && if ((f->families&(1<<AF_INET6)) &&
(fp = net_raw6_open()) >= 0) { (fp = net_raw6_open()) != NULL) {
if (generic_record_read(fp, dgram_show_line, f, AF_INET6)) if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
goto outerr; goto outerr;
fclose(fp); fclose(fp);

View File

@ -73,9 +73,9 @@ libtc.a: $(TCLIB)
install: all install: all
mkdir -p $(DESTDIR)/usr/lib/tc mkdir -p $(DESTDIR)/usr/lib/tc
install -m 0755 -s tc $(DESTDIR)$(SBINDIR) install -m 0755 tc $(DESTDIR)$(SBINDIR)
for i in $(TCSO); \ for i in $(TCSO); \
do install -m 755 -s $$i $(DESTDIR)/usr/lib/tc; \ do install -m 755 $$i $(DESTDIR)/usr/lib/tc; \
done done
clean: clean:

View File

@ -35,7 +35,7 @@ struct action_util police_action_util = {
static void usage(void) static void usage(void)
{ {
fprintf(stderr, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n"); fprintf(stderr, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n");
fprintf(stderr, " [ peakrate BPS ] [ avrate BPS ]\n"); fprintf(stderr, " [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n");
fprintf(stderr, " [ ACTIONTERM ]\n"); fprintf(stderr, " [ ACTIONTERM ]\n");
fprintf(stderr, "Old Syntax ACTIONTERM := action <EXCEEDACT>[/NOTEXCEEDACT] \n"); fprintf(stderr, "Old Syntax ACTIONTERM := action <EXCEEDACT>[/NOTEXCEEDACT] \n");
fprintf(stderr, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \n"); fprintf(stderr, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \n");
@ -133,6 +133,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
__u32 avrate = 0; __u32 avrate = 0;
int presult = 0; int presult = 0;
unsigned buffer=0, mtu=0, mpu=0; unsigned buffer=0, mtu=0, mpu=0;
unsigned short overhead;
int Rcell_log=-1, Pcell_log = -1; int Rcell_log=-1, Pcell_log = -1;
struct rtattr *tail; struct rtattr *tail;
@ -234,6 +235,11 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
fprintf(stderr, "Illegal \"action\"\n"); fprintf(stderr, "Illegal \"action\"\n");
return -1; return -1;
} }
} else if (matches(*argv, "overhead") == 0) {
NEXT_ARG();
if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1;
}
} else if (strcmp(*argv, "help") == 0) { } else if (strcmp(*argv, "help") == 0) {
usage(); usage();
} else { } else {
@ -263,6 +269,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
if (p.rate.rate) { if (p.rate.rate) {
p.rate.mpu = mpu; p.rate.mpu = mpu;
p.rate.overhead = overhead;
if (tc_calc_rtable(&p.rate, rtab, Rcell_log, mtu) < 0) { if (tc_calc_rtable(&p.rate, rtab, Rcell_log, mtu) < 0) {
fprintf(stderr, "TBF: failed to calculate rate table.\n"); fprintf(stderr, "TBF: failed to calculate rate table.\n");
return -1; return -1;
@ -272,6 +279,7 @@ int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_
p.mtu = mtu; p.mtu = mtu;
if (p.peakrate.rate) { if (p.peakrate.rate) {
p.peakrate.mpu = mpu; p.peakrate.mpu = mpu;
p.peakrate.overhead = overhead;
if (tc_calc_rtable(&p.peakrate, ptab, Pcell_log, mtu) < 0) { if (tc_calc_rtable(&p.peakrate, ptab, Pcell_log, mtu) < 0) {
fprintf(stderr, "POLICE: failed to calculate peak rate table.\n"); fprintf(stderr, "POLICE: failed to calculate peak rate table.\n");
return -1; return -1;
@ -344,6 +352,7 @@ print_police(struct action_util *a, FILE *f, struct rtattr *arg)
fprintf(f, "/%s ", police_action_n2a(*(int*)RTA_DATA(tb[TCA_POLICE_RESULT]), b1, sizeof(b1))); fprintf(f, "/%s ", police_action_n2a(*(int*)RTA_DATA(tb[TCA_POLICE_RESULT]), b1, sizeof(b1)));
} else } else
fprintf(f, " "); fprintf(f, " ");
fprintf(f, "overhead %ub ", p->rate.overhead);
fprintf(f, "\nref %d bind %d\n",p->refcnt, p->bindcnt); fprintf(f, "\nref %d bind %d\n",p->refcnt, p->bindcnt);
return 0; return 0;

View File

@ -32,6 +32,7 @@ static void explain_class(void)
fprintf(stderr, " [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n"); fprintf(stderr, " [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n");
fprintf(stderr, " [ estimator INTERVAL TIME_CONSTANT ]\n"); fprintf(stderr, " [ estimator INTERVAL TIME_CONSTANT ]\n");
fprintf(stderr, " [ split CLASSID ] [ defmap MASK/CHANGE ]\n"); fprintf(stderr, " [ split CLASSID ] [ defmap MASK/CHANGE ]\n");
fprintf(stderr, " [ overhead BYTES ]\n");
} }
static void explain(void) static void explain(void)
@ -53,6 +54,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
struct tc_cbq_lssopt lss; struct tc_cbq_lssopt lss;
__u32 rtab[256]; __u32 rtab[256];
unsigned mpu=0, avpkt=0, allot=0; unsigned mpu=0, avpkt=0, allot=0;
unsigned short overhead=0;
int cell_log=-1; int cell_log=-1;
int ewma_log=-1; int ewma_log=-1;
struct rtattr *tail; struct rtattr *tail;
@ -61,14 +63,14 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
memset(&r, 0, sizeof(r)); memset(&r, 0, sizeof(r));
while (argc > 0) { while (argc > 0) {
if (strcmp(*argv, "bandwidth") == 0 || if (matches(*argv, "bandwidth") == 0 ||
strcmp(*argv, "rate") == 0) { matches(*argv, "rate") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_rate(&r.rate, *argv)) { if (get_rate(&r.rate, *argv)) {
explain1("bandwidth"); explain1("bandwidth");
return -1; return -1;
} }
} else if (strcmp(*argv, "ewma") == 0) { } else if (matches(*argv, "ewma") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_integer(&ewma_log, *argv, 0)) { if (get_integer(&ewma_log, *argv, 0)) {
explain1("ewma"); explain1("ewma");
@ -78,7 +80,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
fprintf(stderr, "ewma_log must be < 32\n"); fprintf(stderr, "ewma_log must be < 32\n");
return -1; return -1;
} }
} else if (strcmp(*argv, "cell") == 0) { } else if (matches(*argv, "cell") == 0) {
unsigned cell; unsigned cell;
int i; int i;
NEXT_ARG(); NEXT_ARG();
@ -94,26 +96,31 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
return -1; return -1;
} }
cell_log = i; cell_log = i;
} else if (strcmp(*argv, "avpkt") == 0) { } else if (matches(*argv, "avpkt") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_size(&avpkt, *argv)) { if (get_size(&avpkt, *argv)) {
explain1("avpkt"); explain1("avpkt");
return -1; return -1;
} }
} else if (strcmp(*argv, "mpu") == 0) { } else if (matches(*argv, "mpu") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_size(&mpu, *argv)) { if (get_size(&mpu, *argv)) {
explain1("mpu"); explain1("mpu");
return -1; return -1;
} }
} else if (strcmp(*argv, "allot") == 0) { } else if (matches(*argv, "allot") == 0) {
NEXT_ARG(); NEXT_ARG();
/* Accept and ignore "allot" for backward compatibility */ /* Accept and ignore "allot" for backward compatibility */
if (get_size(&allot, *argv)) { if (get_size(&allot, *argv)) {
explain1("allot"); explain1("allot");
return -1; return -1;
} }
} else if (strcmp(*argv, "help") == 0) { } else if (matches(*argv, "overhead") == 0) {
NEXT_ARG();
if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1;
}
} else if (matches(*argv, "help") == 0) {
explain(); explain();
return -1; return -1;
} else { } else {
@ -138,6 +145,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
allot = (avpkt*3)/2; allot = (avpkt*3)/2;
r.mpu = mpu; r.mpu = mpu;
r.overhead = overhead;
if (tc_calc_rtable(&r, rtab, cell_log, allot) < 0) { if (tc_calc_rtable(&r, rtab, cell_log, allot) < 0) {
fprintf(stderr, "CBQ: failed to calculate rate table.\n"); fprintf(stderr, "CBQ: failed to calculate rate table.\n");
return -1; return -1;
@ -179,6 +187,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
int ewma_log=-1; int ewma_log=-1;
unsigned bndw = 0; unsigned bndw = 0;
unsigned minburst=0, maxburst=0; unsigned minburst=0, maxburst=0;
unsigned short overhead=0;
struct rtattr *tail; struct rtattr *tail;
memset(&r, 0, sizeof(r)); memset(&r, 0, sizeof(r));
@ -188,52 +197,52 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
memset(&ovl, 0, sizeof(ovl)); memset(&ovl, 0, sizeof(ovl));
while (argc > 0) { while (argc > 0) {
if (strcmp(*argv, "rate") == 0) { if (matches(*argv, "rate") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_rate(&r.rate, *argv)) { if (get_rate(&r.rate, *argv)) {
explain1("rate"); explain1("rate");
return -1; return -1;
} }
} else if (strcmp(*argv, "bandwidth") == 0) { } else if (matches(*argv, "bandwidth") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_rate(&bndw, *argv)) { if (get_rate(&bndw, *argv)) {
explain1("bandwidth"); explain1("bandwidth");
return -1; return -1;
} }
} else if (strcmp(*argv, "minidle") == 0) { } else if (matches(*argv, "minidle") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_u32(&lss.minidle, *argv, 0)) { if (get_u32(&lss.minidle, *argv, 0)) {
explain1("minidle"); explain1("minidle");
return -1; return -1;
} }
lss.change |= TCF_CBQ_LSS_MINIDLE; lss.change |= TCF_CBQ_LSS_MINIDLE;
} else if (strcmp(*argv, "minburst") == 0) { } else if (matches(*argv, "minburst") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_u32(&minburst, *argv, 0)) { if (get_u32(&minburst, *argv, 0)) {
explain1("minburst"); explain1("minburst");
return -1; return -1;
} }
lss.change |= TCF_CBQ_LSS_OFFTIME; lss.change |= TCF_CBQ_LSS_OFFTIME;
} else if (strcmp(*argv, "maxburst") == 0) { } else if (matches(*argv, "maxburst") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_u32(&maxburst, *argv, 0)) { if (get_u32(&maxburst, *argv, 0)) {
explain1("maxburst"); explain1("maxburst");
return -1; return -1;
} }
lss.change |= TCF_CBQ_LSS_MAXIDLE; lss.change |= TCF_CBQ_LSS_MAXIDLE;
} else if (strcmp(*argv, "bounded") == 0) { } else if (matches(*argv, "bounded") == 0) {
lss.flags |= TCF_CBQ_LSS_BOUNDED; lss.flags |= TCF_CBQ_LSS_BOUNDED;
lss.change |= TCF_CBQ_LSS_FLAGS; lss.change |= TCF_CBQ_LSS_FLAGS;
} else if (strcmp(*argv, "borrow") == 0) { } else if (matches(*argv, "borrow") == 0) {
lss.flags &= ~TCF_CBQ_LSS_BOUNDED; lss.flags &= ~TCF_CBQ_LSS_BOUNDED;
lss.change |= TCF_CBQ_LSS_FLAGS; lss.change |= TCF_CBQ_LSS_FLAGS;
} else if (strcmp(*argv, "isolated") == 0) { } else if (matches(*argv, "isolated") == 0) {
lss.flags |= TCF_CBQ_LSS_ISOLATED; lss.flags |= TCF_CBQ_LSS_ISOLATED;
lss.change |= TCF_CBQ_LSS_FLAGS; lss.change |= TCF_CBQ_LSS_FLAGS;
} else if (strcmp(*argv, "sharing") == 0) { } else if (matches(*argv, "sharing") == 0) {
lss.flags &= ~TCF_CBQ_LSS_ISOLATED; lss.flags &= ~TCF_CBQ_LSS_ISOLATED;
lss.change |= TCF_CBQ_LSS_FLAGS; lss.change |= TCF_CBQ_LSS_FLAGS;
} else if (strcmp(*argv, "ewma") == 0) { } else if (matches(*argv, "ewma") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_integer(&ewma_log, *argv, 0)) { if (get_integer(&ewma_log, *argv, 0)) {
explain1("ewma"); explain1("ewma");
@ -244,7 +253,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
return -1; return -1;
} }
lss.change |= TCF_CBQ_LSS_EWMA; lss.change |= TCF_CBQ_LSS_EWMA;
} else if (strcmp(*argv, "cell") == 0) { } else if (matches(*argv, "cell") == 0) {
unsigned cell; unsigned cell;
int i; int i;
NEXT_ARG(); NEXT_ARG();
@ -260,7 +269,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
return -1; return -1;
} }
cell_log = i; cell_log = i;
} else if (strcmp(*argv, "prio") == 0) { } else if (matches(*argv, "prio") == 0) {
unsigned prio; unsigned prio;
NEXT_ARG(); NEXT_ARG();
if (get_u32(&prio, *argv, 0)) { if (get_u32(&prio, *argv, 0)) {
@ -273,40 +282,40 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
} }
wrr.priority = prio; wrr.priority = prio;
wrr_ok++; wrr_ok++;
} else if (strcmp(*argv, "allot") == 0) { } else if (matches(*argv, "allot") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_size(&wrr.allot, *argv)) { if (get_size(&wrr.allot, *argv)) {
explain1("allot"); explain1("allot");
return -1; return -1;
} }
} else if (strcmp(*argv, "avpkt") == 0) { } else if (matches(*argv, "avpkt") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_size(&lss.avpkt, *argv)) { if (get_size(&lss.avpkt, *argv)) {
explain1("avpkt"); explain1("avpkt");
return -1; return -1;
} }
lss.change |= TCF_CBQ_LSS_AVPKT; lss.change |= TCF_CBQ_LSS_AVPKT;
} else if (strcmp(*argv, "mpu") == 0) { } else if (matches(*argv, "mpu") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_size(&mpu, *argv)) { if (get_size(&mpu, *argv)) {
explain1("mpu"); explain1("mpu");
return -1; return -1;
} }
} else if (strcmp(*argv, "weight") == 0) { } else if (matches(*argv, "weight") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_size(&wrr.weight, *argv)) { if (get_size(&wrr.weight, *argv)) {
explain1("weight"); explain1("weight");
return -1; return -1;
} }
wrr_ok++; wrr_ok++;
} else if (strcmp(*argv, "split") == 0) { } else if (matches(*argv, "split") == 0) {
NEXT_ARG(); NEXT_ARG();
if (get_tc_classid(&fopt.split, *argv)) { if (get_tc_classid(&fopt.split, *argv)) {
fprintf(stderr, "Invalid split node ID.\n"); fprintf(stderr, "Invalid split node ID.\n");
usage(); usage();
} }
fopt_ok++; fopt_ok++;
} else if (strcmp(*argv, "defmap") == 0) { } else if (matches(*argv, "defmap") == 0) {
int err; int err;
NEXT_ARG(); NEXT_ARG();
err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange); err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange);
@ -317,7 +326,12 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
if (err == 1) if (err == 1)
fopt.defchange = ~0; fopt.defchange = ~0;
fopt_ok++; fopt_ok++;
} else if (strcmp(*argv, "help") == 0) { } else if (matches(*argv, "overhead") == 0) {
NEXT_ARG();
if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1;
}
} else if (matches(*argv, "help") == 0) {
explain_class(); explain_class();
return -1; return -1;
} else { } else {
@ -336,6 +350,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
if (wrr.allot < (lss.avpkt*3)/2) if (wrr.allot < (lss.avpkt*3)/2)
wrr.allot = (lss.avpkt*3)/2; wrr.allot = (lss.avpkt*3)/2;
r.mpu = mpu; r.mpu = mpu;
r.overhead = overhead;
if (tc_calc_rtable(&r, rtab, cell_log, pktsize) < 0) { if (tc_calc_rtable(&r, rtab, cell_log, pktsize) < 0) {
fprintf(stderr, "CBQ: failed to calculate rate table.\n"); fprintf(stderr, "CBQ: failed to calculate rate table.\n");
return -1; return -1;
@ -464,6 +479,8 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
fprintf(f, "cell %ub ", 1<<r->cell_log); fprintf(f, "cell %ub ", 1<<r->cell_log);
if (r->mpu) if (r->mpu)
fprintf(f, "mpu %ub ", r->mpu); fprintf(f, "mpu %ub ", r->mpu);
if (r->overhead)
fprintf(f, "overhead %ub ", r->overhead);
} }
} }
if (lss && lss->flags) { if (lss && lss->flags) {

View File

@ -26,7 +26,8 @@
static void explain(void) static void explain(void)
{ {
fprintf(stderr, "Usage: ... tbf limit BYTES burst BYTES[/BYTES] rate KBPS [ mtu BYTES[/BYTES] ]\n"); fprintf(stderr, "Usage: ... tbf limit BYTES burst BYTES[/BYTES] rate KBPS [ mtu BYTES[/BYTES] ]\n");
fprintf(stderr, " [ peakrate KBPS ] [ latency TIME ]\n"); fprintf(stderr, " [ peakrate KBPS ] [ latency TIME ] ");
fprintf(stderr, "[ overhead BYTES ]\n");
} }
static void explain1(char *arg) static void explain1(char *arg)
@ -45,6 +46,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
__u32 ptab[256]; __u32 ptab[256];
unsigned buffer=0, mtu=0, mpu=0, latency=0; unsigned buffer=0, mtu=0, mpu=0, latency=0;
int Rcell_log=-1, Pcell_log = -1; int Rcell_log=-1, Pcell_log = -1;
unsigned short overhead=0;
struct rtattr *tail; struct rtattr *tail;
memset(&opt, 0, sizeof(opt)); memset(&opt, 0, sizeof(opt));
@ -130,6 +132,15 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
return -1; return -1;
} }
ok++; ok++;
} else if (matches(*argv, "overhead") == 0) {
NEXT_ARG();
if (overhead) {
fprintf(stderr, "Double \"overhead\" spec\n");
return -1;
}
if (get_u16(&overhead, *argv, 10)) {
explain1("overhead"); return -1;
}
} else if (strcmp(*argv, "help") == 0) { } else if (strcmp(*argv, "help") == 0) {
explain(); explain();
return -1; return -1;
@ -171,6 +182,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
} }
opt.rate.mpu = mpu; opt.rate.mpu = mpu;
opt.rate.overhead = overhead;
if (tc_calc_rtable(&opt.rate, rtab, Rcell_log, mtu) < 0) { if (tc_calc_rtable(&opt.rate, rtab, Rcell_log, mtu) < 0) {
fprintf(stderr, "TBF: failed to calculate rate table.\n"); fprintf(stderr, "TBF: failed to calculate rate table.\n");
return -1; return -1;
@ -179,6 +191,7 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
if (opt.peakrate.rate) { if (opt.peakrate.rate) {
opt.peakrate.mpu = mpu; opt.peakrate.mpu = mpu;
opt.peakrate.overhead = overhead;
if (tc_calc_rtable(&opt.peakrate, ptab, Pcell_log, mtu) < 0) { if (tc_calc_rtable(&opt.peakrate, ptab, Pcell_log, mtu) < 0) {
fprintf(stderr, "TBF: failed to calculate peak rate table.\n"); fprintf(stderr, "TBF: failed to calculate peak rate table.\n");
return -1; return -1;
@ -252,6 +265,10 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
} }
fprintf(f, "lat %s ", sprint_time(latency, b1)); fprintf(f, "lat %s ", sprint_time(latency, b1));
if (qopt->rate.overhead) {
fprintf(f, "overhead %d", qopt->rate.overhead);
}
return 0; return 0;
} }