Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  net/dccp/qpolicy.c
0004  *
0005  *  Policy-based packet dequeueing interface for DCCP.
0006  *
0007  *  Copyright (c) 2008 Tomasz Grobelny <tomasz@grobelny.oswiecenia.net>
0008  */
0009 #include "dccp.h"
0010 
0011 /*
0012  *  Simple Dequeueing Policy:
0013  *  If tx_qlen is different from 0, enqueue up to tx_qlen elements.
0014  */
0015 static void qpolicy_simple_push(struct sock *sk, struct sk_buff *skb)
0016 {
0017     skb_queue_tail(&sk->sk_write_queue, skb);
0018 }
0019 
0020 static bool qpolicy_simple_full(struct sock *sk)
0021 {
0022     return dccp_sk(sk)->dccps_tx_qlen &&
0023            sk->sk_write_queue.qlen >= dccp_sk(sk)->dccps_tx_qlen;
0024 }
0025 
0026 static struct sk_buff *qpolicy_simple_top(struct sock *sk)
0027 {
0028     return skb_peek(&sk->sk_write_queue);
0029 }
0030 
0031 /*
0032  *  Priority-based Dequeueing Policy:
0033  *  If tx_qlen is different from 0 and the queue has reached its upper bound
0034  *  of tx_qlen elements, replace older packets lowest-priority-first.
0035  */
0036 static struct sk_buff *qpolicy_prio_best_skb(struct sock *sk)
0037 {
0038     struct sk_buff *skb, *best = NULL;
0039 
0040     skb_queue_walk(&sk->sk_write_queue, skb)
0041         if (best == NULL || skb->priority > best->priority)
0042             best = skb;
0043     return best;
0044 }
0045 
0046 static struct sk_buff *qpolicy_prio_worst_skb(struct sock *sk)
0047 {
0048     struct sk_buff *skb, *worst = NULL;
0049 
0050     skb_queue_walk(&sk->sk_write_queue, skb)
0051         if (worst == NULL || skb->priority < worst->priority)
0052             worst = skb;
0053     return worst;
0054 }
0055 
0056 static bool qpolicy_prio_full(struct sock *sk)
0057 {
0058     if (qpolicy_simple_full(sk))
0059         dccp_qpolicy_drop(sk, qpolicy_prio_worst_skb(sk));
0060     return false;
0061 }
0062 
0063 /**
0064  * struct dccp_qpolicy_operations  -  TX Packet Dequeueing Interface
0065  * @push: add a new @skb to the write queue
0066  * @full: indicates that no more packets will be admitted
0067  * @top:  peeks at whatever the queueing policy defines as its `top'
0068  * @params: parameter passed to policy operation
0069  */
0070 struct dccp_qpolicy_operations {
0071     void        (*push) (struct sock *sk, struct sk_buff *skb);
0072     bool        (*full) (struct sock *sk);
0073     struct sk_buff* (*top)  (struct sock *sk);
0074     __be32      params;
0075 };
0076 
0077 static struct dccp_qpolicy_operations qpol_table[DCCPQ_POLICY_MAX] = {
0078     [DCCPQ_POLICY_SIMPLE] = {
0079         .push   = qpolicy_simple_push,
0080         .full   = qpolicy_simple_full,
0081         .top    = qpolicy_simple_top,
0082         .params = 0,
0083     },
0084     [DCCPQ_POLICY_PRIO] = {
0085         .push   = qpolicy_simple_push,
0086         .full   = qpolicy_prio_full,
0087         .top    = qpolicy_prio_best_skb,
0088         .params = DCCP_SCM_PRIORITY,
0089     },
0090 };
0091 
0092 /*
0093  *  Externally visible interface
0094  */
0095 void dccp_qpolicy_push(struct sock *sk, struct sk_buff *skb)
0096 {
0097     qpol_table[dccp_sk(sk)->dccps_qpolicy].push(sk, skb);
0098 }
0099 
0100 bool dccp_qpolicy_full(struct sock *sk)
0101 {
0102     return qpol_table[dccp_sk(sk)->dccps_qpolicy].full(sk);
0103 }
0104 
0105 void dccp_qpolicy_drop(struct sock *sk, struct sk_buff *skb)
0106 {
0107     if (skb != NULL) {
0108         skb_unlink(skb, &sk->sk_write_queue);
0109         kfree_skb(skb);
0110     }
0111 }
0112 
0113 struct sk_buff *dccp_qpolicy_top(struct sock *sk)
0114 {
0115     return qpol_table[dccp_sk(sk)->dccps_qpolicy].top(sk);
0116 }
0117 
0118 struct sk_buff *dccp_qpolicy_pop(struct sock *sk)
0119 {
0120     struct sk_buff *skb = dccp_qpolicy_top(sk);
0121 
0122     if (skb != NULL) {
0123         /* Clear any skb fields that we used internally */
0124         skb->priority = 0;
0125         skb_unlink(skb, &sk->sk_write_queue);
0126     }
0127     return skb;
0128 }
0129 
0130 bool dccp_qpolicy_param_ok(struct sock *sk, __be32 param)
0131 {
0132     /* check if exactly one bit is set */
0133     if (!param || (param & (param - 1)))
0134         return false;
0135     return (qpol_table[dccp_sk(sk)->dccps_qpolicy].params & param) == param;
0136 }