summaryrefslogtreecommitdiff
path: root/patches/backport-adjustments
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2014-02-10 17:50:52 +0100
committerHauke Mehrtens <hauke@hauke-m.de>2014-02-10 23:31:13 +0100
commiteea6b955fe16a63890b1bb3a5d5d02fb11ff7c05 (patch)
tree16c924fcc09297897773e4ed60378701bb3ad737 /patches/backport-adjustments
parent6399aaa1cf1ce4fe45756e481a5d702c90e22b04 (diff)
backports: copy sch_fq_codel.c from kernelbackports-20140210
Instead of using an own version of sch_fq_codel.c make backports copy that code from the kernel and use that. This ensures that we will always use the latest version. This also includes flow_dissector.c which provides a function used by sch_fq_codel.c. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Diffstat (limited to 'patches/backport-adjustments')
-rw-r--r--patches/backport-adjustments/flow_dissector.patch246
-rw-r--r--patches/backport-adjustments/sch_fq_codel.patch106
2 files changed, 352 insertions, 0 deletions
diff --git a/patches/backport-adjustments/flow_dissector.patch b/patches/backport-adjustments/flow_dissector.patch
new file mode 100644
index 00000000..6a6fc165
--- /dev/null
+++ b/patches/backport-adjustments/flow_dissector.patch
@@ -0,0 +1,246 @@
+--- a/compat/net-core-flow_dissector.c
++++ b/compat/net-core-flow_dissector.c
+@@ -177,241 +177,10 @@ ipv6:
+
+ flow->ip_proto = ip_proto;
+ flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
+ flow->thoff = (u16) nhoff;
++#endif
+
+ return true;
+ }
+ EXPORT_SYMBOL(skb_flow_dissect);
+-
+-static u32 hashrnd __read_mostly;
+-static __always_inline void __flow_hash_secret_init(void)
+-{
+- net_get_random_once(&hashrnd, sizeof(hashrnd));
+-}
+-
+-static __always_inline u32 __flow_hash_3words(u32 a, u32 b, u32 c)
+-{
+- __flow_hash_secret_init();
+- return jhash_3words(a, b, c, hashrnd);
+-}
+-
+-static __always_inline u32 __flow_hash_1word(u32 a)
+-{
+- __flow_hash_secret_init();
+- return jhash_1word(a, hashrnd);
+-}
+-
+-/*
+- * __skb_get_hash: calculate a flow hash based on src/dst addresses
+- * and src/dst port numbers. Sets rxhash in skb to non-zero hash value
+- * on success, zero indicates no valid hash. Also, sets l4_rxhash in skb
+- * if hash is a canonical 4-tuple hash over transport ports.
+- */
+-void __skb_get_hash(struct sk_buff *skb)
+-{
+- struct flow_keys keys;
+- u32 hash;
+-
+- if (!skb_flow_dissect(skb, &keys))
+- return;
+-
+- if (keys.ports)
+- skb->l4_rxhash = 1;
+-
+- /* get a consistent hash (same value on both flow directions) */
+- if (((__force u32)keys.dst < (__force u32)keys.src) ||
+- (((__force u32)keys.dst == (__force u32)keys.src) &&
+- ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) {
+- swap(keys.dst, keys.src);
+- swap(keys.port16[0], keys.port16[1]);
+- }
+-
+- hash = __flow_hash_3words((__force u32)keys.dst,
+- (__force u32)keys.src,
+- (__force u32)keys.ports);
+- if (!hash)
+- hash = 1;
+-
+- skb->rxhash = hash;
+-}
+-EXPORT_SYMBOL(__skb_get_hash);
+-
+-/*
+- * Returns a Tx hash based on the given packet descriptor a Tx queues' number
+- * to be used as a distribution range.
+- */
+-u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
+- unsigned int num_tx_queues)
+-{
+- u32 hash;
+- u16 qoffset = 0;
+- u16 qcount = num_tx_queues;
+-
+- if (skb_rx_queue_recorded(skb)) {
+- hash = skb_get_rx_queue(skb);
+- while (unlikely(hash >= num_tx_queues))
+- hash -= num_tx_queues;
+- return hash;
+- }
+-
+- if (dev->num_tc) {
+- u8 tc = netdev_get_prio_tc_map(dev, skb->priority);
+- qoffset = dev->tc_to_txq[tc].offset;
+- qcount = dev->tc_to_txq[tc].count;
+- }
+-
+- if (skb->sk && skb->sk->sk_hash)
+- hash = skb->sk->sk_hash;
+- else
+- hash = (__force u16) skb->protocol;
+- hash = __flow_hash_1word(hash);
+-
+- return (u16) (((u64) hash * qcount) >> 32) + qoffset;
+-}
+-EXPORT_SYMBOL(__skb_tx_hash);
+-
+-/* __skb_get_poff() returns the offset to the payload as far as it could
+- * be dissected. The main user is currently BPF, so that we can dynamically
+- * truncate packets without needing to push actual payload to the user
+- * space and can analyze headers only, instead.
+- */
+-u32 __skb_get_poff(const struct sk_buff *skb)
+-{
+- struct flow_keys keys;
+- u32 poff = 0;
+-
+- if (!skb_flow_dissect(skb, &keys))
+- return 0;
+-
+- poff += keys.thoff;
+- switch (keys.ip_proto) {
+- case IPPROTO_TCP: {
+- const struct tcphdr *tcph;
+- struct tcphdr _tcph;
+-
+- tcph = skb_header_pointer(skb, poff, sizeof(_tcph), &_tcph);
+- if (!tcph)
+- return poff;
+-
+- poff += max_t(u32, sizeof(struct tcphdr), tcph->doff * 4);
+- break;
+- }
+- case IPPROTO_UDP:
+- case IPPROTO_UDPLITE:
+- poff += sizeof(struct udphdr);
+- break;
+- /* For the rest, we do not really care about header
+- * extensions at this point for now.
+- */
+- case IPPROTO_ICMP:
+- poff += sizeof(struct icmphdr);
+- break;
+- case IPPROTO_ICMPV6:
+- poff += sizeof(struct icmp6hdr);
+- break;
+- case IPPROTO_IGMP:
+- poff += sizeof(struct igmphdr);
+- break;
+- case IPPROTO_DCCP:
+- poff += sizeof(struct dccp_hdr);
+- break;
+- case IPPROTO_SCTP:
+- poff += sizeof(struct sctphdr);
+- break;
+- }
+-
+- return poff;
+-}
+-
+-static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
+-{
+- if (unlikely(queue_index >= dev->real_num_tx_queues)) {
+- net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
+- dev->name, queue_index,
+- dev->real_num_tx_queues);
+- return 0;
+- }
+- return queue_index;
+-}
+-
+-static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
+-{
+-#ifdef CONFIG_XPS
+- struct xps_dev_maps *dev_maps;
+- struct xps_map *map;
+- int queue_index = -1;
+-
+- rcu_read_lock();
+- dev_maps = rcu_dereference(dev->xps_maps);
+- if (dev_maps) {
+- map = rcu_dereference(
+- dev_maps->cpu_map[raw_smp_processor_id()]);
+- if (map) {
+- if (map->len == 1)
+- queue_index = map->queues[0];
+- else {
+- u32 hash;
+- if (skb->sk && skb->sk->sk_hash)
+- hash = skb->sk->sk_hash;
+- else
+- hash = (__force u16) skb->protocol ^
+- skb->rxhash;
+- hash = __flow_hash_1word(hash);
+- queue_index = map->queues[
+- ((u64)hash * map->len) >> 32];
+- }
+- if (unlikely(queue_index >= dev->real_num_tx_queues))
+- queue_index = -1;
+- }
+- }
+- rcu_read_unlock();
+-
+- return queue_index;
+-#else
+- return -1;
+-#endif
+-}
+-
+-u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
+-{
+- struct sock *sk = skb->sk;
+- int queue_index = sk_tx_queue_get(sk);
+-
+- if (queue_index < 0 || skb->ooo_okay ||
+- queue_index >= dev->real_num_tx_queues) {
+- int new_index = get_xps_queue(dev, skb);
+- if (new_index < 0)
+- new_index = skb_tx_hash(dev, skb);
+-
+- if (queue_index != new_index && sk &&
+- rcu_access_pointer(sk->sk_dst_cache))
+- sk_tx_queue_set(sk, new_index);
+-
+- queue_index = new_index;
+- }
+-
+- return queue_index;
+-}
+-EXPORT_SYMBOL(__netdev_pick_tx);
+-
+-struct netdev_queue *netdev_pick_tx(struct net_device *dev,
+- struct sk_buff *skb,
+- void *accel_priv)
+-{
+- int queue_index = 0;
+-
+- if (dev->real_num_tx_queues != 1) {
+- const struct net_device_ops *ops = dev->netdev_ops;
+- if (ops->ndo_select_queue)
+- queue_index = ops->ndo_select_queue(dev, skb,
+- accel_priv);
+- else
+- queue_index = __netdev_pick_tx(dev, skb);
+-
+- if (!accel_priv)
+- queue_index = dev_cap_txqueue(dev, queue_index);
+- }
+-
+- skb_set_queue_mapping(skb, queue_index);
+- return netdev_get_tx_queue(dev, queue_index);
+-}
diff --git a/patches/backport-adjustments/sch_fq_codel.patch b/patches/backport-adjustments/sch_fq_codel.patch
new file mode 100644
index 00000000..b6bd6769
--- /dev/null
+++ b/patches/backport-adjustments/sch_fq_codel.patch
@@ -0,0 +1,106 @@
+--- a/compat/net-sched-sch_fq_codel.c
++++ b/compat/net-sched-sch_fq_codel.c
+@@ -65,6 +65,9 @@ struct fq_codel_sched_data {
+
+ struct list_head new_flows; /* list of new flows */
+ struct list_head old_flows; /* list of old flows */
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39))
++ u32 limit;
++#endif
+ };
+
+ static unsigned int fq_codel_hash(const struct fq_codel_sched_data *q,
+@@ -195,7 +198,11 @@ static int fq_codel_enqueue(struct sk_bu
+ flow->deficit = q->quantum;
+ flow->dropped = 0;
+ }
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39))
++ if (++sch->q.qlen <= q->limit)
++#else
+ if (++sch->q.qlen <= sch->limit)
++#endif
+ return NET_XMIT_SUCCESS;
+
+ q->drop_overlimit++;
+@@ -333,7 +340,11 @@ static int fq_codel_change(struct Qdisc
+ }
+
+ if (tb[TCA_FQ_CODEL_LIMIT])
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39))
++ q->limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]);
++#else
+ sch->limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]);
++#endif
+
+ if (tb[TCA_FQ_CODEL_ECN])
+ q->cparams.ecn = !!nla_get_u32(tb[TCA_FQ_CODEL_ECN]);
+@@ -341,7 +352,11 @@ static int fq_codel_change(struct Qdisc
+ if (tb[TCA_FQ_CODEL_QUANTUM])
+ q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
+
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39))
++ while (sch->q.qlen > q->limit) {
++#else
+ while (sch->q.qlen > sch->limit) {
++#endif
+ struct sk_buff *skb = fq_codel_dequeue(sch);
+
+ kfree_skb(skb);
+@@ -377,7 +392,11 @@ static void fq_codel_destroy(struct Qdis
+ {
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
+
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25))
++ tcf_destroy_chain(q->filter_list);
++#else
+ tcf_destroy_chain(&q->filter_list);
++#endif
+ fq_codel_free(q->backlogs);
+ fq_codel_free(q->flows);
+ }
+@@ -387,7 +406,11 @@ static int fq_codel_init(struct Qdisc *s
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
+ int i;
+
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39))
++ q->limit = 10*1024;
++#else
+ sch->limit = 10*1024;
++#endif
+ q->flows_cnt = 1024;
+ q->quantum = psched_mtu(qdisc_dev(sch));
+ q->perturbation = prandom_u32();
+@@ -420,7 +443,11 @@ static int fq_codel_init(struct Qdisc *s
+ codel_vars_init(&flow->cvars);
+ }
+ }
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39))
++ if (q->limit >= 1)
++#else
+ if (sch->limit >= 1)
++#endif
+ sch->flags |= TCQ_F_CAN_BYPASS;
+ else
+ sch->flags &= ~TCQ_F_CAN_BYPASS;
+@@ -439,7 +466,11 @@ static int fq_codel_dump(struct Qdisc *s
+ if (nla_put_u32(skb, TCA_FQ_CODEL_TARGET,
+ codel_time_to_us(q->cparams.target)) ||
+ nla_put_u32(skb, TCA_FQ_CODEL_LIMIT,
++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39))
++ q->limit) ||
++#else
+ sch->limit) ||
++#endif
+ nla_put_u32(skb, TCA_FQ_CODEL_INTERVAL,
+ codel_time_to_us(q->cparams.interval)) ||
+ nla_put_u32(skb, TCA_FQ_CODEL_ECN,
+@@ -599,7 +630,9 @@ static struct Qdisc_ops fq_codel_qdisc_o
+ .priv_size = sizeof(struct fq_codel_sched_data),
+ .enqueue = fq_codel_enqueue,
+ .dequeue = fq_codel_dequeue,
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
+ .peek = qdisc_peek_dequeued,
++#endif
+ .drop = fq_codel_drop,
+ .init = fq_codel_init,
+ .reset = fq_codel_reset,