diff --git a/lib/include/srslte/upper/gtpu.h b/lib/include/srslte/upper/gtpu.h index 55c8189cc..5cb0ed8ce 100644 --- a/lib/include/srslte/upper/gtpu.h +++ b/lib/include/srslte/upper/gtpu.h @@ -40,22 +40,54 @@ namespace srslte { * | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | * * 1 | Version |PT | * | E | S |PN | - * 2 | Message Type | - * 3 | Length (1st Octet) | - * 4 | Length (2nd Octet) | - * 5 | TEID (1st Octet) | - * 6 | TEID (2nd Octet) | - * 7 | TEID (3rd Octet) | - * 8 | TEID (4th Octet) | + * 2 | Message Type | + * 3 | Length (1st Octet) | + * 4 | Length (2nd Octet) | + * 5 | TEID (1st Octet) | + * 6 | TEID (2nd Octet) | + * 7 | TEID (3rd Octet) | + * 8 | TEID (4th Octet) | + * 9 | Seq Number (1st Octet) | + * 10 | Seq Number (2st Octet) | + * 11 | N-PDU | + * 12 | Next Extension Header Type | ***************************************************************************/ -#define GTPU_HEADER_LEN 8 +#define GTPU_BASE_HEADER_LEN 8 +#define GTPU_EXTENDED_HEADER_LEN 12 + +#define GTPU_VERSION_V1 1 + +#define GTP_PRIME_PROTO 0 +#define GTP_PROTO 1 + +#define GTPU_MSG_ECHO_REQUEST 0 +#define GTPU_MSG_ECHO_RESPONSE 1 +#define GTPU_MSG_ERROR_INDICATION 26 +#define GTPU_MSG_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION 31 +#define GTPU_MSG_END_MARKER 254 +#define GTPU_MSG_DATA_PDU 255 + +typedef struct{ + uint8_t version : 3; + uint8_t protocol_type : 1; + uint8_t star : 1; + uint8_t ext_header :1; + uint8_t sequence :1; + uint8_t pkt_number :1; +}gtpu_flags_t; typedef struct{ - uint8_t flags; + union{ + gtpu_flags_t flag_bits; + uint8_t flags; + } gtpu_flags; uint8_t message_type; uint16_t length; uint32_t teid; + uint16_t seq_number; + uint8_t n_pdu; + uint8_t next_ext_hdr_type; }gtpu_header_t; diff --git a/lib/src/upper/gtpu.cc b/lib/src/upper/gtpu.cc index a8046aa4d..54ecdf6fc 100644 --- a/lib/src/upper/gtpu.cc +++ b/lib/src/upper/gtpu.cc @@ -37,21 +37,30 @@ namespace srslte { bool gtpu_write_header(gtpu_header_t *header, srslte::byte_buffer_t *pdu, srslte::log *gtpu_log) { - if(header->flags != 0x30) { - gtpu_log->error("gtpu_write_header - Unhandled header flags: 0x%x\n", header->flags); + + if(header->flags.version != GTPU_VERSION_V1) { + gtpu_log->error("gtpu_write_header - Unhandled GTP-U Version.\n"); + return false; + } + if(header->flags.protocol_type != GTP_PROTO) { + gtpu_log->error("gtpu_write_header - Unhandled Protocol Type.\n"); + return false; + } + if(header->flags.ext_header) { + gtpu_log->error("gtpu_write_header - Unhandled Header Extensions.\n"); return false; } - if(header->message_type != 0xFF) { + if(header->message_type != GTPU_MSG_DATA_PDU) { gtpu_log->error("gtpu_write_header - Unhandled message type: 0x%x\n", header->message_type); return false; } - if(pdu->get_headroom() < GTPU_HEADER_LEN) { + if(pdu->get_headroom() < GTPU_BASE_HEADER_LEN) { gtpu_log->error("gtpu_write_header - No room in PDU for header\n"); return false; } - pdu->msg -= GTPU_HEADER_LEN; - pdu->N_bytes += GTPU_HEADER_LEN; + pdu->msg -= GTPU_BASE_HEADER_LEN; + pdu->N_bytes += GTPU_BASE_HEADER_LEN; uint8_t *ptr = pdu->msg; @@ -70,22 +79,50 @@ bool gtpu_read_header(srslte::byte_buffer_t *pdu, gtpu_header_t *header, srslte: { uint8_t *ptr = pdu->msg; - pdu->msg += GTPU_HEADER_LEN; - pdu->N_bytes -= GTPU_HEADER_LEN; - - header->flags = *ptr; + header->flags = *ptr; ptr++; - header->message_type = *ptr; + header->message_type = *ptr; ptr++; uint8_to_uint16(ptr, &header->length); ptr += 2; uint8_to_uint32(ptr, &header->teid); - if(header->flags != 0x30) { - gtpu_log->error("gtpu_read_header - Unhandled header flags: 0x%x\n", header->flags); + if(header->gtpu_flags.flag_bits.version != GTPU_VERSION_V1) { + gtpu_log->error("gtpu_read_header - Unhandled GTP-U version. Flags: 0x%x\n", header->gtpu_flags.flags); + return false; + } + if(header->gtpu_flags.flag_bits.protocol_type != GTP_PROTO) { + gtpu_log->error("gtpu_read_header - Unhandled GTP Protocol. Flags: 0x%x\n", header->gtpu_flags.flags); + return false; + } + if(header->gtpu_flags.flag_bits.ext_header) { + gtpu_log->error("gtpu_read_header - Unhandled GTP-U Header Extensions. Flags: 0x%x\n", header->gtpu_flags.flags); return false; } - if(header->message_type != 0xFF) { + + //If E, S or PN are set, header is longer + if(header->gtpu_flags.flag_bits.sequence || header->gtpu_flags.flag_bits.ext_header || header->gtpu_flags.flag_bits.ext_header) { + pdu->msg += GTPU_EXTENDED_HEADER_LEN; + pdu->N_bytes -= GTPU_EXTENDED_HEADER_LEN; + + uint8_to_uint16(ptr, &header->seq_number); + ptr+=2; + + header->n_pdu = *ptr; + ptr++; + + header->next_ext_hdr_type = *ptr; + ptr++; + } else { + pdu->msg += GTPU_BASE_HEADER_LEN; + pdu->N_bytes -= GTPU_BASE_HEADER_LEN; + } + + if(header->gtpu_flags.flag_bits.sequence){ + ptr+=2; + } + + if(header->message_type != GTPU_MSG_DATA_PDU || header->message_type != GTPU_MSG_ECHO_REQUEST) { gtpu_log->error("gtpu_read_header - Unhandled message type: 0x%x\n", header->message_type); return false; } diff --git a/srsenb/src/upper/gtpu.cc b/srsenb/src/upper/gtpu.cc index 777943125..62855ff5f 100644 --- a/srsenb/src/upper/gtpu.cc +++ b/srsenb/src/upper/gtpu.cc @@ -122,8 +122,10 @@ void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* pdu) { gtpu_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU, RNTI: 0x%x, LCID: %d, n_bytes=%d", rnti, lcid, pdu->N_bytes); gtpu_header_t header; - header.flags = 0x30; - header.message_type = 0xFF; + bzero(&header,sizeof(header)); + header.flags.version = GTPU_VERSION_V1; + header.flags.protocol_type = GTP_PROTO; + header.message_type = GTPU_MSG_DATA_PDU; header.length = pdu->N_bytes; header.teid = rnti_bearers[rnti].teids_out[lcid]; @@ -224,48 +226,50 @@ void gtpu::run_thread() pdu->N_bytes = (uint32_t) n; - if(pdu->msg[1] == 0x01) { - if(n<10) { - continue; - } - // Echo request - send response - uint16_t seq = 0; - uint8_to_uint16(&pdu->msg[8], &seq); - echo_response(client.sin_addr.s_addr, client.sin_port, seq); - - }else{ - gtpu_header_t header; - gtpu_read_header(pdu, &header,gtpu_log); - - uint16_t rnti = 0; - uint16_t lcid = 0; - teidin_to_rntilcid(header.teid, &rnti, &lcid); - - pthread_mutex_lock(&mutex); - bool user_exists = (rnti_bearers.count(rnti) > 0); - pthread_mutex_unlock(&mutex); - - if(!user_exists) { - gtpu_log->error("Unrecognized RNTI for DL PDU: 0x%x - dropping packet\n", rnti); - continue; - } + gtpu_header_t header; + if(!gtpu_read_header(pdu, &header,gtpu_log)){ + continue; + } - if(lcid < SRSENB_N_SRB || lcid >= SRSENB_N_RADIO_BEARERS) { - gtpu_log->error("Invalid LCID for DL PDU: %d - dropping packet\n", lcid); - continue; - } + switch(header.message_type) { + + case GTPU_MSG_ECHO_REQUEST: + // Echo request - send response + echo_response(client.sin_addr.s_addr, client.sin_port, header.seq_number); + break; - gtpu_log->info_hex(pdu->msg, pdu->N_bytes, "RX GTPU PDU rnti=0x%x, lcid=%d, n_bytes=%d", rnti, lcid, pdu->N_bytes); + case GTPU_MSG_DATA_PDU: - pdcp->write_sdu(rnti, lcid, pdu); + uint16_t rnti = 0; + uint16_t lcid = 0; + teidin_to_rntilcid(header.teid, &rnti, &lcid); - do { - pdu = pool_allocate; - if (!pdu) { - gtpu_log->console("GTPU Buffer pool empty. Trying again...\n"); - usleep(10000); + pthread_mutex_lock(&mutex); + bool user_exists = (rnti_bearers.count(rnti) > 0); + pthread_mutex_unlock(&mutex); + + if(!user_exists) { + gtpu_log->error("Unrecognized RNTI for DL PDU: 0x%x - dropping packet\n", rnti); + continue; } - } while(!pdu); + + if(lcid < SRSENB_N_SRB || lcid >= SRSENB_N_RADIO_BEARERS) { + gtpu_log->error("Invalid LCID for DL PDU: %d - dropping packet\n", lcid); + continue; + } + + gtpu_log->info_hex(pdu->msg, pdu->N_bytes, "RX GTPU PDU rnti=0x%x, lcid=%d, n_bytes=%d", rnti, lcid, pdu->N_bytes); + + pdcp->write_sdu(rnti, lcid, pdu); + + do { + pdu = pool_allocate; + if (!pdu) { + gtpu_log->console("GTPU Buffer pool empty. Trying again...\n"); + usleep(10000); + } + } while(!pdu); + break; } } running = false; @@ -275,6 +279,14 @@ void gtpu::echo_response(in_addr_t addr, in_port_t port, uint16_t seq) { gtpu_log->info("TX GTPU Echo Response, Seq: %d\n", seq); + gtpu_header_t header; + bzero(&header, sizeof(header)); + + //flags + header.flags.version = GTPU_VERSION_V1; + header.flags.protocol_type = GTP_PROTO; + header.flags.sequence = 1; + uint8_t resp[12]; bzero(resp, 12); resp[0] = 0x32; //flags diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc index b373df4e7..03f08bcc6 100644 --- a/srsepc/src/mbms-gw/mbms-gw.cc +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -285,31 +285,30 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) { uint8_t version; srslte::gtpu_header_t header; + bzero(&header, sizeof(srslte::gtpu_header_t)); //Setup GTP-U header - header.flags = 0x30; - header.message_type = 0xFF; + header.flags.version = GTPU_VERSION_V1; + header.flags.protocol_type = GTP_PROTO; + header.message_type = GTPU_MSG_DATA_PDU; header.length = msg->N_bytes; header.teid = 0xAAAA; //FIXME Harcoded TEID for now //Sanity Check IP packet - if(msg->N_bytes < 20) - { + if (msg->N_bytes < 20) { m_mbms_gw_log->error("IPv4 min len: %d, drop msg len %d\n", 20, msg->N_bytes); return; } //IP Headers struct iphdr *iph = (struct iphdr *) msg->msg; - if(iph->version != 4) - { + if(iph->version != 4) { m_mbms_gw_log->warning("IPv6 not supported yet.\n"); return; } //Write GTP-U header into packet - if(!srslte::gtpu_write_header(&header, msg, m_mbms_gw_log)) - { + if (!srslte::gtpu_write_header(&header, msg, m_mbms_gw_log)) { m_mbms_gw_log->console("Error writing GTP-U header on PDU\n"); } diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 20311cc16..2c34e5da8 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -363,14 +363,15 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) //Setup GTP-U header srslte::gtpu_header_t header; - header.flags = 0x30; - header.message_type = 0xFF; + bzero(&header,sizeof(srslte::gtpu_header_t)); + header.flags.version = GTPU_VERSION_V1; + header.flags.protocol_type = GTP_PROTO; + header.message_type = GTPU_MSG_DATA_PDU; header.length = msg->N_bytes; header.teid = enb_fteid.teid; //Write header into packet - if(!srslte::gtpu_write_header(&header, msg, m_spgw_log)) - { + if (!srslte::gtpu_write_header(&header, msg, m_spgw_log)) { m_spgw_log->console("Error writing GTP-U header on PDU\n"); }