GPRS核心网-GTP-C协议解析

GPRS隧道协议(GTP)是3GPP标准定义的隧道协议,用于在3G /4G/5G网络中承载通用分组无线服务(GPRS)。

GTP用于在服务网关(S-GW)和分组数据网络网关(P-GW)以及S-GW和移动性管理实体(MME)之间为用户设备建立GTP隧道。如图-EPC架构:

GPRS核心网-GTP-C协议解析

GTP包含哪些单独的协议?

GTP包括在UDP / IP上传输的控制平面(GTP-C),用户平面(GTP-U)和计费(从GTP-C派生的GTP)流量。

GTP-C-在核心GPRS网络中的S-GW和P-GW之间执行信令,以激活和停用用户会话,调整服务质量参数或更新从另一个S-GW到达的漫游用户的会话。GTP-C支持以IPv4格式传输控制数据包。它用于各种EPC(演进的分组核心)信令接口,例如S5,S8和S11。还承载各种类型的控制平面信令消息。GTP-C端口号是2123。

GTP-U-在核心GPRS网络内以及在无线访问网络(RAN)和核心网络之间传输用户数据。GTP-U支持IPv4和IPv6用户数据,但传输是IPv4。它跨多个信令接口(例如S1,S5和S8)封装和路由用户平面流量。GTP-U消息是用户平面消息或信令消息。GTP-U端口号是2152。

什么是MME

MME是移动管理实体,是一个用于信令控制的网元,主要做移动的管理,此外还需要做会话相关的控制处理。

MME主要的功能是:

1、NAS信令处理
2、 3GPP内不同节点之间的移动性管理
3、PGW和SGW选择
4、漫游控制

什么是PGW

PGW是PDN网关,所谓PDN就是公共数据网,可以理解成核心网后端的网络系统,PDN负责用户数据包与其他网络的处理。

PGW功能描述:

1、基于用户包过滤
2、IP地址分配
3、上下行传输层数据包标记
4、上下行的承载绑定、校验。

什么是SGW

SGW是服务网关,它是数据面的网元,所谓数据面可以理解成数据传输的通道,负责本地网络用户数据的处理部分。

SGW功能描述

1、(基站)eNodeB之间的切换的本地
2、数据包路由和转发
3、上下行传输层数据包标记
4、用户和QCI力度的统计,主要用于运营商间计费
5、基于用户、PDN和QCI力度的上下行的计费。

EPC网元之间的接口

上面已经描述了MME、SGW、PGW。接下来介绍EPC协议围绕这三个网元之间的接口讲解。分别是eNodeB和MME之间的(S1-MME),eNodeB和SGW之间的(S1-U),MME和SGW之间的(S11),SGW和PGW之间的协议(S5)

GPRS核心网-GTP-C协议解析
S1-MME接口承载的协议是S1-AP/SCTP/IP,S1-U承载的协议是GTPv1-U,S5接口承载的协议是GTPv2-C。

GTPv2消息格式

各个版本的差异主要是协议功能,即传输的内容的差异,新版本一般来说比旧版本承载更多的信息。

控制平面GTP使用可变长度的标头。 控制平面GTP报头长度应为4个八位位组的倍数。
下面是GTPv2-C标头的格式。

GPRS核心网-GTP-C协议解析

Create Session Request
GPRS核心网-GTP-C协议解析

Create Session Response

GPRS核心网-GTP-C协议解析

对协议分析还原而言,知道如何识别,再知道如何解析协议格式,那么,就可以去实现解析了。

GTP消息类型

作为移动网络的协议,GTP当然是由3GPP组织来定义的,GTP v2参考3GPP TS 29.274,GTP v1参考3GPP TS 29.060。

