This adds datastructures and a VTY frontend to configure the
different type of RTP header patching: SSRC and timestamp.

Note that timestamp patching is not yet implemented.

Sponsored-by: On-Waves ehf
---
 openbsc/include/openbsc/mgcp.h          |    4 +++
 openbsc/include/openbsc/mgcp_internal.h |   10 ++++--
 openbsc/src/libmgcp/mgcp_network.c      |    2 +-
 openbsc/src/libmgcp/mgcp_protocol.c     |   12 ++++++-
 openbsc/src/libmgcp/mgcp_vty.c          |   56 ++++++++++++++++++++++++++++++-
 openbsc/tests/mgcp/mgcp_test.c          |    6 +++-
 6 files changed, 83 insertions(+), 7 deletions(-)

diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index 4e22e0f..8ab52ce 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -118,6 +118,10 @@ struct mgcp_trunk_config {
 
        int omit_rtcp;
 
+       /* RTP patching */
+       int force_constant_ssrc; /* 0: don't, 1: once */
+       int force_constant_timing;
+
        /* spec handling */
        int force_realloc;
 
diff --git a/openbsc/include/openbsc/mgcp_internal.h 
b/openbsc/include/openbsc/mgcp_internal.h
index 0b52c1c..02e193d 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -83,6 +83,10 @@ struct mgcp_rtp_end {
        int  frames_per_packet;
        char *fmtp_extra;
 
+       /* RTP patching */
+       int force_constant_ssrc;
+       int force_constant_timing;
+
        /*
         * Each end has a socket...
         */
@@ -142,9 +146,6 @@ struct mgcp_endpoint {
        struct mgcp_rtp_state net_state;
        struct mgcp_rtp_state bts_state;
 
-       /* SSRC/seq/ts patching for loop */
-       int allow_patch;
-
        /* fields for re-transmission */
        char *last_trans;
        char *last_response;
@@ -176,6 +177,9 @@ static inline int endp_back_channel(int endpoint)
 struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
 struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
 
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
+                        struct mgcp_rtp_end *rtp);
+
 void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
                        uint32_t *expected, int *loss);
 uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
diff --git a/openbsc/src/libmgcp/mgcp_network.c 
b/openbsc/src/libmgcp/mgcp_network.c
index 06452a6..ce4e1d3 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -263,7 +263,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, 
struct mgcp_rtp_state *sta
                state->seq_offset = (state->out_stream.last_seq + 1) - seq;
                state->timestamp_offset =
                        (state->out_stream.last_timestamp + tsdelta) - 
timestamp;
-               state->patch = endp->allow_patch;
+               state->patch = rtp_end->force_constant_ssrc;
                LOGP(DMGCP, LOGL_NOTICE,
                        "The SSRC changed on 0x%x SSRC: %u offset: %d tsdelta: 
%d "
                        "from %s:%d in %d\n",
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c 
b/openbsc/src/libmgcp/mgcp_protocol.c
index f09058d..6d31ace 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -612,6 +612,15 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct 
mgcp_parse_data *p)
        return found_media;
 }
 
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
+                        struct mgcp_rtp_end *rtp)
+{
+       struct mgcp_trunk_config *tcfg = endp->tcfg;
+
+       rtp->force_constant_timing = tcfg->force_constant_timing;
+       rtp->force_constant_ssrc = tcfg->force_constant_ssrc;
+}
+
 static struct msgb *handle_create_con(struct mgcp_parse_data *p)
 {
        struct mgcp_trunk_config *tcfg;
@@ -686,6 +695,8 @@ mgcp_header_done:
 
        /* initialize */
        endp->net_end.rtp_port = endp->net_end.rtcp_port = 
endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0;
+       mgcp_rtp_end_config(endp, 0, &endp->net_end);
+       mgcp_rtp_end_config(endp, 0, &endp->bts_end);
 
        /* set to zero until we get the info */
        memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr));
@@ -1119,7 +1130,6 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
        memset(&endp->bts_state, 0, sizeof(endp->bts_state));
 
        endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE;
-       endp->allow_patch = 0;
 
        memset(&endp->taps, 0, sizeof(endp->taps));
 }
diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c
index 5aeb393..16b973f 100644
--- a/openbsc/src/libmgcp/mgcp_vty.c
+++ b/openbsc/src/libmgcp/mgcp_vty.c
@@ -31,6 +31,7 @@
 #include <string.h>
 
 #define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
+#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
 
 static struct mgcp_config *g_cfg = NULL;
 
