blob: 27ccf097df204e07f37891cc3457cd1567257c8a [file] [log] [blame]
Benny Prijono4d79b0f2009-10-25 09:02:07 +00001/* $Id$ */
2/*
3 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/sock_qos.h>
20#include <pj/assert.h>
21#include <pj/errno.h>
22#include <pj/log.h>
23#include <pj/string.h>
24
25#define THIS_FILE "sock_qos_common.c"
Benny Prijono610973a2009-10-25 10:50:17 +000026#define ALL_FLAGS (PJ_QOS_PARAM_HAS_DSCP | PJ_QOS_PARAM_HAS_SO_PRIO | \
Benny Prijono4d79b0f2009-10-25 09:02:07 +000027 PJ_QOS_PARAM_HAS_WMM)
28
29/* "Standard" mapping between traffic type and QoS params */
30static const pj_qos_params qos_map[] =
31{
32 /* flags dscp prio wmm_prio */
33 {ALL_FLAGS, 0x00, 0, PJ_QOS_WMM_PRIO_BULK_EFFORT}, /* BE */
34 {ALL_FLAGS, 0x08, 2, PJ_QOS_WMM_PRIO_BULK}, /* BK */
35 {ALL_FLAGS, 0x28, 5, PJ_QOS_WMM_PRIO_VIDEO}, /* VI */
36 {ALL_FLAGS, 0x30, 6, PJ_QOS_WMM_PRIO_VOICE}, /* VO */
37 {ALL_FLAGS, 0x38, 7, PJ_QOS_WMM_PRIO_VOICE} /* CO */
38};
39
40
41/* Retrieve the mapping for the specified type */
42PJ_DEF(pj_status_t) pj_qos_get_params(pj_qos_type type,
43 pj_qos_params *p_param)
44{
45 PJ_ASSERT_RETURN(type<=PJ_QOS_TYPE_CONTROL && p_param, PJ_EINVAL);
46 pj_memcpy(p_param, &qos_map[type], sizeof(*p_param));
47 return PJ_SUCCESS;
48}
49
50/* Get the matching traffic type */
51PJ_DEF(pj_status_t) pj_qos_get_type( const pj_qos_params *param,
52 pj_qos_type *p_type)
53{
54 unsigned dscp_type = PJ_QOS_TYPE_BEST_EFFORT,
55 prio_type = PJ_QOS_TYPE_BEST_EFFORT,
56 wmm_type = PJ_QOS_TYPE_BEST_EFFORT;
57 unsigned i, count=0;
58
59 PJ_ASSERT_RETURN(param && p_type, PJ_EINVAL);
60
61 if (param->flags & PJ_QOS_PARAM_HAS_DSCP) {
62 for (i=0; i<=PJ_QOS_TYPE_CONTROL; ++i) {
63 if (param->dscp_val >= qos_map[i].dscp_val)
64 dscp_type = (pj_qos_type)i;
65 }
66 ++count;
67 }
68
Benny Prijono610973a2009-10-25 10:50:17 +000069 if (param->flags & PJ_QOS_PARAM_HAS_SO_PRIO) {
Benny Prijono4d79b0f2009-10-25 09:02:07 +000070 for (i=0; i<=PJ_QOS_TYPE_CONTROL; ++i) {
71 if (param->so_prio >= qos_map[i].so_prio)
72 prio_type = (pj_qos_type)i;
73 }
74 ++count;
75 }
76
77 if (param->flags & PJ_QOS_PARAM_HAS_WMM) {
78 for (i=0; i<=PJ_QOS_TYPE_CONTROL; ++i) {
79 if (param->wmm_prio >= qos_map[i].wmm_prio)
80 wmm_type = (pj_qos_type)i;
81 }
82 ++count;
83 }
84
85 if (count)
86 *p_type = (pj_qos_type)((dscp_type + prio_type + wmm_type) / count);
87 else
88 *p_type = PJ_QOS_TYPE_BEST_EFFORT;
89
90 return PJ_SUCCESS;
91}
92
93/* Apply QoS */
94PJ_DEF(pj_status_t) pj_sock_apply_qos( pj_sock_t sock,
95 pj_qos_type qos_type,
96 pj_qos_params *qos_params,
97 unsigned log_level,
98 const char *log_sender,
99 const char *sock_name)
100{
101 char fmt[60];
102 pj_status_t qos_type_rc = PJ_SUCCESS,
103 qos_params_rc = PJ_SUCCESS;
104
105 if (!log_sender)
106 log_sender = THIS_FILE;
107 if (!sock_name)
108 sock_name = "socket";
109
110 if (qos_type != PJ_QOS_TYPE_BEST_EFFORT) {
111 qos_type_rc = pj_sock_set_qos_type(sock, qos_type);
112
113 if (qos_type_rc != PJ_SUCCESS) {
114 pj_ansi_snprintf(fmt, sizeof(fmt),
115 "Error setting QoS type %d to %s",
116 qos_type, sock_name);
117 pj_perror(log_level, log_sender, qos_type_rc, fmt, 0);
118 }
119 }
120
121 if (qos_params && qos_params->flags) {
122 qos_params_rc = pj_sock_set_qos_params(sock, qos_params);
123 if (qos_params_rc != PJ_SUCCESS) {
124 pj_ansi_snprintf(fmt, sizeof(fmt),
125 "Error setting QoS params (flags=%d) to %s",
126 qos_params->flags, sock_name);
127 pj_perror(log_level, log_sender, qos_params_rc, fmt, 0);
128 if (qos_type_rc != PJ_SUCCESS)
129 return qos_params_rc;
130 }
131 } else if (qos_type_rc != PJ_SUCCESS)
132 return qos_type_rc;
133
134 return PJ_SUCCESS;
135}
136
137
138PJ_DEF(pj_status_t) pj_sock_apply_qos2( pj_sock_t sock,
139 pj_qos_type qos_type,
140 const pj_qos_params *qos_params,
141 unsigned log_level,
142 const char *log_sender,
143 const char *sock_name)
144{
145 pj_qos_params qos_params_buf, *qos_params_copy = NULL;
146
147 if (qos_params) {
148 pj_memcpy(&qos_params_buf, qos_params, sizeof(*qos_params));
149 qos_params_copy = &qos_params_buf;
150 }
151
152 return pj_sock_apply_qos(sock, qos_type, qos_params_copy,
153 log_level, log_sender, sock_name);
154}