#define GTPV2_IE_RESERVED                 0
#define GTPV2_IE_IMSI                     1
#define GTPV2_IE_CAUSE                    2
#define GTPV2_REC_REST_CNT                3
/*Start SRVCC Messages*/
#define GTPV2_IE_STN_SR                  51
#define GTPV2_IE_SRC_TGT_TRANS_CON       52
#define GTPV2_IE_TGT_SRC_TRANS_CON       53
#define GTPV2_IE_MM_CON_EUTRAN_SRVCC     54
#define GTPV2_IE_MM_CON_UTRAN_SRVCC      55
#define GTPV2_IE_SRVCC_CAUSE             56
#define GTPV2_IE_TGT_RNC_ID              57
#define GTPV2_IE_TGT_GLOGAL_CELL_ID      58
#define GTPV2_IE_TEID_C                  59
#define GTPV2_IE_SV_FLAGS                60
#define GTPV2_IE_SAI                     61
#define GTPV2_IE_MM_CTX_FOR_CS_TO_PS_SRVCC 62
/* 61 - 70 for future sv interface use*/
/*End SRVCC Messages*/
#define GTPV2_APN                        71
#define GTPV2_AMBR                       72
#define GTPV2_EBI                        73
#define GTPV2_IP_ADDRESS                 74
#define GTPV2_MEI                        75
#define GTPV2_IE_MSISDN                  76
#define GTPV2_INDICATION                 77
#define GTPV2_PCO                        78
#define GTPV2_PAA                        79
#define GTPV2_BEARER_QOS                 80
#define GTPV2_IE_FLOW_QOS                81
#define GTPV2_IE_RAT_TYPE                82
#define GTPV2_IE_SERV_NET                83
#define GTPV2_IE_BEARER_TFT              84
#define GTPV2_IE_TAD                     85
#define GTPV2_IE_ULI                     86
#define GTPV2_IE_F_TEID                  87
#define GTPV2_IE_TMSI                    88
#define GTPV2_IE_GLOBAL_CNID             89
#define GTPV2_IE_S103PDF                 90
#define GTPV2_IE_S1UDF                   91
#define GTPV2_IE_DEL_VAL                 92
#define GTPV2_IE_BEARER_CTX              93
#define GTPV2_IE_CHAR_ID                 94
#define GTPV2_IE_CHAR_CHAR               95
#define GTPV2_IE_TRA_INFO                96
#define GTPV2_BEARER_FLAG                97
/* define GTPV2_IE_PAGING_CAUSE          98 (void) */
#define GTPV2_IE_PDN_TYPE                99
#define GTPV2_IE_PTI                    100
#define GTPV2_IE_DRX_PARAM              101
#define GTPV2_IE_UE_NET_CAPABILITY      102
#define GTPV2_IE_MM_CONTEXT_GSM_T       103
#define GTPV2_IE_MM_CONTEXT_UTMS_CQ     104
#define GTPV2_IE_MM_CONTEXT_GSM_CQ      105
#define GTPV2_IE_MM_CONTEXT_UTMS_Q      106
#define GTPV2_IE_MM_CONTEXT_EPS_QQ      107
#define GTPV2_IE_MM_CONTEXT_UTMS_QQ     108
#define GTPV2_IE_PDN_CONNECTION         109
#define GTPV2_IE_PDN_NUMBERS            110
#define GTPV2_IE_P_TMSI                 111
#define GTPV2_IE_P_TMSI_SIG             112
#define GTPV2_IE_HOP_COUNTER            113
#define GTPV2_IE_UE_TIME_ZONE           114
#define GTPV2_IE_TRACE_REFERENCE        115
#define GTPV2_IE_COMPLETE_REQUEST_MSG   116
#define GTPV2_IE_GUTI                   117
#define GTPV2_IE_F_CONTAINER            118
#define GTPV2_IE_F_CAUSE                119
#define GTPV2_IE_SEL_PLMN_ID            120
#define GTPV2_IE_TARGET_ID              121
/* GTPV2_IE_NSAPI                       122 */
#define GTPV2_IE_PKT_FLOW_ID            123
#define GTPV2_IE_RAB_CONTEXT            124
#define GTPV2_IE_S_RNC_PDCP_CTX_INFO    125
#define GTPV2_IE_UDP_S_PORT_NR          126
#define GTPV2_IE_APN_RESTRICTION        127
#define GTPV2_IE_SEL_MODE               128
#define GTPV2_IE_SOURCE_IDENT           129
#define GTPV2_IE_BEARER_CONTROL_MODE    130
#define GTPV2_IE_CNG_REP_ACT            131
#define GTPV2_IE_FQ_CSID                132
#define GTPV2_IE_CHANNEL_NEEDED         133
#define GTPV2_IE_EMLPP_PRI              134
#define GTPV2_IE_NODE_TYPE              135
#define GTPV2_IE_FQDN                   136
#define GTPV2_IE_TI                     137
#define GTPV2_IE_MBMS_SESSION_DURATION  138
#define GTPV2_IE_MBMS_SERVICE_AREA      139
#define GTPV2_IE_MBMS_SESSION_ID        140
#define GTPV2_IE_MBMS_FLOW_ID           141
#define GTPV2_IE_MBMS_IP_MC_DIST        142
#define GTPV2_IE_MBMS_DIST_ACK          143
#define GTPV2_IE_RFSP_INDEX             144
#define GTPV2_IE_UCI                    145
#define GTPV2_IE_CSG_INFO_REP_ACTION    146
#define GTPV2_IE_CSG_ID                 147
#define GTPV2_IE_CMI                    148
#define GTPV2_IE_SERVICE_INDICATOR      149
#define GTPV2_IE_DETACH_TYPE            150
#define GTPV2_IE_LDN                    151
#define GTPV2_IE_NODE_FEATURES          152
#define GTPV2_IE_MBMS_TIME_TO_DATA_XFER 153
#define GTPV2_IE_THROTTLING             154
#define GTPV2_IE_ARP                    155
#define GTPV2_IE_EPC_TIMER              156
#define GTPV2_IE_SIG_PRIO_IND           157
#define GTPV2_IE_TMGI                   158
#define GTPV2_IE_ADD_MM_CONT_FOR_SRVCC  159
#define GTPV2_IE_ADD_FLAGS_FOR_SRVCC    160
#define GTPV2_IE_MMBR                   161
#define GTPV2_IE_MDT_CONFIG             162
#define GTPV2_IE_APCO                   163
#define GTPV2_IE_ABS_MBMS_DATA_TF_TIME  164
#define GTPV2_IE_HENB_INFO_REPORT       165
#define GTPV2_IE_IP4CP                  166
#define GTPV2_IE_CHANGE_TO_REPORT_FLAGS 167
#define GTPV2_IE_ACTION_INDICATION      168
#define GTPV2_IE_TWAN_IDENTIFIER        169
#define GTPV2_IE_ULI_TIMESTAMP          170
#define GTPV2_IE_MBMS_FLAGS             171
#define GTPV2_IE_RAN_NAS_CAUSE          172
#define GTPV2_IE_CN_OP_SEL_ENT          173
#define GTPV2_IE_TRUST_WLAN_MODE_IND    174
#define GTPV2_IE_NODE_NUMBER            175
#define GTPV2_IE_NODE_IDENTIFIER        176
#define GTPV2_IE_PRES_REP_AREA_ACT      177
#define GTPV2_IE_PRES_REP_AREA_INF      178
#define GTPV2_IE_TWAN_ID_TS             179
#define GTPV2_IE_OVERLOAD_CONTROL_INF   180
#define GTPV2_IE_LOAD_CONTROL_INF       181
#define GTPV2_IE_METRIC                 182
#define GTPV2_IE_SEQ_NO                 183
#define GTPV2_IE_APN_AND_REL_CAP        184
#define GTPV2_IE_WLAN_OFFLOADABILITY_IND 185
#define GTPV2_IE_PAGING_AND_SERVICE_INF 186
#define GTPV2_IE_INTEGER_NUMBER         187
#define GTPV2_IE_MILLISECOND_TS         188
#define GTPV2_IE_MON_EVENT_INF          189
/*
190    ECGI List
191    Remote UE Context
192    Remote User ID
193    Remote UE IP information
*/
#define GTPV2_IE_CIOT_OPT_SUPPORT_IND       194
#define GTPV2_IE_SCEF_PDN_CONNECTION        195
#define GTPV2_IE_HEADER_COMP_CONF           196
#define GTPV2_IE_EXTENDED_PCO               197
#define GTPV2_IE_SERV_PLMN_RATE_CONTROL     198
#define GTPV2_IE_COUNTER                    199
#define GTPV2_IE_MAPPED_UE_USAGE_TYPE                200
#define GTPV2_IE_SECONDARY_RAT_USAGE_DATA_REPORT     201
#define GTPV2_IE_UP_FUNC_SEL_INDI_FLG                202
#define GTPV2_IE_MAX_PKT_LOSS_RTE                    203
#define GTPV2_IE_APN_RTE_CNTRL_STATUS                204
#define GTPV2_IE_EXT_TRS_INF                         205
#define GTPV2_IE_MON_EVENT_EXT_INF                   206
/*
203 to 253    Spare. For future use.
254    Special IE type for IE Type Extension
255    Private Extension
256 to 65535    Spare. For future use.

*/
/* 169 to 254 reserved for future use */
#define GTPV2_IE_PRIVATE_EXT            255

