mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 04:53:24 +00:00
wip
Change-Id: I4fdcebf3b006a72c5318a9105a2be2cc7057dca1
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
/* Debug Areas of the code */
|
||||
enum {
|
||||
DRTP,
|
||||
DIUUP,
|
||||
Debug_LastEntry,
|
||||
};
|
||||
|
||||
|
||||
@@ -10,22 +10,23 @@
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
struct osmo_iuup_cn;
|
||||
struct msgb;
|
||||
|
||||
typedef int (*osmo_iuup_data_cb_t)(struct msgb *msg, void *node_priv, void *pdu_priv);
|
||||
typedef int (*osmo_iuup_data_cb_t)(struct msgb *msg, void *node_priv);
|
||||
|
||||
struct osmo_iuup_cn_cfg {
|
||||
void *node_priv;
|
||||
|
||||
/* When an IuUP PDU containing voice payload has been received, this callback is invoked to pass
|
||||
* the voice payload towards the Core Network, msgb_l3() pointing at the payload. */
|
||||
/* When the IuUP peer sent a voice packet, the clean RTP without the IuUP header is fed to this
|
||||
* callback. */
|
||||
osmo_iuup_data_cb_t rx_payload;
|
||||
|
||||
/* IuUP handler sends a PDU to the IuUP peer (e.g. the RNC) */
|
||||
/* IuUP handler requests that a PDU shall be sent to the IuUP peer (e.g. the RNC).
|
||||
* It is guaranteed that the msgb->dst pointer is preserved or copied from the msgb that
|
||||
* originated the request. */
|
||||
osmo_iuup_data_cb_t tx_msg;
|
||||
};
|
||||
|
||||
@@ -35,12 +36,6 @@ struct osmo_iuup_cn *osmo_iuup_cn_init(void *ctx, struct osmo_iuup_cn_cfg *cfg,
|
||||
const char *name_fmt, ...);
|
||||
void osmo_iuup_cn_free(struct osmo_iuup_cn *cn);
|
||||
|
||||
/* Encapsulate voice stream payload in IuUP and, if appropriate, call the tx_msg() to transmit the
|
||||
* resulting message to the IuUP peer. msgb_l3() should point at the payload data.
|
||||
* pdu_priv is transparently passed on to tx_msg().
|
||||
* Returns 0 on success, negative on error. */
|
||||
int osmo_iuup_cn_tx_payload(struct osmo_iuup_cn *cn, struct msgb *payload, void *pdu_priv);
|
||||
int osmo_iuup_cn_tx_payload(struct osmo_iuup_cn *cn, struct msgb *payload);
|
||||
|
||||
/* Feed a received PDU to the IuUP CN node. This function takes ownership of the msgb, it must not be
|
||||
* freed by the caller. */
|
||||
int osmo_iuup_cn_rx_pdu(struct osmo_iuup_cn *cn, struct msgb *pdu, void *pdu_priv);
|
||||
int osmo_iuup_cn_rx_pdu(struct osmo_iuup_cn *cn, struct msgb *pdu);
|
||||
|
||||
@@ -21,6 +21,9 @@ enum osmo_iuup_acknack {
|
||||
|
||||
enum osmo_iuup_procedure {
|
||||
OSMO_IUUP_PROC_INITIALIZATION = 0,
|
||||
OSMO_IUUP_PROC_RATE_CONTROL = 1,
|
||||
OSMO_IUUP_PROC_TIME_ALIGNMENT = 2,
|
||||
OSMO_IUUP_PROC_ERROR_EVENT = 3,
|
||||
};
|
||||
|
||||
enum osmo_iuup_frame_good {
|
||||
@@ -40,10 +43,6 @@ struct osmo_iuup_hdr_ctrl {
|
||||
payload_crc_hi:2;
|
||||
uint8_t payload_crc_lo;
|
||||
uint8_t payload[0];
|
||||
uint8_t spare:3,
|
||||
iptis_present:1,
|
||||
subflows:3,
|
||||
chain:1;
|
||||
#elif OSMO_IS_LITTLE_ENDIAN
|
||||
uint8_t frame_nr:2,
|
||||
ack_nack:2,
|
||||
@@ -54,12 +53,38 @@ struct osmo_iuup_hdr_ctrl {
|
||||
header_crc:6;
|
||||
uint8_t payload_crc_lo;
|
||||
uint8_t payload[0];
|
||||
#endif
|
||||
} __attribute__((packed));
|
||||
|
||||
union osmo_iuup_hdr_ctrl_payload {
|
||||
struct {
|
||||
#if OSMO_IS_BIG_ENDIAN
|
||||
uint8_t spare:3,
|
||||
iptis_present:1,
|
||||
subflows:3,
|
||||
chain:1;
|
||||
#elif OSMO_IS_LITTLE_ENDIAN
|
||||
uint8_t spare:3,
|
||||
iptis_present:1,
|
||||
subflows:3,
|
||||
chain:1;
|
||||
#endif
|
||||
} __attribute__((packed));
|
||||
} initialization;
|
||||
|
||||
struct {
|
||||
#if OSMO_IS_BIG_ENDIAN
|
||||
uint8_t error_distance:2,
|
||||
error_cause:6;
|
||||
#elif OSMO_IS_LITTLE_ENDIAN
|
||||
uint8_t error_cause:6,
|
||||
error_distance:2;
|
||||
#endif
|
||||
} error_event;
|
||||
};
|
||||
|
||||
extern const struct value_string osmo_iuup_error_cause_names[];
|
||||
static inline const char *osmo_iuup_error_cause_name(uint8_t val)
|
||||
{ return get_value_string(osmo_iuup_error_cause_names, val); }
|
||||
|
||||
struct osmo_iuup_hdr_data {
|
||||
#if OSMO_IS_BIG_ENDIAN
|
||||
|
||||
@@ -23,18 +23,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
struct sockaddr_in;
|
||||
struct mgcp_conn;
|
||||
struct mgcp_conn_rtp;
|
||||
struct mgcp_endpoint;
|
||||
|
||||
struct osmo_rtp_msg_ctx {
|
||||
int proto;
|
||||
struct mgcp_conn_rtp *conn_src;
|
||||
struct sockaddr_in *from_addr;
|
||||
};
|
||||
|
||||
#define OSMO_RTP_MSG_CTX(MSGB) (*(struct osmo_rtp_msg_ctx**)&((MSGB)->dst))
|
||||
|
||||
#define LOG_ENDP(endp, level, fmt, args...) \
|
||||
LOGP(DRTP, level, "%x@ " fmt, ENDPOINT_NUMBER(endp), ## args)
|
||||
|
||||
/* Callback type for RTP dispatcher functions
|
||||
(e.g mgcp_dispatch_rtp_bridge_cb, see below) */
|
||||
typedef int (*mgcp_dispatch_rtp_cb) (int proto, struct sockaddr_in *addr,
|
||||
struct msgb *payload,
|
||||
struct mgcp_conn *conn);
|
||||
/* Callback type for RTP dispatcher functions (e.g mgcp_dispatch_rtp_bridge_cb, see below).
|
||||
* The fields OSMO_RTP_MSG_PROTO, OSMO_RTP_MSG_CONN_SRC, OSMO_RTP_MSG_FROM_ADDR should be set
|
||||
* appropriately on the msg. */
|
||||
typedef int (*mgcp_dispatch_rtp_cb) (struct msgb *msg);
|
||||
|
||||
/* Callback type for endpoint specific cleanup actions. This function
|
||||
* is automatically executed when a connection is freed (see mgcp_conn_free()
|
||||
|
||||
@@ -271,8 +271,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
struct msgb *msg, struct mgcp_conn_rtp *conn_src,
|
||||
struct mgcp_conn_rtp *conn_dst);
|
||||
int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
|
||||
int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr,
|
||||
struct msgb *payload, struct mgcp_conn *conn);
|
||||
int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg);
|
||||
void mgcp_cleanup_rtp_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
|
||||
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
|
||||
struct mgcp_conn_rtp *conn);
|
||||
|
||||
@@ -39,12 +39,13 @@
|
||||
#include <osmocom/mgcp/debug.h>
|
||||
|
||||
#define LOG_IUUP_CN(cn, level, fmt, args...) \
|
||||
LOGP(DRTP, level, "(%s) " fmt, (cn)->name, ## args)
|
||||
LOGP(DIUUP, level, "(%s) " fmt, (cn)->name, ## args)
|
||||
|
||||
struct osmo_iuup_cn {
|
||||
struct osmo_iuup_cn_cfg cfg;
|
||||
char *name;
|
||||
uint8_t next_frame_nr;
|
||||
int rtp_payload_type;
|
||||
};
|
||||
|
||||
struct osmo_iuup_cn *osmo_iuup_cn_init(void *ctx, struct osmo_iuup_cn_cfg *cfg,
|
||||
@@ -63,8 +64,10 @@ struct osmo_iuup_cn *osmo_iuup_cn_init(void *ctx, struct osmo_iuup_cn_cfg *cfg,
|
||||
cn->name = talloc_vasprintf(cn, name_fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LOGP(DIUUP, LOGL_INFO, "(%s) Initializing IuUP node\n", cn->name);
|
||||
|
||||
if (!osmo_identifier_valid(cn->name)) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "Attempting to set illegal id for IuUP CN instance: %s\n",
|
||||
LOGP(DIUUP, LOGL_ERROR, "Attempting to set illegal id for IuUP CN instance: %s\n",
|
||||
osmo_quote_str(cn->name, -1));
|
||||
talloc_free(cn);
|
||||
return NULL;
|
||||
@@ -79,7 +82,7 @@ void osmo_iuup_cn_free(struct osmo_iuup_cn *cn)
|
||||
}
|
||||
|
||||
static int rx_data(struct osmo_iuup_cn *cn, struct msgb *pdu,
|
||||
struct osmo_iuup_hdr_data *hdr, void *pdu_priv)
|
||||
struct osmo_iuup_hdr_data *hdr)
|
||||
{
|
||||
/* Remove the IuUP bit from the middle of the buffer by writing the RTP header forward. */
|
||||
unsigned int pre_hdr_len = ((uint8_t*)hdr) - pdu->data;
|
||||
@@ -87,42 +90,72 @@ static int rx_data(struct osmo_iuup_cn *cn, struct msgb *pdu,
|
||||
|
||||
msgb_pull(pdu, sizeof(*hdr));
|
||||
|
||||
cn->cfg.rx_payload(pdu, cn->cfg.node_priv, pdu_priv);
|
||||
LOGP(DIUUP, LOGL_DEBUG, "(%s) IuUP stripping IuUP header from RTP data\n", cn->name);
|
||||
cn->cfg.rx_payload(pdu, cn->cfg.node_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tx_init_ack(struct osmo_iuup_cn *cn, void *pdu_priv)
|
||||
static int tx_init_ack(struct osmo_iuup_cn *cn, struct msgb *src_pdu)
|
||||
{
|
||||
/* Send Initialization Ack PDU back to the sender */
|
||||
int rc;
|
||||
struct msgb *ack = msgb_alloc(4096, "IuUP Initialization Ack");
|
||||
OSMO_ASSERT(ack);
|
||||
ack->dst = src_pdu->dst;
|
||||
|
||||
/* Just copy the RTP header that was sent... TODO: tweak some RTP values?? */
|
||||
memcpy(msgb_put(ack, sizeof(struct rtp_hdr)), src_pdu->data, sizeof(struct rtp_hdr));
|
||||
|
||||
osmo_iuup_make_init_ack(ack);
|
||||
return cn->cfg.tx_msg(ack, cn->cfg.node_priv, pdu_priv);
|
||||
|
||||
LOGP(DIUUP, LOGL_DEBUG, "(%s) Sending Initialization ACK %p\n", cn->name, cn->cfg.node_priv);
|
||||
rc = cn->cfg.tx_msg(ack, cn->cfg.node_priv);
|
||||
msgb_free(ack);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rx_control(struct osmo_iuup_cn *cn, struct msgb *pdu,
|
||||
struct osmo_iuup_hdr_ctrl *hdr, void *pdu_priv)
|
||||
struct osmo_iuup_hdr_ctrl *hdr)
|
||||
{
|
||||
switch (hdr->procedure) {
|
||||
case OSMO_IUUP_PROC_INITIALIZATION:
|
||||
switch (hdr->ack_nack) {
|
||||
case OSMO_IUUP_ACKNACK_PROCEDURE:
|
||||
return tx_init_ack(cn, pdu_priv);
|
||||
LOGP(DIUUP, LOGL_INFO, "(%s) Rx IuUP Initialization, sending ACK\n", cn->name);
|
||||
cn->rtp_payload_type = ((struct rtp_hdr*)pdu->data)->payload_type;
|
||||
return tx_init_ack(cn, pdu);
|
||||
|
||||
default:
|
||||
LOGP(DIUUP, LOGL_DEBUG, "(%s) Rx IuUP Initialization, unhandled ack_nack = %d\n",
|
||||
cn->name, hdr->ack_nack);
|
||||
break;
|
||||
}
|
||||
/* fall thru */
|
||||
/* Continue to log "unexpected procedure" below. */
|
||||
break;
|
||||
|
||||
case OSMO_IUUP_PROC_ERROR_EVENT:
|
||||
{
|
||||
union osmo_iuup_hdr_ctrl_payload *p = (void*)hdr->payload;
|
||||
LOGP(DIUUP, LOGL_ERROR,
|
||||
"(%s) Rx IuUP Error Event: distance=%u, cause=%u=\"%s\"\n",
|
||||
cn->name, p->error_event.error_distance, p->error_event.error_cause,
|
||||
osmo_iuup_error_cause_name(p->error_event.error_cause));
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_IUUP_CN(cn, LOGL_ERROR,
|
||||
"Rx control PDU with unexpected procedure: 0x%x acknack=0x%x\n",
|
||||
hdr->procedure, hdr->ack_nack);
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
LOG_IUUP_CN(cn, LOGL_ERROR,
|
||||
"Rx control PDU with unexpected procedure: 0x%x acknack=0x%x\n",
|
||||
hdr->procedure, hdr->ack_nack);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int osmo_iuup_cn_rx_pdu(struct osmo_iuup_cn *cn, struct msgb *pdu, void *pdu_priv)
|
||||
/* Feed a received PDU to the IuUP CN node. This function takes ownership of the msgb, it must not be
|
||||
* freed by the caller. */
|
||||
int osmo_iuup_cn_rx_pdu(struct osmo_iuup_cn *cn, struct msgb *pdu)
|
||||
{
|
||||
struct osmo_iuup_hdr_ctrl *is_ctrl;
|
||||
struct osmo_iuup_hdr_data *is_data;
|
||||
@@ -133,20 +166,23 @@ int osmo_iuup_cn_rx_pdu(struct osmo_iuup_cn *cn, struct msgb *pdu, void *pdu_pri
|
||||
return rc;
|
||||
|
||||
if (is_ctrl)
|
||||
return rx_control(cn, pdu, is_ctrl, pdu_priv);
|
||||
return rx_control(cn, pdu, is_ctrl);
|
||||
if (is_data)
|
||||
return rx_data(cn, pdu, is_data, pdu_priv);
|
||||
return rx_data(cn, pdu, is_data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static uint8_t next_frame_nr(struct osmo_iuup_cn *cn)
|
||||
{
|
||||
uint8_t frame_nr = cn->next_frame_nr;
|
||||
cn->next_frame_nr = (cn->next_frame_nr + 1) % 0x0f;
|
||||
cn->next_frame_nr = (frame_nr + 1) & 0x0f;
|
||||
return frame_nr;
|
||||
}
|
||||
|
||||
int osmo_iuup_cn_tx_payload(struct osmo_iuup_cn *cn, struct msgb *pdu, void *pdu_priv)
|
||||
/* Send this RTP packet to the IuUP peer: add IuUP header and call the tx_msg() to transmit the resulting
|
||||
* message to the IuUP peer.
|
||||
* Returns 0 on success, negative on error. */
|
||||
int osmo_iuup_cn_tx_payload(struct osmo_iuup_cn *cn, struct msgb *pdu)
|
||||
{
|
||||
struct rtp_hdr *rtp_was, *rtp;
|
||||
struct osmo_iuup_hdr_data *iuup_hdr;
|
||||
@@ -157,6 +193,10 @@ int osmo_iuup_cn_tx_payload(struct osmo_iuup_cn *cn, struct msgb *pdu, void *pdu
|
||||
/* copy the RTP header part backwards by the size needed for the IuUP header */
|
||||
rtp = (void*)msgb_push(pdu, sizeof(*iuup_hdr));
|
||||
memmove(rtp, rtp_was, sizeof(*rtp));
|
||||
|
||||
/* Send the same payload type to the peer (erm...) */
|
||||
rtp->payload_type = cn->rtp_payload_type;
|
||||
|
||||
iuup_hdr = (void*)rtp->data;
|
||||
|
||||
*iuup_hdr = (struct osmo_iuup_hdr_data){
|
||||
@@ -166,6 +206,8 @@ int osmo_iuup_cn_tx_payload(struct osmo_iuup_cn *cn, struct msgb *pdu, void *pdu
|
||||
};
|
||||
|
||||
osmo_iuup_set_checksums((uint8_t*)iuup_hdr, pdu->tail - (uint8_t*)iuup_hdr);
|
||||
LOGP(DIUUP, LOGL_DEBUG, "(%s) IuUP inserting IuUP header in RTP data (frame nr %u)\n",
|
||||
cn->name, iuup_hdr->frame_nr);
|
||||
|
||||
return cn->cfg.tx_msg(pdu, cn->cfg.node_priv, pdu_priv);
|
||||
return cn->cfg.tx_msg(pdu, cn->cfg.node_priv);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ void osmo_iuup_set_checksums(uint8_t *iuup_header_and_payload, unsigned int head
|
||||
|
||||
/* Validate minimum message sizes, IuUP PDU type, header- and payload checksums. If it is a Control
|
||||
* Procedure PDU, return the header position in is_ctrl, if it is a Data PDU, return the header position
|
||||
* in is_data. If log_errors is true, log on DRTP with the given log label for context. Return NULL in
|
||||
* in is_data. If log_errors is true, log on DIUUP with the given log label for context. Return NULL in
|
||||
* both is_ctrl and is_data, and return a negative error code if the PDU could not be identified as a
|
||||
* valid RTP PDU containing an IuUP part. */
|
||||
int osmo_iuup_classify(bool log_errors,
|
||||
@@ -169,7 +169,7 @@ int osmo_iuup_classify(bool log_errors,
|
||||
|
||||
#define ERR(fmt, args...) do { \
|
||||
if (log_errors) \
|
||||
LOGP(DRTP, LOGL_ERROR, "(%s) " fmt, log_label? : "-", ## args); \
|
||||
LOGP(DIUUP, LOGL_ERROR, "(%s) " fmt, log_label? : "-", ## args); \
|
||||
return -EINVAL; \
|
||||
} while (0)
|
||||
|
||||
@@ -240,6 +240,7 @@ bool osmo_iuup_is_init(struct msgb *pdu)
|
||||
&& is_ctrl->ack_nack == OSMO_IUUP_ACKNACK_PROCEDURE;
|
||||
}
|
||||
|
||||
/* Append an IuUP Initialization ACK message */
|
||||
void osmo_iuup_make_init_ack(struct msgb *ack)
|
||||
{
|
||||
/* Send Initialization Ack PDU back to the sender */
|
||||
@@ -256,3 +257,30 @@ void osmo_iuup_make_init_ack(struct msgb *ack)
|
||||
|
||||
osmo_iuup_set_checksums((uint8_t*)hdr, sizeof(*hdr));
|
||||
}
|
||||
|
||||
const struct value_string osmo_iuup_error_cause_names[] = {
|
||||
{ 0, "CRC error of frame header" },
|
||||
{ 1, "CRC error of frame payload" },
|
||||
{ 2, "Unexpected frame number" },
|
||||
{ 3, "Frame loss" },
|
||||
{ 4, "PDU type unknown" },
|
||||
{ 5, "Unknown procedure" },
|
||||
{ 6, "Unknown reserved value" },
|
||||
{ 7, "Unknown field" },
|
||||
{ 8, "Frame too short" },
|
||||
{ 9, "Missing fields" },
|
||||
{ 16, "Unexpected PDU type" },
|
||||
{ 17, "spare" },
|
||||
{ 18, "Unexpected procedure" },
|
||||
{ 19, "Unexpected RFCI" },
|
||||
{ 20, "Unexpected value" },
|
||||
{ 42, "Initialisation failure" },
|
||||
{ 43, "Initialisation failure (network error, timer expiry)" },
|
||||
{ 44, "Initialisation failure (Iu UP function error, repeated NACK)" },
|
||||
{ 45, "Rate control failure" },
|
||||
{ 46, "Error event failure" },
|
||||
{ 47, "Time Alignment not supported" },
|
||||
{ 48, "Requested Time Alignment not possible" },
|
||||
{ 49, "Iu UP Mode version not supported" },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -57,10 +57,7 @@ enum rtp_proto {
|
||||
MGCP_PROTO_RTCP,
|
||||
};
|
||||
|
||||
static int rx_rtp(struct mgcp_conn_rtp *conn_src, struct msgb *payload,
|
||||
enum rtp_proto proto, struct sockaddr_in *from_addr);
|
||||
static int tx_rtp(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst,
|
||||
enum rtp_proto proto, struct sockaddr_in *from_addr, struct msgb *payload);
|
||||
static int rx_rtp(struct msgb *msg);
|
||||
|
||||
/*! Determine the local rtp bind IP-address.
|
||||
* \param[out] addr caller provided memory to store the resulting IP-Address
|
||||
@@ -494,8 +491,8 @@ static int mgcp_patch_pt(struct mgcp_conn_rtp *conn_src,
|
||||
uint8_t pt_in;
|
||||
int pt_out;
|
||||
|
||||
OSMO_ASSERT(msgb_l3len(msg) >= sizeof(struct rtp_hdr));
|
||||
rtp_hdr = (struct rtp_hdr *)msgb_l3(msg);
|
||||
OSMO_ASSERT(msg->len >= sizeof(struct rtp_hdr));
|
||||
rtp_hdr = (struct rtp_hdr *)msg->data;
|
||||
|
||||
pt_in = rtp_hdr->payload_type;
|
||||
pt_out = mgcp_codec_pt_translate(conn_src, conn_dst, pt_in);
|
||||
@@ -523,12 +520,12 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
|
||||
uint32_t timestamp, ssrc;
|
||||
struct rtp_hdr *rtp_hdr;
|
||||
int payload = rtp_end->codec->payload_type;
|
||||
unsigned int len = msgb_l3len(msg);
|
||||
unsigned int len = msg->len;
|
||||
|
||||
if (len < sizeof(*rtp_hdr))
|
||||
return;
|
||||
|
||||
rtp_hdr = (struct rtp_hdr *)msgb_l3(msg);
|
||||
rtp_hdr = (struct rtp_hdr *)msg->data;
|
||||
seq = ntohs(rtp_hdr->sequence);
|
||||
timestamp = ntohl(rtp_hdr->timestamp);
|
||||
arrival_time = get_current_ts(rtp_end->codec->rate);
|
||||
@@ -668,7 +665,7 @@ static void forward_data(int fd, struct mgcp_rtp_tap *tap, struct msgb *msg)
|
||||
if (!tap->enabled)
|
||||
return;
|
||||
|
||||
rc = sendto(fd, msgb_l3(msg), msgb_l3len(msg), 0, (struct sockaddr *)&tap->forward,
|
||||
rc = sendto(fd, msg->data, msg->len, 0, (struct sockaddr *)&tap->forward,
|
||||
sizeof(tap->forward));
|
||||
|
||||
if (rc < 0)
|
||||
@@ -754,11 +751,11 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
} else if (is_rtp) {
|
||||
int cont;
|
||||
int nbytes = 0;
|
||||
int buflen = msgb_l3len(msg);
|
||||
int buflen = msg->len;
|
||||
do {
|
||||
/* Run transcoder */
|
||||
cont = endp->cfg->rtp_processing_cb(endp, rtp_end,
|
||||
msgb_l3(msg), &buflen,
|
||||
(char*)msg->data, &buflen,
|
||||
RTP_BUF_SIZE);
|
||||
if (cont < 0)
|
||||
break;
|
||||
@@ -778,6 +775,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
forward_data(rtp_end->rtp.fd, &conn_src->tap_out,
|
||||
msg);
|
||||
|
||||
#if 0
|
||||
/* FIXME: HACK HACK HACK. See OS#2459.
|
||||
* The ip.access nano3G needs the first RTP payload's first two bytes to read hex
|
||||
* 'e400', or it will reject the RAB assignment. It seems to not harm other femto
|
||||
@@ -785,7 +783,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
*/
|
||||
if (!rtp_state->patched_first_rtp_payload
|
||||
&& conn_src->conn->mode == MGCP_CONN_LOOPBACK) {
|
||||
uint8_t *data = ((uint8_t *)msgb_l3(msg)) + 12;
|
||||
uint8_t *data = msg->data + 12;
|
||||
if (data[0] == 0xe0) {
|
||||
data[0] = 0xe4;
|
||||
data[1] = 0x00;
|
||||
@@ -796,11 +794,13 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
ENDPOINT_NUMBER(endp));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
len = mgcp_udp_send(rtp_end->rtp.fd,
|
||||
&rtp_end->addr,
|
||||
rtp_end->rtp_port,
|
||||
msgb_l3(msg), msgb_l3len(msg));
|
||||
if (conn_dst->iuup)
|
||||
len = osmo_iuup_cn_tx_payload(conn_dst->iuup, msg);
|
||||
else
|
||||
len = mgcp_udp_send(rtp_end->rtp.fd, &rtp_end->addr, rtp_end->rtp_port,
|
||||
(char*)msg->data, msg->len);
|
||||
|
||||
if (len <= 0)
|
||||
return len;
|
||||
@@ -823,7 +823,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
|
||||
|
||||
len = mgcp_udp_send(rtp_end->rtcp.fd,
|
||||
&rtp_end->addr,
|
||||
rtp_end->rtcp_port, msgb_l3(msg), msgb_l3len(msg));
|
||||
rtp_end->rtcp_port, (char*)msg->data, msg->len);
|
||||
|
||||
rate_ctr_inc(&conn_dst->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR]);
|
||||
rate_ctr_add(&conn_dst->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR], len);
|
||||
@@ -914,7 +914,7 @@ static int check_rtp_destin(struct mgcp_conn_rtp *conn)
|
||||
* and IP-address for outgoing data. */
|
||||
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0 && conn->end.rtp_port == 0) {
|
||||
LOGP(DRTP, LOGL_DEBUG,
|
||||
"endpoint:0x%x destination IP-address and rtp port is (not yet) known\n",
|
||||
"endpoint:0x%x destination IP-address and rtp port is not known (yet)\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
return -1;
|
||||
}
|
||||
@@ -943,23 +943,22 @@ static int check_rtcp(struct mgcp_conn_rtp *conn_src, struct msgb *msg)
|
||||
struct rtcp_hdr *hdr;
|
||||
unsigned int len;
|
||||
uint8_t type;
|
||||
unsigned int buf_size = msgb_l3len(msg);
|
||||
|
||||
/* RTPC packets that are just a header without data do not make
|
||||
* any sense. */
|
||||
if (buf_size < sizeof(struct rtcp_hdr)) {
|
||||
if (msg->len < sizeof(struct rtcp_hdr)) {
|
||||
LOG_CONN_RTP(conn_src, LOGL_ERROR, "RTCP packet too short (%u < %zu)\n",
|
||||
buf_size, sizeof(struct rtcp_hdr));
|
||||
msg->len, sizeof(struct rtcp_hdr));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Make sure that the length of the received packet does not exceed
|
||||
* the available buffer size */
|
||||
hdr = (struct rtcp_hdr *)msgb_l3(msg);
|
||||
hdr = (struct rtcp_hdr *)msg->data;
|
||||
len = (osmo_ntohs(hdr->length) + 1) * 4;
|
||||
if (len > buf_size) {
|
||||
if (len > msg->len) {
|
||||
LOG_CONN_RTP(conn_src, LOGL_ERROR, "RTCP header length exceeds packet size (%u > %u)\n",
|
||||
len, buf_size);
|
||||
len, msg->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -981,9 +980,9 @@ static int check_rtp(struct mgcp_conn_rtp *conn_src, struct msgb *msg)
|
||||
size_t min_size = sizeof(struct rtp_hdr);
|
||||
if (conn_src->iuup)
|
||||
min_size += sizeof(struct osmo_iuup_hdr_data);
|
||||
if (msgb_l3len(msg) < min_size) {
|
||||
if (msg->len < min_size) {
|
||||
LOG_CONN_RTP(conn_src, LOGL_ERROR, "RTP packet too short (%u < %zu)\n",
|
||||
msgb_l3len(msg), min_size);
|
||||
msg->len, min_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -998,11 +997,11 @@ static int check_rtp(struct mgcp_conn_rtp *conn_src, struct msgb *msg)
|
||||
|
||||
/* Send RTP data. Possible options are standard RTP packet
|
||||
* transmission or trsmission via an osmux connection */
|
||||
static int mgcp_send_rtp(int proto, struct sockaddr_in *addr,
|
||||
struct msgb *payload,
|
||||
struct mgcp_conn_rtp *conn_src,
|
||||
struct mgcp_conn_rtp *conn_dst)
|
||||
static int mgcp_send_rtp(struct mgcp_conn_rtp *conn_dst, struct msgb *msg)
|
||||
{
|
||||
enum rtp_proto proto = OSMO_RTP_MSG_CTX(msg)->proto;
|
||||
struct mgcp_conn_rtp *conn_src = OSMO_RTP_MSG_CTX(msg)->conn_src;
|
||||
struct sockaddr_in *from_addr = OSMO_RTP_MSG_CTX(msg)->from_addr;
|
||||
struct mgcp_endpoint *endp = conn_src->conn->endp;
|
||||
|
||||
LOGP(DRTP, LOGL_DEBUG, "endpoint:0x%x destin conn:%s\n",
|
||||
@@ -1023,14 +1022,14 @@ static int mgcp_send_rtp(int proto, struct sockaddr_in *addr,
|
||||
"using mgcp_send() to forward data directly\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
return mgcp_send(endp, proto == MGCP_PROTO_RTP,
|
||||
addr, payload, conn_src, conn_dst);
|
||||
from_addr, msg, conn_src, conn_dst);
|
||||
case MGCP_OSMUX_BSC_NAT:
|
||||
case MGCP_OSMUX_BSC:
|
||||
LOGP(DRTP, LOGL_DEBUG,
|
||||
"endpoint:0x%x endpoint type is MGCP_OSMUX_BSC_NAT, "
|
||||
"using osmux_xfrm_to_osmux() to forward data through OSMUX\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
return osmux_xfrm_to_osmux(msgb_l3(payload), msgb_l3len(payload), conn_dst);
|
||||
return osmux_xfrm_to_osmux((char*)msg->data, msg->len, conn_dst);
|
||||
}
|
||||
|
||||
/* If the data has not been handled/forwarded until here, it will
|
||||
@@ -1050,9 +1049,10 @@ static int mgcp_send_rtp(int proto, struct sockaddr_in *addr,
|
||||
* \param[in] buf_size size data length of buf
|
||||
* \param[in] conn originating connection
|
||||
* \returns 0 on success, -1 on ERROR */
|
||||
int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr,
|
||||
struct msgb *payload, struct mgcp_conn *conn)
|
||||
int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg)
|
||||
{
|
||||
struct mgcp_conn_rtp *conn_src = OSMO_RTP_MSG_CTX(msg)->conn_src;
|
||||
struct mgcp_conn *conn = conn_src->conn;
|
||||
struct mgcp_conn *conn_dst;
|
||||
struct mgcp_endpoint *endp;
|
||||
endp = conn->endp;
|
||||
@@ -1096,7 +1096,7 @@ int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr,
|
||||
}
|
||||
|
||||
/* Dispatch RTP packet to destination RTP connection */
|
||||
return tx_rtp(&conn->u.rtp, &conn_dst->u.rtp, proto, addr, payload);
|
||||
return mgcp_send_rtp(&conn_dst->u.rtp, msg);
|
||||
}
|
||||
|
||||
/*! cleanup an endpoint when a connection on an RTP bridge endpoint is removed.
|
||||
@@ -1120,14 +1120,7 @@ void mgcp_cleanup_rtp_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *co
|
||||
|
||||
static bool is_dummy_msg(enum rtp_proto proto, struct msgb *msg)
|
||||
{
|
||||
return msgb_l3len(msg) == 1 && ((char*)msgb_l3(msg))[0] == MGCP_DUMMY_LOAD;
|
||||
}
|
||||
|
||||
int rx_rtp_from_iuup(struct msgb *msg, void *node_priv, void *pdu_priv)
|
||||
{
|
||||
struct mgcp_conn_rtp *conn_src = node_priv;
|
||||
struct sockaddr_in *from_addr = pdu_priv;
|
||||
return rx_rtp(conn_src, msg, MGCP_PROTO_RTP, from_addr);
|
||||
return msg->len == 1 && msg->data[0] == MGCP_DUMMY_LOAD;
|
||||
}
|
||||
|
||||
struct pdu_ctx {
|
||||
@@ -1135,23 +1128,64 @@ struct pdu_ctx {
|
||||
struct mgcp_conn_rtp *conn_src;
|
||||
};
|
||||
|
||||
int tx_pdu_from_iuup(struct msgb *msg, void *node_priv, void *pdu_priv)
|
||||
/* IuUP CN node has stripped an IuUP header and forwards RTP data to distribute to the peers. */
|
||||
int iuup_rx_payload(struct msgb *msg, void *node_priv)
|
||||
{
|
||||
struct mgcp_conn_rtp *conn_dst = node_priv;
|
||||
struct pdu_ctx *p = pdu_priv;
|
||||
return mgcp_send_rtp(MGCP_PROTO_RTP, p->from_addr, msg, p->conn_src, conn_dst);
|
||||
struct mgcp_conn_rtp *conn_src = OSMO_RTP_MSG_CTX(msg)->conn_src;
|
||||
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "iuup_rx_payload(%u bytes)\n", msg->len);
|
||||
return rx_rtp(msg);
|
||||
}
|
||||
|
||||
static void init_iuup(struct mgcp_conn_rtp *conn_src)
|
||||
/* IuUP CN node has composed a message that contains an IuUP header and asks us to send to the IuUP peer.
|
||||
*/
|
||||
int iuup_tx_msg(struct msgb *msg, void *node_priv)
|
||||
{
|
||||
const struct in_addr zero_addr = {};
|
||||
struct mgcp_conn_rtp *conn_src = OSMO_RTP_MSG_CTX(msg)->conn_src;
|
||||
struct mgcp_conn_rtp *conn_dst = node_priv;
|
||||
struct sockaddr_in *from_addr = OSMO_RTP_MSG_CTX(msg)->from_addr;
|
||||
struct mgcp_rtp_end *rtp_end = &conn_dst->end;
|
||||
struct in_addr to_addr = rtp_end->addr;
|
||||
uint16_t to_port = rtp_end->rtp_port;
|
||||
|
||||
if (conn_src == conn_dst
|
||||
&& !memcmp(&zero_addr, &to_addr, sizeof(zero_addr)) && !to_port) {
|
||||
LOG_CONN_RTP(conn_dst, LOGL_DEBUG, "iuup_tx_msg(): direct IuUP reply\n");
|
||||
/* IuUP wants to send a message back to the same peer that sent an RTP package, but there
|
||||
* is no address configured for that peer yet. It is probably an IuUP Initialization ACK
|
||||
* reply. Use the sender address to send the reply.
|
||||
*
|
||||
* During 3G RAB Assignment, a 3G cell might first probe the MGW and expect an IuUP
|
||||
* Initialization ACK before it replies to the MSC with a successful RAB Assignment; only
|
||||
* after that reply does MSC officially know which RTP address+port the 3G cell wants to
|
||||
* use and can tell this MGW about it, so this "loopback" is, for some 3G cells, the only
|
||||
* chance we have to get a successful RAB Assignment done (particularly the nano3G does
|
||||
* this). */
|
||||
to_addr = from_addr->sin_addr;
|
||||
to_port = from_addr->sin_port;
|
||||
}
|
||||
|
||||
LOG_CONN_RTP(conn_dst, LOGL_DEBUG, "iuup_tx_msg(%u bytes) to %s:%u\n", msg->len,
|
||||
inet_ntoa(to_addr), ntohs(to_port));
|
||||
|
||||
return mgcp_udp_send(rtp_end->rtp.fd, &to_addr, to_port, (char*)msg->data, msg->len);
|
||||
}
|
||||
|
||||
static void iuup_init(struct mgcp_conn_rtp *conn_src)
|
||||
{
|
||||
struct osmo_iuup_cn_cfg cfg = {
|
||||
.node_priv = conn_src,
|
||||
.rx_payload = rx_rtp_from_iuup,
|
||||
.tx_msg = tx_pdu_from_iuup,
|
||||
.rx_payload = iuup_rx_payload,
|
||||
.tx_msg = iuup_tx_msg,
|
||||
};
|
||||
|
||||
osmo_iuup_cn_init(conn_src, &cfg, "%d@ I:%s",
|
||||
ENDPOINT_NUMBER(conn_src->conn->endp), conn_src->conn->id);
|
||||
if (conn_src->iuup) {
|
||||
LOG_CONN_RTP(conn_src, LOGL_NOTICE, "Rx IuUP init, but already initialized. Ignoring.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
conn_src->iuup = osmo_iuup_cn_init(conn_src->conn, &cfg, "endp_%d_conn_%s",
|
||||
ENDPOINT_NUMBER(conn_src->conn->endp), conn_src->conn->id);
|
||||
}
|
||||
|
||||
/* Handle incoming RTP data from NET */
|
||||
@@ -1170,6 +1204,7 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
|
||||
socklen_t slen = sizeof(addr);
|
||||
int ret;
|
||||
enum rtp_proto proto;
|
||||
struct osmo_rtp_msg_ctx mc;
|
||||
struct msgb *msg = msgb_alloc_headroom(RTP_BUF_SIZE + OSMO_IUUP_HEADROOM,
|
||||
OSMO_IUUP_HEADROOM, "RTP-rx");
|
||||
|
||||
@@ -1188,12 +1223,11 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* By default, indicate that RTP payload starts right from the buffer's beginning. */
|
||||
msg->l3h = msgb_put(msg, ret);
|
||||
msgb_put(msg, ret);
|
||||
|
||||
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "%s: rx %u bytes from %s:%u\n",
|
||||
proto == MGCP_PROTO_RTP ? "RTP" : "RTPC",
|
||||
msgb_l3len(msg), inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
msg->len, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
|
||||
if ((proto == MGCP_PROTO_RTP && check_rtp(conn_src, msg))
|
||||
|| (proto == MGCP_PROTO_RTCP && check_rtcp(conn_src, msg))) {
|
||||
@@ -1206,32 +1240,47 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
|
||||
return 0;
|
||||
}
|
||||
|
||||
mc = (struct osmo_rtp_msg_ctx){
|
||||
.proto = proto,
|
||||
.conn_src = conn_src,
|
||||
.from_addr = &addr,
|
||||
};
|
||||
OSMO_RTP_MSG_CTX(msg) = &mc;
|
||||
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "msg ctx: %d %p %s\n",
|
||||
OSMO_RTP_MSG_CTX(msg)->proto,
|
||||
OSMO_RTP_MSG_CTX(msg)->conn_src,
|
||||
osmo_hexdump((void*)OSMO_RTP_MSG_CTX(msg)->from_addr, sizeof(struct sockaddr_in)));
|
||||
|
||||
/* Increment RX statistics */
|
||||
rate_ctr_inc(&conn_src->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR]);
|
||||
rate_ctr_add(&conn_src->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR], msgb_l3len(msg));
|
||||
rate_ctr_add(&conn_src->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR], msg->len);
|
||||
/* FIXME: count RTP and RTCP separately, also count IuUP payload-less separately */
|
||||
|
||||
/* Forward a copy of the RTP data to a debug ip/port */
|
||||
forward_data(fd->fd, &conn_src->tap_in, msg);
|
||||
|
||||
if (proto == MGCP_PROTO_RTP && osmo_iuup_is_init(msg))
|
||||
init_iuup(conn_src);
|
||||
iuup_init(conn_src);
|
||||
|
||||
if (conn_src->iuup && proto == MGCP_PROTO_RTP)
|
||||
return osmo_iuup_cn_rx_pdu(conn_src->iuup, msg, &addr);
|
||||
return osmo_iuup_cn_rx_pdu(conn_src->iuup, msg);
|
||||
else
|
||||
return rx_rtp(conn_src, msg, proto, &addr);
|
||||
return rx_rtp(msg);
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
static int rx_rtp(struct mgcp_conn_rtp *conn_src, struct msgb *payload,
|
||||
enum rtp_proto proto, struct sockaddr_in *from_addr)
|
||||
static int rx_rtp(struct msgb *msg)
|
||||
{
|
||||
struct mgcp_endpoint *endp = conn_src->conn->endp;
|
||||
struct mgcp_trunk_config *tcfg = endp->tcfg;
|
||||
struct mgcp_conn_rtp *conn_src = OSMO_RTP_MSG_CTX(msg)->conn_src;
|
||||
struct sockaddr_in *from_addr = OSMO_RTP_MSG_CTX(msg)->from_addr;
|
||||
struct mgcp_conn *conn = conn_src->conn;
|
||||
struct mgcp_trunk_config *tcfg = conn->endp->tcfg;
|
||||
|
||||
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "rx_rtp(%u bytes)\n", msg->len);
|
||||
|
||||
/* Check if the connection is in loopback mode, if yes, just send the
|
||||
* incoming data back to the origin */
|
||||
if (conn_src->conn->mode == MGCP_CONN_LOOPBACK) {
|
||||
if (conn->mode == MGCP_CONN_LOOPBACK) {
|
||||
/* When we are in loopback mode, we loop back all incoming
|
||||
* packets back to their origin. We will use the originating
|
||||
* address data from the UDP packet header to patch the
|
||||
@@ -1240,7 +1289,7 @@ static int rx_rtp(struct mgcp_conn_rtp *conn_src, struct msgb *payload,
|
||||
conn_src->end.addr = from_addr->sin_addr;
|
||||
conn_src->end.rtp_port = from_addr->sin_port;
|
||||
}
|
||||
return tx_rtp(conn_src, conn_src, proto, from_addr, payload);
|
||||
return mgcp_send_rtp(conn_src, msg);
|
||||
}
|
||||
|
||||
/* Check if the origin of the RTP packet seems plausible */
|
||||
@@ -1249,16 +1298,7 @@ static int rx_rtp(struct mgcp_conn_rtp *conn_src, struct msgb *payload,
|
||||
|
||||
/* Execute endpoint specific implementation that handles the
|
||||
* dispatching of the RTP data */
|
||||
return conn_src->conn->endp->type->dispatch_rtp_cb(proto, from_addr, payload, conn_src->conn);
|
||||
}
|
||||
|
||||
static int tx_rtp(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst,
|
||||
enum rtp_proto proto, struct sockaddr_in *from_addr, struct msgb *payload)
|
||||
{
|
||||
if (conn_dst->iuup && proto == MGCP_PROTO_RTP)
|
||||
return osmo_iuup_cn_tx_payload(conn_dst->iuup, payload, from_addr);
|
||||
else
|
||||
return mgcp_send_rtp(proto, from_addr, payload, conn_src, conn_dst);
|
||||
return conn->endp->type->dispatch_rtp_cb(msg);
|
||||
}
|
||||
|
||||
/*! set IP Type of Service parameter.
|
||||
|
||||
@@ -244,6 +244,12 @@ static const struct log_info_cat log_categories[] = {
|
||||
.color = "\033[1;30m",
|
||||
.enabled = 1,.loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DIUUP] = {
|
||||
.name = "DIUUP",
|
||||
.description = "IuUP within RTP stream handling",
|
||||
.color = "\033[1;31m",
|
||||
.enabled = 1,.loglevel = LOGL_NOTICE,
|
||||
},
|
||||
};
|
||||
|
||||
const struct log_info log_info = {
|
||||
|
||||
@@ -27,12 +27,12 @@ struct msgb *msgb_from_hex(const char *label, const char *hex)
|
||||
}
|
||||
|
||||
const char *expect_rx_payload = NULL;
|
||||
int rx_payload(struct msgb *msg, void *node_priv, void *pdu_priv)
|
||||
int rx_payload(struct msgb *msg, void *node_priv)
|
||||
{
|
||||
printf("rx_payload() invoked by iuup_cn!\n");
|
||||
printf(" [IuUP] -RTP->\n");
|
||||
printf("%s\n", dump(msg));
|
||||
printf("node_priv=%p pdu_priv=%p\n", node_priv, pdu_priv);
|
||||
printf("node_priv=%p\n", node_priv);
|
||||
if (!expect_rx_payload) {
|
||||
printf("ERROR: did not expect rx_payload()\n");
|
||||
exit(-1);
|
||||
@@ -41,18 +41,17 @@ int rx_payload(struct msgb *msg, void *node_priv, void *pdu_priv)
|
||||
exit(-1);
|
||||
} else
|
||||
printf("ok: matches expected msg\n");
|
||||
msgb_free(msg);
|
||||
expect_rx_payload = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *expect_tx_msg = NULL;
|
||||
int tx_msg(struct msgb *msg, void *node_priv, void *pdu_priv)
|
||||
int tx_msg(struct msgb *msg, void *node_priv)
|
||||
{
|
||||
printf("tx_msg() invoked by iuup_cn!\n");
|
||||
printf(" <-PDU- [IuUP]\n");
|
||||
printf("%s\n", dump(msg));
|
||||
printf("node_priv=%p pdu_priv=%p\n", node_priv, pdu_priv);
|
||||
printf("node_priv=%p\n", node_priv);
|
||||
if (!expect_tx_msg) {
|
||||
printf("ERROR: did not expect tx_msg()\n");
|
||||
exit(-1);
|
||||
@@ -61,29 +60,26 @@ int tx_msg(struct msgb *msg, void *node_priv, void *pdu_priv)
|
||||
exit(-1);
|
||||
} else
|
||||
printf("ok: matches expected msg\n");
|
||||
msgb_free(msg);
|
||||
expect_tx_msg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rx_pdu(struct osmo_iuup_cn *cn, struct msgb *msg, void *pdu_priv)
|
||||
static int rx_pdu(struct osmo_iuup_cn *cn, struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
printf(" -PDU-> [IuUP]\n");
|
||||
printf("%s\n", dump(msg));
|
||||
printf("pdu_priv=%p\n", pdu_priv);
|
||||
rc = osmo_iuup_cn_rx_pdu(cn, msg, pdu_priv);
|
||||
rc = osmo_iuup_cn_rx_pdu(cn, msg);
|
||||
printf("rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tx_payload(struct osmo_iuup_cn *cn, struct msgb *msg, void *pdu_priv)
|
||||
static int tx_payload(struct osmo_iuup_cn *cn, struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
printf(" [IuUP] <-RTP-\n");
|
||||
printf("%s\n", dump(msg));
|
||||
printf("pdu_priv=%p\n", pdu_priv);
|
||||
rc = osmo_iuup_cn_tx_payload(cn, msg, pdu_priv);
|
||||
rc = osmo_iuup_cn_tx_payload(cn, msg);
|
||||
printf("rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
@@ -91,7 +87,6 @@ static int tx_payload(struct osmo_iuup_cn *cn, struct msgb *msg, void *pdu_priv)
|
||||
void test_cn_session()
|
||||
{
|
||||
void *node_priv = (void*)0x2342;
|
||||
void *pdu_priv = (void*)0xfeed;
|
||||
|
||||
struct osmo_iuup_cn_cfg cfg = {
|
||||
.node_priv = node_priv,
|
||||
@@ -103,13 +98,13 @@ void test_cn_session()
|
||||
OSMO_ASSERT(cn);
|
||||
|
||||
printf("\nSend IuUP Initialization. Expecting direct tx_msg() of the Initialization Ack\n");
|
||||
expect_tx_msg = "e400240000";
|
||||
expect_tx_msg = "8060dc5219495e3f00010111" /* RTP header */
|
||||
"e4002400"; /* IuUP Init Ack */
|
||||
rx_pdu(cn,
|
||||
msgb_from_hex("IuUP-Init",
|
||||
"8060dc5219495e3f00010111" /* <- RTP header */
|
||||
"e000df99" /* <- IuUP header */
|
||||
"160051673c01270000820000001710000100" /* IuUP params */),
|
||||
pdu_priv);
|
||||
"160051673c01270000820000001710000100" /* IuUP params */));
|
||||
|
||||
#define RTP_HEADER "8060944c6256042c00010102"
|
||||
#define IUUP_HEADER "0100e2b3"
|
||||
@@ -119,28 +114,23 @@ void test_cn_session()
|
||||
expect_rx_payload = RTP_HEADER RTP_PAYLOAD;
|
||||
rx_pdu(cn,
|
||||
msgb_from_hex("IuUP-Data",
|
||||
RTP_HEADER IUUP_HEADER RTP_PAYLOAD),
|
||||
pdu_priv);
|
||||
RTP_HEADER IUUP_HEADER RTP_PAYLOAD));
|
||||
|
||||
printf("\nTransmit RTP. Expecting tx_msg() with inserted IuUP header\n");
|
||||
expect_tx_msg = RTP_HEADER "000002b3" RTP_PAYLOAD;
|
||||
tx_payload(cn,
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD),
|
||||
pdu_priv);
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD));
|
||||
|
||||
printf("\nMore RTP, each time the Frame Nr advances, causing a new header CRC.\n");
|
||||
expect_tx_msg = RTP_HEADER "0100e2b3" RTP_PAYLOAD;
|
||||
tx_payload(cn,
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD),
|
||||
pdu_priv);
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD));
|
||||
expect_tx_msg = RTP_HEADER "02007eb3" RTP_PAYLOAD;
|
||||
tx_payload(cn,
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD),
|
||||
pdu_priv);
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD));
|
||||
expect_tx_msg = RTP_HEADER "03009eb3" RTP_PAYLOAD;
|
||||
tx_payload(cn,
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD),
|
||||
pdu_priv);
|
||||
msgb_from_hex("RTP data", RTP_HEADER RTP_PAYLOAD));
|
||||
|
||||
printf("All done.\n");
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
Send IuUP Initialization. Expecting direct tx_msg() of the Initialization Ack
|
||||
-PDU-> [IuUP]
|
||||
8060dc5219495e3f00010111e000df99160051673c01270000820000001710000100
|
||||
pdu_priv=0xfeed
|
||||
tx_msg() invoked by iuup_cn!
|
||||
<-PDU- [IuUP]
|
||||
e400240000
|
||||
node_priv=0x2342 pdu_priv=0xfeed
|
||||
8060dc5219495e3f00010111e4002400
|
||||
node_priv=0x2342
|
||||
ok: matches expected msg
|
||||
rc=0
|
||||
|
||||
@@ -14,51 +13,46 @@ Receive payload encapsulated in IuUP. Expecting rx_payload() of just RTP packet
|
||||
i.e. should strip away 0100e2b3
|
||||
-PDU-> [IuUP]
|
||||
8060944c6256042c000101020100e2b36cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
pdu_priv=0xfeed
|
||||
rx_payload() invoked by iuup_cn!
|
||||
[IuUP] -RTP->
|
||||
8060944c6256042c000101026cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
node_priv=0x2342 pdu_priv=0xfeed
|
||||
node_priv=0x2342
|
||||
ok: matches expected msg
|
||||
rc=0
|
||||
|
||||
Transmit RTP. Expecting tx_msg() with inserted IuUP header
|
||||
[IuUP] <-RTP-
|
||||
8060944c6256042c000101026cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
pdu_priv=0xfeed
|
||||
tx_msg() invoked by iuup_cn!
|
||||
<-PDU- [IuUP]
|
||||
8060944c6256042c00010102000002b36cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
node_priv=0x2342 pdu_priv=0xfeed
|
||||
node_priv=0x2342
|
||||
ok: matches expected msg
|
||||
rc=0
|
||||
|
||||
More RTP, each time the Frame Nr advances, causing a new header CRC.
|
||||
[IuUP] <-RTP-
|
||||
8060944c6256042c000101026cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
pdu_priv=0xfeed
|
||||
tx_msg() invoked by iuup_cn!
|
||||
<-PDU- [IuUP]
|
||||
8060944c6256042c000101020100e2b36cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
node_priv=0x2342 pdu_priv=0xfeed
|
||||
node_priv=0x2342
|
||||
ok: matches expected msg
|
||||
rc=0
|
||||
[IuUP] <-RTP-
|
||||
8060944c6256042c000101026cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
pdu_priv=0xfeed
|
||||
tx_msg() invoked by iuup_cn!
|
||||
<-PDU- [IuUP]
|
||||
8060944c6256042c0001010202007eb36cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
node_priv=0x2342 pdu_priv=0xfeed
|
||||
node_priv=0x2342
|
||||
ok: matches expected msg
|
||||
rc=0
|
||||
[IuUP] <-RTP-
|
||||
8060944c6256042c000101026cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
pdu_priv=0xfeed
|
||||
tx_msg() invoked by iuup_cn!
|
||||
<-PDU- [IuUP]
|
||||
8060944c6256042c0001010203009eb36cfb23bc46d18180c3e5ffe040045600005a7d35b625b80005fff03214ced0
|
||||
node_priv=0x2342 pdu_priv=0xfeed
|
||||
node_priv=0x2342
|
||||
ok: matches expected msg
|
||||
rc=0
|
||||
All done.
|
||||
|
||||
Reference in New Issue
Block a user