blob: 936dd00b38a92910772f0b6ed17452e8b096b7e9 [file] [log] [blame]
/*
* Copyright (c) 2010 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#ifndef _MODULE_RTP_RELAY_H_
#define _MODULE_RTP_RELAY_H_
#include "module_timer.h"
#include "fe.h"
#include "mtd.h"
#if !defined(COMCERTO_2000) || defined(COMCERTO_2000_CONTROL)
#include "module_ipv4.h"
#include "module_mc4.h"
#include "module_mc6.h"
#endif
#if defined(COMCERTO_2000)
#define NUM_RTPFLOW_ENTRIES 64
#else
#define NUM_RTPFLOW_ENTRIES 256
#endif
#define MAX_RTP_STATS_ENTRY 64
#define RTP_SPECIAL_PAYLOAD_LEN 160
#define RTP_MIN_SEQUENTIAL 2
#define RTP_MAX_DROPOUT 3000
#define RTP_LATE_THRESH 0xFF00
#define RTP_SEQ_MOD 1 << 16
#define RTP_MAX_SEQNUM 0xFFFF
enum {
RCVD_OK,
RCVD_ERR,
RCVD_FIRST_PACKET, // 1st received packet
RCVD_IN_ORDER_PACKET, // sequential packet
RCVD_OUT_OF_ORDER_PACKET, // out-of-order packet (could be late or duplicated)
RCVD_FIRST_UNEXPECTED_PACKET, // large jump of seq.
RCVD_SECOND_SEQUENTIAL_PACKET, // 2nd of the new seq.
RCVD_LATE_PACKET,
RCVD_DUPLICATED_PACKET,
RCVD_NEW_SSRC_DECTECTED,
INVALID
};
typedef enum {
RTCP_SR = 200,
RTCP_RR = 201,
RTCP_SDES = 202,
RTCP_BYE = 203,
RTCP_APP = 204,
RTCP_XR = 207
}rtcp_type_t;
typedef enum {
RTP_PT_G711U = 0,
RTP_PT_G711A = 8,
} rtp_pt_t;
#ifdef ENDIAN_LITTLE
typedef struct RTP_HDR_STRUCT
{
U8 cc:4; // CSRC count
U8 x:1; // header extension flag
U8 p:1; // padding flag
U8 version:2; // protocol version
U8 pt:7; // payload type
U8 m:1; // marker bit
U16 seq; // sequence number
U32 ts; // timestamp
U32 ssrc; // synchronization source
} __attribute__((packed)) rtp_hdr_t;
#else
typedef struct RTP_HDR_STRUCT
{
U8 version:2; // protocol version
U8 p:1; // padding flag
U8 x:1; // header extension flag
U8 cc:4; // CSRC count
U8 m:1; // marker bit
U8 pt:7; // payload type
U16 seq; // sequence number
U32 ts; // timestamp
U32 ssrc; // synchronization source
} __attribute__((packed)) rtp_hdr_t;
#endif
#define RTP_HDR_SIZE 12
#define RTP_DISCARD 0x0
#define RTP_RELAY 0x1
#if defined(COMCERTO_2000)
#define FLOW_VALID (1 << 0)
#define FLOW_USED (1 << 1)
#define FLOW_UPDATING (1 << 2)
#endif
typedef struct _tRTPinfo {
BOOL first_packet;
BOOL probation;
U16 last_Seq;
STIME last_rx_time;
U32 last_TS;
U32 last_SSRC;
U32 last_transit;
U16 seq_base;
U16 mode;
U32 cycles;
}RTPinfo, *PRTPinfo;
#if defined (COMCERTO_2000)
#if defined (COMCERTO_2000_CONTROL)
/* control path HW flow entry */
typedef struct _thw_rtpflow {
U32 flags;
U32 dma_addr;
U32 next;
struct _tRTPinfo rtp_info;
U16 ingress_socketID;
U16 egress_socketID;
U8 state;
BOOL takeover_resync;
U8 SSRC_takeover;
U8 Seq_takeover;
U8 TS_takeover;
U8 call_update_seen;
U16 hash;
U32 SSRC;
U32 TimestampBase;
U32 TimeStampIncr;
U16 Seq;
U8 takeover_mode;
U8 Special_tx_active;
U8 Special_tx_type;
U8 pad[7]; /* padding to get first part of the flow structure multiple of 64bits */
/* following part 2*160 bytes is fetched (efet) only if special packet feature is active */
U8 Special_payload1[RTP_SPECIAL_PAYLOAD_LEN];
U8 Special_payload2[RTP_SPECIAL_PAYLOAD_LEN];
/* These fields are only used by host software (not fetched by data path), so keep them at the end of the structure */
struct dlist_head list;
struct _tRTPflow *sw_flow; /** pointer to the software flow entry */
unsigned long removal_time;
}hw_rtpflow, *Phw_rtpflow;
/* control path SW flow entry */
typedef struct _tRTPflow {
struct slist_entry list;
struct _tRTPflow *next;
struct _tRTPcall *RTPcall;
struct _tRTPinfo rtp_info;
U16 ingress_socketID;
U16 egress_socketID;
U8 state; // 0 discard, 1 relay
BOOL takeover_resync;
U8 SSRC_takeover; // 0 transparent / 1 mangle
U8 Seq_takeover; // 0 transparent / 1 mangle
U8 TS_takeover; // 0 transparent / 1 mangle
U8 takeover_mode;
U16 hash;
U32 SSRC;
U32 TimestampBase;
U32 TimeStampIncr;
U16 Seq;
struct _thw_rtpflow *hw_flow;
}RTPflow, *PRTPflow;
#else
/* data path rtp flow entry for util-pe (MUST have a size multiple of 64bits) */
typedef struct _tRTPflow {
U32 flags;
U32 dma_addr;
U32 next;
struct _tRTPinfo rtp_info;
U16 ingress_socketID;
U16 egress_socketID;
U8 state;
BOOL takeover_resync;
U8 SSRC_takeover;
U8 Seq_takeover;
U8 TS_takeover;
U8 call_update_seen;
U16 hash;
U32 SSRC;
U32 TimestampBase;
U32 TimeStampIncr;
U16 Seq;
U8 takeover_mode;
U8 Special_tx_active;
U8 Special_tx_type;
U8 pad[7]; /* padding to get first part of the flow structure multiple of 64bits */
/* following part 2*160 bytes is fetched (efet) only if special packet feature is active */
U8 Special_payload1[RTP_SPECIAL_PAYLOAD_LEN];
U8 Special_payload2[RTP_SPECIAL_PAYLOAD_LEN];
}RTPflow, *PRTPflow;
#endif
#else /* COMCERTO _1000 */
typedef struct _tRTPflow {
struct slist_entry list;
struct _tRTPflow *next;
struct _tRTPcall *RTPcall;
struct _tRTPinfo rtp_info;
U16 ingress_socketID;
U16 egress_socketID;
U8 state; // 0 discard, 1 relay
BOOL takeover_resync;
U8 SSRC_takeover; // 0 transparent / 1 mangle
U8 Seq_takeover; // 0 transparent / 1 mangle
U8 TS_takeover; // 0 transparent / 1 mangle
U8 takeover_mode;
U32 SSRC;
U32 TimestampBase;
U32 TimeStampIncr;
U32 cycles;
U8 call_update_seen;
}RTPflow, *PRTPflow;
#endif
#if !defined(COMCERTO_2000) || defined (COMCERTO_2000_CONTROL)
typedef struct _tRTPcall {
struct slist_entry list;
U16 call_id; // unique id
U16 valid;
struct _tRTPflow *AtoB_flow;
struct _tRTPflow *BtoA_flow;
U8 Special_payload1[RTP_SPECIAL_PAYLOAD_LEN];
U8 Special_payload2[RTP_SPECIAL_PAYLOAD_LEN];
U8 Next_Special_payload1[RTP_SPECIAL_PAYLOAD_LEN];
U8 Next_Special_payload2[RTP_SPECIAL_PAYLOAD_LEN];
U8 Special_tx_active;
U8 Special_tx_type;
}RTPCall, *PRTPCall;
#else
typedef struct _tRTPcall {
U8 Special_payload1[RTP_SPECIAL_PAYLOAD_LEN];
U8 Special_payload2[RTP_SPECIAL_PAYLOAD_LEN];
}RTPCall, *PRTPCall;
#endif
typedef struct _tRTCPStats {
U64 average_reception_period;
U32 prev_reception_period;
U32 last_reception_period;
U32 num_tx_pkts;
U32 num_rx_pkts;
U32 num_rx_pkts_in_seq;
U32 last_TimeStamp;
U32 packets_duplicated;
U32 num_rx_since_RTCP;
U32 num_tx_bytes;
U32 min_jitter;
U32 max_jitter;
U32 mean_jitter;
U32 num_rx_lost_pkts;
U32 min_reception_period;
U32 max_reception_period;
U32 num_expected_pkts;
U32 num_malformed_pkts;
U32 cycles;
U32 num_late_pkts;
STIME last_tx_time;
U32 num_big_jumps;
U32 num_previous_rx_lost_pkts;
U16 sport;
U16 dport;
U16 last_rx_Seq;
U16 seq_base;
U16 state;
U8 first_received_RTP_header[RTP_HDR_SIZE];
U32 ssrc_overwrite_value; /* make sure to get multiple of 64bits */
}RTCPStats, *PRTCPStats;
typedef struct _tRTPOpenCommand {
U16 CallID;
U16 SocketA;
U16 SocketB;
U16 rsvd1;
}RTPOpenCommand, *PRTPOpenCommand;
typedef struct _tRTPCloseCommand {
U16 CallID;
U16 rsvd1;
}RTPCloseCommand, *PRTPCloseCommand;
typedef struct _tRTPTakeoverCommand {
U16 CallID;
U16 Socket;
U16 mode;
U16 SeqNumberBase;
U32 SSRC;
U32 TimeStampBase;
U32 TimeStampIncr;
}RTPTakeoverCommand, *PRTPTakeoverCommand;
/* bit field definition for takeover modes */
#define RTP_TAKEOVER_MODE_TSINCR_FREQ 1
#define RTP_TAKEOVER_MODE_SSRC 2
#define RTP_TAKEOVER_SSRC_TRANSPARENT 0
#define RTP_TAKEOVER_SSRC_MANGLE 1
#define RTP_TAKEOVER_SSRC_AUTO 2
typedef struct _tRTPControlCommand {
U16 CallID;
U16 ControlDir;
}RTPControlCommand, *PRTPControlCommand;
#define RTP_SPEC_TX_START 0
#define RTP_SPEC_TX_RESPONSE 1
#define RTP_SPEC_TX_STOP 2
#define RTP_SPEC_TX_START_ONE_SHOT 3
typedef struct _tRTPSpecTxCtrlCommand {
U16 CallID;
U16 Type;
}RTPSpecTxCtrlCommand, *PRTPSpecTxCtrlCommand;
typedef struct _tRTPSpecTxPayloadCommand {
U16 CallID;
U16 payloadID;
U16 payloadLength;
U16 payload[RTP_SPECIAL_PAYLOAD_LEN/2];
}RTPSpecTxPayloadCommand, *PRTPSpecTxPayloadCommand;
typedef struct _tRTCPQueryCommand {
U16 SocketID;
U16 flags;
}RTCPQueryCommand, *PRTCPQueryCommand;
typedef struct _tRTCPQueryResponse {
U32 prev_reception_period;
U32 last_reception_period;
U32 num_tx_pkts;
U32 num_rx_pkts;
U32 last_rx_Seq;
U32 last_TimeStamp;
U8 RTP_header[RTP_HDR_SIZE];
U32 num_rx_dup;
U32 num_rx_since_RTCP;
U32 num_tx_bytes;
U32 min_jitter;
U32 max_jitter;
U32 mean_jitter;
U32 num_rx_lost_pkts;
U32 min_reception_period;
U32 max_reception_period;
U32 average_reception_period;
U32 num_malformed_pkts;
U32 num_expected_pkts;
U32 num_late_pkts;
U16 sport;
U16 dport;
U32 num_cumulative_rx_lost_pkts;
U32 ssrc_overwrite_value;
}RTCPQueryResponse, *PRTCPQueryResponse;
/**************** RTP Statistics for FF connections *******************/
#define RTP_STATS_FREE 0xFFFF
#define RTP_STATS_FULL_RESET 1
#define RTP_STATS_PARTIAL_RESET 2
#define RTP_STATS_RX_RESET 3
#define RTP_STATS_FIRST_PACKET 4
#define IP4 0
#define IP6 1
#define MC4 2
#define MC6 3
#define RLY 4
#define RLY6 5
#if defined(COMCERTO_2000)
#define RTPQOS_VALID (1 << 0)
#define RTPQOS_USED (1 << 1)
#define RTPQOS_UPDATING (1 << 2)
#endif
#if defined (COMCERTO_2000)
#if defined (COMCERTO_2000_CONTROL)
/* control path HW rtp qos stats entry */
typedef struct _thw_rtpqos_entry
{
U32 flags;
U32 dma_addr;
U32 next;
U16 stream_id;
U16 stream_type;
U32 saddr[4];
U32 daddr[4];
U16 sport;
U16 dport;
U16 proto;
U16 slot;
struct _tRTPinfo rtp_info;
struct _tRTCPStats stats;
/* HOST only , these fields are only used by host software, so keep them at the end of the structure */
struct dlist_head list;
struct _trtpqos_entry *sw_rtpqos;
unsigned long removal_time;
} hw_RTPQOS_ENTRY, *hw_PRTPQOS_ENTRY;
/* control path SW rtp qos stats entry */
typedef struct _trtpqos_entry
{
struct slist_entry list;
U16 stream_id;
U16 stream_type;
U32 saddr[4];
U32 daddr[4];
U16 sport;
U16 dport;
U16 proto;
U16 slot;
struct _tRTPinfo rtp_info;
struct _tRTCPStats stats;
struct _thw_rtpqos_entry *hw_rtpqos;
} RTPQOS_ENTRY, *PRTPQOS_ENTRY;
#else
/* data path rtp qos stats entry for util-pe (MUST have a size multiple of 64bits) */
typedef struct _trtpqos_entry
{
U32 flags;
U32 dma_addr;
U32 next;
U16 stream_id;
U16 stream_type;
U32 saddr[4];
U32 daddr[4];
U16 sport;
U16 dport;
U16 proto;
U16 slot;
struct _tRTPinfo rtp_info;
struct _tRTCPStats stats;
} RTPQOS_ENTRY, *PRTPQOS_ENTRY;
#endif
#else
/* C1000 */
typedef struct _trtpqos_entry
{
struct slist_entry list;
U32 flags;
U16 stream_id;
U16 stream_type;
U32 saddr[4];
U32 daddr[4];
U16 sport;
U16 dport;
U16 proto;
U16 slot;
struct _tRTPinfo rtp_info;
struct _tRTCPStats stats;
} RTPQOS_ENTRY, *PRTPQOS_ENTRY;
#endif
typedef struct _tRTP_enable_stats_command {
U16 stream_id;
U16 stream_type;
U32 saddr[4];
U32 daddr[4];
U16 sport;
U16 dport;
U16 proto;
U16 mode;
}RTP_ENABLE_STATS_COMMAND, *PRTP_ENABLE_STATS_COMMAND;
typedef struct _tRTP_disable_stats_command {
U16 stream_id;
}RTP_DISABLE_STATS_COMMAND, *PRTP_DISABLE_STATS_COMMAND;
typedef struct _tRTP_query_stats_command {
U16 stream_id;
U16 flags;
}RTP_QUERY_STATS_COMMAND, *PRTP_QUERY_STATS_COMMAND;
typedef struct _tRTP_dmtf_pt_command {
U16 pt;
}RTP_DTMF_PT_COMMAND, *PRTP_DTMF_PT_COMMAND;
#if !defined(COMCERTO_2000) || defined(COMCERTO_2000_CONTROL)
extern struct _trtpqos_entry rtpqos_cache[MAX_RTP_STATS_ENTRY];
#else
extern PVOID rtpqos_cache[MAX_RTP_STATS_ENTRY];
#endif
extern U8 gDTMF_PT[2];
#if !defined(COMCERTO_2000) || defined(COMCERTO_2000_CONTROL)
extern struct slist_head rtpflow_cache[];
extern struct slist_head rtpcall_cache;
#else
extern PVOID rtpflow_cache[];
#endif
void RTP_compute_stats(PMetadata mtd, udp_hdr_t *pUdpHdr, rtp_hdr_t *pRtpHeader, u8 slot);
void RTP_clear_stats(PRTCPStats pStats, U8 type);
#if !defined(COMCERTO_2000) || defined(COMCERTO_2000_CONTROL)
int rtpqos_ipv4_link_stats_entry_by_tuple(PCtEntry pClient, U32 saddr, U32 daddr, U16 sport, U16 dport);
int rtpqos_ipv6_link_stats_entry_by_tuple(PCtEntryIPv6 pClient, U32 *saddr, U32 *daddr, U16 sport, U16 dport);
int rtpqos_mc4_link_stats_entry_by_tuple(PMC4Entry pClient, U32 saddr, U32 daddr);
int rtpqos_mc6_link_stats_entry_by_tuple(PMC6Entry pClient, U32 *saddr, U32 *daddr);
#endif
BOOL rtp_relay_init(void);
void rtp_relay_exit(void);
#if defined(COMCERTO_2000_UTIL)
#include "module_socket.h"
#include "util_dmem_storage.h"
void M_rtp_receive(PMetadata mtd);
void M_rtp_rx_handler(PMetadata mtd);
void M_rtp_qos_stats_handler(PMetadata mtd);
void RTP_tx_special_packet(PSockEntry pSocket, U8* rtpheader, U8* payload);
#else
void M_rtp_receive(PMetadata mtd) __attribute__((section ("fast_path")));
void M_rtp_entry(void) __attribute__((section ("fast_path")));
#endif
PRTPflow RTP_find_flow(U16 in_socket);
static __inline U32 HASH_RTP(U16 socketID)
{
return (((socketID & 0xff) ^ (socketID >> 8)) & (NUM_RTPFLOW_ENTRIES - 1));
}
static inline U32 x1000(U32 x)
{
U32 x125;
x125 = x + (x << 7) - (x << 2); // x + 128*x - 4*x => 125*x
return x125 << 3; // 8*(125*x) => 1000*x
}
#endif /* _MODULE_RTP_RELAY_H_ */