4 * Policy-based packet dequeueing interface for DCCP.
6 * Copyright (c) 2008 Tomasz Grobelny <tomasz@grobelny.oswiecenia.net>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License v2
10 * as published by the Free Software Foundation.
15 * Simple Dequeueing Policy:
16 * If tx_qlen is different from 0, enqueue up to tx_qlen elements.
18 static void qpolicy_simple_push(struct sock
*sk
, struct sk_buff
*skb
)
20 skb_queue_tail(&sk
->sk_write_queue
, skb
);
23 static bool qpolicy_simple_full(struct sock
*sk
)
25 return dccp_sk(sk
)->dccps_tx_qlen
&&
26 sk
->sk_write_queue
.qlen
>= dccp_sk(sk
)->dccps_tx_qlen
;
29 static struct sk_buff
*qpolicy_simple_top(struct sock
*sk
)
31 return skb_peek(&sk
->sk_write_queue
);
35 * Priority-based Dequeueing Policy:
36 * If tx_qlen is different from 0 and the queue has reached its upper bound
37 * of tx_qlen elements, replace older packets lowest-priority-first.
39 static struct sk_buff
*qpolicy_prio_best_skb(struct sock
*sk
)
41 struct sk_buff
*skb
, *best
= NULL
;
43 skb_queue_walk(&sk
->sk_write_queue
, skb
)
44 if (best
== NULL
|| skb
->priority
> best
->priority
)
49 static struct sk_buff
*qpolicy_prio_worst_skb(struct sock
*sk
)
51 struct sk_buff
*skb
, *worst
= NULL
;
53 skb_queue_walk(&sk
->sk_write_queue
, skb
)
54 if (worst
== NULL
|| skb
->priority
< worst
->priority
)
59 static bool qpolicy_prio_full(struct sock
*sk
)
61 if (qpolicy_simple_full(sk
))
62 dccp_qpolicy_drop(sk
, qpolicy_prio_worst_skb(sk
));
67 * struct dccp_qpolicy_operations - TX Packet Dequeueing Interface
68 * @push: add a new @skb to the write queue
69 * @full: indicates that no more packets will be admitted
70 * @top: peeks at whatever the queueing policy defines as its `top'
72 static struct dccp_qpolicy_operations
{
73 void (*push
) (struct sock
*sk
, struct sk_buff
*skb
);
74 bool (*full
) (struct sock
*sk
);
75 struct sk_buff
* (*top
) (struct sock
*sk
);
78 } qpol_table
[DCCPQ_POLICY_MAX
] = {
79 [DCCPQ_POLICY_SIMPLE
] = {
80 .push
= qpolicy_simple_push
,
81 .full
= qpolicy_simple_full
,
82 .top
= qpolicy_simple_top
,
85 [DCCPQ_POLICY_PRIO
] = {
86 .push
= qpolicy_simple_push
,
87 .full
= qpolicy_prio_full
,
88 .top
= qpolicy_prio_best_skb
,
89 .params
= DCCP_SCM_PRIORITY
,
94 * Externally visible interface
96 void dccp_qpolicy_push(struct sock
*sk
, struct sk_buff
*skb
)
98 qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].push(sk
, skb
);
101 bool dccp_qpolicy_full(struct sock
*sk
)
103 return qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].full(sk
);
106 void dccp_qpolicy_drop(struct sock
*sk
, struct sk_buff
*skb
)
109 skb_unlink(skb
, &sk
->sk_write_queue
);
114 struct sk_buff
*dccp_qpolicy_top(struct sock
*sk
)
116 return qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].top(sk
);
119 struct sk_buff
*dccp_qpolicy_pop(struct sock
*sk
)
121 struct sk_buff
*skb
= dccp_qpolicy_top(sk
);
124 /* Clear any skb fields that we used internally */
126 skb_unlink(skb
, &sk
->sk_write_queue
);
131 bool dccp_qpolicy_param_ok(struct sock
*sk
, __be32 param
)
133 /* check if exactly one bit is set */
134 if (!param
|| (param
& (param
- 1)))
136 return (qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].params
& param
) == param
;