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'
68 * @params: parameter passed to policy operation
70 struct dccp_qpolicy_operations
{
71 void (*push
) (struct sock
*sk
, struct sk_buff
*skb
);
72 bool (*full
) (struct sock
*sk
);
73 struct sk_buff
* (*top
) (struct sock
*sk
);
77 static struct dccp_qpolicy_operations qpol_table
[DCCPQ_POLICY_MAX
] = {
78 [DCCPQ_POLICY_SIMPLE
] = {
79 .push
= qpolicy_simple_push
,
80 .full
= qpolicy_simple_full
,
81 .top
= qpolicy_simple_top
,
84 [DCCPQ_POLICY_PRIO
] = {
85 .push
= qpolicy_simple_push
,
86 .full
= qpolicy_prio_full
,
87 .top
= qpolicy_prio_best_skb
,
88 .params
= DCCP_SCM_PRIORITY
,
93 * Externally visible interface
95 void dccp_qpolicy_push(struct sock
*sk
, struct sk_buff
*skb
)
97 qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].push(sk
, skb
);
100 bool dccp_qpolicy_full(struct sock
*sk
)
102 return qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].full(sk
);
105 void dccp_qpolicy_drop(struct sock
*sk
, struct sk_buff
*skb
)
108 skb_unlink(skb
, &sk
->sk_write_queue
);
113 struct sk_buff
*dccp_qpolicy_top(struct sock
*sk
)
115 return qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].top(sk
);
118 struct sk_buff
*dccp_qpolicy_pop(struct sock
*sk
)
120 struct sk_buff
*skb
= dccp_qpolicy_top(sk
);
123 /* Clear any skb fields that we used internally */
125 skb_unlink(skb
, &sk
->sk_write_queue
);
130 bool dccp_qpolicy_param_ok(struct sock
*sk
, __be32 param
)
132 /* check if exactly one bit is set */
133 if (!param
|| (param
& (param
- 1)))
135 return (qpol_table
[dccp_sk(sk
)->dccps_qpolicy
].params
& param
) == param
;