diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2014-02-10 17:50:52 +0100 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2014-02-10 23:31:13 +0100 |
commit | eea6b955fe16a63890b1bb3a5d5d02fb11ff7c05 (patch) | |
tree | 16c924fcc09297897773e4ed60378701bb3ad737 /patches/backport-adjustments | |
parent | 6399aaa1cf1ce4fe45756e481a5d702c90e22b04 (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.patch | 246 | ||||
-rw-r--r-- | patches/backport-adjustments/sch_fq_codel.patch | 106 |
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, |