Osmocom Packet control Unit (PCU): Network-side GPRS (RLC/MAC); BTS- or BSC-colocated https://osmocom.org/projects/osmopcu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
osmo-pcu/src/pcu_vty.c

1317 lines
40 KiB

/* OsmoBTS VTY interface */
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <osmocom/core/tdef.h>
#include <osmocom/core/utils.h>
#include <osmocom/vty/tdef_vty.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/stats.h>
#include <osmocom/vty/misc.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/ctrl/ports.h>
#include <osmocom/pcu/pcuif_proto.h>
#include <osmocom/gprs/gprs_ns2.h>
#include "pcu_vty.h"
#include "gprs_rlcmac.h"
#include <pdch.h>
#include "bts.h"
#include "tbf.h"
#include "pcu_vty_functions.h"
#define X(x) (1 << x)
extern void *tall_pcu_ctx;
static const struct value_string pcu_gsmtap_categ_names[] = {
{ PCU_GSMTAP_C_DL_UNKNOWN, "dl-unknown" },
{ PCU_GSMTAP_C_DL_DUMMY, "dl-dummy" },
{ PCU_GSMTAP_C_DL_CTRL, "dl-ctrl" },
{ PCU_GSMTAP_C_DL_DATA_GPRS, "dl-data-gprs" },
{ PCU_GSMTAP_C_DL_DATA_EGPRS, "dl-data-egprs" },
{ PCU_GSMTAP_C_DL_PTCCH, "dl-ptcch" },
{ PCU_GSMTAP_C_DL_AGCH, "dl-agch" },
{ PCU_GSMTAP_C_DL_PCH, "dl-pch" },
{ PCU_GSMTAP_C_UL_UNKNOWN, "ul-unknown" },
{ PCU_GSMTAP_C_UL_DUMMY, "ul-dummy" },
{ PCU_GSMTAP_C_UL_CTRL, "ul-ctrl" },
{ PCU_GSMTAP_C_UL_DATA_GPRS, "ul-data-gprs" },
{ PCU_GSMTAP_C_UL_DATA_EGPRS, "ul-data-egprs" },
{ PCU_GSMTAP_C_UL_RACH, "ul-rach" },
{ PCU_GSMTAP_C_UL_PTCCH, "ul-ptcch" },
{ 0, NULL }
};
static const struct value_string pcu_gsmtap_categ_help[] = {
{ PCU_GSMTAP_C_DL_UNKNOWN, "Unknown / Unparseable / Erroneous Downlink Blocks" },
{ PCU_GSMTAP_C_DL_DUMMY, "Downlink Dummy Blocks" },
{ PCU_GSMTAP_C_DL_CTRL, "Downlink Control Blocks" },
{ PCU_GSMTAP_C_DL_DATA_GPRS, "Downlink Data Blocks (GPRS)" },
{ PCU_GSMTAP_C_DL_DATA_EGPRS, "Downlink Data Blocks (EGPRS)" },
{ PCU_GSMTAP_C_DL_PTCCH, "Downlink PTCCH Blocks" },
{ PCU_GSMTAP_C_DL_AGCH, "Downlink AGCH Blocks" },
{ PCU_GSMTAP_C_DL_PCH, "Downlink PCH Blocks" },
{ PCU_GSMTAP_C_UL_UNKNOWN, "Unknown / Unparseable / Erroneous Downlink Blocks" },
{ PCU_GSMTAP_C_UL_DUMMY, "Uplink Dummy Blocks" },
{ PCU_GSMTAP_C_UL_CTRL, "Uplink Control Blocks" },
{ PCU_GSMTAP_C_UL_DATA_GPRS, "Uplink Data Blocks (GPRS)" },
{ PCU_GSMTAP_C_UL_DATA_EGPRS, "Uplink Data Blocks (EGPRS)" },
{ PCU_GSMTAP_C_UL_RACH, "Uplink RACH Bursts" },
{ PCU_GSMTAP_C_UL_PTCCH, "Uplink PTCCH Bursts" },
{ 0, NULL }
};
DEFUN(cfg_pcu_gsmtap_categ, cfg_pcu_gsmtap_categ_cmd, "HIDDEN", "HIDDEN")
{
int categ;
categ = get_string_value(pcu_gsmtap_categ_names, argv[0]);
if (categ < 0)
return CMD_WARNING;
the_pcu->gsmtap_categ_mask |= (1 << categ);
return CMD_SUCCESS;
}
DEFUN(cfg_pcu_no_gsmtap_categ, cfg_pcu_no_gsmtap_categ_cmd, "HIDDEN", "HIDDEN")
{
int categ;
categ = get_string_value(pcu_gsmtap_categ_names, argv[0]);
if (categ < 0)
return CMD_WARNING;
the_pcu->gsmtap_categ_mask &= ~(1 << categ);
return CMD_SUCCESS;
}
static struct cmd_node pcu_node = {
(enum node_type) PCU_NODE,
"%s(config-pcu)# ",
1,
};
static int config_write_pcu(struct vty *vty)
{
unsigned int i;
vty_out(vty, "pcu%s", VTY_NEWLINE);
vty_out(vty, " flow-control-interval %d%s", the_pcu->vty.fc_interval,
VTY_NEWLINE);
if (the_pcu->vty.fc_bvc_bucket_size)
vty_out(vty, " flow-control force-bvc-bucket-size %d%s",
the_pcu->vty.fc_bvc_bucket_size, VTY_NEWLINE);
if (the_pcu->vty.fc_bvc_leak_rate)
vty_out(vty, " flow-control force-bvc-leak-rate %d%s",
the_pcu->vty.fc_bvc_leak_rate, VTY_NEWLINE);
if (the_pcu->vty.fc_ms_bucket_size)
vty_out(vty, " flow-control force-ms-bucket-size %d%s",
the_pcu->vty.fc_ms_bucket_size, VTY_NEWLINE);
if (the_pcu->vty.fc_ms_leak_rate)
vty_out(vty, " flow-control force-ms-leak-rate %d%s",
the_pcu->vty.fc_ms_leak_rate, VTY_NEWLINE);
if (the_pcu->vty.force_initial_cs) {
if (the_pcu->vty.initial_cs_ul == the_pcu->vty.initial_cs_dl)
vty_out(vty, " cs %d%s", the_pcu->vty.initial_cs_dl,
VTY_NEWLINE);
else
vty_out(vty, " cs %d %d%s", the_pcu->vty.initial_cs_dl,
the_pcu->vty.initial_cs_ul, VTY_NEWLINE);
}
if (the_pcu->vty.max_cs_dl && the_pcu->vty.max_cs_ul) {
if (the_pcu->vty.max_cs_ul == the_pcu->vty.max_cs_dl)
vty_out(vty, " cs max %d%s", the_pcu->vty.max_cs_dl,
VTY_NEWLINE);
else
vty_out(vty, " cs max %d %d%s", the_pcu->vty.max_cs_dl,
the_pcu->vty.max_cs_ul, VTY_NEWLINE);
}
if (the_pcu->vty.cs_adj_enabled)
vty_out(vty, " cs threshold %d %d%s",
the_pcu->vty.cs_adj_lower_limit, the_pcu->vty.cs_adj_upper_limit,
VTY_NEWLINE);
else
vty_out(vty, " no cs threshold%s", VTY_NEWLINE);
if (the_pcu->vty.cs_downgrade_threshold)
vty_out(vty, " cs downgrade-threshold %d%s",
the_pcu->vty.cs_downgrade_threshold, VTY_NEWLINE);
else
vty_out(vty, " no cs downgrade-threshold%s", VTY_NEWLINE);
vty_out(vty, " cs link-quality-ranges cs1 %d cs2 %d %d cs3 %d %d cs4 %d%s",
the_pcu->vty.cs_lqual_ranges[0].high,
the_pcu->vty.cs_lqual_ranges[1].low,
the_pcu->vty.cs_lqual_ranges[1].high,
the_pcu->vty.cs_lqual_ranges[2].low,
the_pcu->vty.cs_lqual_ranges[2].high,
the_pcu->vty.cs_lqual_ranges[3].low,
VTY_NEWLINE);
vty_out(vty, " mcs link-quality-ranges mcs1 %d mcs2 %d %d mcs3 %d %d mcs4 %d %d mcs5 %d %d mcs6 %d %d mcs7 %d %d mcs8 %d %d mcs9 %d%s",
the_pcu->vty.mcs_lqual_ranges[0].high,
the_pcu->vty.mcs_lqual_ranges[1].low,
the_pcu->vty.mcs_lqual_ranges[1].high,
the_pcu->vty.mcs_lqual_ranges[2].low,
the_pcu->vty.mcs_lqual_ranges[2].high,
the_pcu->vty.mcs_lqual_ranges[3].low,
the_pcu->vty.mcs_lqual_ranges[3].high,
the_pcu->vty.mcs_lqual_ranges[4].low,
the_pcu->vty.mcs_lqual_ranges[4].high,
the_pcu->vty.mcs_lqual_ranges[5].low,
the_pcu->vty.mcs_lqual_ranges[5].high,
the_pcu->vty.mcs_lqual_ranges[6].low,
the_pcu->vty.mcs_lqual_ranges[6].high,
the_pcu->vty.mcs_lqual_ranges[7].low,
the_pcu->vty.mcs_lqual_ranges[7].high,
the_pcu->vty.mcs_lqual_ranges[8].low,
VTY_NEWLINE);
if (the_pcu->vty.force_initial_mcs) {
if (the_pcu->vty.initial_mcs_ul == the_pcu->vty.initial_mcs_dl)
vty_out(vty, " mcs %d%s", the_pcu->vty.initial_mcs_dl,
VTY_NEWLINE);
else
vty_out(vty, " mcs %d %d%s", the_pcu->vty.initial_mcs_dl,
the_pcu->vty.initial_mcs_ul, VTY_NEWLINE);
}
if (the_pcu->vty.max_mcs_dl && the_pcu->vty.max_mcs_ul) {
if (the_pcu->vty.max_mcs_ul == the_pcu->vty.max_mcs_dl)
vty_out(vty, " mcs max %d%s", the_pcu->vty.max_mcs_dl,
VTY_NEWLINE);
else
vty_out(vty, " mcs max %d %d%s", the_pcu->vty.max_mcs_dl,
the_pcu->vty.max_mcs_ul, VTY_NEWLINE);
}
vty_out(vty, " window-size %d %d%s", the_pcu->vty.ws_base, the_pcu->vty.ws_pdch,
VTY_NEWLINE);
if (the_pcu->vty.dl_arq_type == EGPRS_ARQ2)
vty_out(vty, " egprs dl arq-type arq2%s", VTY_NEWLINE);
if (the_pcu->vty.force_llc_lifetime == 0xffff)
vty_out(vty, " queue lifetime infinite%s", VTY_NEWLINE);
else if (the_pcu->vty.force_llc_lifetime)
vty_out(vty, " queue lifetime %d%s", the_pcu->vty.force_llc_lifetime,
VTY_NEWLINE);
if (the_pcu->vty.llc_discard_csec)
vty_out(vty, " queue hysteresis %d%s", the_pcu->vty.llc_discard_csec,
tbf: Use a hysteresis when discarding DL LLC frames Currently single LLC blocks are discarded when the PDU lifetime expires. If an IP packet has been fragmented either on the IP or on the LLC layer and is therefore distributed over several LLC frames, the kept fragments are transmitted and then discarded by the MS because of the missing PDU. This can cause massive IP packet loss when there are many fragmented packets (e.g. when trying 'ping -s1800' or if the GGSN chops downlink IP packets into several SNDCP packets). On the other hand, discarding too many packets might disturb the congestion handling of TCP. Dropping plain TCP ACKs might also hinder flow control and congestion avoidance. This commit adds a hysteresis algorithm to the LLC discard loop. If an LLC message's age reaches the high water mark, further message's with an age above the low water mark are discarded, too. This is aborted, if a GMM, a non-UI, or a small message is detected. In these cases, that message is kept. The following VTY commands are added (pcu config node): - queue hysteresis <1-65535> set the difference between high (lifetime) and low watermark in centiseconds - no queue hysteresis disable this feature (default) Since the SGSN will most probably send all fragments of a single N-PDU without much delay between them, a value slightly above the average transmission delay jitter between SGSN and PCU is probably a sensible value to discard all fragments of a single IP packet. This is an experimental feature that might be replaced by more advanced means of active queue management in the future. Sponsored-by: On-Waves ehf
8 years ago
VTY_NEWLINE);
if (the_pcu->vty.llc_idle_ack_csec)
vty_out(vty, " queue idle-ack-delay %d%s", the_pcu->vty.llc_idle_ack_csec,
VTY_NEWLINE);
if (the_pcu->vty.llc_codel_interval_msec == LLC_CODEL_USE_DEFAULT)
llc: Use CoDel to drop packages from the LLC queue Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
8 years ago
vty_out(vty, " queue codel%s", VTY_NEWLINE);
else if (the_pcu->vty.llc_codel_interval_msec == LLC_CODEL_DISABLE)
llc: Use CoDel to drop packages from the LLC queue Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
8 years ago
vty_out(vty, " no queue codel%s", VTY_NEWLINE);
else
vty_out(vty, " queue codel interval %d%s",
the_pcu->vty.llc_codel_interval_msec/10, VTY_NEWLINE);
llc: Use CoDel to drop packages from the LLC queue Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
8 years ago
if (the_pcu->alloc_algorithm == alloc_algorithm_a)
vty_out(vty, " alloc-algorithm a%s", VTY_NEWLINE);
if (the_pcu->alloc_algorithm == alloc_algorithm_b)
vty_out(vty, " alloc-algorithm b%s", VTY_NEWLINE);
if (the_pcu->alloc_algorithm == alloc_algorithm_dynamic)
vty_out(vty, " alloc-algorithm dynamic%s", VTY_NEWLINE);
if (the_pcu->vty.force_two_phase)
vty_out(vty, " two-phase-access%s", VTY_NEWLINE);
if (the_pcu->vty.force_alpha != (uint8_t)-1)
vty_out(vty, " alpha %u%s", the_pcu->vty.force_alpha, VTY_NEWLINE);
vty_out(vty, " gamma %d%s", the_pcu->vty.gamma * 2, VTY_NEWLINE);
if (!the_pcu->vty.dl_tbf_preemptive_retransmission)
vty_out(vty, " no dl-tbf-preemptive-retransmission%s", VTY_NEWLINE);
if (strcmp(the_pcu->pcu_sock_path, PCU_SOCK_DEFAULT))
vty_out(vty, " pcu-socket %s%s", the_pcu->pcu_sock_path, VTY_NEWLINE);
for (i = 0; i < 32; i++) {
uint32_t cs = ((uint32_t)1 << i);
if (the_pcu->gsmtap_categ_mask & cs) {
vty_out(vty, " gsmtap-category %s%s",
get_value_string(pcu_gsmtap_categ_names, i), VTY_NEWLINE);
}
}
if (the_pcu->vty.ns_dialect == GPRS_NS2_DIALECT_SNS)
vty_out(vty, " gb-dialect ip-sns%s", VTY_NEWLINE);
else
vty_out(vty, " gb-dialect classic%s", VTY_NEWLINE);
if (the_pcu->vty.ns_ip_dscp != -1)
vty_out(vty, " gb ip-dscp %d%s", the_pcu->vty.ns_ip_dscp, VTY_NEWLINE);
if (the_pcu->vty.ns_priority != -1)
vty_out(vty, " gb socket-priority %d%s", the_pcu->vty.ns_priority, VTY_NEWLINE);
if (the_pcu->vty.neigh_ctrl_addr) {
vty_out(vty, " neighbor resolution %s %u%s",
the_pcu->vty.neigh_ctrl_addr, the_pcu->vty.neigh_ctrl_port, VTY_NEWLINE);
}
osmo_tdef_vty_write(vty, the_pcu->T_defs, " timer ");
return CMD_SUCCESS;
}
/* per-BTS configuration */
DEFUN_ATTR(cfg_pcu,
cfg_pcu_cmd,
"pcu",
"BTS specific configure",
CMD_ATTR_IMMEDIATE)
{
vty->node = PCU_NODE;
return CMD_SUCCESS;
}
#define EGPRS_STR "EGPRS configuration\n"
DEFUN_DEPRECATED(cfg_pcu_egprs,
cfg_pcu_egprs_cmd,
"egprs only",
EGPRS_STR "Use EGPRS and disable plain GPRS\n")
{
vty_out (vty, "'egprs only' is deprecated, egprs support is controled from BTS/BSC config, this is now a no-op%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN_DEPRECATED(cfg_pcu_no_egprs,
cfg_pcu_no_egprs_cmd,
"no egprs",
NO_STR EGPRS_STR)
{
vty_out (vty, "'no egprs only' is deprecated, egprs support is controled from BTS/BSC config, this is now a no-op%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_fc_interval,
cfg_pcu_fc_interval_cmd,
"flow-control-interval <1-10>",
"Interval between sending subsequent Flow Control PDUs\n"
"Interval time in seconds\n",
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_interval = atoi(argv[0]);
return CMD_SUCCESS;
}
#define FC_STR "BSSGP Flow Control configuration\n"
#define FC_BMAX_STR(who) "Force a fixed value for the " who " bucket size\n"
#define FC_LR_STR(who) "Force a fixed value for the " who " leak rate\n"
DEFUN_ATTR(cfg_pcu_fc_bvc_bucket_size,
cfg_pcu_fc_bvc_bucket_size_cmd,
"flow-control force-bvc-bucket-size <1-6553500>",
FC_STR FC_BMAX_STR("BVC") "Bucket size in octets\n",
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_bvc_bucket_size = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_fc_bvc_bucket_size,
cfg_pcu_no_fc_bvc_bucket_size_cmd,
"no flow-control force-bvc-bucket-size",
NO_STR FC_STR FC_BMAX_STR("BVC"),
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_bvc_bucket_size = 0;
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_fc_bvc_leak_rate,
cfg_pcu_fc_bvc_leak_rate_cmd,
"flow-control force-bvc-leak-rate <1-6553500>",
FC_STR FC_LR_STR("BVC") "Leak rate in bit/s\n",
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_bvc_leak_rate = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_fc_bvc_leak_rate,
cfg_pcu_no_fc_bvc_leak_rate_cmd,
"no flow-control force-bvc-leak-rate",
NO_STR FC_STR FC_LR_STR("BVC"),
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_bvc_leak_rate = 0;
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_fc_ms_bucket_size,
cfg_pcu_fc_ms_bucket_size_cmd,
"flow-control force-ms-bucket-size <1-6553500>",
FC_STR FC_BMAX_STR("default MS") "Bucket size in octets\n",
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_ms_bucket_size = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_fc_ms_bucket_size,
cfg_pcu_no_fc_ms_bucket_size_cmd,
"no flow-control force-ms-bucket-size",
NO_STR FC_STR FC_BMAX_STR("default MS"),
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_ms_bucket_size = 0;
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_fc_ms_leak_rate,
cfg_pcu_fc_ms_leak_rate_cmd,
"flow-control force-ms-leak-rate <1-6553500>",
FC_STR FC_LR_STR("default MS") "Leak rate in bit/s\n",
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_ms_leak_rate = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_fc_ms_leak_rate,
cfg_pcu_no_fc_ms_leak_rate_cmd,
"no flow-control force-ms-leak-rate",
NO_STR FC_STR FC_LR_STR("default MS"),
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_ms_leak_rate = 0;
return CMD_SUCCESS;
}
#define FC_BTIME_STR "Set target downlink maximum queueing time (only affects the advertised bucket size)\n"
DEFUN_ATTR(cfg_pcu_fc_bucket_time,
cfg_pcu_fc_bucket_time_cmd,
"flow-control bucket-time <1-65534>",
FC_STR FC_BTIME_STR "Time in centi-seconds\n",
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_bucket_time = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_fc_bucket_time,
cfg_pcu_no_fc_bucket_time_cmd,
"no flow-control bucket-time",
NO_STR FC_STR FC_BTIME_STR,
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.fc_bucket_time = 0;
return CMD_SUCCESS;
}
#define CS_STR "Coding Scheme configuration\n"
DEFUN_ATTR(cfg_pcu_cs,
cfg_pcu_cs_cmd,
"cs <1-4> [<1-4>]",
CS_STR
"Initial CS value to be used (overrides BTS config)\n"
"Use a different initial CS value for the uplink",
CMD_ATTR_IMMEDIATE)
{
uint8_t cs_dl, cs_ul;
cs_dl = atoi(argv[0]);
if (argc > 1)
cs_ul = atoi(argv[1]);
else
cs_ul = cs_dl;
the_pcu->vty.force_initial_cs = true;
gprs_pcu_set_initial_cs(the_pcu, cs_dl, cs_ul);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_cs,
cfg_pcu_no_cs_cmd,
"no cs",
NO_STR CS_STR,
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.force_initial_cs = false;
gprs_pcu_set_initial_cs(the_pcu, 0, 0);
return CMD_SUCCESS;
}
#define CS_MAX_STR "Set maximum values for adaptive CS selection (overrides BTS config)\n"
DEFUN_ATTR(cfg_pcu_cs_max,
cfg_pcu_cs_max_cmd,
"cs max <1-4> [<1-4>]",
CS_STR
CS_MAX_STR
"Maximum CS value to be used\n"
"Use a different maximum CS value for the uplink",
CMD_ATTR_IMMEDIATE)
{
uint8_t cs_dl = atoi(argv[0]);
uint8_t cs_ul;
if (argc > 1)
cs_ul = atoi(argv[1]);
else
cs_ul = cs_dl;
gprs_pcu_set_max_cs(the_pcu, cs_dl, cs_ul);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_cs_max,
cfg_pcu_no_cs_max_cmd,
"no cs max",
NO_STR CS_STR CS_MAX_STR,
CMD_ATTR_IMMEDIATE)
{
gprs_pcu_set_max_cs(the_pcu, 0, 0);
return CMD_SUCCESS;
}
#define MCS_STR "Modulation and Coding Scheme configuration (EGPRS)\n"
DEFUN_ATTR(cfg_pcu_mcs,
cfg_pcu_mcs_cmd,
"mcs <1-9> [<1-9>]",
MCS_STR
"Initial MCS value to be used (default 1)\n"
"Use a different initial MCS value for the uplink",
CMD_ATTR_IMMEDIATE)
{
uint8_t mcs_dl, mcs_ul;
mcs_dl = atoi(argv[0]);
if (argc > 1)
mcs_ul = atoi(argv[1]);
else
mcs_ul = mcs_dl;
the_pcu->vty.force_initial_mcs = true;
gprs_pcu_set_initial_mcs(the_pcu, mcs_dl, mcs_ul);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_no_mcs,
cfg_pcu_no_mcs_cmd,
"no mcs",
NO_STR MCS_STR,
CMD_ATTR_IMMEDIATE)
{
the_pcu->vty.force_initial_mcs = false;
gprs_pcu_set_initial_mcs(the_pcu, 0, 0);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_pcu_mcs_max,
cfg_pcu_mcs_max_cmd,
"mcs max <1-9> [<1-9>]",
MCS_STR
CS_MAX_STR
"Maximum MCS value to be used\n"
"Use a different maximum MCS value for the uplink",
CMD_ATTR_IMMEDIATE)
{
uint8_t mcs_dl = atoi(argv[0]);
uint8_t mcs_ul;