GTP-C协议解析实现

下面主要对GTPv2协议的IMSI、TEID、MSISDN、用户IP进行解析。

struct gtpv2_hdr_t {
    u_int8_t flags;   /* GTP header flags */
    u_int8_t msg_type; /* Message type */
    u_int16_t length; /* Length of header */
    long teid;    /* Tunnel End-point ID */
};


static void dissect_gtpv2_ie_common(u_char *gtpv2_info, int offset,int package_len, u_int8_t message_type)
{
	u_int8_t    type = 0, instance = 0;
    u_int16_t     length = 0;
    int         i = 0, remaining_length = 0, msg_length = 0;
    /*
     * Octets   8   7   6   5       4   3   2   1
     *  1       Type
     *  2-3     Length = n
     *  4       CR          Spare   Instance
     * 5-(n+4)  IE specific data
     */
    msg_length = package_len;
	
	while (offset < msg_length)
	{
        /* Get the type and length */
        remaining_length = msg_length - offset;
        if (remaining_length < 3) {
			printf("Not enough data left for IE and length, %i bytes\n", remaining_length);
            return;
        }
        type    = gtpv2_info[offset];
		printf("IE Type: %d\n",type);
        length  = ntohs(*(uint16_t *)(gtpv2_info + offset + 1));
		printf("IE Length: %d\n",length);
        remaining_length = remaining_length -4;
        if (remaining_length < length) {
            printf("Less data left than indicated by length %u, remaining length %i \n", length, remaining_length);
            /* Octet 1 */
            offset += 1;

            /*Octet 2 - 3 */
            return;
        }
        /* type */
        offset += 1;

        /*Length */
        offset += 2; 


		instance = gtpv2_info[offset]&0x0f;
		printf("instance: %d\n",instance);
		
		/*instance*/
        offset += 1; 

        /* TODO: call IE dissector here */
        if (type == GTPV2_IE_RESERVED) {
            /* Treat IE type zero specal as type zero is used to end the loop in the else branch */

        } 
		else 
		{

            /* Loop over the IE dissector list to se if we find an entry;
               the last entry will have ie_type=0 breaking the loop */
			   
			   switch(type)
			   {
				case GTPV2_IE_IMSI:
				{
					uint8_t *imsi = (uint8_t*)malloc(length+1);
					if (imsi == NULL)
					{
						return ;
					}							
					memcpy(imsi, gtpv2_info + offset,length);
					//imsi[length] = '\0';
						
					printf("IMSI: ");
					for(i=0; i < length; i++)
						printf("%.2x ",imsi[i]);

					printf("\n");
				}
				break;
				
				case GTPV2_IE_MSISDN:
				{
					
					uint8_t *msisdn = (uint8_t*)malloc(length+1);
					if (msisdn == NULL)
					{
						return ;
					}
					
					memcpy(msisdn, gtpv2_info + offset + 1,length);
					//msisdn[length] = '\0';
						
					printf("MSISDN: ");
					for(i=0; i < length; i++)
						printf("%.2x ",msisdn[i]);

					printf("\n");
					
				}
				break;
				
				case GTPV2_IE_F_TEID:
				{
					//user ip
					uint32_t user_ipv4;
					
					uint8_t *teid = (uint8_t*)malloc(length+1);
					if (teid == NULL)
					{
						return ;
					}
					
					memcpy(&user_ipv4, gtpv2_info + offset + 1 + 4,length);		
					
					printf("F-TEID IPv4: %s\n",int_ntoa(user_ipv4));
					
				}
				break;

				default:            

				break;		
		
				   
			   }

        }

        offset += length;
		
	}
	
	
}

