struct msgb *rua_new_dt(int is_ps, uint32_t context_id, struct msgb *inmsg) { RUA_DirectTransfer_t out; RUA_DirectTransferIEs_t ies; struct msgb *msg; uint32_t ctxidbuf; int rc; memset(&ies, 0, sizeof(ies)); if (is_ps) ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain; else ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain; asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id); OCTET_STRING_fromBuf(&ies.ranaP_Message, inmsg->data, msgb_length(inmsg)); msgb_free(inmsg); memset(&out, 0, sizeof(out)); rc = rua_encode_directtransferies(&out, &ies); if (rc < 0) return NULL; msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer, RUA_Criticality_reject, &asn_DEF_RUA_DirectTransfer, &out); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out); DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg)); msgb_sctp_ppid(msg) = IUH_PPI_RUA; return msg; }
struct msgb *rua_new_udt(struct msgb *inmsg) { RUA_ConnectionlessTransfer_t out; RUA_ConnectionlessTransferIEs_t ies; struct msgb *msg; int rc; memset(&ies, 0, sizeof(ies)); OCTET_STRING_fromBuf(&ies.ranaP_Message, inmsg->data, msgb_length(inmsg)); msgb_free(inmsg); memset(&out, 0, sizeof(out)); rc = rua_encode_connectionlesstransferies(&out, &ies); if (rc < 0) return NULL; msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer, RUA_Criticality_reject, &asn_DEF_RUA_ConnectionlessTransfer, &out); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out); DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg)); msgb_sctp_ppid(msg) = IUH_PPI_RUA; return msg; }
int main(int argc, char **argv) { struct ss_request req; const int size = sizeof(ussd_request); int i; struct msgb *msg; osmo_init_logging(&info); memset(&req, 0, sizeof(req)); gsm0480_decode_ss_request((struct gsm48_hdr *) ussd_request, size, &req); printf("Tested if it still works. Text was: %s\n", req.ussd_text); memset(&req, 0, sizeof(req)); gsm0480_decode_ss_request((struct gsm48_hdr *) interrogate_ss, size, &req); OSMO_ASSERT(strlen((char *) req.ussd_text) == 0); OSMO_ASSERT(req.ss_code == 33); printf("interrogateSS CFU text..'%s' code %d\n", req.ussd_text, req.ss_code); printf("Testing parsing a USSD request and truncated versions\n"); for (i = size; i > sizeof(struct gsm48_hdr); --i) { int rc = parse_ussd(&ussd_request[0], i); printf("Result for %d is %d\n", rc, i); } printf("Mangling the container now\n"); for (i = size; i > sizeof(struct gsm48_hdr) + 2; --i) { int rc = parse_mangle_ussd(&ussd_request[0], i); printf("Result for %d is %d\n", rc, i); } printf("<CR> case test for 7 bit encode\n"); test_7bit_ussd("01234567", "b0986c46abd96e", ""); test_7bit_ussd("0123456", "b0986c46abd91a", ""); test_7bit_ussd("01234567\r", "b0986c46abd96e0d", ""); /* The appended \r is compliant to GSM 03.38 section 6.1.2.3.1: */ test_7bit_ussd("0123456\r", "b0986c46abd91a0d", "\r"); test_7bit_ussd("012345\r", "b0986c46ab351a", ""); printf("Checking GSM 04.80 USSD message generation.\n"); test_7bit_ussd("", "", ""); msg = gsm0480_create_unstructuredSS_Notify (0x00, ""); printf ("Created unstructuredSS_Notify (0x00): %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg))); msgb_free (msg); test_7bit_ussd("forty-two", "e6b79c9e6fd1ef6f", ""); msg = gsm0480_create_unstructuredSS_Notify (0x42, "forty-two"); printf ("Created unstructuredSS_Notify (0x42): %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg))); msgb_free (msg); return 0; }
int l1ctl_sock_write_msg(struct l1ctl_sock_client *lsc, struct msgb *msg) { int rc; rc = write(lsc->ofd.fd, msgb_data(msg), msgb_length(msg)); msgb_free(msg); return rc; }
/* * I get called from the LAPDm code when something was sent my way... */ static int bts_to_ms_tx_cb(struct msgb *in_msg, struct lapdm_entity *le, void *_ctx) { struct lapdm_polling_state *state = _ctx; printf("%s: MS->BTS(us) message %d\n", __func__, msgb_length(in_msg)); if (state->bts_read == 0) { printf("BTS: Verifying CM request.\n"); ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(cm_padded)); ASSERT(memcmp(in_msg->l3h, cm_padded, ARRAY_SIZE(cm_padded)) == 0); } else if (state->bts_read == 1) { printf("BTS: Verifying dummy message.\n"); ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(dummy1)); ASSERT(memcmp(in_msg->l3h, dummy1, ARRAY_SIZE(dummy1)) == 0); } else { printf("BTS: Do not know to verify: %d\n", state->bts_read); } state->bts_read += 1; msgb_free(in_msg); return 0; }
static int ms_to_bts_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *_ctx) { struct lapdm_polling_state *state = _ctx; printf("%s: BTS->MS(us) message %d\n", __func__, msgb_length(msg)); if (state->ms_read == 0) { struct abis_rsl_rll_hdr hdr; printf("MS: Verifying incoming primitive.\n"); ASSERT(msg->len == sizeof(struct abis_rsl_rll_hdr) + 3); /* verify the header */ memset(&hdr, 0, sizeof(hdr)); rsl_init_rll_hdr(&hdr, RSL_MT_EST_CONF); hdr.c.msg_discr |= ABIS_RSL_MDISC_TRANSP; ASSERT(memcmp(msg->data, &hdr, sizeof(hdr)) == 0); /* Verify the added RSL_IE_L3_INFO but we have a bug here */ ASSERT(msg->data[6] == RSL_IE_L3_INFO); #warning "RSL_IE_L3_INFO 16 bit length is wrong" /* ASSERT(msg->data[7] == 0x0 && msg->data[8] == 0x9c); */ /* this should be 0x0 and 0x0... but we have a bug */ } else if (state->ms_read == 1) { printf("MS: Verifying incoming MM message: %d\n", msgb_l3len(msg)); ASSERT(msgb_l3len(msg) == 3); ASSERT(memcmp(msg->l3h, &mm[12], msgb_l3len(msg)) == 0); } else { printf("MS: Do not know to verify: %d\n", state->ms_read); } state->ms_read += 1; msgb_free(msg); return 0; }
static void esme_write_cb(struct osmo_fd *ofd, struct msgb *msg) { struct esme *esme = ofd->data; int rc; rc = write(ofd->fd, msgb_data(msg), msgb_length(msg)); if (rc == 0) { osmo_fd_unregister(&esme->wqueue.bfd); close(esme->wqueue.bfd.fd); esme->wqueue.bfd.fd = -1; exit(99); } else if (rc < msgb_length(msg)) { LOGP(DSMPP, LOGL_ERROR, "[%s] Short write\n", esme->system_id); return; } }
int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len) { RUA_ConnectionlessTransfer_t out; RUA_ConnectionlessTransferIEs_t ies; struct msgb *msg; int rc; memset(&ies, 0, sizeof(ies)); ies.ranaP_Message.buf = (uint8_t *) data; ies.ranaP_Message.size = len; /* FIXME: msgb_free(msg)? ownership not yet clear */ memset(&out, 0, sizeof(out)); rc = rua_encode_connectionlesstransferies(&out, &ies); if (rc < 0) return rc; msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer, RUA_Criticality_reject, &asn_DEF_RUA_ConnectionlessTransfer, &out); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out); DEBUGP(DRUA, "transmitting RUA payload of %u bytes\n", msgb_length(msg)); return hnbgw_rua_tx(hnb, msg); }
/* override */ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) { msgb_free(last_ns_tx_msg); last_ns_tx_msg = msg; return msgb_length(msg); }
static int pcu_sock_write(struct osmo_fd *bfd) { struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data; int rc; while (!llist_empty(&state->upqueue)) { struct msgb *msg, *msg2; struct gsm_pcu_if *pcu_prim; /* peek at the beginning of the queue */ msg = llist_entry(state->upqueue.next, struct msgb, list); pcu_prim = (struct gsm_pcu_if *)msg->data; bfd->when &= ~BSC_FD_WRITE; /* bug hunter 8-): maybe someone forgot msgb_put(...) ? */ if (!msgb_length(msg)) { LOGP(DL1IF, LOGL_ERROR, "message type (%d) with ZERO " "bytes!\n", pcu_prim->msg_type); goto dontsend; } /* try to send it over the socket */ rc = write(bfd->fd, msgb_data(msg), msgb_length(msg)); if (rc == 0) goto close; if (rc < 0) { if (errno == EAGAIN) { bfd->when |= BSC_FD_WRITE; break; } goto close; } dontsend: /* _after_ we send it, we can deueue */ msg2 = msgb_dequeue(&state->upqueue); assert(msg == msg2); msgb_free(msg); } return 0; close: pcu_sock_close(state, 1); return -1; }
static int smpp_handle_deliver(struct esme *esme, struct msgb *msg) { struct deliver_sm_t deliver; struct deliver_sm_resp_t deliver_r; struct submit_sm_t submit; int rc; memset(&deliver, 0, sizeof(deliver)); SMPP34_UNPACK(rc, DELIVER_SM, &deliver, msgb_data(msg), msgb_length(msg)); if (rc < 0) return rc; INIT_RESP(DELIVER_SM_RESP, &deliver_r, &deliver); PACK_AND_SEND(esme, &deliver_r); memset(&submit, 0, sizeof(submit)); submit.command_id = SUBMIT_SM; submit.command_status = ESME_ROK; submit.sequence_number = esme_inc_seq_nr(esme); submit.dest_addr_ton = deliver.source_addr_ton; submit.dest_addr_npi = deliver.source_addr_npi; memcpy(submit.destination_addr, deliver.source_addr, OSMO_MIN(sizeof(submit.destination_addr), sizeof(deliver.source_addr))); submit.source_addr_ton = deliver.dest_addr_ton; submit.source_addr_npi = deliver.dest_addr_npi; memcpy(submit.source_addr, deliver.destination_addr, OSMO_MIN(sizeof(submit.source_addr), sizeof(deliver.destination_addr))); submit.esm_class = deliver.esm_class; submit.protocol_id = deliver.protocol_id; submit.priority_flag = deliver.priority_flag; memcpy(submit.schedule_delivery_time, deliver.schedule_delivery_time, OSMO_MIN(sizeof(submit.schedule_delivery_time), sizeof(deliver.schedule_delivery_time))); memcpy(submit.validity_period, deliver.validity_period, OSMO_MIN(sizeof(submit.validity_period), sizeof(deliver.validity_period))); submit.registered_delivery = deliver.registered_delivery; submit.replace_if_present_flag = deliver.replace_if_present_flag; submit.data_coding = deliver.data_coding; submit.sm_default_msg_id = deliver.sm_default_msg_id; submit.sm_length = deliver.sm_length; memcpy(submit.short_message, deliver.short_message, OSMO_MIN(sizeof(submit.short_message), sizeof(deliver.short_message))); /* FIXME: TLV? */ return PACK_AND_SEND(esme, &submit); }
struct msgb *rua_new_disc(int is_ps, uint32_t context_id, struct msgb *inmsg) { RUA_Disconnect_t out; RUA_DisconnectIEs_t ies; struct msgb *msg; uint32_t ctxidbuf; int rc; memset(&ies, 0, sizeof(ies)); if (is_ps) ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain; else ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain; asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id); /* FIXME: make cause configurable */ ies.cause.present = RUA_Cause_PR_radioNetwork; ies.cause.choice.radioNetwork = RUA_CauseRadioNetwork_normal; if (inmsg && inmsg->data&& msgb_length(inmsg)) { ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT; OCTET_STRING_fromBuf(&ies.ranaP_Message, inmsg->data, msgb_length(inmsg)); } msgb_free(inmsg); memset(&out, 0, sizeof(out)); rc = rua_encode_disconnecties(&out, &ies); if (rc < 0) return NULL; msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect, RUA_Criticality_reject, &asn_DEF_RUA_Disconnect, &out); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out); DEBUGP(DMAIN, "transmitting RUA payload of %u bytes\n", msgb_length(msg)); msgb_sctp_ppid(msg) = IUH_PPI_RUA; return msg; }
static struct xua_msg *m3ua_gen_error_msg(uint32_t err_code, struct msgb *msg) { struct xua_msg *xua = m3ua_gen_error(err_code); unsigned int len_max_40 = msgb_length(msg); if (len_max_40 > 40) len_max_40 = 40; xua_msg_add_data(xua, M3UA_IEI_DIAG_INFO, len_max_40, msgb_data(msg)); return xua; }
static int ranap_tx_reset_ack(struct hnb_context *hnb, RANAP_CN_DomainIndicator_t domain) { struct msgb *msg; int rc; msg = ranap_new_msg_reset_ack(domain, NULL); if (!msg) return -1; rc = rua_tx_udt(hnb, msg->data, msgb_length(msg)); msgb_free(msg); return rc; }
/* push a common header (1 dword) to the start of a msgb */ void octpkt_push_common_hdr(struct msgb *msg, uint8_t format, uint8_t trace, uint32_t ptype) { uint32_t ch; uint32_t *chptr; uint32_t tot_len = msgb_length(msg) + sizeof(ch); ch = ((format & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_FORMAT_BIT_MASK) << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_FORMAT_BIT_OFFSET) | ((trace & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_TRACE_BIT_MASK) << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_TRACE_BIT_OFFSET) | ((ptype & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_CONTROL_PROTOCOL_TYPE_BIT_MASK) << cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_CONTROL_PROTOCOL_TYPE_BIT_OFFSET) | (tot_len & cOCTPKT_HDR_FORMAT_PROTO_TYPE_LEN_MASK_LENGTH_BIT_MASK); chptr = (uint32_t *) msgb_push(msg, sizeof(ch)); *chptr = htonl(ch); }
int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg) { RUA_RUA_PDU_t _pdu, *pdu = &_pdu; asn_dec_rval_t dec_ret; int rc; /* decode and handle to _hnbgw_hnbap_rx() */ memset(pdu, 0, sizeof(*pdu)); dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu, msg->data, msgb_length(msg), 0, 0); if (dec_ret.code != RC_OK) { LOGP(DRUA, LOGL_ERROR, "Error in ASN.1 decode\n"); return rc; } rc = _hnbgw_rua_rx(msg, pdu); return rc; }
int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id, const RUA_Cause_t *cause, const uint8_t *data, unsigned int len) { RUA_Disconnect_t out; RUA_DisconnectIEs_t ies; struct msgb *msg; uint32_t ctxidbuf; int rc; memset(&ies, 0, sizeof(ies)); if (is_ps) ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain; else ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain; asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id); memcpy(&ies.cause, cause, sizeof(ies.cause)); if (data && len) { ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT; ies.ranaP_Message.buf = (uint8_t *) data; ies.ranaP_Message.size = len; } /* FIXME: msgb_free(msg)? ownership not yet clear */ memset(&out, 0, sizeof(out)); rc = rua_encode_disconnecties(&out, &ies); if (rc < 0) return rc; msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect, RUA_Criticality_reject, &asn_DEF_RUA_Disconnect, &out); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out); DEBUGP(DRUA, "transmitting RUA (cn=%s) payload of %u bytes\n", is_ps ? "ps" : "cs", msgb_length(msg)); return hnbgw_rua_tx(hnb, msg); }
/*! \brief process M3UA message received from socket * \param[in] asp Application Server Process receiving \ref msg * \param[in] msg received message buffer * \returns 0 on success; negative on error */ int m3ua_rx_msg(struct osmo_ss7_asp *asp, struct msgb *msg) { struct xua_msg *xua = NULL, *err = NULL; int rc = 0; OSMO_ASSERT(asp->cfg.proto == OSMO_SS7_ASP_PROT_M3UA); /* caller owns msg memory, we shall neither free it here nor * keep references beyond the executin of this function and its * callees */ xua = xua_from_msg(M3UA_VERSION, msgb_length(msg), msgb_data(msg)); if (!xua) { struct xua_common_hdr *hdr = (struct xua_common_hdr *) msg->data; LOGPASP(asp, DLM3UA, LOGL_ERROR, "Unable to parse incoming " "M3UA message\n"); if (hdr->version != M3UA_VERSION) err = m3ua_gen_error_msg(M3UA_ERR_INVALID_VERSION, msg); else err = m3ua_gen_error_msg(M3UA_ERR_PARAM_FIELD_ERR, msg); goto out; } LOGPASP(asp, DLM3UA, LOGL_DEBUG, "Received M3UA Message (%s)\n", xua_hdr_dump(xua, &xua_dialect_m3ua)); if (!xua_dialect_check_all_mand_ies(&xua_dialect_m3ua, xua)) { err = m3ua_gen_error_msg(M3UA_ERR_MISSING_PARAM, msg); goto out; } /* TODO: check if any AS configured in ASP */ /* TODO: check for valid routing context */ switch (xua->hdr.msg_class) { case M3UA_MSGC_XFER: /* The DATA message MUST NOT be sent on stream 0. */ if (msgb_sctp_stream(msg) == 0) { rc = M3UA_ERR_INVAL_STREAM_ID; break; } rc = m3ua_rx_xfer(asp, xua); break; case M3UA_MSGC_ASPSM: case M3UA_MSGC_ASPTM: rc = m3ua_rx_asp(asp, xua); break; case M3UA_MSGC_MGMT: rc = m3ua_rx_mgmt(asp, xua); break; case M3UA_MSGC_RKM: rc = m3ua_rx_rkm(asp, xua); break; case M3UA_MSGC_SNM: /* FIXME */ LOGPASP(asp, DLM3UA, LOGL_NOTICE, "Received unsupported M3UA " "Message Class %u\n", xua->hdr.msg_class); err = m3ua_gen_error_msg(M3UA_ERR_UNSUPP_MSG_CLASS, msg); break; default: LOGPASP(asp, DLM3UA, LOGL_NOTICE, "Received unknown M3UA " "Message Class %u\n", xua->hdr.msg_class); err = m3ua_gen_error_msg(M3UA_ERR_UNSUPP_MSG_CLASS, msg); break; } if (rc > 0) err = m3ua_gen_error_msg(rc, msg); out: if (err) m3ua_tx_xua_asp(asp, err); xua_msg_free(xua); return rc; }
static int feed_write_cb(struct osmo_fd *ofd, struct msgb *msg) { return write(ofd->fd, msgb_data(msg), msgb_length(msg)); }
static int osmo_stats_reporter_statsd_send(struct osmo_stats_reporter *srep, const char *name1, unsigned int index1, const char *name2, int64_t value, const char *unit) { char *buf; int buf_size; int nchars, rc = 0; char *fmt = NULL; char *prefix = srep->name_prefix; int old_len = msgb_length(srep->buffer); if (prefix) { if (name1) { if (index1 != 0) fmt = "%1$s.%2$s.%6$u.%3$s:%4$d|%5$s"; else fmt = "%1$s.%2$s.%3$s:%4$d|%5$s"; } else { fmt = "%1$s.%2$0.0s%3$s:%4$d|%5$s"; } } else { prefix = ""; if (name1) { if (index1 != 0) fmt = "%1$s%2$s.%6$u.%3$s:%4$d|%5$s"; else fmt = "%1$s%2$s.%3$s:%4$d|%5$s"; } else { fmt = "%1$s%2$0.0s%3$s:%4$d|%5$s"; } } if (srep->agg_enabled) { if (msgb_length(srep->buffer) > 0 && msgb_tailroom(srep->buffer) > 0) { msgb_put_u8(srep->buffer, '\n'); } } buf = (char *)msgb_put(srep->buffer, 0); buf_size = msgb_tailroom(srep->buffer); nchars = snprintf(buf, buf_size, fmt, prefix, name1, name2, value, unit, index1); if (nchars >= buf_size) { /* Truncated */ /* Restore original buffer (without trailing LF) */ msgb_trim(srep->buffer, old_len); /* Send it */ rc = osmo_stats_reporter_send_buffer(srep); /* Try again */ buf = (char *)msgb_put(srep->buffer, 0); buf_size = msgb_tailroom(srep->buffer); nchars = snprintf(buf, buf_size, fmt, prefix, name1, name2, value, unit, index1); if (nchars >= buf_size) return -EMSGSIZE; } if (nchars > 0) msgb_trim(srep->buffer, msgb_length(srep->buffer) + nchars); if (!srep->agg_enabled) rc = osmo_stats_reporter_send_buffer(srep); return rc; }
static void test_bssgp_flow_control_bvc(void) { struct bssgp_bvc_ctx bctx = { .nsei = 0x1234, .bvci = 0x5678, }; const uint8_t tag = 42; const uint32_t bmax = 0x1022 * 100; const uint32_t rate = 0xc040 / 8 * 100; const uint32_t bmax_ms = bmax / 2; const uint32_t rate_ms = rate / 2; uint8_t ratio = 0x78; uint32_t qdelay = 0x1144 * 10; int rc; static uint8_t expected_simple_msg[] = { 0x26, 0x1e, 0x81, 0x2a, /* tag */ 0x05, 0x82, 0x10, 0x22, /* Bmax */ 0x03, 0x82, 0xc0, 0x40, /* R */ 0x01, 0x82, 0x08, 0x11, /* Bmax_MS */ 0x1c, 0x82, 0x60, 0x20, /* R_MS */ }; static uint8_t expected_ext_msg[] = { 0x26, 0x1e, 0x81, 0x2a, /* tag */ 0x05, 0x82, 0x10, 0x22, /* Bmax */ 0x03, 0x82, 0xc0, 0x40, /* R */ 0x01, 0x82, 0x08, 0x11, /* Bmax_MS */ 0x1c, 0x82, 0x60, 0x20, /* R_MS */ 0x3c, 0x81, 0x78, /* ratio */ 0x06, 0x82, 0x11, 0x44, /* Qdelay */ }; printf("----- %s START\n", __func__); rc = bssgp_tx_fc_bvc(&bctx, tag, bmax, rate, bmax_ms, rate_ms, NULL, NULL); OSMO_ASSERT(rc >= 0); OSMO_ASSERT(last_ns_tx_msg != NULL); printf("Got message: %s\n", msgb_hexdump(last_ns_tx_msg)); OSMO_ASSERT(msgb_length(last_ns_tx_msg) == sizeof(expected_simple_msg)); OSMO_ASSERT(0 == memcmp(msgb_data(last_ns_tx_msg), expected_simple_msg, sizeof(expected_simple_msg))); rc = bssgp_tx_fc_bvc(&bctx, tag, bmax, rate, bmax_ms, rate_ms, &ratio, &qdelay); OSMO_ASSERT(rc >= 0); OSMO_ASSERT(last_ns_tx_msg != NULL); printf("Got message: %s\n", msgb_hexdump(last_ns_tx_msg)); OSMO_ASSERT(msgb_length(last_ns_tx_msg) == sizeof(expected_ext_msg)); OSMO_ASSERT(0 == memcmp(msgb_data(last_ns_tx_msg), expected_ext_msg, sizeof(expected_ext_msg))); msgb_free(last_ns_tx_msg); last_ns_tx_msg = NULL; printf("----- %s END\n", __func__); } static struct log_info info = {}; int main(int argc, char **argv) { struct sockaddr_in bss_peer= {0}; osmo_init_logging(&info); log_set_use_color(osmo_stderr_target, 0); log_set_print_filename(osmo_stderr_target, 0); bssgp_nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); bss_peer.sin_family = AF_INET; bss_peer.sin_port = htons(32000); bss_peer.sin_addr.s_addr = htonl(0x7f0000ff); gprs_ns_nsip_connect(bssgp_nsi, &bss_peer, BSS_NSEI, BSS_NSEI+1); printf("===== BSSGP test START\n"); test_bssgp_suspend_resume(); test_bssgp_status(); test_bssgp_bad_reset(); test_bssgp_flow_control_bvc(); printf("===== BSSGP test END\n\n"); exit(EXIT_SUCCESS); }