root/net/dccp/qpolicy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qpolicy_simple_push
  2. qpolicy_simple_full
  3. qpolicy_simple_top
  4. qpolicy_prio_best_skb
  5. qpolicy_prio_worst_skb
  6. qpolicy_prio_full
  7. dccp_qpolicy_push
  8. dccp_qpolicy_full
  9. dccp_qpolicy_drop
  10. dccp_qpolicy_top
  11. dccp_qpolicy_pop
  12. dccp_qpolicy_param_ok

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  net/dccp/qpolicy.c
   4  *
   5  *  Policy-based packet dequeueing interface for DCCP.
   6  *
   7  *  Copyright (c) 2008 Tomasz Grobelny <tomasz@grobelny.oswiecenia.net>
   8  */
   9 #include "dccp.h"
  10 
  11 /*
  12  *      Simple Dequeueing Policy:
  13  *      If tx_qlen is different from 0, enqueue up to tx_qlen elements.
  14  */
  15 static void qpolicy_simple_push(struct sock *sk, struct sk_buff *skb)
  16 {
  17         skb_queue_tail(&sk->sk_write_queue, skb);
  18 }
  19 
  20 static bool qpolicy_simple_full(struct sock *sk)
  21 {
  22         return dccp_sk(sk)->dccps_tx_qlen &&
  23                sk->sk_write_queue.qlen >= dccp_sk(sk)->dccps_tx_qlen;
  24 }
  25 
  26 static struct sk_buff *qpolicy_simple_top(struct sock *sk)
  27 {
  28         return skb_peek(&sk->sk_write_queue);
  29 }
  30 
  31 /*
  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.
  35  */
  36 static struct sk_buff *qpolicy_prio_best_skb(struct sock *sk)
  37 {
  38         struct sk_buff *skb, *best = NULL;
  39 
  40         skb_queue_walk(&sk->sk_write_queue, skb)
  41                 if (best == NULL || skb->priority > best->priority)
  42                         best = skb;
  43         return best;
  44 }
  45 
  46 static struct sk_buff *qpolicy_prio_worst_skb(struct sock *sk)
  47 {
  48         struct sk_buff *skb, *worst = NULL;
  49 
  50         skb_queue_walk(&sk->sk_write_queue, skb)
  51                 if (worst == NULL || skb->priority < worst->priority)
  52                         worst = skb;
  53         return worst;
  54 }
  55 
  56 static bool qpolicy_prio_full(struct sock *sk)
  57 {
  58         if (qpolicy_simple_full(sk))
  59                 dccp_qpolicy_drop(sk, qpolicy_prio_worst_skb(sk));
  60         return false;
  61 }
  62 
  63 /**
  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  */
  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);
  73         __be32          params;
  74 
  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,
  80                 .params = 0,
  81         },
  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,
  87         },
  88 };
  89 
  90 /*
  91  *      Externally visible interface
  92  */
  93 void dccp_qpolicy_push(struct sock *sk, struct sk_buff *skb)
  94 {
  95         qpol_table[dccp_sk(sk)->dccps_qpolicy].push(sk, skb);
  96 }
  97 
  98 bool dccp_qpolicy_full(struct sock *sk)
  99 {
 100         return qpol_table[dccp_sk(sk)->dccps_qpolicy].full(sk);
 101 }
 102 
 103 void dccp_qpolicy_drop(struct sock *sk, struct sk_buff *skb)
 104 {
 105         if (skb != NULL) {
 106                 skb_unlink(skb, &sk->sk_write_queue);
 107                 kfree_skb(skb);
 108         }
 109 }
 110 
 111 struct sk_buff *dccp_qpolicy_top(struct sock *sk)
 112 {
 113         return qpol_table[dccp_sk(sk)->dccps_qpolicy].top(sk);
 114 }
 115 
 116 struct sk_buff *dccp_qpolicy_pop(struct sock *sk)
 117 {
 118         struct sk_buff *skb = dccp_qpolicy_top(sk);
 119 
 120         if (skb != NULL) {
 121                 /* Clear any skb fields that we used internally */
 122                 skb->priority = 0;
 123                 skb_unlink(skb, &sk->sk_write_queue);
 124         }
 125         return skb;
 126 }
 127 
 128 bool dccp_qpolicy_param_ok(struct sock *sk, __be32 param)
 129 {
 130         /* check if exactly one bit is set */
 131         if (!param || (param & (param - 1)))
 132                 return false;
 133         return (qpol_table[dccp_sk(sk)->dccps_qpolicy].params & param) == param;
 134 }

/* [<][>][^][v][top][bottom][index][help] */