diff options
author | Eric Dumazet <edumazet@google.com> | 2014-09-18 11:02:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-22 14:21:47 -0400 |
commit | 257117862634d89de33fec74858b1a0ba5ab444b (patch) | |
tree | 799321753c9f5ac9358c708bced556df7e309772 | |
parent | 476c18850c6cbaa3f2bb661ae9710645081563b9 (diff) |
net: sched: shrink struct qdisc_skb_cb to 28 bytes
We cannot make struct qdisc_skb_cb bigger without impacting IPoIB,
or increasing skb->cb[] size.
Commit e0f31d849867 ("flow_keys: Record IP layer protocol in
skb_flow_dissect()") broke IPoIB.
Only current offender is sch_choke, and this one do not need an
absolutely precise flow key.
If we store 17 bytes of flow key, its more than enough. (Its the actual
size of flow_keys if it was a packed structure, but we might add new
fields at the end of it later)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Fixes: e0f31d849867 ("flow_keys: Record IP layer protocol in skb_flow_dissect()")
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sch_generic.h | 3 | ||||
-rw-r--r-- | net/sched/sch_choke.c | 18 |
2 files changed, 16 insertions, 5 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index a3cfb8ebeb53..620e086c0cbe 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -231,7 +231,8 @@ struct qdisc_skb_cb { | |||
231 | unsigned int pkt_len; | 231 | unsigned int pkt_len; |
232 | u16 slave_dev_queue_mapping; | 232 | u16 slave_dev_queue_mapping; |
233 | u16 _pad; | 233 | u16 _pad; |
234 | unsigned char data[24]; | 234 | #define QDISC_CB_PRIV_LEN 20 |
235 | unsigned char data[QDISC_CB_PRIV_LEN]; | ||
235 | }; | 236 | }; |
236 | 237 | ||
237 | static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) | 238 | static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) |
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index ed30e436128b..fb666d1e4de3 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c | |||
@@ -133,10 +133,16 @@ static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx) | |||
133 | --sch->q.qlen; | 133 | --sch->q.qlen; |
134 | } | 134 | } |
135 | 135 | ||
136 | /* private part of skb->cb[] that a qdisc is allowed to use | ||
137 | * is limited to QDISC_CB_PRIV_LEN bytes. | ||
138 | * As a flow key might be too large, we store a part of it only. | ||
139 | */ | ||
140 | #define CHOKE_K_LEN min_t(u32, sizeof(struct flow_keys), QDISC_CB_PRIV_LEN - 3) | ||
141 | |||
136 | struct choke_skb_cb { | 142 | struct choke_skb_cb { |
137 | u16 classid; | 143 | u16 classid; |
138 | u8 keys_valid; | 144 | u8 keys_valid; |
139 | struct flow_keys keys; | 145 | u8 keys[QDISC_CB_PRIV_LEN - 3]; |
140 | }; | 146 | }; |
141 | 147 | ||
142 | static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb) | 148 | static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb) |
@@ -163,22 +169,26 @@ static u16 choke_get_classid(const struct sk_buff *skb) | |||
163 | static bool choke_match_flow(struct sk_buff *skb1, | 169 | static bool choke_match_flow(struct sk_buff *skb1, |
164 | struct sk_buff *skb2) | 170 | struct sk_buff *skb2) |
165 | { | 171 | { |
172 | struct flow_keys temp; | ||
173 | |||
166 | if (skb1->protocol != skb2->protocol) | 174 | if (skb1->protocol != skb2->protocol) |
167 | return false; | 175 | return false; |
168 | 176 | ||
169 | if (!choke_skb_cb(skb1)->keys_valid) { | 177 | if (!choke_skb_cb(skb1)->keys_valid) { |
170 | choke_skb_cb(skb1)->keys_valid = 1; | 178 | choke_skb_cb(skb1)->keys_valid = 1; |
171 | skb_flow_dissect(skb1, &choke_skb_cb(skb1)->keys); | 179 | skb_flow_dissect(skb1, &temp); |
180 | memcpy(&choke_skb_cb(skb1)->keys, &temp, CHOKE_K_LEN); | ||
172 | } | 181 | } |
173 | 182 | ||
174 | if (!choke_skb_cb(skb2)->keys_valid) { | 183 | if (!choke_skb_cb(skb2)->keys_valid) { |
175 | choke_skb_cb(skb2)->keys_valid = 1; | 184 | choke_skb_cb(skb2)->keys_valid = 1; |
176 | skb_flow_dissect(skb2, &choke_skb_cb(skb2)->keys); | 185 | skb_flow_dissect(skb2, &temp); |
186 | memcpy(&choke_skb_cb(skb2)->keys, &temp, CHOKE_K_LEN); | ||
177 | } | 187 | } |
178 | 188 | ||
179 | return !memcmp(&choke_skb_cb(skb1)->keys, | 189 | return !memcmp(&choke_skb_cb(skb1)->keys, |
180 | &choke_skb_cb(skb2)->keys, | 190 | &choke_skb_cb(skb2)->keys, |
181 | sizeof(struct flow_keys)); | 191 | CHOKE_K_LEN); |
182 | } | 192 | } |
183 | 193 | ||
184 | /* | 194 | /* |