0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "dccp.h"
0010
0011
0012
0013
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
0033
0034
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
0065
0066
0067
0068
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
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
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
0133 if (!param || (param & (param - 1)))
0134 return false;
0135 return (qpol_table[dccp_sk(sk)->dccps_qpolicy].params & param) == param;
0136 }