static int dissect_gtpv2(u_char *gtpv2_info,int PayloadLen)
{
	struct gtpv2_hdr_t gtpv2_hdr;
	int         offset = 0;
	//gtpv2_hdr->teid = -1;
	u_int8_t  message_type, t_flag, p_flag, mp_flag, cause_aux;
	u_int8_t  version = 0;
	int package_len = PayloadLen;
	memset(&gtpv2_hdr, 0, sizeof(struct gtpv2_hdr_t));
	
	
	/* Setting the TEID to -1 to say that the TEID is not valid for this packet */

	
	version = gtpv2_info[0] >> 5;
	printf("version: %d\n",version);
	if (version != 2)
		return 0;
	
	p_flag  = (gtpv2_info[0] & 0x10) >> 4;
    t_flag  = (gtpv2_info[0] & 0x08) >> 3;
    mp_flag = (gtpv2_info[0] & 0x04) >> 2;
	//printf("p_flag: %d\n",p_flag);
	//printf("t_flag: %d\n",t_flag);
	//printf("mp_flag: %d\n",mp_flag);
	
	offset += 1;

    /* Octet 2 */
	message_type = gtpv2_info[offset];
    gtpv2_hdr.msg_type = message_type;
	printf("Message type: %d\n",gtpv2_hdr.msg_type);
    offset += 1;
    /* Octet 3 - 4 */
    gtpv2_hdr.length = ntohs(*(uint16_t*)(gtpv2_info + offset));
	printf("Message Length: %d\n",gtpv2_hdr.length);
	
	offset += 2;

    if (t_flag) 
	{
        /* Tunnel Endpoint Identifier 4 octets */
        gtpv2_hdr.teid = ntohl(*(long*)(gtpv2_info + offset));
		printf("Tunnel Endpoint Identifier: %ld\n",gtpv2_hdr.teid);
        offset += 4;
    }
	
	/* Sequence Number 3 octets */
    offset += 3;
	
	 /* Spare 1 octet or if the "MP" flag is set to "1",
     * then bits 8 to 5 of octet 12 shall indicate the message priority.
     */
    if (mp_flag) 
	{
        /* Bits 8 to 5 of octet 12 shall be encoded as the binary value of the Message Priority
         * and it may take any value between 0 and 15, where 0 corresponds to the highest priority
         * and 15 the lowest priority.
         */
        
    }
	else
	{
        
    }
    offset += 1;
	
	if (p_flag)
	{
        
    } 
	else 
	{
        dissect_gtpv2_ie_common(gtpv2_info,offset, package_len,message_type);
    }
	
}


