From a4eca97cff0391d73b4ad4d5598cdc9a35771fa4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 13 Jan 2011 09:23:17 -0800 Subject: [PATCH 01/31] CHOKe scheduler TC commands for CHOKe qdisc --- include/linux/pkt_sched.h | 29 +++++ tc/Makefile | 1 + tc/q_choke.c | 215 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 tc/q_choke.c diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 2cfa4bc8..83bac92d 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -247,6 +247,35 @@ struct tc_gred_sopt { __u16 pad1; }; +/* CHOKe section */ + +enum { + TCA_CHOKE_UNSPEC, + TCA_CHOKE_PARMS, + TCA_CHOKE_STAB, + __TCA_CHOKE_MAX, +}; + +#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1) + +struct tc_choke_qopt { + __u32 limit; /* HARD maximal queue length (packets) */ + __u32 qth_min; /* Min average length threshold (packets) */ + __u32 qth_max; /* Max average length threshold (packets) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; /* see RED flags */ +}; + +struct tc_choke_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ + __u32 matched; /* Drops due to flow match */ +}; + /* HTB section */ #define TC_HTB_NUMPRIO 8 #define TC_HTB_MAXDEPTH 8 diff --git a/tc/Makefile b/tc/Makefile index 101cc835..2cbd5d52 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -15,6 +15,7 @@ TCMODULES += q_cbq.o TCMODULES += q_rr.o TCMODULES += q_multiq.o TCMODULES += q_netem.o +TCMODULES += q_choke.o TCMODULES += f_rsvp.o TCMODULES += f_u32.o TCMODULES += f_route.o diff --git a/tc/q_choke.c b/tc/q_choke.c new file mode 100644 index 00000000..6e54cb71 --- /dev/null +++ b/tc/q_choke.c @@ -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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, +}; From 08dc32e13065a182551f3e034db8ad6ad3390c62 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 25 Feb 2011 12:31:36 -0800 Subject: [PATCH 02/31] update to net-next (2.6.39) headers --- include/linux/if_link.h | 1 + include/linux/netfilter.h | 17 ++++-- include/linux/pkt_sched.h | 107 ++++++++++++++++++++++++++++++++++++++ include/linux/xfrm.h | 1 + 4 files changed, 121 insertions(+), 5 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index e87456c7..e4a3a2d7 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -135,6 +135,7 @@ enum { IFLA_VF_PORTS, IFLA_PORT_SELF, IFLA_AF_SPEC, + IFLA_GROUP, /* Group the device belongs to */ __IFLA_MAX }; diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 6ba6fe2b..9b7240d5 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -14,16 +14,20 @@ #define NF_MAX_VERDICT NF_STOP /* we overload the higher bits for encoding auxiliary data such as the queue - * number. Not nice, but better than additional function arguments. */ -#define NF_VERDICT_MASK 0x0000ffff -#define NF_VERDICT_BITS 16 + * number or errno values. Not nice, but better than additional function + * arguments. */ +#define NF_VERDICT_MASK 0x000000ff +/* extra verdict flags have mask 0x0000ff00 */ +#define NF_VERDICT_FLAG_QUEUE_BYPASS 0x00008000 + +/* queue number (NF_QUEUE) or errno (NF_DROP) */ #define NF_VERDICT_QMASK 0xffff0000 #define NF_VERDICT_QBITS 16 -#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE) +#define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE) -#define NF_DROP_ERR(x) (((-x) << NF_VERDICT_BITS) | NF_DROP) +#define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP) /* only for userspace compatibility */ /* Generic cache responses from hook functions. @@ -31,6 +35,9 @@ #define NFC_UNKNOWN 0x4000 #define NFC_ALTERED 0x8000 +/* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */ +#define NF_VERDICT_BITS 16 + enum nf_inet_hooks { NF_INET_PRE_ROUTING, NF_INET_LOCAL_IN, diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 2cfa4bc8..b1032a3f 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -247,6 +247,35 @@ struct tc_gred_sopt { __u16 pad1; }; +/* CHOKe section */ + +enum { + TCA_CHOKE_UNSPEC, + TCA_CHOKE_PARMS, + TCA_CHOKE_STAB, + __TCA_CHOKE_MAX, +}; + +#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1) + +struct tc_choke_qopt { + __u32 limit; /* Hard queue length (packets) */ + __u32 qth_min; /* Min average threshold (packets) */ + __u32 qth_max; /* Max average threshold (packets) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; /* see RED flags */ +}; + +struct tc_choke_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ + __u32 matched; /* Drops due to flow match */ +}; + /* HTB section */ #define TC_HTB_NUMPRIO 8 #define TC_HTB_MAXDEPTH 8 @@ -435,6 +464,7 @@ enum { TCA_NETEM_DELAY_DIST, TCA_NETEM_REORDER, TCA_NETEM_CORRUPT, + TCA_NETEM_LOSS, __TCA_NETEM_MAX, }; @@ -465,7 +495,33 @@ struct tc_netem_corrupt { __u32 correlation; }; +enum { + NETEM_LOSS_UNSPEC, + NETEM_LOSS_GI, /* General Intuitive - 4 state model */ + NETEM_LOSS_GE, /* Gilbert Elliot models */ + __NETEM_LOSS_MAX +}; +#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1) + +/* State transition probablities for 4 state model */ +struct tc_netem_gimodel { + __u32 p13; + __u32 p31; + __u32 p32; + __u32 p14; + __u32 p23; +}; + +/* Gilbert-Elliot models */ +struct tc_netem_gemodel { + __u32 p; + __u32 r; + __u32 h; + __u32 k1; +}; + #define NETEM_DIST_SCALE 8192 +#define NETEM_DIST_MAX 16384 /* DRR */ @@ -481,4 +537,55 @@ struct tc_drr_stats { __u32 deficit; }; +/* MQPRIO */ +#define TC_QOPT_BITMASK 15 +#define TC_QOPT_MAX_QUEUE 16 + +struct tc_mqprio_qopt { + __u8 num_tc; + __u8 prio_tc_map[TC_QOPT_BITMASK + 1]; + __u8 hw; + __u16 count[TC_QOPT_MAX_QUEUE]; + __u16 offset[TC_QOPT_MAX_QUEUE]; +}; + +/* SFB */ + +enum { + TCA_SFB_UNSPEC, + TCA_SFB_PARMS, + __TCA_SFB_MAX, +}; + +#define TCA_SFB_MAX (__TCA_SFB_MAX - 1) + +/* + * Note: increment, decrement are Q0.16 fixed-point values. + */ +struct tc_sfb_qopt { + __u32 rehash_interval; /* delay between hash move, in ms */ + __u32 warmup_time; /* double buffering warmup time in ms (warmup_time < rehash_interval) */ + __u32 max; /* max len of qlen_min */ + __u32 bin_size; /* maximum queue length per bin */ + __u32 increment; /* probability increment, (d1 in Blue) */ + __u32 decrement; /* probability decrement, (d2 in Blue) */ + __u32 limit; /* max SFB queue length */ + __u32 penalty_rate; /* inelastic flows are rate limited to 'rate' pps */ + __u32 penalty_burst; +}; + +struct tc_sfb_xstats { + __u32 earlydrop; + __u32 penaltydrop; + __u32 bucketdrop; + __u32 queuedrop; + __u32 childdrop; /* drops in child qdisc */ + __u32 marked; + __u32 maxqlen; + __u32 maxprob; + __u32 avgprob; +}; + +#define SFB_MAX_PROB 0xFFFF + #endif diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 593565d8..b405b701 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -350,6 +350,7 @@ struct xfrm_usersa_info { #define XFRM_STATE_WILDRECV 8 #define XFRM_STATE_ICMP 16 #define XFRM_STATE_AF_UNSPEC 32 +#define XFRM_STATE_ALIGN4 64 }; struct xfrm_usersa_id { From f960c92aac1838e0f336c0ca0f657bb55a42d8e9 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Wed, 2 Feb 2011 20:23:40 +0200 Subject: [PATCH 03/31] iproute2: support listing devices by group User can specify device group to list by using the group keyword: ip link show group test If no group is specified, 0 (default) is implied. Signed-off-by: Vlad Dogaru --- etc/iproute2/group | 2 ++ include/rt_names.h | 1 + ip/ipaddress.c | 14 +++++++++++++ ip/iplink.c | 2 +- lib/rt_names.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ man/man8/ip.8 | 11 ++++++++-- 6 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 etc/iproute2/group diff --git a/etc/iproute2/group b/etc/iproute2/group new file mode 100644 index 00000000..6f000b24 --- /dev/null +++ b/etc/iproute2/group @@ -0,0 +1,2 @@ +# device group names +0 default diff --git a/include/rt_names.h b/include/rt_names.h index 07a10e0b..e5dbd45b 100644 --- a/include/rt_names.h +++ b/include/rt_names.h @@ -13,6 +13,7 @@ int rtnl_rtscope_a2n(__u32 *id, char *arg); int rtnl_rttable_a2n(__u32 *id, char *arg); int rtnl_rtrealm_a2n(__u32 *id, char *arg); int rtnl_dsfield_a2n(__u32 *id, char *arg); +int rtnl_group_a2n(int *id, char *arg); const char *inet_proto_n2a(int proto, char *buf, int len); int inet_proto_a2n(char *buf); diff --git a/ip/ipaddress.c b/ip/ipaddress.c index a775ecd3..e4748e3d 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -49,6 +49,7 @@ static struct char *flushb; int flushp; int flushe; + int group; } filter; static int do_link; @@ -246,6 +247,12 @@ int print_linkinfo(const struct sockaddr_nl *who, fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)) return 0; + if (tb[IFLA_GROUP]) { + int group = *(int*)RTA_DATA(tb[IFLA_GROUP]); + if (group != filter.group) + return -1; + } + if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); @@ -718,9 +725,12 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush) if (filter.family == AF_UNSPEC) filter.family = preferred_family; + filter.group = INIT_NETDEV_GROUP; + if (flush) { if (argc <= 0) { fprintf(stderr, "Flush requires arguments.\n"); + return -1; } if (filter.family == AF_PACKET) { @@ -779,6 +789,10 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush) } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); filter.label = *argv; + } else if (strcmp(*argv, "group") == 0) { + NEXT_ARG(); + if (rtnl_group_a2n(&filter.group, *argv)) + invarg("Invalid \"group\" value\n", *argv); } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); diff --git a/ip/iplink.c b/ip/iplink.c index cb2c4f5e..97a960ba 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -71,7 +71,7 @@ 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, " ip link show [ DEVICE ]\n"); + fprintf(stderr, " ip link show [ DEVICE | group GROUP ]\n"); if (iplink_have_newlink()) { fprintf(stderr, "\n"); diff --git a/lib/rt_names.c b/lib/rt_names.c index 52edfe33..30d43cd0 100644 --- a/lib/rt_names.c +++ b/lib/rt_names.c @@ -447,3 +447,53 @@ int rtnl_dsfield_a2n(__u32 *id, char *arg) return 0; } + +static struct rtnl_hash_entry dflt_group_entry = { .id = 0, .name = "default" }; + +static struct rtnl_hash_entry * rtnl_group_hash[256] = { + [0] = &dflt_group_entry, +}; + +static int rtnl_group_init; + +static void rtnl_group_initialize(void) +{ + rtnl_group_init = 1; + rtnl_hash_initialize("/etc/iproute2/group", + rtnl_group_hash, 256); +} + +int rtnl_group_a2n(int *id, char *arg) +{ + static char *cache = NULL; + static unsigned long res; + struct rtnl_hash_entry *entry; + char *end; + int i; + + if (cache && strcmp(cache, arg) == 0) { + *id = res; + return 0; + } + + if (!rtnl_group_init) + rtnl_group_initialize(); + + for (i=0; i<256; i++) { + entry = rtnl_group_hash[i]; + while (entry && strcmp(entry->name, arg)) + entry = entry->next; + if (entry) { + cache = entry->name; + res = entry->id; + *id = res; + return 0; + } + } + + i = strtol(arg, &end, 0); + if (!end || end == arg || *end || i < 0) + return -1; + *id = i; + return 0; +} diff --git a/man/man8/ip.8 b/man/man8/ip.8 index 8d55fa9d..730788ab 100644 --- a/man/man8/ip.8 +++ b/man/man8/ip.8 @@ -99,7 +99,9 @@ ip \- show / manipulate routing, devices, policy routing and tunnels .ti -8 .B ip link show -.RI "[ " DEVICE " ]" +.RI "[ " DEVICE " | " +.B group +.IR GROUP " ]" .ti -8 .BR "ip addr" " { " add " | " del " } " @@ -1056,7 +1058,12 @@ call. .BI dev " NAME " (default) .I NAME specifies the network device to show. -If this argument is omitted all devices are listed. +If this argument is omitted all devices in the default group are listed. + +.TP +.BI group " GROUP " +.I GROUP +specifies what group of devices to show. .TP .B up From 26ad3aecfeeb93cd396a199a5e664e749bcabc8d Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Wed, 2 Feb 2011 20:23:41 +0200 Subject: [PATCH 04/31] iproute2: support device group semantics Add the group keyword to ip link set, which has the following meaning: If both a group and a device name are pressent, we change the device's group to the specified one. If only a group is present, then the operation specified by the rest of the command should apply on an entire group, not a single device. So, to set eth0 to the default group, one would use ip link set dev eth0 group default Conversely, to set all the devices in the default group down, use ip link set group default down Signed-off-by: Vlad Dogaru --- ip/ipaddress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index e4748e3d..524ea018 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -725,7 +725,7 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush) if (filter.family == AF_UNSPEC) filter.family = preferred_family; - filter.group = INIT_NETDEV_GROUP; + filter.group = 0; /* INIT_NETDEV_GROUP */ if (flush) { if (argc <= 0) { From db02608b6f408998ea8c823fb791cead3e574f50 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Wed, 2 Feb 2011 20:23:41 +0200 Subject: [PATCH 05/31] iproute2: support device group semantics Add the group keyword to ip link set, which has the following meaning: If both a group and a device name are pressent, we change the device's group to the specified one. If only a group is present, then the operation specified by the rest of the command should apply on an entire group, not a single device. So, to set eth0 to the default group, one would use ip link set dev eth0 group default Conversely, to set all the devices in the default group down, use ip link set group default down Signed-off-by: Vlad Dogaru --- include/utils.h | 3 ++- ip/iplink.c | 40 +++++++++++++++++++++++++++++++++++++--- ip/link_veth.c | 3 ++- man/man8/ip.8 | 19 +++++++++++++++++-- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/include/utils.h b/include/utils.h index 3da69985..595a7d6d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -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__ */ diff --git a/ip/iplink.c b/ip/iplink.c index 97a960ba..8160855c 100644 --- a/ip/iplink.c +++ b/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"); @@ -244,7 +244,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 +253,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) { @@ -383,6 +384,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 +413,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 +425,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) { diff --git a/ip/link_veth.c b/ip/link_veth.c index 9f5e8715..3d19b01f 100644 --- a/ip/link_veth.c +++ b/ip/link_veth.c @@ -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; diff --git a/man/man8/ip.8 b/man/man8/ip.8 index 730788ab..8f82842e 100644 --- a/man/man8/ip.8 +++ b/man/man8/ip.8 @@ -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 @@ -929,6 +931,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 +1004,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 From b2bb289a57fe7be63ebe0d1fe6ff94555bf6c936 Mon Sep 17 00:00:00 2001 From: Joy Latten Date: Wed, 2 Feb 2011 17:31:39 -0600 Subject: [PATCH 06/31] xfrm security context support In the Linux kernel, ipsec policy and SAs can include a security context to support MAC networking. This feature is often referred to as "labeled ipsec". This patchset adds security context support into ip xfrm such that a security context can be included when add/delete/display SAs and policies with the ip command. The user provides the security context when adding SAs and policies. If a policy or SA contains a security context, the changes allow the security context to be displayed. For example, ip xfrm state src 10.1.1.6 dst 10.1.1.2 proto esp spi 0x00000301 reqid 0 mode transport replay-window 0 auth hmac(digest_null) 0x3078 enc cbc(des3_ede) 0x6970763672656164796c6f676f33646573636263696e3031 security context root:system_r:unconfined_t:s0 Please let me know if all is ok with the patchset. Thanks!! regards, Joy Signed-off-by: Joy Latten --- ip/ipxfrm.c | 28 ++++++++++++++++++++++++++++ ip/xfrm.h | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c index 9753822d..cc4dc803 100644 --- a/ip/ipxfrm.c +++ b/ip/ipxfrm.c @@ -850,6 +850,20 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo, xfrm_lifetime_print(&xsinfo->lft, &xsinfo->curlft, fp, buf); xfrm_stats_print(&xsinfo->stats, fp, buf); } + + if (tb[XFRMA_SEC_CTX]) { + struct xfrm_user_sec_ctx *sctx; + + fprintf(fp, "\tsecurity context "); + + if (RTA_PAYLOAD(tb[XFRMA_SEC_CTX]) < sizeof(*sctx)) + fprintf(fp, "(ERROR truncated)"); + + sctx = (struct xfrm_user_sec_ctx *)RTA_DATA(tb[XFRMA_SEC_CTX]); + + fprintf(fp, "%s %s", (char *)(sctx + 1), _SL_); + } + } void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo, @@ -862,6 +876,20 @@ void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo, xfrm_selector_print(&xpinfo->sel, preferred_family, fp, title); + if (tb[XFRMA_SEC_CTX]) { + struct xfrm_user_sec_ctx *sctx; + + fprintf(fp, "\tsecurity context "); + + if (RTA_PAYLOAD(tb[XFRMA_SEC_CTX]) < sizeof(*sctx)) + fprintf(fp, "(ERROR truncated)"); + + sctx = (struct xfrm_user_sec_ctx *)RTA_DATA(tb[XFRMA_SEC_CTX]); + + fprintf(fp, "%s ", (char *)(sctx + 1)); + fprintf(fp, "%s", _SL_); + } + if (prefix) STRBUF_CAT(buf, prefix); STRBUF_CAT(buf, "\t"); diff --git a/ip/xfrm.h b/ip/xfrm.h index d3ca5c53..784a2012 100644 --- a/ip/xfrm.h +++ b/ip/xfrm.h @@ -154,5 +154,6 @@ int xfrm_reqid_parse(__u32 *reqid, int *argcp, char ***argvp); int xfrm_selector_parse(struct xfrm_selector *sel, int *argcp, char ***argvp); int xfrm_lifetime_cfg_parse(struct xfrm_lifetime_cfg *lft, int *argcp, char ***argvp); - +int xfrm_sctx_parse(char *ctxstr, char *context, + struct xfrm_user_sec_ctx *sctx); #endif From e4f054f017d0daa7ff9bba6027c5df264999ff1a Mon Sep 17 00:00:00 2001 From: Joy Latten Date: Wed, 2 Feb 2011 17:32:18 -0600 Subject: [PATCH 07/31] xfrm security context support Adds security context support to ip xfrm policy. Signed-off-by: Joy Latten --- ip/xfrm_policy.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c index dcb3da42..9ef5c09d 100644 --- a/ip/xfrm_policy.c +++ b/ip/xfrm_policy.c @@ -48,14 +48,15 @@ #define NLMSG_BUF_SIZE 4096 #define RTA_BUF_SIZE 2048 #define XFRM_TMPLS_BUF_SIZE 1024 +#define CTX_BUF_SIZE 256 static void usage(void) __attribute__((noreturn)); static void usage(void) { - fprintf(stderr, "Usage: ip xfrm policy { add | update } dir DIR SELECTOR [ index INDEX ] [ ptype PTYPE ]\n"); + fprintf(stderr, "Usage: ip xfrm policy { add | update } dir DIR SELECTOR [ ctx SEC_CTX ][ index INDEX ] [ ptype PTYPE ]\n"); fprintf(stderr, " [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ] [ LIMIT-LIST ] [ TMPL-LIST ] [mark MARK [mask MASK]]\n"); - fprintf(stderr, "Usage: ip xfrm policy { delete | get } dir DIR [ SELECTOR | index INDEX ] [ ptype PTYPE ] [mark MARK [mask MASK]]\n"); + fprintf(stderr, "Usage: ip xfrm policy { delete | get } dir DIR [ SELECTOR | index INDEX ] [ ctx SEC_CTX ][ ptype PTYPE ] [mark MARK [mask MASK]]\n"); fprintf(stderr, "Usage: ip xfrm policy { deleteall | list } [ dir DIR ] [ SELECTOR ]\n"); fprintf(stderr, " [ index INDEX ] [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ]\n"); fprintf(stderr, "Usage: ip xfrm policy flush [ ptype PTYPE ]\n"); @@ -222,6 +223,23 @@ static int xfrm_tmpl_parse(struct xfrm_user_tmpl *tmpl, return 0; } +int xfrm_sctx_parse(char *ctxstr, char *s, + struct xfrm_user_sec_ctx *sctx) +{ + int slen; + + slen = strlen(s) + 1; + + sctx->exttype = XFRMA_SEC_CTX; + sctx->ctx_doi = 1; + sctx->ctx_alg = 1; + sctx->ctx_len = slen; + sctx->len = sizeof(struct xfrm_user_sec_ctx) + slen; + memcpy(ctxstr, s, slen); + + return 0; +} + static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) { struct rtnl_handle rth; @@ -233,14 +251,20 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) char *dirp = NULL; char *selp = NULL; char *ptypep = NULL; + char *sctxp = NULL; struct xfrm_userpolicy_type upt; char tmpls_buf[XFRM_TMPLS_BUF_SIZE]; int tmpls_len = 0; struct xfrm_mark mark = {0, 0}; + struct { + struct xfrm_user_sec_ctx sctx; + char str[CTX_BUF_SIZE]; + } ctx; memset(&req, 0, sizeof(req)); memset(&upt, 0, sizeof(upt)); memset(&tmpls_buf, 0, sizeof(tmpls_buf)); + memset(&ctx, 0, sizeof(ctx)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; @@ -260,6 +284,15 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) NEXT_ARG(); xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv); + } else if (strcmp(*argv, "ctx") == 0) { + char *context; + + if (sctxp) + duparg("ctx", *argv); + sctxp = *argv; + NEXT_ARG(); + context = *argv; + xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx); } else if (strcmp(*argv, "mark") == 0) { xfrm_parse_mark(&mark, &argc, &argv); } else if (strcmp(*argv, "index") == 0) { @@ -347,6 +380,10 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) } } + if (sctxp) { + addattr_l(&req.n, sizeof(req), XFRMA_SEC_CTX, + (void *)&ctx, ctx.sctx.len); + } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); @@ -528,11 +565,18 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, char *selp = NULL; char *indexp = NULL; char *ptypep = NULL; + char *sctxp = NULL; struct xfrm_userpolicy_type upt; struct xfrm_mark mark = {0, 0}; + struct { + struct xfrm_user_sec_ctx sctx; + char str[CTX_BUF_SIZE]; + } ctx; + memset(&req, 0, sizeof(req)); memset(&upt, 0, sizeof(upt)); + memset(&ctx, 0, sizeof(ctx)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid)); req.n.nlmsg_flags = NLM_F_REQUEST; @@ -547,6 +591,15 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, NEXT_ARG(); xfrm_policy_dir_parse(&req.xpid.dir, &argc, &argv); + } else if (strcmp(*argv, "ctx") == 0) { + char *context; + + if (sctxp) + duparg("ctx", *argv); + sctxp = *argv; + NEXT_ARG(); + context = *argv; + xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx); } else if (strcmp(*argv, "mark") == 0) { xfrm_parse_mark(&mark, &argc, &argv); } else if (strcmp(*argv, "index") == 0) { @@ -610,6 +663,11 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, } } + if (sctxp) { + addattr_l(&req.n, sizeof(req), XFRMA_SEC_CTX, + (void *)&ctx, ctx.sctx.len); + } + if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf, NULL, NULL) < 0) exit(2); From 0c7a594541df84d3497681a8ecc09b05c1449dd0 Mon Sep 17 00:00:00 2001 From: Joy Latten Date: Wed, 2 Feb 2011 17:32:59 -0600 Subject: [PATCH 08/31] xfrm security context support Adds security context support to ip xfrm state. Signed-off-by: Joy Latten --- ip/xfrm_state.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c index 38d40391..165888d3 100644 --- a/ip/xfrm_state.c +++ b/ip/xfrm_state.c @@ -50,12 +50,13 @@ #define NLMSG_BUF_SIZE 4096 #define RTA_BUF_SIZE 2048 #define XFRM_ALGO_KEY_BUF_SIZE 512 +#define CTX_BUF_SIZE 256 static void usage(void) __attribute__((noreturn)); static void usage(void) { - fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ XFRM_OPT ] [ mode MODE ]\n"); + fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ XFRM_OPT ] [ ctx SEC_CTX ] [ mode MODE ]\n"); fprintf(stderr, " [ reqid REQID ] [ seq SEQ ] [ replay-window SIZE ] [ flag FLAG-LIST ]\n"); fprintf(stderr, " [ encap ENCAP ] [ sel SELECTOR ] [ replay-seq SEQ ]\n"); fprintf(stderr, " [ replay-oseq SEQ ] [ LIMIT-LIST ]\n"); @@ -246,10 +247,16 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) char *aalgop = NULL; char *calgop = NULL; char *coap = NULL; + char *sctxp = NULL; struct xfrm_mark mark = {0, 0}; + struct { + struct xfrm_user_sec_ctx sctx; + char str[CTX_BUF_SIZE]; + } ctx; memset(&req, 0, sizeof(req)); memset(&replay, 0, sizeof(replay)); + memset(&ctx, 0, sizeof(ctx)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; @@ -333,6 +340,19 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR, (void *)&xcoa, sizeof(xcoa)); + } else if (strcmp(*argv, "ctx") == 0) { + char *context; + + if (sctxp) + duparg("ctx", *argv); + sctxp = *argv; + + NEXT_ARG(); + context = *argv; + + xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx); + addattr_l(&req.n, sizeof(req.buf), XFRMA_SEC_CTX, + (void *)&ctx, ctx.sctx.len); } else { /* try to assume ALGO */ int type = xfrm_algotype_getbyname(*argv); From 94089ef7726cc25bffbd133fe5e1e16e0fd4654e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 21 Dec 2010 12:54:09 +0100 Subject: [PATCH 09/31] utils: get_jiffies always uses base=0 get_jiffies() is in all places called in the same manner, with base=0; simplify argument list by putting the constant value into the function. --- include/utils.h | 2 +- ip/iproute.c | 6 +++--- lib/utils.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/utils.h b/include/utils.h index 595a7d6d..77c8e5a4 100644 --- a/include/utils.h +++ b/include/utils.h @@ -79,7 +79,7 @@ extern int mask2bits(__u32 netmask); extern int get_integer(int *val, const char *arg, int base); extern int get_unsigned(unsigned *val, const char *arg, int base); -extern int get_jiffies(unsigned *val, const char *arg, int base, int *raw); +extern int get_jiffies(unsigned *val, const char *arg, int *raw); #define get_byte get_u8 #define get_ushort get_u16 #define get_short get_s16 diff --git a/ip/iproute.c b/ip/iproute.c index 0d69290b..f3e7eb42 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -840,7 +840,7 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv) mxlock |= (1< UINT_MAX) return -1; t = (double)res; From 9b2cdc00dab7b601938901e20b5e1e66188d388b Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 25 Feb 2011 12:51:48 -0800 Subject: [PATCH 10/31] iproute: fix unit conversion of rtt/rttvar/rto_min Since July 2008 (2.6.27, c1e20f7c8b9), the kernel stores the values for RTAX_{RTT{,VAR},RTO_MIN} in milliseconds. When using a kernel > 2.6.27 with the current iproute2, conversion of these values is broken in either way. This patch * updates the code to pass and retrieve milliseconds; * since values < 1msec would be rounded up, also drops the usec/nsec variants; * since there is no way to query kernel HZ, also drops the jiffies variant. Arguments such as rtt 3.23sec rto_min 0xff rto_min 0.200s rttvar 25ms now all work as expected when reading back previously set values. --- ip/iproute.c | 13 ++++--------- lib/utils.c | 15 +-------------- man/man8/ip.8 | 7 ++----- 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/ip/iproute.c b/ip/iproute.c index f3e7eb42..d48e743b 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -85,7 +85,7 @@ static void usage(void) fprintf(stderr, "MP_ALGO := { rr | drr | random | wrandom }\n"); fprintf(stderr, "NHFLAGS := [ onlink | pervasive ]\n"); fprintf(stderr, "RTPROTO := [ kernel | boot | static | NUMBER ]\n"); - fprintf(stderr, "TIME := NUMBER[s|ms|us|ns|j]\n"); + fprintf(stderr, "TIME := NUMBER[s|ms]\n"); exit(-1); } @@ -526,8 +526,6 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (mxrta[i] == NULL) continue; - if (!hz) - hz = get_user_hz(); if (i < sizeof(mx_names)/sizeof(char*) && mx_names[i]) fprintf(fp, " %s", mx_names[i]); @@ -549,18 +547,15 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) case RTAX_RTT: case RTAX_RTTVAR: case RTAX_RTO_MIN: - val *= 1000; if (i == RTAX_RTT) val /= 8; else if (i == RTAX_RTTVAR) val /= 4; - if (val >= hz) - fprintf(fp, " %llums", - (unsigned long long) val / hz); + if (val >= 1000) + fprintf(fp, " %gs", val/1e3); else - fprintf(fp, " %.2fms", - (double)val / hz); + fprintf(fp, " %ums", val); } } } diff --git a/lib/utils.c b/lib/utils.c index 52f2b1f4..95adc0cf 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -119,28 +119,15 @@ int get_jiffies(unsigned *jiffies, const char *arg, int *raw) } if (p == arg) return -1; - - if (__iproute2_hz_internal == 0) - __iproute2_hz_internal = __get_hz(); - *raw = 1; if (*p) { *raw = 0; if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 || strcasecmp(p, "secs")==0) - t *= __iproute2_hz_internal; + t *= 1000; else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 || strcasecmp(p, "msecs") == 0) - t *= __iproute2_hz_internal/1000.0; - else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 || - strcasecmp(p, "usecs") == 0) - t *= __iproute2_hz_internal/1000000.0; - else if (strcasecmp(p, "ns") == 0 || strcasecmp(p, "nsec")==0 || - strcasecmp(p, "nsecs") == 0) - t *= __iproute2_hz_internal/1000000000.0; - else if (strcasecmp(p, "j") == 0 || strcasecmp(p, "hz") == 0 || - strcasecmp(p,"jiffies") == 0) t *= 1.0; /* allow suffix, do nothing */ else return -1; diff --git a/man/man8/ip.8 b/man/man8/ip.8 index 8f82842e..c2db5800 100644 --- a/man/man8/ip.8 +++ b/man/man8/ip.8 @@ -395,7 +395,7 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]" .IR KEY " := { " DOTTED_QUAD " | " NUMBER " }" .ti -8 -.IR TIME " := " NUMBER "[s|ms|us|ns|j]" +.IR TIME " := " NUMBER "[s|ms]" .ti -8 .BR "ip maddr" " [ " add " | " del " ]" @@ -1638,10 +1638,7 @@ the initial RTT ('Round Trip Time') estimate. If no suffix is specified the units are raw values passed directly to the routing code to maintain compatibility with previous releases. Otherwise if a suffix of s, sec or secs is used to specify -seconds; ms, msec or msecs to specify milliseconds; us, usec -or usecs to specify microseconds; ns, nsec or nsecs to specify -nanoseconds; j, hz or jiffies to specify jiffies, the value is -converted to what the routing code expects. +seconds and ms, msec or msecs to specify milliseconds. .TP From 81d03dc356df24d55443535eace247b93ff47b4e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 25 Feb 2011 12:54:37 -0800 Subject: [PATCH 11/31] iproute: rename 'get_jiffies' since it uses msecs The get_jiffies() function retrieves rtt-type values in units of milliseconds. This patch updates the function name accordingly, following the pattern given by dst_metric() <=> dst_metric_rtt(). --- include/utils.h | 2 +- ip/iproute.c | 6 +++--- lib/utils.c | 19 +++++++++---------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/utils.h b/include/utils.h index 77c8e5a4..47f8e07d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -79,7 +79,7 @@ extern int mask2bits(__u32 netmask); extern int get_integer(int *val, const char *arg, int base); extern int get_unsigned(unsigned *val, const char *arg, int base); -extern int get_jiffies(unsigned *val, const char *arg, int *raw); +extern int get_time_rtt(unsigned *val, const char *arg, int *raw); #define get_byte get_u8 #define get_ushort get_u16 #define get_short get_s16 diff --git a/ip/iproute.c b/ip/iproute.c index d48e743b..06d2507c 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -835,7 +835,7 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv) mxlock |= (1<= 1 */ - *jiffies = t; - if (*jiffies < t) - *jiffies += 1; + *val = t; + if (*val < t) + *val += 1; return 0; From f3f28c2126343fea70a697fc61392c433e0dc9e1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 23 Jan 2011 00:09:06 +0000 Subject: [PATCH 12/31] sfq: add divisor support In 2.6.39, we can build SFQ queues with a given hash table size, --- tc/q_sfq.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tc/q_sfq.c b/tc/q_sfq.c index 71a3c9ac..98ec530d 100644 --- a/tc/q_sfq.c +++ b/tc/q_sfq.c @@ -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; From 678b99ee6d80a1e80a3ee404dfb32c4bb3202827 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Wed, 26 Jan 2011 07:35:27 +0000 Subject: [PATCH 13/31] iproute2: fix man page whitespace Signed-off-by: Vlad Dogaru --- man/man8/ip.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/man8/ip.8 b/man/man8/ip.8 index c2db5800..0a95b1b0 100644 --- a/man/man8/ip.8 +++ b/man/man8/ip.8 @@ -42,7 +42,7 @@ ip \- show / manipulate routing, devices, policy routing and tunnels .RB "[ " mtu .IR MTU " ]" .br -.BR type TYPE +.BR type " TYPE" .RI "[ " ARGS " ]" .ti -8 @@ -51,7 +51,7 @@ ip \- show / manipulate routing, devices, policy routing and tunnels .ti -8 .BI "ip link delete " DEVICE -.BI type TYPE +.BI type " TYPE" .RI "[ " ARGS " ]" .ti -8 From f323f2a32c3b9c29fb91c812472b7fd663f9ae73 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 11 Jan 2011 06:32:46 +0000 Subject: [PATCH 14/31] iproute2: allow to specify truncation bits on auth algo Hi, here is a patch against iproute2 to allow user to set a state with a specific auth length. Example: $ ip xfrm state add src 10.16.0.72 dst 10.16.0.121 proto ah spi 0x10000000 auth-trunc "sha256" "azertyuiopqsdfghjklmwxcvbn123456" 96 mode tunnel $ ip xfrm state src 10.16.0.72 dst 10.16.0.121 proto ah spi 0x10000000 reqid 0 mode tunnel replay-window 0 auth-trunc hmac(sha256) 0x617a6572747975696f707173646667686a6b6c6d77786376626e313233343536 96 sel src 0.0.0.0/0 dst 0.0.0.0/0 Regards, Nicolas >From 522ed7348cdf3b6f501af2a5a5d989de1696565a Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 23 Dec 2010 06:48:12 -0500 Subject: [PATCH] iproute2: allow to specify truncation bits on auth algo Attribute XFRMA_ALG_AUTH_TRUNC can be used to specify truncation bits, so we add a new algo type: auth-trunc. Signed-off-by: Nicolas Dichtel --- ip/ipxfrm.c | 28 +++++++++++++++++++++++++++- ip/xfrm_state.c | 44 ++++++++++++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c index cc4dc803..a276c0b8 100644 --- a/ip/ipxfrm.c +++ b/ip/ipxfrm.c @@ -155,6 +155,7 @@ const char *strxf_xfrmproto(__u8 proto) static const struct typeent algo_types[]= { { "enc", XFRMA_ALG_CRYPT }, { "auth", XFRMA_ALG_AUTH }, { "comp", XFRMA_ALG_COMP }, { "aead", XFRMA_ALG_AEAD }, + { "auth-trunc", XFRMA_ALG_AUTH_TRUNC }, { NULL, -1 } }; @@ -570,6 +571,25 @@ static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len, fprintf(fp, "%s", _SL_); } +static void xfrm_auth_trunc_print(struct xfrm_algo_auth *algo, int len, + FILE *fp, const char *prefix) +{ + struct { + struct xfrm_algo algo; + char key[algo->alg_key_len / 8]; + } base; + + memcpy(base.algo.alg_name, algo->alg_name, sizeof(base.algo.alg_name)); + base.algo.alg_key_len = algo->alg_key_len; + memcpy(base.algo.alg_key, algo->alg_key, algo->alg_key_len / 8); + + __xfrm_algo_print(&base.algo, XFRMA_ALG_AUTH_TRUNC, len, fp, prefix, 0); + + fprintf(fp, " %d", algo->alg_trunc_len); + + fprintf(fp, "%s", _SL_); +} + static void xfrm_tmpl_print(struct xfrm_user_tmpl *tmpls, int len, __u16 family, FILE *fp, const char *prefix) { @@ -677,12 +697,18 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, fprintf(fp, "\tmark %d/0x%x\n", m->v, m->m); } - if (tb[XFRMA_ALG_AUTH]) { + if (tb[XFRMA_ALG_AUTH] && !tb[XFRMA_ALG_AUTH_TRUNC]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix); } + if (tb[XFRMA_ALG_AUTH_TRUNC]) { + struct rtattr *rta = tb[XFRMA_ALG_AUTH_TRUNC]; + xfrm_auth_trunc_print((struct xfrm_algo_auth *) RTA_DATA(rta), + RTA_PAYLOAD(rta), fp, prefix); + } + if (tb[XFRMA_ALG_AEAD]) { struct rtattr *rta = tb[XFRMA_ALG_AEAD]; xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta), diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c index 165888d3..94acd66b 100644 --- a/ip/xfrm_state.c +++ b/ip/xfrm_state.c @@ -91,11 +91,12 @@ static void usage(void) fprintf(stderr, "ALGO-LIST := [ ALGO-LIST ] | [ ALGO ]\n"); fprintf(stderr, "ALGO := ALGO_TYPE ALGO_NAME ALGO_KEY " - "[ ALGO_ICV_LEN ]\n"); + "[ ALGO_ICV_LEN | ALGO_TRUNC_LEN ]\n"); fprintf(stderr, "ALGO_TYPE := [ "); fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AEAD)); fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_CRYPT)); fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AUTH)); + fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AUTH_TRUNC)); fprintf(stderr, "%s ", strxf_algotype(XFRMA_ALG_COMP)); fprintf(stderr, "]\n"); @@ -360,6 +361,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) case XFRMA_ALG_AEAD: case XFRMA_ALG_CRYPT: case XFRMA_ALG_AUTH: + case XFRMA_ALG_AUTH_TRUNC: case XFRMA_ALG_COMP: { /* ALGO */ @@ -367,11 +369,12 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) union { struct xfrm_algo alg; struct xfrm_algo_aead aead; + struct xfrm_algo_auth auth; } u; char buf[XFRM_ALGO_KEY_BUF_SIZE]; } alg = {}; int len; - __u32 icvlen; + __u32 icvlen, trunclen; char *name; char *key; char *buf; @@ -388,6 +391,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) ealgop = *argv; break; case XFRMA_ALG_AUTH: + case XFRMA_ALG_AUTH_TRUNC: if (aalgop) duparg("ALGOTYPE", *argv); aalgop = *argv; @@ -415,21 +419,33 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) buf = alg.u.alg.alg_key; len = sizeof(alg.u.alg); - if (type != XFRMA_ALG_AEAD) - goto parse_algo; + switch (type) { + case XFRMA_ALG_AEAD: + if (!NEXT_ARG_OK()) + missarg("ALGOICVLEN"); + NEXT_ARG(); + if (get_u32(&icvlen, *argv, 0)) + invarg("\"aead\" ICV length is invalid", + *argv); + alg.u.aead.alg_icv_len = icvlen; - if (!NEXT_ARG_OK()) - missarg("ALGOICVLEN"); - NEXT_ARG(); - if (get_u32(&icvlen, *argv, 0)) - invarg("\"aead\" ICV length is invalid", - *argv); - alg.u.aead.alg_icv_len = icvlen; + buf = alg.u.aead.alg_key; + len = sizeof(alg.u.aead); + break; + case XFRMA_ALG_AUTH_TRUNC: + if (!NEXT_ARG_OK()) + missarg("ALGOTRUNCLEN"); + NEXT_ARG(); + if (get_u32(&trunclen, *argv, 0)) + invarg("\"auth\" trunc length is invalid", + *argv); + alg.u.auth.alg_trunc_len = trunclen; - buf = alg.u.aead.alg_key; - len = sizeof(alg.u.aead); + buf = alg.u.auth.alg_key; + len = sizeof(alg.u.auth); + break; + } -parse_algo: xfrm_algo_parse((void *)&alg, type, name, key, buf, sizeof(alg.buf)); len += alg.u.alg.alg_key_len; From a1e191b90c35f5ef5d7dfba5ad8b5b7a7f57a421 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 25 Feb 2011 19:55:19 -0800 Subject: [PATCH 15/31] iplink: implement setting of master devic --- ip/iplink.c | 16 ++++++++++++++++ man/man8/ip.8 | 15 ++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ip/iplink.c b/ip/iplink.c index 8160855c..8c92bb1c 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -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()) { @@ -362,6 +364,20 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, if (len < 0) return -1; addattr_nest_end(&req->n, vflist); +#ifdef IFLA_MASTER + } 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); +#endif #ifdef IFF_DYNAMIC } else if (matches(*argv, "dynamic") == 0) { NEXT_ARG(); diff --git a/man/man8/ip.8 b/man/man8/ip.8 index 0a95b1b0..c5248ef4 100644 --- a/man/man8/ip.8 +++ b/man/man8/ip.8 @@ -97,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 @@ -1055,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, From d5b7420a269e6e220e00cfbd69546d157fac1332 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 25 Feb 2011 20:00:54 -0800 Subject: [PATCH 16/31] Remove #ifdef's The iproute package keeps its own headers so there is no need of polluting code with #ifdef's --- ip/ipaddress.c | 2 -- ip/iplink.c | 6 ------ ip/ipneigh.c | 2 -- ip/iproute.c | 11 ++--------- lib/ll_proto.c | 17 ----------------- 5 files changed, 2 insertions(+), 36 deletions(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 524ea018..a7350af4 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -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])); diff --git a/ip/iplink.c b/ip/iplink.c index 8c92bb1c..48c02548 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -364,7 +364,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, if (len < 0) return -1; addattr_nest_end(&req->n, vflist); -#ifdef IFLA_MASTER } else if (matches(*argv, "master") == 0) { int ifindex; NEXT_ARG(); @@ -377,8 +376,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, int ifindex = 0; addattr_l(&req->n, sizeof(*req), IFLA_MASTER, &ifindex, 4); -#endif -#ifdef IFF_DYNAMIC } else if (matches(*argv, "dynamic") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_DYNAMIC; @@ -388,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; @@ -829,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; @@ -839,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(); diff --git a/ip/ipneigh.c b/ip/ipneigh.c index 2d96ab7c..dff9eb46 100644 --- a/ip/ipneigh.c +++ b/ip/ipneigh.c @@ -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; diff --git a/ip/iproute.c b/ip/iproute.c index 06d2507c..2fef35b7 100644 --- a/ip/iproute.c +++ b/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(); diff --git a/lib/ll_proto.c b/lib/ll_proto.c index cdd1602e..2277cda3 100644 --- a/lib/ll_proto.c +++ b/lib/ll_proto.c @@ -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) From 98f5519cd9db9d1ca58c49af27698101c8fff373 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 1 Feb 2011 07:29:54 -0500 Subject: [PATCH 17/31] iproute2: add support of flag XFRM_STATE_ALIGN4 Signed-off-by: Nicolas Dichtel --- ip/ipxfrm.c | 1 + ip/xfrm_state.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c index a276c0b8..0c7aaad8 100644 --- a/ip/ipxfrm.c +++ b/ip/ipxfrm.c @@ -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); } diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c index 94acd66b..8ac3437a 100644 --- a/ip/xfrm_state.c +++ b/ip/xfrm_state.c @@ -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; From 2230ac1d1871b121284cb163fdf54062663d1ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Wed, 9 Mar 2011 10:18:03 -0800 Subject: [PATCH 18/31] Remove -L flags from link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the previous code was supposed to work nonetheless, it could be messed up if further -L were used in LDFLAGS to list the path where glibc's libutil was to be found. References: https://bugs.gentoo.org/347489 Signed-off-by: Diego Elio Pettenò --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c03d74c9..d1ace1f7 100644 --- a/Makefile +++ b/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; \ From 46dc73a57d569bc036c36d922f2699e725b5c1aa Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 9 Mar 2011 10:39:17 -0800 Subject: [PATCH 19/31] Add no-strict-aliasing to genl The genl code uses constructs which violate the strict aliasing constraints of gcc 4.4. Disable the optimization to avoid warnings and potential breakage. --- genl/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/genl/Makefile b/genl/Makefile index 44bb83cd..03d1f26a 100644 --- a/genl/Makefile +++ b/genl/Makefile @@ -3,6 +3,8 @@ GENLOBJ=genl.o include ../Config SHARED_LIBS ?= y +CFLAGS += -fno-strict-aliasing + GENLMODULES := GENLMODULES += ctrl.o From 38c867d2a82d6f2b60450550fbaaadc5d9c77579 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 9 Mar 2011 10:41:09 -0800 Subject: [PATCH 20/31] Add checks for fgets() when reading proc If expected proc headers are missing, catch and print error. --- ip/ip6tunnel.c | 7 +++++-- ip/ipmaddr.c | 3 ++- ip/ipmroute.c | 6 ++++-- ip/iptunnel.c | 8 ++++++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c index f0db5aa0..b08723a8 100644 --- a/ip/ip6tunnel.c +++ b/ip/ip6tunnel.c @@ -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]; diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c index 44ffdfcf..ec326bc0 100644 --- a/ip/ipmaddr.c +++ b/ip/ipmaddr.c @@ -128,7 +128,8 @@ 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; diff --git a/ip/ipmroute.c b/ip/ipmroute.c index 977143cc..a4389f57 100644 --- a/ip/ipmroute.c +++ b/ip/ipmroute.c @@ -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; diff --git a/ip/iptunnel.c b/ip/iptunnel.c index fe5e3f96..f038f0a6 100644 --- a/ip/iptunnel.c +++ b/ip/iptunnel.c @@ -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; From 8988b02ee1d04fdf07b913454b8d4e7b5e3092e5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 9 Mar 2011 10:41:44 -0800 Subject: [PATCH 21/31] Fix snprintf with non format snprintf was being called with environment variable. If variable had format string (like %s) then program would crash. --- misc/rtacct.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/misc/rtacct.c b/misc/rtacct.c index a247dfd2..ab8fdbb8 100644 --- a/misc/rtacct.c +++ b/misc/rtacct.c @@ -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, From d7ac9ad4f480d6e162165ec3f2c8e1bf50003ec3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 9 Mar 2011 10:42:35 -0800 Subject: [PATCH 22/31] Fix warning in u32 from assignment in conditional --- tc/f_u32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tc/f_u32.c b/tc/f_u32.c index d9d40914..c77e9cc8 100644 --- a/tc/f_u32.c +++ b/tc/f_u32.c @@ -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; From 1f7190db3920f76cca7fdcd1bb318c6cfa4a3266 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 23 Mar 2011 12:03:49 -0700 Subject: [PATCH 23/31] ip: fix memory leak in ipmaddr.c If the continue is taken, then there is a memory leak. https://bugzilla.novell.com/show_bug.cgi?id=538996 Reported-by: David Binderman Signed-off-by: Brandon Philips --- ip/ipmaddr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c index ec326bc0..5a52c856 100644 --- a/ip/ipmaddr.c +++ b/ip/ipmaddr.c @@ -136,7 +136,7 @@ void read_igmp(struct ma_info **result_p) 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); From 59a935d2045b233539a2d0be00310d355a9e0ebd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 23 Mar 2011 12:29:06 -0700 Subject: [PATCH 24/31] Update email address of netem --- tc/q_netem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc/q_netem.c b/tc/q_netem.c index 6aaaded9..01639a87 100644 --- a/tc/q_netem.c +++ b/tc/q_netem.c @@ -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 + * Authors: Stephen Hemminger * */ From 876cd7fa1001c538f6d2211745ac396d32659b2b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 23 Mar 2011 12:34:21 -0700 Subject: [PATCH 25/31] Add README.devel --- README.devel | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 README.devel diff --git a/README.devel b/README.devel new file mode 100644 index 00000000..2022869a --- /dev/null +++ b/README.devel @@ -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 + + +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. + From d7f3299d591e31f84ea3b8d4549d4019da1f9a7b Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Thu, 24 Mar 2011 18:44:09 +0100 Subject: [PATCH 26/31] tc : SFB flow scheduler Supports SFB qdisc (included in linux-2.6.39) 1) Setup phase : accept non default parameters 2) dump information qdisc sfb 11: parent 1:11 limit 1 max 25 target 20 increment 0.00050 decrement 0.00005 penalty rate 10 burst 20 (600000ms 60000ms) Sent 47991616 bytes 521648 pkt (dropped 549245, overlimits 549245 requeues 0) rate 7193Kbit 9774pps backlog 0b 0p requeues 0 earlydrop 0 penaltydrop 0 bucketdrop 0 queuedrop 549245 childdrop 0 marked 0 maxqlen 0 maxprob 0.00000 avgprob 0.00000 Signed-off-by: Juliusz Chroboczek Signed-off-by: Eric Dumazet --- tc/Makefile | 1 + tc/q_sfb.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 tc/q_sfb.c diff --git a/tc/Makefile b/tc/Makefile index 2cbd5d52..24584f12 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -16,6 +16,7 @@ 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 diff --git a/tc/q_sfb.c b/tc/q_sfb.c new file mode 100644 index 00000000..f11c33aa --- /dev/null +++ b/tc/q_sfb.c @@ -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 + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, +}; From 27b3f524443ec617b125fcecb36ad1bc25268b72 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Fri, 25 Mar 2011 14:43:44 -0700 Subject: [PATCH 27/31] doc: add pdf targets Hello Stephen- Here is one more patch that SUSE has been carrying. Cheers, Brandon --- doc/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/Makefile b/doc/Makefile index 84836a28..1df60813 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -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 $@ From 914953046aac346b16143eee1c04b8a49bec8c8e Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Tue, 12 Apr 2011 08:57:27 -0700 Subject: [PATCH 28/31] iproute2: tc add mqprio qdisc support Add mqprio qdisc support. Output matches the following, qdisc mq 0: dev eth1 root qdisc mq 0: dev eth2 root qdisc mqprio 8001: dev eth3 root tc 8 map 0 1 2 3 4 5 6 7 1 1 1 1 1 1 1 1 queues:(0:7) (8:15) (16:23) (24:31) (32:39) (40:47) (48:55) (56:63) And usage is, Usage: ... mclass [num_tc NUMBER] [map P0 P1...] [offset txq0 txq1 ...] [count cnt0 cnt1 ...] [hw 1|0] Signed-off-by: John Fastabend --- tc/Makefile | 1 + tc/q_mqprio.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 tc/q_mqprio.c diff --git a/tc/Makefile b/tc/Makefile index 24584f12..961e5ce7 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -45,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) diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c new file mode 100644 index 00000000..c589b4ca --- /dev/null +++ b/tc/q_mqprio.c @@ -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, + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, +}; From 7b032a1f773ed5f17e16c1feff8b0a124d5db98d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 23 Mar 2011 12:29:17 -0700 Subject: [PATCH 29/31] Update README information Change url's and describe current kernel header values. --- README | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/README b/README index 7d54bd2d..0ed03729 100644 --- a/README +++ b/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 From c0635644cd0a4471c09f665f7098713f3157c170 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Thu, 7 Apr 2011 09:37:05 +0200 Subject: [PATCH 30/31] iproute2: parse flag XFRM_POLICY_ICMP parse flag XFRM_POLICY_ICMP Signed-off-by: Ulrich Weber --- ip/ipxfrm.c | 1 + ip/xfrm_policy.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c index 0c7aaad8..48a732f0 100644 --- a/ip/ipxfrm.c +++ b/ip/ipxfrm.c @@ -981,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); } diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c index 9ef5c09d..7827f91a 100644 --- a/ip/xfrm_policy.c +++ b/ip/xfrm_policy.c @@ -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; From 242b8da71be73204500cc85613a399d6968f23af Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 12 Apr 2011 14:40:14 -0700 Subject: [PATCH 31/31] Use INIT_NETDEV_GROUP Now that headers are sanitized, use the define. --- ip/ipaddress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index a7350af4..a1f78b94 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -723,7 +723,7 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush) if (filter.family == AF_UNSPEC) filter.family = preferred_family; - filter.group = 0; /* INIT_NETDEV_GROUP */ + filter.group = INIT_NETDEV_GROUP; if (flush) { if (argc <= 0) {