aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_teql.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/sched/sch_teql.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'net/sched/sch_teql.c')
-rw-r--r--net/sched/sch_teql.c57
1 files changed, 31 insertions, 26 deletions
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 47416716294..4f4c52c0eeb 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -67,6 +67,7 @@ struct teql_master {
67struct teql_sched_data { 67struct teql_sched_data {
68 struct Qdisc *next; 68 struct Qdisc *next;
69 struct teql_master *m; 69 struct teql_master *m;
70 struct neighbour *ncache;
70 struct sk_buff_head q; 71 struct sk_buff_head q;
71}; 72};
72 73
@@ -87,7 +88,9 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc *sch)
87 return NET_XMIT_SUCCESS; 88 return NET_XMIT_SUCCESS;
88 } 89 }
89 90
90 return qdisc_drop(skb, sch); 91 kfree_skb(skb);
92 sch->qstats.drops++;
93 return NET_XMIT_DROP;
91} 94}
92 95
93static struct sk_buff * 96static struct sk_buff *
@@ -133,6 +136,7 @@ teql_reset(struct Qdisc *sch)
133 136
134 skb_queue_purge(&dat->q); 137 skb_queue_purge(&dat->q);
135 sch->q.qlen = 0; 138 sch->q.qlen = 0;
139 teql_neigh_release(xchg(&dat->ncache, NULL));
136} 140}
137 141
138static void 142static void
@@ -164,6 +168,7 @@ teql_destroy(struct Qdisc *sch)
164 } 168 }
165 } 169 }
166 skb_queue_purge(&dat->q); 170 skb_queue_purge(&dat->q);
171 teql_neigh_release(xchg(&dat->ncache, NULL));
167 break; 172 break;
168 } 173 }
169 174
@@ -222,25 +227,21 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
222static int 227static int
223__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, 228__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res,
224 struct net_device *dev, struct netdev_queue *txq, 229 struct net_device *dev, struct netdev_queue *txq,
225 struct dst_entry *dst) 230 struct neighbour *mn)
226{ 231{
227 struct neighbour *n; 232 struct teql_sched_data *q = qdisc_priv(txq->qdisc);
228 int err = 0; 233 struct neighbour *n = q->ncache;
229 234
230 n = dst_neigh_lookup_skb(dst, skb); 235 if (mn->tbl == NULL)
231 if (!n) 236 return -EINVAL;
232 return -ENOENT; 237 if (n && n->tbl == mn->tbl &&
233 238 memcmp(n->primary_key, mn->primary_key, mn->tbl->key_len) == 0) {
234 if (dst->dev != dev) { 239 atomic_inc(&n->refcnt);
235 struct neighbour *mn; 240 } else {
236 241 n = __neigh_lookup_errno(mn->tbl, mn->primary_key, dev);
237 mn = __neigh_lookup_errno(n->tbl, n->primary_key, dev); 242 if (IS_ERR(n))
238 neigh_release(n); 243 return PTR_ERR(n);
239 if (IS_ERR(mn))
240 return PTR_ERR(mn);
241 n = mn;
242 } 244 }
243
244 if (neigh_event_send(n, skb_res) == 0) { 245 if (neigh_event_send(n, skb_res) == 0) {
245 int err; 246 int err;
246 char haddr[MAX_ADDR_LEN]; 247 char haddr[MAX_ADDR_LEN];
@@ -249,13 +250,15 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res,
249 err = dev_hard_header(skb, dev, ntohs(skb->protocol), haddr, 250 err = dev_hard_header(skb, dev, ntohs(skb->protocol), haddr,
250 NULL, skb->len); 251 NULL, skb->len);
251 252
252 if (err < 0) 253 if (err < 0) {
253 err = -EINVAL; 254 neigh_release(n);
254 } else { 255 return -EINVAL;
255 err = (skb_res == NULL) ? -EAGAIN : 1; 256 }
257 teql_neigh_release(xchg(&q->ncache, n));
258 return 0;
256 } 259 }
257 neigh_release(n); 260 neigh_release(n);
258 return err; 261 return (skb_res == NULL) ? -EAGAIN : 1;
259} 262}
260 263
261static inline int teql_resolve(struct sk_buff *skb, 264static inline int teql_resolve(struct sk_buff *skb,
@@ -264,6 +267,7 @@ static inline int teql_resolve(struct sk_buff *skb,
264 struct netdev_queue *txq) 267 struct netdev_queue *txq)
265{ 268{
266 struct dst_entry *dst = skb_dst(skb); 269 struct dst_entry *dst = skb_dst(skb);
270 struct neighbour *mn;
267 int res; 271 int res;
268 272
269 if (txq->qdisc == &noop_qdisc) 273 if (txq->qdisc == &noop_qdisc)
@@ -273,7 +277,8 @@ static inline int teql_resolve(struct sk_buff *skb,
273 return 0; 277 return 0;
274 278
275 rcu_read_lock(); 279 rcu_read_lock();
276 res = __teql_resolve(skb, skb_res, dev, txq, dst); 280 mn = dst_get_neighbour(dst);
281 res = mn ? __teql_resolve(skb, skb_res, dev, txq, mn) : 0;
277 rcu_read_unlock(); 282 rcu_read_unlock();
278 283
279 return res; 284 return res;
@@ -305,7 +310,7 @@ restart:
305 310
306 if (slave_txq->qdisc_sleeping != q) 311 if (slave_txq->qdisc_sleeping != q)
307 continue; 312 continue;
308 if (netif_xmit_stopped(netdev_get_tx_queue(slave, subq)) || 313 if (__netif_subqueue_stopped(slave, subq) ||
309 !netif_running(slave)) { 314 !netif_running(slave)) {
310 busy = 1; 315 busy = 1;
311 continue; 316 continue;
@@ -316,7 +321,7 @@ restart:
316 if (__netif_tx_trylock(slave_txq)) { 321 if (__netif_tx_trylock(slave_txq)) {
317 unsigned int length = qdisc_pkt_len(skb); 322 unsigned int length = qdisc_pkt_len(skb);
318 323
319 if (!netif_xmit_frozen_or_stopped(slave_txq) && 324 if (!netif_tx_queue_frozen_or_stopped(slave_txq) &&
320 slave_ops->ndo_start_xmit(skb, slave) == NETDEV_TX_OK) { 325 slave_ops->ndo_start_xmit(skb, slave) == NETDEV_TX_OK) {
321 txq_trans_update(slave_txq); 326 txq_trans_update(slave_txq);
322 __netif_tx_unlock(slave_txq); 327 __netif_tx_unlock(slave_txq);
@@ -328,7 +333,7 @@ restart:
328 } 333 }
329 __netif_tx_unlock(slave_txq); 334 __netif_tx_unlock(slave_txq);
330 } 335 }
331 if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0))) 336 if (netif_queue_stopped(dev))
332 busy = 1; 337 busy = 1;
333 break; 338 break;
334 case 1: 339 case 1: