linux/net/dccp/qpolicy.c
<<
>>
Prefs
   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 */
  15static void qpolicy_simple_push(struct sock *sk, struct sk_buff *skb)
  16{
  17        skb_queue_tail(&sk->sk_write_queue, skb);
  18}
  19
  20static 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
  26static 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 */
  36static 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
  46static 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
  56static 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 */
  69static 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 */
  93void dccp_qpolicy_push(struct sock *sk, struct sk_buff *skb)
  94{
  95        qpol_table[dccp_sk(sk)->dccps_qpolicy].push(sk, skb);
  96}
  97
  98bool dccp_qpolicy_full(struct sock *sk)
  99{
 100        return qpol_table[dccp_sk(sk)->dccps_qpolicy].full(sk);
 101}
 102
 103void 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
 111struct sk_buff *dccp_qpolicy_top(struct sock *sk)
 112{
 113        return qpol_table[dccp_sk(sk)->dccps_qpolicy].top(sk);
 114}
 115
 116struct 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
 128bool 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}
 135