@@ -511,6 +512,13 @@ static int config_write_trunk(struct vty *vty)
                        vty_out(vty, "  rtcp-omit%s", VTY_NEWLINE);
                else
                        vty_out(vty, "  no rtcp-omit%s", VTY_NEWLINE);
+               if (trunk->force_constant_ssrc || trunk->force_constant_timing) 
{
+                       vty_out(vty, "  rtp-patch ssrc %d%s",
+                               trunk->force_constant_ssrc, VTY_NEWLINE);
+                       vty_out(vty, "  rtp-patch timestamp %d%s",
+                               trunk->force_constant_timing, VTY_NEWLINE);
+               } else
+                       vty_out(vty, "  no rtp-patch%s", VTY_NEWLINE);
                if (trunk->audio_fmtp_extra)
                        vty_out(vty, "   sdp audio fmtp-extra %s%s",
                                trunk->audio_fmtp_extra, VTY_NEWLINE);
@@ -599,6 +607,46 @@ DEFUN(cfg_trunk_no_omit_rtcp,
        return CMD_SUCCESS;
 }
 
+DEFUN(cfg_trunk_patch_rtp_ssrc,
+      cfg_trunk_patch_rtp_ssrc_cmd,
+      "rtp-patch ssrc (0|1)",
+      RTP_PATCH_STR
+      "Force a fixed SSRC\n"
+      "Disable\n"
+      "Enable\n"
+      )
+{
+       struct mgcp_trunk_config *trunk = vty->index;
+       trunk->force_constant_ssrc = atoi(argv[0]);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_patch_rtp_ts,
+      cfg_trunk_patch_rtp_ts_cmd,
+      "rtp-patch timestamp (0|1)",
+      RTP_PATCH_STR
+      "Adjust RTP timestamp\n"
+      "Disable\n"
+      "Enable\n"
+      )
+{
+       struct mgcp_trunk_config *trunk = vty->index;
+       trunk->force_constant_timing = atoi(argv[0]);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_patch_rtp,
+      cfg_trunk_no_patch_rtp_cmd,
+      "no rtp-patch",
+      NO_STR RTP_PATCH_STR)
+{
+       struct mgcp_trunk_config *trunk = vty->index;
+       trunk->force_constant_ssrc = 0;
+       trunk->force_constant_timing = 0;
+       return CMD_SUCCESS;
+}
+
+
 DEFUN(loop_endp,
       loop_endp_cmd,
       "loop-endpoint <0-64> NAME (0|1)",
@@ -636,7 +684,10 @@ DEFUN(loop_endp,
                endp->conn_mode = MGCP_CONN_LOOPBACK;
        else
                endp->conn_mode = endp->orig_mode;
-       endp->allow_patch = 1;
+
+       /* Handle it like a MDCX, switch on SSRC patching if enabled */
+       mgcp_rtp_end_config(endp, 1, &endp->bts_end);
+       mgcp_rtp_end_config(endp, 1, &endp->net_end);
 
        return CMD_SUCCESS;
 }
@@ -839,6 +890,9 @@ int mgcp_vty_init(void)
        install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
        install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
        install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
+       install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
+       install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
+       install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
        install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
 
        return 0;
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index 4326738..8c292f1 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -537,6 +537,9 @@ static void test_packet_error_detection(int patch_ssrc, int 
patch_ts)
 
        trunk.number_endpoints = 1;
        trunk.endpoints = &endp;
+       trunk.force_constant_ssrc = patch_ssrc;
+       trunk.force_constant_timing = patch_ts;
+
        endp.tcfg = &trunk;
 
        /* This doesn't free endp but resets/frees all fields of the structure
@@ -547,7 +550,6 @@ static void test_packet_error_detection(int patch_ssrc, int 
patch_ts)
        mgcp_free_endp(&endp);
 
        rtp->payload_type = 98;
-       endp.allow_patch = patch_ssrc;
 
        for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) {
                struct rtp_packet_info *info = test_rtp_packets1 + i;
@@ -556,6 +558,8 @@ static void test_packet_error_detection(int patch_ssrc, int 
patch_ts)
                OSMO_ASSERT(info->len >= 0);
                memmove(buffer, info->data, info->len);
 
+               mgcp_rtp_end_config(&endp, 1, rtp);
+
                mgcp_patch_and_count(&endp, &state, rtp, &addr,
                                     buffer, info->len);
 
-- 
1.7.9.5


Reply via email to