* [PATCH] sched: QFQ - quick fair queue scheduler (v3.1)
From: Stephen Hemminger @ 2011-03-03 23:02 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Eric Dumazet, David Miller, Fabio Checconi, Luigi Rizzo, netdev
In-Reply-To: <20110303145947.44209d0a@nehalam>
This is an implementation of the Quick Fair Queue scheduler developed
by Fabio Checconi. The same algorithm is already implemented in ipfw
in FreeBSD. Fabio had an earlier version developed on Linux, I just
cleaned it up. Thanks to Eric Dumazet for doing the testing and
finding bugs.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
---
v3 - fix bugs in statistics and initialization
include/linux/pkt_sched.h | 15
net/sched/Kconfig | 11
net/sched/Makefile | 1
net/sched/sch_qfq.c | 1125 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1152 insertions(+)
--- a/include/linux/pkt_sched.h 2011-03-03 13:47:51.606153909 -0800
+++ b/include/linux/pkt_sched.h 2011-03-03 13:48:01.850269983 -0800
@@ -588,4 +588,19 @@ struct tc_sfb_xstats {
#define SFB_MAX_PROB 0xFFFF
+/* QFQ */
+enum {
+ TCA_QFQ_UNSPEC,
+ TCA_QFQ_WEIGHT,
+ TCA_QFQ_LMAX,
+ __TCA_QFQ_MAX
+};
+
+#define TCA_QFQ_MAX (__TCA_QFQ_MAX - 1)
+
+struct tc_qfq_stats {
+ __u32 weight;
+ __u32 lmax;
+};
+
#endif
--- a/net/sched/Kconfig 2011-03-03 13:47:51.614153999 -0800
+++ b/net/sched/Kconfig 2011-03-03 13:48:01.850269983 -0800
@@ -239,6 +239,17 @@ config NET_SCH_CHOKE
To compile this code as a module, choose M here: the
module will be called sch_choke.
+config NET_SCH_QFQ
+ tristate "Quick Fair Queueing scheduler (QFQ)"
+ help
+ Say Y here if you want to use the Quick Fair Queueing Scheduler (QFQ)
+ packet scheduling algorithm.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sch_qfq.
+
+ If unsure, say N.
+
config NET_SCH_INGRESS
tristate "Ingress Qdisc"
depends on NET_CLS_ACT
--- a/net/sched/Makefile 2011-03-03 13:47:51.618154045 -0800
+++ b/net/sched/Makefile 2011-03-03 13:48:01.850269983 -0800
@@ -35,6 +35,7 @@ obj-$(CONFIG_NET_SCH_NETEM) += sch_netem
obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o
obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o
obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o
+obj-$(CONFIG_NET_SCH_QFQ) += sch_qfq.o
obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/net/sched/sch_qfq.c 2011-03-03 13:48:01.850269983 -0800
@@ -0,0 +1,1125 @@
+/*
+ * net/sched/sch_qfq.c Quick Fair Queueing Scheduler.
+ *
+ * Copyright (c) 2009 Fabio Checconi, Luigi Rizzo, and Paolo Valente.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/pkt_sched.h>
+#include <net/sch_generic.h>
+#include <net/pkt_sched.h>
+#include <net/pkt_cls.h>
+
+
+/* Quick Fair Queueing
+ ===================
+
+ Sources:
+ Fabio Checconi and Scuola Superiore and S. Anna
+ and Paolo Valente and Luigi Riz "QFQ: Efficient Packet Scheduling
+ with Tight Bandwidth Distribution Guarantees"
+
+ See also:
+ http://retis.sssup.it/~fabio/linux/qfq/
+ */
+
+/*
+
+ Virtual time computations.
+
+ S, F and V are all computed in fixed point arithmetic with
+ FRAC_BITS decimal bits.
+
+ QFQ_MAX_INDEX is the maximum index allowed for a group. We need
+ one bit per index.
+ QFQ_MAX_WSHIFT is the maximum power of two supported as a weight.
+
+ The layout of the bits is as below:
+
+ [ MTU_SHIFT ][ FRAC_BITS ]
+ [ MAX_INDEX ][ MIN_SLOT_SHIFT ]
+ ^.__grp->index = 0
+ *.__grp->slot_shift
+
+ where MIN_SLOT_SHIFT is derived by difference from the others.
+
+ The max group index corresponds to Lmax/w_min, where
+ Lmax=1<<MTU_SHIFT, w_min = 1 .
+ From this, and knowing how many groups (MAX_INDEX) we want,
+ we can derive the shift corresponding to each group.
+
+ Because we often need to compute
+ F = S + len/w_i and V = V + len/wsum
+ instead of storing w_i store the value
+ inv_w = (1<<FRAC_BITS)/w_i
+ so we can do F = S + len * inv_w * wsum.
+ We use W_TOT in the formulas so we can easily move between
+ static and adaptive weight sum.
+
+ The per-scheduler-instance data contain all the data structures
+ for the scheduler: bitmaps and bucket lists.
+
+ */
+
+/*
+ * Maximum number of consecutive slots occupied by backlogged classes
+ * inside a group.
+ */
+#define QFQ_MAX_SLOTS 32
+
+/*
+ * Shifts used for class<->group mapping. We allow class weights that are
+ * in the range [1, 2^MAX_WSHIFT], and we try to map each class i to the
+ * group with the smallest index that can support the L_i / r_i configured
+ * for the class.
+ *
+ * grp->index is the index of the group; and grp->slot_shift
+ * is the shift for the corresponding (scaled) sigma_i.
+ */
+#define QFQ_MAX_INDEX 19
+#define QFQ_MAX_WSHIFT 16
+
+#define QFQ_MAX_WEIGHT (1<<QFQ_MAX_WSHIFT)
+#define QFQ_MAX_WSUM (2*QFQ_MAX_WEIGHT)
+
+#define FRAC_BITS 30 /* fixed point arithmetic */
+#define ONE_FP (1UL << FRAC_BITS)
+#define IWSUM (ONE_FP/QFQ_MAX_WSUM)
+
+#define QFQ_MTU_SHIFT 11
+#define QFQ_MIN_SLOT_SHIFT (FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX)
+
+/*
+ * Possible group states. These values are used as indexes for the bitmaps
+ * array of struct qfq_queue.
+ */
+enum qfq_state { ER, IR, EB, IB, QFQ_MAX_STATE };
+
+struct qfq_group;
+
+struct qfq_class {
+ struct Qdisc_class_common common;
+
+ unsigned int refcnt;
+ unsigned int filter_cnt;
+
+ struct gnet_stats_basic_packed bstats;
+ struct gnet_stats_queue qstats;
+ struct gnet_stats_rate_est rate_est;
+ struct Qdisc *qdisc;
+
+ struct qfq_class *next; /* Link for the slot list. */
+ u64 S, F; /* flow timestamps (exact) */
+
+ /* group we belong to. In principle we would need the index,
+ * which is log_2(lmax/weight), but we never reference it
+ * directly, only the group.
+ */
+ struct qfq_group *grp;
+
+ /* these are copied from the flowset. */
+ u32 inv_w; /* ONE_FP/weight */
+ u32 lmax; /* Max packet size for this flow. */
+};
+
+struct qfq_group {
+ u64 S, F; /* group timestamps (approx). */
+ unsigned int slot_shift; /* Slot shift. */
+ unsigned int index; /* Group index. */
+ unsigned int front; /* Index of the front slot. */
+ unsigned long full_slots; /* non-empty slots */
+
+ /* Array of RR lists of active classes. */
+ struct qfq_class *slots[QFQ_MAX_SLOTS];
+};
+
+struct qfq_sched {
+ struct tcf_proto *filter_list;
+ struct Qdisc_class_hash clhash;
+
+ u64 V; /* Precise virtual time. */
+ u32 wsum; /* weight sum */
+
+ unsigned long bitmaps[QFQ_MAX_STATE]; /* Group bitmaps. */
+ struct qfq_group groups[QFQ_MAX_INDEX + 1]; /* The groups. */
+};
+
+static struct qfq_class *qfq_find_class(struct Qdisc *sch, u32 classid)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct Qdisc_class_common *clc;
+
+ clc = qdisc_class_find(&q->clhash, classid);
+ if (clc == NULL)
+ return NULL;
+ return container_of(clc, struct qfq_class, common);
+}
+
+static void qfq_purge_queue(struct qfq_class *cl)
+{
+ unsigned int len = cl->qdisc->q.qlen;
+
+ qdisc_reset(cl->qdisc);
+ qdisc_tree_decrease_qlen(cl->qdisc, len);
+}
+
+static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = {
+ [TCA_QFQ_WEIGHT] = { .type = NLA_U32 },
+ [TCA_QFQ_LMAX] = { .type = NLA_U32 },
+};
+
+/*
+ * Calculate a flow index, given its weight and maximum packet length.
+ * index = log_2(maxlen/weight) but we need to apply the scaling.
+ * This is used only once at flow creation.
+ */
+static int qfq_calc_index(u32 inv_w, unsigned int maxlen)
+{
+ u64 slot_size = (u64)maxlen * inv_w;
+ unsigned long size_map;
+ int index = 0;
+
+ size_map = slot_size >> QFQ_MIN_SLOT_SHIFT;
+ if (!size_map)
+ goto out;
+
+ index = __fls(size_map) + 1; /* basically a log_2 */
+ index -= !(slot_size - (1ULL << (index + QFQ_MIN_SLOT_SHIFT - 1)));
+
+ if (index < 0)
+ index = 0;
+out:
+ pr_debug("qfq calc_index: W = %lu, L = %u, I = %d\n",
+ (unsigned long) ONE_FP/inv_w, maxlen, index);
+
+ return index;
+}
+
+static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
+ struct nlattr **tca, unsigned long *arg)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_class *cl = (struct qfq_class *)*arg;
+ struct nlattr *tb[TCA_QFQ_MAX + 1];
+ u32 weight, lmax, inv_w;
+ int i, err;
+
+ if (tca[TCA_OPTIONS] == NULL)
+ return -EINVAL;
+
+ err = nla_parse_nested(tb, TCA_QFQ_MAX, tca[TCA_OPTIONS], qfq_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_QFQ_WEIGHT]) {
+ weight = nla_get_u32(tb[TCA_QFQ_WEIGHT]);
+ if (!weight || weight > (1UL << QFQ_MAX_WSHIFT)) {
+ pr_notice("qfq: invalid weight %u\n", weight);
+ return -EINVAL;
+ }
+ } else
+ weight = 1;
+
+ inv_w = ONE_FP / weight;
+ weight = ONE_FP / inv_w;
+ if (q->wsum + weight > QFQ_MAX_WSUM) {
+ pr_notice("qfq: total weight out of range (%u + %u)\n",
+ weight, q->wsum);
+ return -EINVAL;
+ }
+
+ if (tb[TCA_QFQ_LMAX]) {
+ lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
+ if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) {
+ pr_notice("qfq: invalid max length %u\n", lmax);
+ return -EINVAL;
+ }
+ } else
+ lmax = 1UL << QFQ_MTU_SHIFT;
+
+ if (cl != NULL) {
+ if (tca[TCA_RATE]) {
+ err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
+ qdisc_root_sleeping_lock(sch),
+ tca[TCA_RATE]);
+ if (err)
+ return err;
+ }
+
+ sch_tree_lock(sch);
+ if (tb[TCA_QFQ_WEIGHT]) {
+ q->wsum = weight - ONE_FP / cl->inv_w;
+ cl->inv_w = inv_w;
+ }
+ sch_tree_unlock(sch);
+
+ return 0;
+ }
+
+ cl = kzalloc(sizeof(struct qfq_class), GFP_KERNEL);
+ if (cl == NULL)
+ return -ENOBUFS;
+
+ cl->refcnt = 1;
+ cl->common.classid = classid;
+ cl->lmax = lmax;
+ cl->inv_w = inv_w;
+ i = qfq_calc_index(cl->inv_w, cl->lmax);
+
+ cl->grp = &q->groups[i];
+ q->wsum += weight;
+
+ cl->qdisc = qdisc_create_dflt(sch->dev_queue,
+ &pfifo_qdisc_ops, classid);
+ if (cl->qdisc == NULL)
+ cl->qdisc = &noop_qdisc;
+
+ if (tca[TCA_RATE]) {
+ err = gen_new_estimator(&cl->bstats, &cl->rate_est,
+ qdisc_root_sleeping_lock(sch),
+ tca[TCA_RATE]);
+ if (err) {
+ qdisc_destroy(cl->qdisc);
+ kfree(cl);
+ return err;
+ }
+ }
+
+ sch_tree_lock(sch);
+ qdisc_class_hash_insert(&q->clhash, &cl->common);
+ sch_tree_unlock(sch);
+
+ qdisc_class_hash_grow(sch, &q->clhash);
+
+ *arg = (unsigned long)cl;
+ return 0;
+}
+
+static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+
+ if (cl->inv_w) {
+ q->wsum -= ONE_FP / cl->inv_w;
+ cl->inv_w = 0;
+ }
+
+ gen_kill_estimator(&cl->bstats, &cl->rate_est);
+ qdisc_destroy(cl->qdisc);
+ kfree(cl);
+}
+
+static int qfq_delete_class(struct Qdisc *sch, unsigned long arg)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_class *cl = (struct qfq_class *)arg;
+
+ if (cl->filter_cnt > 0)
+ return -EBUSY;
+
+ sch_tree_lock(sch);
+
+ qfq_purge_queue(cl);
+ qdisc_class_hash_remove(&q->clhash, &cl->common);
+
+ if (--cl->refcnt == 0)
+ qfq_destroy_class(sch, cl);
+
+ sch_tree_unlock(sch);
+ return 0;
+}
+
+static unsigned long qfq_get_class(struct Qdisc *sch, u32 classid)
+{
+ struct qfq_class *cl = qfq_find_class(sch, classid);
+
+ if (cl != NULL)
+ cl->refcnt++;
+
+ return (unsigned long)cl;
+}
+
+static void qfq_put_class(struct Qdisc *sch, unsigned long arg)
+{
+ struct qfq_class *cl = (struct qfq_class *)arg;
+
+ if (--cl->refcnt == 0)
+ qfq_destroy_class(sch, cl);
+}
+
+static struct tcf_proto **qfq_tcf_chain(struct Qdisc *sch, unsigned long cl)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+
+ if (cl)
+ return NULL;
+
+ return &q->filter_list;
+}
+
+static unsigned long qfq_bind_tcf(struct Qdisc *sch, unsigned long parent,
+ u32 classid)
+{
+ struct qfq_class *cl = qfq_find_class(sch, classid);
+
+ if (cl != NULL)
+ cl->filter_cnt++;
+
+ return (unsigned long)cl;
+}
+
+static void qfq_unbind_tcf(struct Qdisc *sch, unsigned long arg)
+{
+ struct qfq_class *cl = (struct qfq_class *)arg;
+
+ cl->filter_cnt--;
+}
+
+static int qfq_graft_class(struct Qdisc *sch, unsigned long arg,
+ struct Qdisc *new, struct Qdisc **old)
+{
+ struct qfq_class *cl = (struct qfq_class *)arg;
+
+ if (new == NULL) {
+ new = qdisc_create_dflt(sch->dev_queue,
+ &pfifo_qdisc_ops, cl->common.classid);
+ if (new == NULL)
+ new = &noop_qdisc;
+ }
+
+ sch_tree_lock(sch);
+ qfq_purge_queue(cl);
+ *old = cl->qdisc;
+ cl->qdisc = new;
+ sch_tree_unlock(sch);
+ return 0;
+}
+
+static struct Qdisc *qfq_class_leaf(struct Qdisc *sch, unsigned long arg)
+{
+ struct qfq_class *cl = (struct qfq_class *)arg;
+
+ return cl->qdisc;
+}
+
+static int qfq_dump_class(struct Qdisc *sch, unsigned long arg,
+ struct sk_buff *skb, struct tcmsg *tcm)
+{
+ struct qfq_class *cl = (struct qfq_class *)arg;
+ struct nlattr *nest;
+
+ tcm->tcm_parent = TC_H_ROOT;
+ tcm->tcm_handle = cl->common.classid;
+ tcm->tcm_info = cl->qdisc->handle;
+
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
+ NLA_PUT_U32(skb, TCA_QFQ_WEIGHT, ONE_FP/cl->inv_w);
+ NLA_PUT_U32(skb, TCA_QFQ_LMAX, cl->lmax);
+ return nla_nest_end(skb, nest);
+
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+}
+
+static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
+ struct gnet_dump *d)
+{
+ struct qfq_class *cl = (struct qfq_class *)arg;
+ struct tc_qfq_stats xstats;
+
+ memset(&xstats, 0, sizeof(xstats));
+ cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
+
+ xstats.weight = ONE_FP/cl->inv_w;
+ xstats.lmax = cl->lmax;
+
+ if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
+ gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
+ gnet_stats_copy_queue(d, &cl->qdisc->qstats) < 0)
+ return -1;
+
+ return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
+}
+
+static void qfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_class *cl;
+ struct hlist_node *n;
+ unsigned int i;
+
+ if (arg->stop)
+ return;
+
+ for (i = 0; i < q->clhash.hashsize; i++) {
+ hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
+ if (arg->count < arg->skip) {
+ arg->count++;
+ continue;
+ }
+ if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
+ arg->stop = 1;
+ return;
+ }
+ arg->count++;
+ }
+ }
+}
+
+static struct qfq_class *qfq_classify(struct sk_buff *skb, struct Qdisc *sch,
+ int *qerr)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_class *cl;
+ struct tcf_result res;
+ int result;
+
+ if (TC_H_MAJ(skb->priority ^ sch->handle) == 0) {
+ pr_debug("qfq_classify: found %d\n", skb->priority);
+ cl = qfq_find_class(sch, skb->priority);
+ if (cl != NULL)
+ return cl;
+ }
+
+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+ result = tc_classify(skb, q->filter_list, &res);
+ if (result >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+ switch (result) {
+ case TC_ACT_QUEUED:
+ case TC_ACT_STOLEN:
+ *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+ case TC_ACT_SHOT:
+ return NULL;
+ }
+#endif
+ cl = (struct qfq_class *)res.class;
+ if (cl == NULL)
+ cl = qfq_find_class(sch, res.classid);
+ return cl;
+ }
+
+ return NULL;
+}
+
+/* Generic comparison function, handling wraparound. */
+static inline int qfq_gt(u64 a, u64 b)
+{
+ return (s64)(a - b) > 0;
+}
+
+/* Round a precise timestamp to its slotted value. */
+static inline u64 qfq_round_down(u64 ts, unsigned int shift)
+{
+ return ts & ~((1ULL << shift) - 1);
+}
+
+/* return the pointer to the group with lowest index in the bitmap */
+static inline struct qfq_group *qfq_ffs(struct qfq_sched *q,
+ unsigned long bitmap)
+{
+ int index = __ffs(bitmap);
+ return &q->groups[index];
+}
+/* Calculate a mask to mimic what would be ffs_from(). */
+static inline unsigned long mask_from(unsigned long bitmap, int from)
+{
+ return bitmap & ~((1UL << from) - 1);
+}
+
+/*
+ * The state computation relies on ER=0, IR=1, EB=2, IB=3
+ * First compute eligibility comparing grp->S, q->V,
+ * then check if someone is blocking us and possibly add EB
+ */
+static int qfq_calc_state(struct qfq_sched *q, const struct qfq_group *grp)
+{
+ /* if S > V we are not eligible */
+ unsigned int state = qfq_gt(grp->S, q->V);
+ unsigned long mask = mask_from(q->bitmaps[ER], grp->index);
+ struct qfq_group *next;
+
+ if (mask) {
+ next = qfq_ffs(q, mask);
+ if (qfq_gt(grp->F, next->F))
+ state |= EB;
+ }
+
+ return state;
+}
+
+
+/*
+ * In principle
+ * q->bitmaps[dst] |= q->bitmaps[src] & mask;
+ * q->bitmaps[src] &= ~mask;
+ * but we should make sure that src != dst
+ */
+static inline void qfq_move_groups(struct qfq_sched *q, unsigned long mask,
+ int src, int dst)
+{
+ q->bitmaps[dst] |= q->bitmaps[src] & mask;
+ q->bitmaps[src] &= ~mask;
+}
+
+static void qfq_unblock_groups(struct qfq_sched *q, int index, u64 old_F)
+{
+ unsigned long mask = mask_from(q->bitmaps[ER], index + 1);
+ struct qfq_group *next;
+
+ if (mask) {
+ next = qfq_ffs(q, mask);
+ if (!qfq_gt(next->F, old_F))
+ return;
+ }
+
+ mask = (1UL << index) - 1;
+ qfq_move_groups(q, mask, EB, ER);
+ qfq_move_groups(q, mask, IB, IR);
+}
+
+/*
+ * perhaps
+ *
+ old_V ^= q->V;
+ old_V >>= QFQ_MIN_SLOT_SHIFT;
+ if (old_V) {
+ ...
+ }
+ *
+ */
+static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)
+{
+ unsigned long vslot = q->V >> QFQ_MIN_SLOT_SHIFT;
+ unsigned long old_vslot = old_V >> QFQ_MIN_SLOT_SHIFT;
+
+ if (vslot != old_vslot) {
+ unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1;
+ qfq_move_groups(q, mask, IR, ER);
+ qfq_move_groups(q, mask, IB, EB);
+ }
+}
+
+/*
+ * XXX we should make sure that slot becomes less than 32.
+ * This is guaranteed by the input values.
+ * roundedS is always cl->S rounded on grp->slot_shift bits.
+ */
+static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl,
+ u64 roundedS)
+{
+ u64 slot = (roundedS - grp->S) >> grp->slot_shift;
+ unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS;
+
+ cl->next = grp->slots[i];
+ grp->slots[i] = cl;
+ __set_bit(slot, &grp->full_slots);
+}
+
+/*
+ * remove the entry from the slot
+ */
+static void qfq_front_slot_remove(struct qfq_group *grp)
+{
+ struct qfq_class **h = &grp->slots[grp->front];
+
+ *h = (*h)->next;
+ if (!*h)
+ __clear_bit(0, &grp->full_slots);
+}
+
+/*
+ * Returns the first full queue in a group. As a side effect,
+ * adjust the bucket list so the first non-empty bucket is at
+ * position 0 in full_slots.
+ */
+static struct qfq_class *qfq_slot_scan(struct qfq_group *grp)
+{
+ unsigned int i;
+
+ pr_debug("qfq slot_scan: grp %u full %#lx\n",
+ grp->index, grp->full_slots);
+
+ if (grp->full_slots == 0)
+ return NULL;
+
+ i = __ffs(grp->full_slots); /* zero based */
+ if (i > 0) {
+ grp->front = (grp->front + i) % QFQ_MAX_SLOTS;
+ grp->full_slots >>= i;
+ }
+
+ return grp->slots[grp->front];
+}
+
+/*
+ * adjust the bucket list. When the start time of a group decreases,
+ * we move the index down (modulo QFQ_MAX_SLOTS) so we don't need to
+ * move the objects. The mask of occupied slots must be shifted
+ * because we use ffs() to find the first non-empty slot.
+ * This covers decreases in the group's start time, but what about
+ * increases of the start time ?
+ * Here too we should make sure that i is less than 32
+ */
+static void qfq_slot_rotate(struct qfq_group *grp, u64 roundedS)
+{
+ unsigned int i = (grp->S - roundedS) >> grp->slot_shift;
+
+ grp->full_slots <<= i;
+ grp->front = (grp->front - i) % QFQ_MAX_SLOTS;
+}
+
+static void qfq_update_eligible(struct qfq_sched *q, u64 old_V)
+{
+ struct qfq_group *grp;
+ unsigned long ineligible;
+
+ ineligible = q->bitmaps[IR] | q->bitmaps[IB];
+ if (ineligible) {
+ if (!q->bitmaps[ER]) {
+ grp = qfq_ffs(q, ineligible);
+ if (qfq_gt(grp->S, q->V))
+ q->V = grp->S;
+ }
+ qfq_make_eligible(q, old_V);
+ }
+}
+
+/* What is length of next packet in queue (0 if queue is empty) */
+static unsigned int qdisc_peek_len(struct Qdisc *sch)
+{
+ struct sk_buff *skb;
+
+ skb = sch->ops->peek(sch);
+ return skb ? qdisc_pkt_len(skb) : 0;
+}
+
+/*
+ * Updates the class, returns true if also the group needs to be updated.
+ */
+static bool qfq_update_class(struct qfq_group *grp, struct qfq_class *cl)
+{
+ unsigned int len = qdisc_peek_len(cl->qdisc);
+
+ cl->S = cl->F;
+ if (!len)
+ qfq_front_slot_remove(grp); /* queue is empty */
+ else {
+ u64 roundedS;
+
+ cl->F = cl->S + (u64)len * cl->inv_w;
+ roundedS = qfq_round_down(cl->S, grp->slot_shift);
+ if (roundedS == grp->S)
+ return false;
+
+ qfq_front_slot_remove(grp);
+ qfq_slot_insert(grp, cl, roundedS);
+ }
+
+ return true;
+}
+
+static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_group *grp;
+ struct qfq_class *cl;
+ struct sk_buff *skb;
+ unsigned int len;
+ u64 old_V;
+
+ if (!q->bitmaps[ER])
+ return NULL;
+
+ grp = qfq_ffs(q, q->bitmaps[ER]);
+
+ cl = grp->slots[grp->front];
+ skb = qdisc_dequeue_peeked(cl->qdisc);
+ if (!skb) {
+ WARN_ONCE(1, "qfq_dequeue: non-workconserving leaf\n");
+ return NULL;
+ }
+
+ sch->q.qlen--;
+ qdisc_bstats_update(sch, skb);
+
+ old_V = q->V;
+ len = qdisc_pkt_len(skb);
+ q->V += (u64)len * IWSUM;
+ pr_debug("qfq dequeue: len %u F %lld now %lld\n",
+ len, (unsigned long long) cl->F, (unsigned long long) q->V);
+
+ if (qfq_update_class(grp, cl)) {
+ u64 old_F = grp->F;
+
+ cl = qfq_slot_scan(grp);
+ if (!cl)
+ __clear_bit(grp->index, &q->bitmaps[ER]);
+ else {
+ u64 roundedS = qfq_round_down(cl->S, grp->slot_shift);
+ unsigned int s;
+
+ if (grp->S == roundedS)
+ goto skip_unblock;
+ grp->S = roundedS;
+ grp->F = roundedS + (2ULL << grp->slot_shift);
+ __clear_bit(grp->index, &q->bitmaps[ER]);
+ s = qfq_calc_state(q, grp);
+ __set_bit(grp->index, &q->bitmaps[s]);
+ }
+
+ qfq_unblock_groups(q, grp->index, old_F);
+ }
+
+skip_unblock:
+ qfq_update_eligible(q, old_V);
+
+ return skb;
+}
+
+/*
+ * Assign a reasonable start time for a new flow k in group i.
+ * Admissible values for \hat(F) are multiples of \sigma_i
+ * no greater than V+\sigma_i . Larger values mean that
+ * we had a wraparound so we consider the timestamp to be stale.
+ *
+ * If F is not stale and F >= V then we set S = F.
+ * Otherwise we should assign S = V, but this may violate
+ * the ordering in ER. So, if we have groups in ER, set S to
+ * the F_j of the first group j which would be blocking us.
+ * We are guaranteed not to move S backward because
+ * otherwise our group i would still be blocked.
+ */
+static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
+{
+ unsigned long mask;
+ uint32_t limit, roundedF;
+ int slot_shift = cl->grp->slot_shift;
+
+ roundedF = qfq_round_down(cl->F, slot_shift);
+ limit = qfq_round_down(q->V, slot_shift) + (1UL << slot_shift);
+
+ if (!qfq_gt(cl->F, q->V) || qfq_gt(roundedF, limit)) {
+ /* timestamp was stale */
+ mask = mask_from(q->bitmaps[ER], cl->grp->index);
+ if (mask) {
+ struct qfq_group *next = qfq_ffs(q, mask);
+ if (qfq_gt(roundedF, next->F)) {
+ cl->S = next->F;
+ return;
+ }
+ }
+ cl->S = q->V;
+ } else /* timestamp is not stale */
+ cl->S = cl->F;
+}
+
+static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_group *grp;
+ struct qfq_class *cl;
+ int err;
+ u64 roundedS;
+ int s;
+
+ cl = qfq_classify(skb, sch, &err);
+ if (cl == NULL) {
+ if (err & __NET_XMIT_BYPASS)
+ sch->qstats.drops++;
+ kfree_skb(skb);
+ return err;
+ }
+ pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
+
+ err = qdisc_enqueue(skb, cl->qdisc);
+ if (unlikely(err != NET_XMIT_SUCCESS)) {
+ pr_debug("qfq_enqueue: enqueue failed %d\n", err);
+ if (net_xmit_drop_count(err)) {
+ cl->qstats.drops++;
+ sch->qstats.drops++;
+ }
+ return err;
+ }
+
+ bstats_update(&cl->bstats, skb);
+ ++sch->q.qlen;
+
+ /* If the new skb is not the head of queue, then done here. */
+ if (cl->qdisc->q.qlen != 1)
+ return err;
+
+ /* If reach this point, queue q was idle */
+ grp = cl->grp;
+ qfq_update_start(q, cl);
+
+ /* compute new finish time and rounded start. */
+ cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w;
+ roundedS = qfq_round_down(cl->S, grp->slot_shift);
+
+ /*
+ * insert cl in the correct bucket.
+ * If cl->S >= grp->S we don't need to adjust the
+ * bucket list and simply go to the insertion phase.
+ * Otherwise grp->S is decreasing, we must make room
+ * in the bucket list, and also recompute the group state.
+ * Finally, if there were no flows in this group and nobody
+ * was in ER make sure to adjust V.
+ */
+ if (grp->full_slots) {
+ if (!qfq_gt(grp->S, cl->S))
+ goto skip_update;
+
+ /* create a slot for this cl->S */
+ qfq_slot_rotate(grp, roundedS);
+ /* group was surely ineligible, remove */
+ __clear_bit(grp->index, &q->bitmaps[IR]);
+ __clear_bit(grp->index, &q->bitmaps[IB]);
+ } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V))
+ q->V = roundedS;
+
+ grp->S = roundedS;
+ grp->F = roundedS + (2ULL << grp->slot_shift);
+ s = qfq_calc_state(q, grp);
+ __set_bit(grp->index, &q->bitmaps[s]);
+
+ pr_debug("qfq enqueue: new state %d %#lx S %lld F %lld V %lld\n",
+ s, q->bitmaps[s],
+ (unsigned long long) cl->S,
+ (unsigned long long) cl->F,
+ (unsigned long long) q->V);
+
+skip_update:
+ qfq_slot_insert(grp, cl, roundedS);
+
+ return err;
+}
+
+
+static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp,
+ struct qfq_class *cl, struct qfq_class **pprev)
+{
+ unsigned int i, offset;
+ u64 roundedS;
+
+ roundedS = qfq_round_down(cl->S, grp->slot_shift);
+ offset = (roundedS - grp->S) >> grp->slot_shift;
+ i = (grp->front + offset) % QFQ_MAX_SLOTS;
+
+ if (!pprev) {
+ pprev = &grp->slots[i];
+ while (*pprev && *pprev != cl)
+ pprev = &(*pprev)->next;
+ }
+
+ *pprev = cl->next;
+ if (!grp->slots[i])
+ __clear_bit(offset, &grp->full_slots);
+}
+
+/*
+ * called to forcibly destroy a queue.
+ * If the queue is not in the front bucket, or if it has
+ * other queues in the front bucket, we can simply remove
+ * the queue with no other side effects.
+ * Otherwise we must propagate the event up.
+ */
+static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl,
+ struct qfq_class **pprev)
+{
+ struct qfq_group *grp = cl->grp;
+ unsigned long mask;
+ u64 roundedS;
+ int s;
+
+ cl->F = cl->S;
+ qfq_slot_remove(q, grp, cl, pprev);
+
+ if (!grp->full_slots) {
+ __clear_bit(grp->index, &q->bitmaps[IR]);
+ __clear_bit(grp->index, &q->bitmaps[EB]);
+ __clear_bit(grp->index, &q->bitmaps[IB]);
+
+ if (test_bit(grp->index, &q->bitmaps[ER]) &&
+ !(q->bitmaps[ER] & ~((1UL << grp->index) - 1))) {
+ mask = q->bitmaps[ER] & ((1UL << grp->index) - 1);
+ if (mask)
+ mask = ~((1UL << __fls(mask)) - 1);
+ else
+ mask = ~0UL;
+ qfq_move_groups(q, mask, EB, ER);
+ qfq_move_groups(q, mask, IB, IR);
+ }
+ __clear_bit(grp->index, &q->bitmaps[ER]);
+ } else if (!grp->slots[grp->front]) {
+ cl = qfq_slot_scan(grp);
+ roundedS = qfq_round_down(cl->S, grp->slot_shift);
+ if (grp->S != roundedS) {
+ __clear_bit(grp->index, &q->bitmaps[ER]);
+ __clear_bit(grp->index, &q->bitmaps[IR]);
+ __clear_bit(grp->index, &q->bitmaps[EB]);
+ __clear_bit(grp->index, &q->bitmaps[IB]);
+ grp->S = roundedS;
+ grp->F = roundedS + (2ULL << grp->slot_shift);
+ s = qfq_calc_state(q, grp);
+ __set_bit(grp->index, &q->bitmaps[s]);
+ }
+ }
+
+ qfq_update_eligible(q, q->V);
+}
+
+static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_class *cl = (struct qfq_class *)arg;
+
+ if (cl->qdisc->q.qlen == 0)
+ qfq_deactivate_class(q, cl, NULL);
+}
+
+static unsigned int qfq_drop(struct Qdisc *sch)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_group *grp;
+ struct qfq_class *cl, **pp;
+ unsigned int i, j, len;
+
+ for (i = 0; i <= QFQ_MAX_INDEX; i++) {
+ grp = &q->groups[i];
+ for (j = 0; j < QFQ_MAX_SLOTS; j++) {
+ for (pp = &grp->slots[j]; *pp; pp = &(*pp)->next) {
+ cl = *pp;
+ if (!cl->qdisc->ops->drop)
+ continue;
+
+ len = cl->qdisc->ops->drop(cl->qdisc);
+ if (len > 0) {
+ sch->q.qlen--;
+ if (!cl->qdisc->q.qlen)
+ qfq_deactivate_class(q, cl, pp);
+
+ return len;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_group *grp;
+ int i, err;
+
+ err = qdisc_class_hash_init(&q->clhash);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i <= QFQ_MAX_INDEX; i++) {
+ grp = &q->groups[i];
+ grp->index = i;
+ }
+
+ return 0;
+}
+
+static void qfq_reset_qdisc(struct Qdisc *sch)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_group *grp;
+ struct qfq_class *cl, **pp;
+ struct hlist_node *n;
+ unsigned int i, j;
+
+ for (i = 0; i <= QFQ_MAX_INDEX; i++) {
+ grp = &q->groups[i];
+ for (j = 0; j < QFQ_MAX_SLOTS; j++) {
+ for (pp = &grp->slots[j]; *pp; pp = &(*pp)->next) {
+ cl = *pp;
+ if (cl->qdisc->q.qlen)
+ qfq_deactivate_class(q, cl, pp);
+ }
+ }
+ }
+
+ for (i = 0; i < q->clhash.hashsize; i++) {
+ hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
+ qdisc_reset(cl->qdisc);
+ }
+ sch->q.qlen = 0;
+}
+
+static void qfq_destroy_qdisc(struct Qdisc *sch)
+{
+ struct qfq_sched *q = qdisc_priv(sch);
+ struct qfq_class *cl;
+ struct hlist_node *n, *next;
+ unsigned int i;
+
+ tcf_destroy_chain(&q->filter_list);
+
+ for (i = 0; i < q->clhash.hashsize; i++) {
+ hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i],
+ common.hnode)
+ qfq_destroy_class(sch, cl);
+ }
+ qdisc_class_hash_destroy(&q->clhash);
+}
+
+static const struct Qdisc_class_ops qfq_class_ops = {
+ .change = qfq_change_class,
+ .delete = qfq_delete_class,
+ .get = qfq_get_class,
+ .put = qfq_put_class,
+ .tcf_chain = qfq_tcf_chain,
+ .bind_tcf = qfq_bind_tcf,
+ .unbind_tcf = qfq_unbind_tcf,
+ .graft = qfq_graft_class,
+ .leaf = qfq_class_leaf,
+ .qlen_notify = qfq_qlen_notify,
+ .dump = qfq_dump_class,
+ .dump_stats = qfq_dump_class_stats,
+ .walk = qfq_walk,
+};
+
+static struct Qdisc_ops qfq_qdisc_ops __read_mostly = {
+ .cl_ops = &qfq_class_ops,
+ .id = "qfq",
+ .priv_size = sizeof(struct qfq_sched),
+ .enqueue = qfq_enqueue,
+ .dequeue = qfq_dequeue,
+ .peek = qdisc_peek_dequeued,
+ .drop = qfq_drop,
+ .init = qfq_init_qdisc,
+ .reset = qfq_reset_qdisc,
+ .destroy = qfq_destroy_qdisc,
+ .owner = THIS_MODULE,
+};
+
+static int __init qfq_init(void)
+{
+ return register_qdisc(&qfq_qdisc_ops);
+}
+
+static void __exit qfq_exit(void)
+{
+ unregister_qdisc(&qfq_qdisc_ops);
+}
+
+module_init(qfq_init);
+module_exit(qfq_exit);
+MODULE_LICENSE("GPL");
^ permalink raw reply
* Re: [PATCH] sched: QFQ - quick fair queue scheduler (v3)
From: Stephen Hemminger @ 2011-03-03 22:59 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, Fabio Checconi, Luigi Rizzo, netdev
In-Reply-To: <1299191333.2547.12.camel@edumazet-laptop>
On Thu, 03 Mar 2011 23:28:53 +0100
Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le jeudi 03 mars 2011 à 08:48 -0800, Stephen Hemminger a écrit :
> > This is an implementation of the Quick Fair Queue scheduler developed
> > by Fabio Checconi. The same algorithm is already implemented in ipfw
> > in FreeBSD. Fabio had an earlier version developed on Linux, I just
> > cleaned it up. Thanks to Eric Dumazet for doing the testing and
> > finding bugs.
> >
> > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> >
> > ---
> > v3 - bug fixes found by Eric
> >
> > include/linux/pkt_sched.h | 15
> > net/sched/Kconfig | 11
> > net/sched/Makefile | 1
> > net/sched/sch_qfq.c | 1125 ++++++++++++++++++++++++++++++++++++++++++++++
> > 4 files changed, 1152 insertions(+)
> >
>
>
> Hmm... please compile before sending your patches ;)
>
> You used sched_priv(sch) calls instead of qdisc_priv(sch)
Argh, forgot to do quilt --refresh
^ permalink raw reply
* Re: [PATCH 2/2 v2] netlink: kill eff_cap from struct netlink_skb_parms
From: Lars Ellenberg @ 2011-03-03 22:37 UTC (permalink / raw)
To: Chris Wright
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
kaber-dcUjhNyLwpNeoWH0uzbU5w, dm-devel-H+wXaHxf7aLQT0dZR+AlfA,
Evgeniy Polyakov, David Miller, drbd-dev-cunTk1MwBs8qoQakbn7OcQ
In-Reply-To: <20110303201522.GT4988-JyIX8gxvWYPr2PDY2+4mTGD2FQJk+8+b@public.gmane.org>
On Thu, Mar 03, 2011 at 12:15:22PM -0800, Chris Wright wrote:
> * David Miller (davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org) wrote:
> > From: Chris Wright <chrisw-69jw2NvuJkxg9hUCZPvPmw@public.gmane.org>
> > Date: Thu, 3 Mar 2011 09:32:30 -0800
> >
> > > * Patrick McHardy (kaber-dcUjhNyLwpNeoWH0uzbU5w@public.gmane.org) wrote:
> > >
> > >> commit 8ff259625f0ab295fa085b0718eed13093813fbc
> > >> Author: Patrick McHardy <kaber-dcUjhNyLwpNeoWH0uzbU5w@public.gmane.org>
> > >> Date: Thu Mar 3 10:17:31 2011 +0100
> > >>
> > >> netlink: kill eff_cap from struct netlink_skb_parms
> > >>
> > >> Netlink message processing in the kernel is synchronous these days,
> > >> capabilities can be checked directly in security_netlink_recv() from
> > >> the current process.
> > >>
> > >> Signed-off-by: Patrick McHardy <kaber-dcUjhNyLwpNeoWH0uzbU5w@public.gmane.org>
> > >
> > > Thanks for doing that Patrick. I looked at this earlier and thought
> > > there was still an async path, but I guess that's just to another
> > > userspace process.
> > >
> > > BTW, I think you missed a couple connector based callers:
> > >
> > > drivers/staging/pohmelfs/config.c: if (!cap_raised(nsp->eff_cap, CAP_SYS_AD
> > > drivers/video/uvesafb.c: if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
Last time I checked, current() for connector based netlink message
consumers was the work queue that is used for connector.
So unless that changed, or my understanding is wrong, current_cap()
inside cn_queue_wrapper(), respectively the d->callback()
will not be the userland sender process' capabilities, but the work
queue capabilities.
If so, then this change introduces the possibility for normal users to
send privileged commands to connector based subsystems, even if they
may not be able to bind() to suitable sockets to receive any replies.
Am I missing something?
Lars
^ permalink raw reply
* [GIT] Networking
From: David Miller @ 2011-03-03 22:34 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
I have one ipv6 regression I'm still working on, but other
than that I think we look reasonably good.
1) skge carrier link state fix from Stephen Hemminger.
2) ipv6 sysctls operate on incorrect namespace sometimes, fix from
Lucian Adrian Grijincu.
3) Add ID to carl9170 USB driver.
4) __hw_addr_del_multiple() passed wrong type into __hw_addr_del(), fix
from Hagen Paul Pfeifer.
5) bnx2x fix to parity error blocking, from Vladislav Zolotarov.
6) netlink_dump() errors ignored and not properly propagated. Fix from
Andrey Vagin.
7) dnet and macb use platform_set_drvdata() on wrong object type, fixes
from Jamie Iles and Ilya Yanok.
8) FEC driver platform_device_id table not terminated properly.
9) f_phonet get OOPS with highmem, fix from Rémi Denis-Courmont.
10) nla_policy_len() forgets to actually iterate policy pointer in loop,
fix from Lars Ellenberg.
11) Missing checks in RX handling result in warnings from davinci_emac
driver, fix from Vinay Hegde.
12) IPVS locking fix from Julian Anastasov.
13) DCCP gets oops on reset after close, fix from Gerrit Renker.
14) nf_log oops on bind with invalid nfproto value, fix from Jan
Engelhardt.
15) Fix e1000e PHY wakeup for ICH10, from Bruce Allan.
16) dcbnl checks wrong OPS for NULL, fix from John Fastabend.
17) CNIC status block race and lost interrupt fix from Michael Chan.
18) RXRPC fixes from David Howells and Anton Blanchard, handle ACKALL
packets which OpenAFS now emits, and fix regression in rxrpc_key
layout.
19) Disable ASPM in r8169, causes lots of problems.
20) The usual peppering of small fixes via John Linville and the
wireless crew.
Please pull, thanks a lot!
The following changes since commit cbdbb4c1d22e26f9d5314fefe6f2c7e5ed7f6a0f:
Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6 (2011-03-02 20:02:32 -0800)
are available in the git repository at:
master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master
Andrey Vagin (1):
netlink: handle errors from netlink_dump()
Anton Blanchard (1):
RxRPC: Fix v1 keys
Arnaldo Carvalho de Melo (1):
dccp: Change maintainer
Axel Lin (1):
net/fec: fix unterminated platform_device_id table
Bruce Allan (1):
e1000e: disable broken PHY wakeup for ICH10 LOMs, use MAC wakeup instead
Christian Lamparter (1):
p54usb: add Senao NUB-350 usbid
David Howells (1):
AF_RXRPC: Handle receiving ACKALL packets
David S. Miller (3):
Merge branch 'master' of git://git.kernel.org/.../linville/wireless-2.6
Merge branch 'master' of git://git.kernel.org/.../kaber/nf-2.6
Merge branch 'master' of master.kernel.org:/.../jkirsher/net-2.6
Dmitry Kravkov (5):
bnx2x: (NPAR mode) Fix FW initialization
bnx2x: Fix nvram test for single port devices.
bnx2x: Fix ethtool -t link test for MF (non-pmf) devices.
bnx2x: properly configure coefficients for MinBW algorithm (NPAR mode).
bnx2x: update driver version to 1.62.00-6
Fry, Donald H (1):
iwlagn: Support new 5000 microcode.
Gerrit Renker (1):
dccp: fix oops on Reset after close
Hagen Paul Pfeifer (1):
net: handle addr_type of 0 properly
Hegde, Vinay (1):
davinci_emac: Add Carrier Link OK check in Davinci RX Handler
Ilya Yanok (1):
dnet: fix wrong use of platform_set_drvdata()
Jamie Iles (1):
macb: don't use platform_set_drvdata() on a net_device
Jan Engelhardt (1):
netfilter: nf_log: avoid oops in (un)bind with invalid nfproto values
Jan Puk (1):
carl9170: add Airlive X.USB a/b/g/n USBID
Jay Vosburgh (1):
MAINTAINERS: Add Andy Gospodarek as co-maintainer.
Jeff Kirsher (1):
igb: fix sparse warning
John Fastabend (1):
net: dcbnl: check correct ops in dcbnl_ieee_set()
John W. Linville (1):
Merge branch 'wireless-2.6' of git://git.kernel.org/.../iwlwifi/iwlwifi-2.6
Julian Anastasov (1):
ipvs: fix dst_lock locking on dest update
Jussi Kivilinna (1):
rndis_wlan: use power save only for BCM4320b
Justin Mattock (1):
drivers:isdn:istream.c Fix typo pice to piece
Ken Kawasaki (1):
fmvj18x_cs: add new id
Kurt Van Dijck (1):
CAN: add controller hardware name for Softing cards
Lars Ellenberg (1):
net: fix nla_policy_len to actually _iterate_ over the policy
Lucian Adrian Grijincu (1):
sysctl: ipv6: use correct net in ipv6_sysctl_rtcache_flush
Michael Chan (2):
cnic: Prevent status block race conditions with hardware
cnic: Fix lost interrupt on bnx2x
Randy Dunlap (1):
net: update Documentation/networking/00-INDEX
Rémi Denis-Courmont (1):
f_phonet: avoid pskb_pull(), fix OOPS with CONFIG_HIGHMEM
Stanislaw Gruszka (2):
ath9k: correct ath9k_hw_set_interrupts
r8169: disable ASPM
Stephen Hemminger (2):
skge: don't mark carrier down at start
e1000: fix sparse warning
Sujith Manoharan (1):
ath9k_htc: Fix an endian issue
Vladislav Zolotarov (3):
bnx2x: Add a missing bit for PXP parity register of 57712.
bnx2x: perform statistics "action" before state transition.
bnx2x: properly calculate lro_mss
Documentation/networking/00-INDEX | 6 ---
MAINTAINERS | 3 +-
drivers/isdn/hardware/eicon/istream.c | 2 +-
drivers/net/bnx2x/bnx2x.h | 28 +++++++-----
drivers/net/bnx2x/bnx2x_cmn.c | 65 +++++++++++++++++++++++------
drivers/net/bnx2x/bnx2x_cmn.h | 20 +++++++++
drivers/net/bnx2x/bnx2x_ethtool.c | 25 +++++------
drivers/net/bnx2x/bnx2x_init.h | 2 +-
drivers/net/bnx2x/bnx2x_main.c | 18 ++++++--
drivers/net/bnx2x/bnx2x_stats.c | 4 +-
drivers/net/can/softing/softing_main.c | 1 +
drivers/net/cnic.c | 33 +++++++++++----
drivers/net/davinci_emac.c | 2 +-
drivers/net/dnet.c | 3 +-
drivers/net/e1000/e1000_osdep.h | 3 +-
drivers/net/e1000e/netdev.c | 3 +-
drivers/net/fec.c | 3 +-
drivers/net/igbvf/vf.c | 2 +-
drivers/net/macb.c | 2 +-
drivers/net/pcmcia/fmvj18x_cs.c | 1 +
drivers/net/r8169.c | 6 +++
drivers/net/skge.c | 3 -
drivers/net/wireless/ath/ath9k/hif_usb.c | 9 ++--
drivers/net/wireless/ath/ath9k/mac.c | 5 +-
drivers/net/wireless/ath/carl9170/usb.c | 2 +
drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +-
drivers/net/wireless/p54/p54usb.c | 1 +
drivers/net/wireless/rndis_wlan.c | 3 +
drivers/tty/serial/serial_cs.c | 1 +
drivers/usb/gadget/f_phonet.c | 15 +++++--
include/keys/rxrpc-type.h | 1 -
lib/nlattr.c | 2 +-
net/core/dev_addr_lists.c | 2 +-
net/dcb/dcbnl.c | 2 +-
net/dccp/input.c | 7 +--
net/ipv6/route.c | 17 +++++---
net/netfilter/ipvs/ip_vs_ctl.c | 4 +-
net/netfilter/nf_log.c | 4 ++
net/netlink/af_netlink.c | 18 ++++++--
net/rxrpc/ar-input.c | 1 +
40 files changed, 225 insertions(+), 106 deletions(-)
^ permalink raw reply
* Re: ANNOUNCE: debloat-testing kernel git tree
From: Rick Jones @ 2011-03-03 22:33 UTC (permalink / raw)
To: Tianji Li
Cc: Dave Täht, sedat.dilek, netdev, linux-wireless, bloat-devel,
linux-kernel
In-Reply-To: <4D6FEFD4.9010608@nuim.ie>
On Thu, 2011-03-03 at 13:45 -0600, Tianji Li wrote:
>
> On 03/03/2011 12:16 PM, Rick Jones wrote:
> >> For wireless routers and cable home gateways especially, this research
> >> shows that the total un-managed buffers in your system should be less
> >> than 32.
> >
> > Would it be a good thing to start describing these queues not so much in
> > terms of packets but in terms of delay (or bandwidth X delay)?
> >
>
> The unit of bandwidth is something like Mbps, that of delay can be
> second, so bandwidth X delay --> Mb, which is the unit of packet size.
> So both packets and delay should have the same effect for sizing buffers.
Yet, not all packets are not created equal - in size. So, 42, 150 byte
packets queued is not the same as 42, 1500 byte packets. However, 10,
1500 byte packets is the same as 100, 150 byte packets.
Had you said something like MB and delay should have the same effect I
would have agreed with you :)
rick jones
^ permalink raw reply
* Re: RFC v1: sysctl: add sysctl header cookie, share tables between nets
From: Lucian Adrian Grijincu @ 2011-03-03 22:32 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: David Miller, adobriyan, tavi, netdev, linux-kernel
In-Reply-To: <m1zkpc1rbc.fsf@fess.ebiederm.org>
On Thu, Mar 3, 2011 at 10:33 AM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
> I may be missing something in these patches. I haven't had time to look
> at this most recent batch carefully. But from a 10,000 foot perspective I
> have a problem with them. With a handful of network devices the size of
> the data structures is negligible.
>
> So until I can see a reason why we should save a few bytes at the cost
> of greater future maintenance costs I'm not in favor of this patch set.
Sorry, I'm moving between countries and I don't have as much time as
I'd like to.
This patch series adds the "cookie" field and uses it in a few places.
I need this for the next step, but I wanted some feedback regarding
the cookie approach (sane? applicable if the 'dynamic header' feature
is accepted?).
Afterwards I want to add a "dynamic ctl_header" which will implement a
few ops (something on the lines of 'find_in_table' and 'scan' from
proc_sysctl.c).
At 'scan' time the "dynamic header" will create inodes for the
directories underneath with:
ctl_table='shared ctl table for /proc/sys/net/ipv4/conf' (or
ipv6/addrconf or neigh)
ctl_table_header=a device specific (not dynamic) table header with
->cookie pointing to a struct {char*dev_name; struct net*net;}
proc_handlers will use the name (or even a pointer to the device or
whatever speeds up the implementation) and the net to find out the
real ->data similar to the netns_proc_handlers from this patch series.
Adding an interface will not need to scan through the list of existing
ctl headers to see if any duplicates exist because there cannot be two
interfaces with the same name.
Promise to get back with patches for this implementation as soon as I can.
PS: sorry if my mumbling does not make much sense, hopefully code will
make things clear.
--
.
..: Lucian
^ permalink raw reply
* Re: Network link detection
From: Nico Schümann @ 2011-03-03 22:29 UTC (permalink / raw)
To: David Miller; +Cc: chris.friesen, linux-kernel, netdev
In-Reply-To: <20110303.140106.191399853.davem@davemloft.net>
On Thu, Mar 03, 2011 at 02:01:06PM -0800, David Miller wrote:
> From: Chris Friesen <chris.friesen@genband.com>
> Date: Thu, 03 Mar 2011 15:38:35 -0600
>
> > You might look at whether you could write a kernel module to register
> > for NETDEV_CHANGE notifications and pass that back to userspace.
>
> This is the kind of responses you get when you ask networking specific
> questions and don't CC: netdev :-/
>
Thank you for CC.
> There is this thing called netlink, you can listen for arbitrary
> network state change events on a socket, and get the link state
> notifications you are looking for. It's in use by many real
> applications like NetworkManager and co.
That really looks like what I'm looking for. I was already wondering
where NetworkManager gets the link state changes from, but I just
expected it to poll. So now I'll read a bit of documentation and
hopefully get it work.
Thanks to everyone,
Nico
^ permalink raw reply
* Re: [PATCH] sched: QFQ - quick fair queue scheduler (v3)
From: Eric Dumazet @ 2011-03-03 22:28 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, Fabio Checconi, Luigi Rizzo, netdev
In-Reply-To: <20110303084839.3ae312ed@nehalam>
Le jeudi 03 mars 2011 à 08:48 -0800, Stephen Hemminger a écrit :
> This is an implementation of the Quick Fair Queue scheduler developed
> by Fabio Checconi. The same algorithm is already implemented in ipfw
> in FreeBSD. Fabio had an earlier version developed on Linux, I just
> cleaned it up. Thanks to Eric Dumazet for doing the testing and
> finding bugs.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
> ---
> v3 - bug fixes found by Eric
>
> include/linux/pkt_sched.h | 15
> net/sched/Kconfig | 11
> net/sched/Makefile | 1
> net/sched/sch_qfq.c | 1125 ++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 1152 insertions(+)
>
Hmm... please compile before sending your patches ;)
You used sched_priv(sch) calls instead of qdisc_priv(sch)
> +}
> +
> +static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
> +{
> + struct qfq_sched *q = sched_priv(sch);
q = qdisc_priv(sch);
> +
> + if (cl->inv_w) {
> + q->wsum -= ONE_FP / cl->inv_w;
> + cl->inv_w = 0;
> + }
> +
> + gen_kill_estimator(&cl->bstats, &cl->rate_est);
> + qdisc_destroy(cl->qdisc);
> + kfree(cl);
> +}
> +
> +static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
> +{
> + struct qfq_sched *q = sched_priv(sch);
q = qdisc_priv(sch);
> + struct qfq_class *cl = (struct qfq_class *)arg;
> +
> + if (cl->qdisc->q.qlen == 0)
> + qfq_deactivate_class(q, cl, NULL);
> +}
> +
> +static void qfq_reset_qdisc(struct Qdisc *sch)
> +{
> + struct qfq_sched *q = qdisc_priv(sch);
> + struct qfq_group *grp;
> + struct qfq_class *cl, **pp;
> + struct hlist_node *n;
> + unsigned int i, j;
> +
> + for (i = 0; i <= QFQ_MAX_INDEX; i++) {
> + grp = &q->groups[i];
> + for (j = 0; j < QFQ_MAX_SLOTS; j++) {
> + for (pp = &grp->slots[j]; *pp; pp = &(*pp)->next) {
> + cl = *pp;
> + if (cl->qdisc->q.qlen)
> + qfq_deactivate_class(q, cl, pp);
Here there is the problem of *pp = cl->next (possibly NULL)
maybe use
for (pp = &grp->slots[j]; (cl = *pp) != NULL;) {
if (cl->qdisc->q.len)
qfq_deactivate_class(...);
else
pp = &cl->next;
}
> + }
> + }
> + }
> +
> + for (i = 0; i < q->clhash.hashsize; i++) {
> + hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
> + qdisc_reset(cl->qdisc);
> + }
> + sch->q.qlen = 0;
> +}
> +
^ permalink raw reply
* Re: [PATCH] via-rhine: do not abort due to invalid MAC address
From: Alex G. @ 2011-03-03 22:08 UTC (permalink / raw)
To: David Miller; +Cc: rl, florian, netdev
In-Reply-To: <20110303.140134.241924015.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 233 bytes --]
On 03/04/2011 12:01 AM, David Miller wrote:
>
> Still wrong, the patch needs to be "-p1" not "-p0" rooted.
Documentation/SubmittingPatches seems to be outdated then. I used "git
diff"; I hope the format is correct this time
Alex
[-- Attachment #2: rhine.patch --]
[-- Type: text/x-patch, Size: 1377 bytes --]
via-rhine drops out of the init code if the hardware provides an invalid
MAC address. Roger Luethi has had several reports of Rhine NICs doing just
that. The hardware still works, though; assigning a random MAC address
allows the NIC to be used as usual. Tested as a standalone interface,
as carrier for ppp, and as bonding slave.
Signed-off-by Alexandru Gagniuc <mr.nuke.me@gmail.com>
diff --git a/drivers/net/via-rhine.c.orig b/drivers/net/via-rhine.c
index 4930f9d..4c1b9e7 100644
--- a/drivers/net/via-rhine.c.orig
+++ b/drivers/net/via-rhine.c
@@ -762,13 +762,16 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
for (i = 0; i < 6; i++)
dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->perm_addr)) {
- rc = -EIO;
- printk(KERN_ERR "Invalid MAC address\n");
- goto err_out_unmap;
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ printk(KERN_ERR "via-rhine: Invalid MAC address: %pM. \n",
+ dev->dev_addr);
+ /* The device may still be used normally if a valid MAC is configured */
+ random_ether_addr(dev->dev_addr);
+ printk(KERN_ERR "via-rhine: Using randomly generated address: %pM instead. \n",
+ dev->dev_addr);
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* For Rhine-I/II, phy_id is loaded from EEPROM */
if (!phy_id)
^ permalink raw reply related
* Re: Network link detection
From: David Miller @ 2011-03-03 22:01 UTC (permalink / raw)
To: chris.friesen; +Cc: dev, linux-kernel, netdev
In-Reply-To: <4D700A5B.2000807@genband.com>
From: Chris Friesen <chris.friesen@genband.com>
Date: Thu, 03 Mar 2011 15:38:35 -0600
> You might look at whether you could write a kernel module to register
> for NETDEV_CHANGE notifications and pass that back to userspace.
This is the kind of responses you get when you ask networking specific
questions and don't CC: netdev :-/
There is this thing called netlink, you can listen for arbitrary
network state change events on a socket, and get the link state
notifications you are looking for. It's in use by many real
applications like NetworkManager and co.
^ permalink raw reply
* Re: [PATCH] via-rhine: do not abort due to invalid MAC address
From: David Miller @ 2011-03-03 22:01 UTC (permalink / raw)
To: mr.nuke.me; +Cc: rl, florian, netdev
In-Reply-To: <4D700D66.5090300@gmail.com>
Still wrong, the patch needs to be "-p1" not "-p0" rooted.
^ permalink raw reply
* Re: [PATCH] via-rhine: do not abort due to invalid MAC address
From: Alex G. @ 2011-03-03 21:51 UTC (permalink / raw)
To: David Miller; +Cc: rl, florian, netdev
In-Reply-To: <20110303.134256.68141248.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 0 bytes --]
[-- Attachment #2: rhine.patch --]
[-- Type: text/x-patch, Size: 1330 bytes --]
via-rhine drops out of the init code if the hardware provides an invalid
MAC address. Roger Luethi has had several reports of Rhine NICs doing just
that. The hardware still works, though; assigning a random MAC address
allows the NIC to be used as usual. Tested as a standalone interface,
as carrier for ppp, and as bonding slave.
Signed-off-by Alexandru Gagniuc <mr.nuke.me@gmail.com>
--- drivers/net/via-rhine.c.orig 2011-02-06 21:04:07.000000000 +0200
+++ drivers/net/via-rhine.c 2011-03-02 22:03:13.000000000 +0200
@@ -762,13 +762,16 @@ static int __devinit rhine_init_one(stru
for (i = 0; i < 6; i++)
dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- if (!is_valid_ether_addr(dev->perm_addr)) {
- rc = -EIO;
- printk(KERN_ERR "Invalid MAC address\n");
- goto err_out_unmap;
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ printk(KERN_ERR "via-rhine: Invalid MAC address: %pM. \n",
+ dev->dev_addr);
+ /* The device may still be used normally if a valid MAC is configured */
+ random_ether_addr(dev->dev_addr);
+ printk(KERN_ERR "via-rhine: Using randomly generated address: %pM instead. \n",
+ dev->dev_addr);
}
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* For Rhine-I/II, phy_id is loaded from EEPROM */
if (!phy_id)
^ permalink raw reply
* Re: [BUG] VPN broken in net-next
From: Stephen Hemminger @ 2011-03-03 21:54 UTC (permalink / raw)
To: David Miller; +Cc: ja, netdev
In-Reply-To: <20110303.112328.59677094.davem@davemloft.net>
On Thu, 03 Mar 2011 11:23:28 -0800 (PST)
David Miller <davem@davemloft.net> wrote:
> From: Julian Anastasov <ja@ssi.bg>
> Date: Thu, 3 Mar 2011 15:09:22 +0200 (EET)
>
> > On Thu, 3 Mar 2011, Julian Anastasov wrote:
> >
> >> May be the problem is in inet_hash_insert(), it should
> >> hash ifa_local, not ifa_address. May be they are equal for
> >
> > ... and of course the new __ip_dev_find should use
> > ifa_local too.
>
> Thanks for looking into this Julian. I will look at the other
> cases you found later.
>
> Stephen, is this sufficient to fix your problem? I suspect it is
> not because fib_add_addr() adds prefixes with RTN_LOCAL to the
> local routing table too :-/
>
> I suspect that even if we need to handle prefixes, we can still use
> the hash for optimistic lookup, and fallback to a local table FIB
> inspection if that fails.
>
> --------------------
> ipv4: Fix __ip_dev_find() to use ifa_local instead of ifa_address.
>
> Reported-by: Stephen Hemminger <shemminger@vyatta.com>
> Reported-by: Julian Anastasov <ja@ssi.bg>
> Signed-off-by: David S. Miller <davem@davemloft.net>
>
VPN works now with this patch on net-next.
^ permalink raw reply
* Re: linux-next: Tree for February 10 (netfilter)
From: Randy Dunlap @ 2011-03-03 21:54 UTC (permalink / raw)
To: Patrick McHardy
Cc: Stephen Rothwell, netdev, linux-next, LKML, netfilter-devel,
Thomas Graf
In-Reply-To: <4D58DB20.5060401@trash.net>
On Mon, 14 Feb 2011 08:34:56 +0100 Patrick McHardy wrote:
> On 10.02.2011 18:52, Randy Dunlap wrote:
> > On Thu, 10 Feb 2011 18:05:25 +1100 Stephen Rothwell wrote:
> >
> >> Hi all,
> >>
> >> [The kernel.org mirroring is being slow ...]
> >>
> >> Changes since 20110209:
> >
> >
> > xt_AUDIT.c:(.text+0x39ca9): undefined reference to `ipv6_skip_exthdr'
> >
> > IPV6 is not enabled.
> >
> > Full config file is attached.
>
> Thomas, please have a look at this.
Ping.
This build error is still with us in linux-next 2011.0303...
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* Re: [RFC !!BONUS!! PATCH 6/5] ipv4: Delete routing cache.
From: David Miller @ 2011-03-03 21:44 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1297842977.3201.7.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 16 Feb 2011 08:56:17 +0100
> I suspect we can zap DST_NOCACHE later ?
So, coming back to this, we really can't since IPV6 and DecNET
still need the non-DST_NOCACHE case.
^ permalink raw reply
* Re: [RFC PATCH] net/core: fix skb handling on netif serves for both bridge and vlan
From: Nicolas de Pesloüan @ 2011-03-03 21:42 UTC (permalink / raw)
To: Ben Hutchings
Cc: Xiaotian Feng, netdev, linux-kernel, David S. Miller,
Eric Dumazet, Tom Herbert, Jiri Pirko
In-Reply-To: <1299160414.4277.49.camel@localhost>
Le 03/03/2011 14:53, Ben Hutchings a écrit :
> On Thu, 2011-03-03 at 18:55 +0800, Xiaotian Feng wrote:
>> Consider network topology as follows:
>>
>> eth0 eth1
>> |_____|
>> |
>> bond0 --- br0
>> |
>> vlan0 --- br1
>>
>> bond0 serves for both br0 and vlan0, if a vlan tagged packet was sent
>> to br1 through bond0, bridge handling code is seeing the packet on bond0
>> and handing it off to my "legacy" bridge before vlan_tx_tag_present
>> and vlan_hwaccel_do_receive even haven't a chance to look at it.
> [...]
>
> This used to work if the underlying device (bond0 in your example)
> implemented VLAN tag extraction, because the VLAN group would be checked
> before the bridge. But it never worked for devices without VLAN tag
> extraction. Perhaps we should just prevent this configuration.
If Jiri Pirko eventually move vlan processing to rx_handler, then the setup won't be possible,
because bond0 would require two rx_handlers : one for bridge (-> br0) and one for vlan (-> vlan0).
Or we need several rx_handlers per net_device, if the above setup is a real one.
Nicolas.
^ permalink raw reply
* Re: [PATCH] via-rhine: do not abort due to invalid MAC address
From: David Miller @ 2011-03-03 21:42 UTC (permalink / raw)
To: mr.nuke.me; +Cc: rl, florian, netdev
In-Reply-To: <4D6EA33D.70801@gmail.com>
From: "Alex G." <mr.nuke.me@gmail.com>
Date: Wed, 02 Mar 2011 22:06:21 +0200
> Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
The file paths in your patch are incorrect, please read
Documentation/SubmittingPatches to learn how to generate
proper diffs.
^ permalink raw reply
* Re: [PATCH 2/2 v2] netlink: kill eff_cap from struct netlink_skb_parms
From: David Miller @ 2011-03-03 21:39 UTC (permalink / raw)
To: chrisw
Cc: kaber, netdev, dm-devel, linux-security-module, drbd-dev, zbr,
linux-fbdev
In-Reply-To: <20110303201522.GT4988@sequoia.sous-sol.org>
From: Chris Wright <chrisw@sous-sol.org>
Date: Thu, 3 Mar 2011 12:15:22 -0800
> Here, I respun it so I could work on top of it
...
> I did not do exhaustive .config compile tests
Thanks a lot Chris, applied.
^ permalink raw reply
* Re: [PATCH 3/3 v2] eql: Convert printks to pr_<level> and netdev_<level>
From: David Miller @ 2011-03-03 21:30 UTC (permalink / raw)
To: joe; +Cc: netdev
In-Reply-To: <1299186492.4338.166.camel@Joe-Laptop>
From: Joe Perches <joe@perches.com>
Date: Thu, 03 Mar 2011 13:08:12 -0800
> Add pr_fmt.
>
> Removed trailing "\n" from version,
> add back via pr_info("%s\n", version);
>
> Signed-off-by: Joe Perches <joe@perches.com>
Applied, thanks.
> Joined of a fixed string with an __initconst string.
Aha, I see.
^ permalink raw reply
* Re: bonding...
From: David Miller @ 2011-03-03 21:29 UTC (permalink / raw)
To: andy; +Cc: fubar, nhorman, netdev
In-Reply-To: <20110303211250.GQ11864@gospo.rdu.redhat.com>
From: Andy Gospodarek <andy@greyhouse.net>
Date: Thu, 3 Mar 2011 16:12:50 -0500
> On Thu, Mar 03, 2011 at 12:43:10PM -0800, Jay Vosburgh wrote:
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 0d83e58..6402703 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1467,6 +1467,7 @@ F: include/net/bluetooth/
>>
>> BONDING DRIVER
>> M: Jay Vosburgh <fubar@us.ibm.com>
>> +M: Andy Gospodarek <andy@greyhouse.net>
>> L: netdev@vger.kernel.org
>> W: http://sourceforge.net/projects/bonding/
>> S: Supported
>>
>>
>
> Acked-by: Andy Gospodarek <andy@greyhouse.net>
Applied, thanks.
^ permalink raw reply
* Re: bonding...
From: Andy Gospodarek @ 2011-03-03 21:12 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: David Miller, andy, nhorman, netdev
In-Reply-To: <13010.1299184990@death>
On Thu, Mar 03, 2011 at 12:43:10PM -0800, Jay Vosburgh wrote:
> David Miller <davem@davemloft.net> wrote:
>
> >From: Jay Vosburgh <fubar@us.ibm.com>
> >Date: Thu, 03 Mar 2011 09:24:25 -0800
> >
> >> My main problem keeping up at the moment is another demand on my
> >> time that should run its course in a couple of weeks. My time for
> >> community activity is somewhat limited until then.
> >
> >Someone needs to exist who can keep things going when you are too
> >busy. Unless you're like me and never take a day off, you need
> >at least one co-maintainer if your subsystem has lots of daily
> >activity as bonding now does.
>
> Agreed. If Andy is amenable, we can make it official:
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0d83e58..6402703 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1467,6 +1467,7 @@ F: include/net/bluetooth/
>
> BONDING DRIVER
> M: Jay Vosburgh <fubar@us.ibm.com>
> +M: Andy Gospodarek <andy@greyhouse.net>
> L: netdev@vger.kernel.org
> W: http://sourceforge.net/projects/bonding/
> S: Supported
>
>
Acked-by: Andy Gospodarek <andy@greyhouse.net>
^ permalink raw reply
* [PATCH 3/3 v2] eql: Convert printks to pr_<level> and netdev_<level>
From: Joe Perches @ 2011-03-03 21:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20110303.125951.200370524.davem@davemloft.net>
Add pr_fmt.
Removed trailing "\n" from version,
add back via pr_info("%s\n", version);
Signed-off-by: Joe Perches <joe@perches.com>
---
> Something is busted with this change, although I can't quite figure it
> out myself:
Joined of a fixed string with an __initconst string.
drivers/net/eql.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 0cb1cf9..a59cf96 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -111,6 +111,8 @@
* Sorry, I had to rewrite most of this for 2.5.x -DaveM
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/capability.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -162,7 +164,7 @@ static void eql_timer(unsigned long param)
}
static const char version[] __initconst =
- "Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)\n";
+ "Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)";
static const struct net_device_ops eql_netdev_ops = {
.ndo_open = eql_open,
@@ -204,8 +206,8 @@ static int eql_open(struct net_device *dev)
equalizer_t *eql = netdev_priv(dev);
/* XXX We should force this off automatically for the user. */
- printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
- "your slave devices.\n", dev->name);
+ netdev_info(dev,
+ "remember to turn off Van-Jacobson compression on your slave devices\n");
BUG_ON(!list_empty(&eql->queue.all_slaves));
@@ -591,7 +593,7 @@ static int __init eql_init_module(void)
{
int err;
- printk(version);
+ pr_info("%s\n", version);
dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", eql_setup);
if (!dev_eql)
^ permalink raw reply related
* Jetway JAD3RTLANG, Daughter Board, 3x GigaBit LAN does not work correctly
From: Markus Feldmann @ 2011-03-03 21:02 UTC (permalink / raw)
To: netdev
Hi All,
i have a mini-ITX server with the mainboard "Jetway JNF92-270-LF" with
the daughterboard "Jetway JAD3RTLANG, 3x GigaBit LAN".
My current kernel is 2.6.36.4 and i can only connect over one of the
network interfaces of my daughterboard at the time.
My loaded modules:
http://pastebin.com/raw.php?i=C9u78SML
And a list of pci devices:
http://pastebin.com/raw.php?i=f00tTdEJ
I am using a bridge br0 to bind all three interfaces eth1, eth2 and eth3
together:
http://pastebin.com/raw.php?i=deUT7iVS
Do i have to configure anything in my kernel to fit this daughterboard?
regards Markus
^ permalink raw reply
* Re: [PATCH 3/3] eql: Convert printks to pr_<level> and netdev_<level>
From: David Miller @ 2011-03-03 20:59 UTC (permalink / raw)
To: joe; +Cc: netdev
In-Reply-To: <20110303.122153.70207563.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Thu, 03 Mar 2011 12:21:53 -0800 (PST)
> From: Joe Perches <joe@perches.com>
> Date: Wed, 2 Mar 2011 09:18:12 -0800
>
>> Add pr_fmt
>>
>> Signed-off-by: Joe Perches <joe@perches.com>
>
> Applied.
Something is busted with this change, although I can't quite figure it
out myself:
drivers/net/eql.c: In function ‘eql_init_module’:
drivers/net/eql.c:596:2: error: expected ‘)’ before ‘version’
^ permalink raw reply
* Re: bonding...
From: Andy Gospodarek @ 2011-03-03 20:59 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Andy Gospodarek, Neil Horman, David Miller, netdev
In-Reply-To: <6286.1299173065@death>
On Thu, Mar 03, 2011 at 09:24:25AM -0800, Jay Vosburgh wrote:
> Andy Gospodarek <andy@greyhouse.net> wrote:
> >
> >I would be willing to do it, but my one of my goals would be to prevent
> >some of the feature creep we are currently seeing with bonding (as Ben
> >has suggested). That doesn't mean I want to stop all new features, but
> >at this point things are starting to get out of control. I suspect this
> >is why Jay has struggled to keep up with the patches.
>
> My main problem keeping up at the moment is another demand on my
> time that should run its course in a couple of weeks. My time for
> community activity is somewhat limited until then.
>
> As far as the features go, yes, I agree that things are getting
> out of hand. The two pending patches for special cases related to
> 802.3ad (Oleg's patch to permit round robining, the other to enable
> spanning aggregators across switches), for example, are fine
> functionality, but there really needs to be a better, generic, way to do
> this sort of niche case activity without adding more knobs.
>
> I personally like Stephen's suggestion to hook bonding into a
> netfilter gadget, similar to ebtables for bridge. Done properly, such a
> gadget should handle (or be extended to handle) the niche cases that
> right now end up as new knobs in the driver.
>
> >I would also want to look at a restructuring of the configuration. The
> >lines are starting to blur between some of the modes and output port
> >selection for other modes and that needs to be cleared up.
>
> What did you have in mind here?
>
This is what I've been thinking about for a while, but it's basically
off the top of my head. Of couse it seems reasonable to me....
As more people try to add functionality that exists in one mode to
another mode it becomes clear that the distinction between some of the
modes isn't clear anymore. If we really want round-robin send on
802.3ad and xor modes, why do we have rr and xor anymore? For that
matter, why not just get rid of active-backup too and add an option for
transmit algorithm to be active-backup. It can get to be a slippery
slope when you start to combine them as it seems like you would just be
changing the language from 'mode' to 'transmit algoritm,' but I still
think it is worth thinking about.
Instead of thinking about the 7 modes of bonding that currently exist,
it makes more sense to me to think of the bond as being dynamic or
static (with 802.3ad being the only mode that is currently dynamic) and
then the user can select the transmit algorithm. Obviously this isn't
totally flushed out since some transmit algorithms will be able to
support arp monitoring and some will not, but I suspect you know where
I'm going.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox