diff options
-rw-r--r-- | include/osmocom/gprs/gprs_bssgp.h | 18 | ||||
-rw-r--r-- | src/gb/gprs_bssgp.c | 45 | ||||
-rw-r--r-- | src/gb/libosmogb.map | 1 |
3 files changed, 49 insertions, 15 deletions
diff --git a/include/osmocom/gprs/gprs_bssgp.h b/include/osmocom/gprs/gprs_bssgp.h index 0646ff79..3a1b7613 100644 --- a/include/osmocom/gprs/gprs_bssgp.h +++ b/include/osmocom/gprs/gprs_bssgp.h @@ -58,15 +58,15 @@ struct osmo_bssgp_prim { /*! \brief BSSGP flow control (SGSN side) According to Section 8.2 */ struct bssgp_flow_control { - uint32_t bucket_size_max; /*!< maximum size of the bucket */ - uint32_t bucket_leak_rate; /*!< leak rate of the bucket */ + uint32_t bucket_size_max; /*!< maximum size of the bucket (octets) */ + uint32_t bucket_leak_rate; /*!< leak rate of the bucket (octets/sec) */ uint32_t bucket_counter; /*!< number of tokens in the bucket */ struct timeval time_last_pdu; /*!< timestamp of last PDU sent */ /* the built-in queue */ - uint32_t max_queue_depth; /*!< how many packets to queue */ - uint32_t queue_depth; /*!< current length of queue */ + uint32_t max_queue_depth; /*!< how many packets to queue (mgs) */ + uint32_t queue_depth; /*!< current length of queue (msgs) */ struct llist_head queue; /*!< linked list of msgb's */ struct osmo_timer_list timer; /*!< timer-based dequeueing */ @@ -94,7 +94,9 @@ struct bssgp_bvc_ctx { struct rate_ctr_group *ctrg; struct bssgp_flow_control fc; + /*! default maximum size of per-MS bucket in octets */ uint32_t bmax_default_ms; + /*! default bucket leak rate of per-MS bucket in octests/s */ uint32_t r_default_ms; /* we might want to add this as a shortcut later, avoiding the NSVC @@ -183,6 +185,12 @@ struct bssgp_paging_info { int bssgp_tx_paging(uint16_t nsei, uint16_t ns_bvci, struct bssgp_paging_info *pinfo); +void bssgp_fc_init(struct bssgp_flow_control *fc, + uint32_t bucket_size_max, uint32_t bucket_leak_rate, + uint32_t max_queue_depth, + int (*out_cb)(struct bssgp_flow_control *fc, struct msgb *msg, + uint32_t llc_pdu_len, void *priv)); + /* input function of the flow control implementation, called first * for the MM flow control, and then as the MM flow control output * callback in order to perform BVC flow control */ @@ -192,7 +200,7 @@ int bssgp_fc_in(struct bssgp_flow_control *fc, struct msgb *msg, /* Initialize the Flow Control parameters for a new MS according to * default values for the BVC specified by BVCI and NSEI */ int bssgp_fc_ms_init(struct bssgp_flow_control *fc_ms, uint16_t bvci, - uint16_t nsei); + uint16_t nsei, uint32_t max_queue_depth); /* gprs_bssgp_vty.c */ int bssgp_vty_init(void); diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c index 93aa5aaa..70e2a1c5 100644 --- a/src/gb/gprs_bssgp.c +++ b/src/gb/gprs_bssgp.c @@ -686,6 +686,13 @@ int bssgp_fc_in(struct bssgp_flow_control *fc, struct msgb *msg, { struct timeval time_now; + if (llc_pdu_len > fc->bucket_size_max) { + LOGP(DBSSGP, LOGL_NOTICE, "Single PDU (size=%u) is larger " + "than maximum bucket size (%u)!\n", llc_pdu_len, + fc->bucket_size_max); + return -EIO; + } + if (bssgp_fc_needs_queueing(fc, llc_pdu_len)) { return fc_enqueue(fc, msg, llc_pdu_len, priv); } else { @@ -696,18 +703,36 @@ int bssgp_fc_in(struct bssgp_flow_control *fc, struct msgb *msg, } } + +/* Initialize the Flow Control structure */ +void bssgp_fc_init(struct bssgp_flow_control *fc, + uint32_t bucket_size_max, uint32_t bucket_leak_rate, + uint32_t max_queue_depth, + int (*out_cb)(struct bssgp_flow_control *fc, struct msgb *msg, + uint32_t llc_pdu_len, void *priv)) +{ + fc->out_cb = out_cb; + fc->bucket_size_max = bucket_size_max; + fc->bucket_leak_rate = bucket_leak_rate; + fc->max_queue_depth = max_queue_depth; + INIT_LLIST_HEAD(&fc->queue); + gettimeofday(&fc->time_last_pdu, NULL); +} + /* Initialize the Flow Control parameters for a new MS according to * default values for the BVC specified by BVCI and NSEI */ int bssgp_fc_ms_init(struct bssgp_flow_control *fc_ms, uint16_t bvci, - uint16_t nsei) + uint16_t nsei, uint32_t max_queue_depth) { struct bssgp_bvc_ctx *ctx; ctx = btsctx_by_bvci_nsei(bvci, nsei); if (!ctx) return -ENODEV; - fc_ms->bucket_size_max = ctx->bmax_default_ms; - fc_ms->bucket_leak_rate = ctx->r_default_ms; + + /* output call-back of per-MS FC is per-CTX FC */ + bssgp_fc_init(fc_ms, ctx->bmax_default_ms, ctx->r_default_ms, + max_queue_depth, bssgp_fc_in); return 0; } @@ -729,18 +754,18 @@ static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp, return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } - /* 11.3.5 */ + /* 11.3.5 Bucket Size in 100 octets unit */ bctx->fc.bucket_size_max = 100 * ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BVC_BUCKET_SIZE)); - /* 11.3.4 */ + /* 11.3.4 Bucket Leak Rate in 100 bits/sec unit */ bctx->fc.bucket_leak_rate = 100 * - ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BUCKET_LEAK_RATE)); - /* 11.3.2 */ - bctx->bmax_default_ms = 100 * + ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BUCKET_LEAK_RATE)) / 8; + /* 11.3.2 in octets */ + bctx->bmax_default_ms = ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BMAX_DEFAULT_MS)); - /* 11.3.32 */ + /* 11.3.32 Bucket Leak rate in 100bits/sec unit */ bctx->r_default_ms = 100 * - ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_R_DEFAULT_MS)); + ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_R_DEFAULT_MS)) / 8; /* Send FLOW_CONTROL_BVC_ACK */ return bssgp_tx_fc_bvc_ack(msgb_nsei(msg), *TLVP_VAL(tp, BSSGP_IE_TAG), diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index 8e9f3727..d0f76f86 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -3,6 +3,7 @@ global: bssgp_cause_str; bssgp_create_cell_id; bssgp_fc_in; +bssgp_fc_init; bssgp_fc_ms_init; bssgp_msgb_alloc; bssgp_msgb_tlli_put; |