static void confirm_gtpv2_packet(struct ip *pIp)
{
	int iIpTotalLen = ntohs(pIp->ip_len);
	int offset = 0;
	int nFragSeq = 0;
	struct udphdr* pUdpHdr = (struct udphdr*)((char*)pIp + (pIp->ip_hl<<2));
	/*判断是否是gtpv2协议,gtpv2端口是514*/
	if (pIp->ip_p == IPPROTO_UDP && (ntohs(pUdpHdr->dest) == GTPv2C_PORT) || (ntohs(pUdpHdr->source) == GTPv2C_PORT) ) 
	{
		printf("\n");
		//printf("info udp\n");
		
		int iPayloadLen = iIpTotalLen - (pIp->ip_hl<<2) - 8;
		//printf("UDP Payload Len %d\n", iPayloadLen);
		
		u_char *pGtpV2Hdr = (u_char*)(pUdpHdr+1);
		dissect_gtpv2(pGtpV2Hdr,iPayloadLen);
		
	}	
}

编译运行:

GPRS核心网-GTP-C协议解析

总结

在LTE中,GTP(GPRS隧道协议)隧道用于通过基于GTP的接口进行通信的两个节点之间,以将流量分离为不同的通信流。

通过TEID(隧道端点标识符),IP地址和UDP端口号在每个节点中标识GTP隧道。

GTP隧道的接收端在本地分配发送方必须使用的TEID值。GTPv2包括一个更新的控制平面,该控制平面使控制消息能够在MME,S-GW,PDN GW等之间传递。最后,对于具体协议的实现,请参考3gpp相关的资料。

参考:
TS 29.281
TS 29.060

欢迎关注微信公众号【程序猿编码】,欢迎添加本人微信号(17865354792),交个朋友,咱们一起学习进步!

上一篇:茶树变身“脱贫树”,春季茶园管理,茶园土壤墒情监测系统


下一篇:无线传感器数据采集传输系统的三种组网应用方式