1 // SPDX-License-Identifier: GPL-2.0-only
5 * Policy-based packet dequeueing interface for DCCP.
7 * Copyright (c) 2008 Tomasz Grobelny <tomasz@grobelny.oswiecenia.net>
12 * Simple Dequeueing Policy:
13 * If tx_qlen is different from 0, enqueue up to tx_qlen elements.
15 static void qpolicy_simple_push(struct sock
*sk
, struct sk_buff
*skb
)
17 skb_queue_tail(&sk
->sk_write_queue
, skb
);
20 static bool qpolicy_simple_full(struct sock
*sk
)
22 return dccp_sk(sk
)->dccps_tx_qlen
&&
23 sk
->sk_write_queue
.qlen
>= dccp_sk(sk
)->dccps_tx_qlen
;
26 static struct sk_buff
*qpolicy_simple_top(struct sock
*sk
)
28 return skb_peek(&sk
->sk_write_queue
);
32 * Priority-based Dequeueing Policy:
33 * If tx_qlen is different from 0 and the queue has reached its upper bound
34 * of tx_qlen elements, replace older packets lowest-priority-first.
36 static struct sk_buff
*qpolicy_prio_best_skb(struct sock
*sk
)
38 struct sk_buff
*skb
, *best
= NULL
;
40 skb_queue_walk(&sk
->sk_write_queue
, skb
)
41 if (best
== NULL
|| skb
->priority
> best
->priority
)
46 static struct sk_buff
*qpolicy_prio_worst_skb(struct sock
*sk
)
48 struct sk_buff
*skb
, *worst
= NULL
;
50 skb_queue_walk(&sk
->sk_write_queue
, skb
)
51 if (worst
== NULL
|| skb
->priority
< worst
->priority
)
56 static bool qpolicy_prio_full(struct sock
*sk
)
58 if (qpolicy_simple_full(sk
))
59 dccp_qpolicy_drop(sk
, qpolicy_prio_worst_skb(sk
));
64 * struct dccp_qpolicy_operations - TX Packet Dequeueing Interface
65 * @push: add a new @skb to the write queue
66 * @full: indicates that no more packets will be admitted
67 * @top: peeks at whatever the queueing policy defines as its `top'
69 static struct dccp_qpolicy_operations
{
70 void (*push
) (struct sock
*sk
, struct sk_buff
*skb
);
71 bool (*full
) (struct sock
*sk
);
72 struct sk_buff
* (*top
) (struct sock
*sk
);
75 } qpol_table
[DCCPQ_POLICY_MAX
] = {
76 [DCCPQ_POLICY_SIMPLE
] = {
77 .push
= qpolicy_simple_push
,
78 .full
= qpolicy_simple_full
,
79 .top
= qpolicy_simple_top
,
82 [DCCPQ_POLICY_PRIO
] = {
83 .push
= qpolicy_simple_push
,
84 .full
= qpolicy_prio_full
,
85 .top
= qpolicy_prio_best_skb
,
86 .params
= DCCP_SCM_PRIORITY
,
91 * Externally visible interface
93 void dccp_qpolicy_push(struct sock
*sk
, struct sk_buff
*skb
)
95 qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].push(sk
, skb
);
98 bool dccp_qpolicy_full(struct sock
*sk
)
100 return qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].full(sk
);
103 void dccp_qpolicy_drop(struct sock
*sk
, struct sk_buff
*skb
)
106 skb_unlink(skb
, &sk
->sk_write_queue
);
111 struct sk_buff
*dccp_qpolicy_top(struct sock
*sk
)
113 return qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].top(sk
);
116 struct sk_buff
*dccp_qpolicy_pop(struct sock
*sk
)
118 struct sk_buff
*skb
= dccp_qpolicy_top(sk
);
121 /* Clear any skb fields that we used internally */
123 skb_unlink(skb
, &sk
->sk_write_queue
);
128 bool dccp_qpolicy_param_ok(struct sock
*sk
, __be32 param
)
130 /* check if exactly one bit is set */
131 if (!param
|| (param
& (param
- 1)))
133 return (qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].params
& param
) == param
;