diff --git a/lib/src/common/pdu.cc b/lib/src/common/pdu.cc index 836e1716c..05c23a389 100644 --- a/lib/src/common/pdu.cc +++ b/lib/src/common/pdu.cc @@ -585,7 +585,7 @@ bool sch_subh::set_ta_cmd(uint8_t ta_cmd) bool sch_subh::set_next_mch_sched_info(uint8_t lcid_, uint16_t mtch_stop) { if (((sch_pdu*)parent)->has_space_ce(2, true)) { - w_payload_ce[nof_mch_sched_ce*2] = (lcid_&0x1F) << 3 | (uint8_t) (mtch_stop&0x0700)>>8 ; + w_payload_ce[nof_mch_sched_ce*2] = (lcid_&0x1F) << 3 | (uint8_t) ((mtch_stop&0x0700)>>8); w_payload_ce[nof_mch_sched_ce*2+1] = (uint8_t) (mtch_stop&0xff); nof_mch_sched_ce++; lcid = MCH_SCHED_INFO; diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 5c9656df2..32c71eafc 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -639,6 +639,7 @@ int mac::get_mch_sched(bool is_mcch, dl_sched_t *dl_sched_res) mch.pdu[i].lcid = srslte::sch_subh::MCH_SCHED_INFO; // mch.mtch_sched[i].lcid = 1+i; } + mch.pdu[mch.num_mtch_sched].lcid = 0; mch.pdu[mch.num_mtch_sched].nbytes = current_mcch_length; dl_sched_res->sched_grants[0].rnti = SRSLTE_MRNTI; diff --git a/srsenb/src/upper/gtpu.cc b/srsenb/src/upper/gtpu.cc index 58357e040..a5cde2c09 100644 --- a/srsenb/src/upper/gtpu.cc +++ b/srsenb/src/upper/gtpu.cc @@ -170,7 +170,6 @@ while(mch_run_enable) { pdu->N_bytes = (uint32_t) n; - printf("Bytes=%d\n",n); gtpu_header_t header; gtpu_read_header(pdu, &header); diff --git a/srsepc/hdr/mbms-gw/mbms-gw.h b/srsepc/hdr/mbms-gw/mbms-gw.h index 2b7daacbf..2beca7dcb 100644 --- a/srsepc/hdr/mbms-gw/mbms-gw.h +++ b/srsepc/hdr/mbms-gw/mbms-gw.h @@ -52,7 +52,14 @@ typedef struct { std::string m1u_multi_addr; } mbms_gw_args_t; - +struct pseudo_hdr +{ + uint32_t src_addr; + uint32_t dst_addr; + uint8_t placeholder; + uint8_t protocol; + uint16_t udp_len; +}; class mbms_gw: public thread @@ -73,8 +80,9 @@ private: srslte::error_t init_sgi_mb_if(mbms_gw_args_t *args); srslte::error_t init_m1_u(mbms_gw_args_t *args); - void handle_sgi_md_pdu(srslte::byte_buffer_t *msg); + uint16_t in_cksum(uint16_t *iphdr, int count); + /* Members */ bool m_running; srslte::byte_buffer_pool *m_pool; diff --git a/srsepc/mbms.conf.example b/srsepc/mbms.conf.example index a7f1a9fa3..393be7648 100644 --- a/srsepc/mbms.conf.example +++ b/srsepc/mbms.conf.example @@ -12,7 +12,7 @@ ##################################################################### [mbms_gw] name = srsmbmsgw01 -sgi_mb_if_addr = 172.16.0.254 +sgi_mb_if_addr = 172.16.1.1 m1u_multi_addr = 239.255.0.1 #################################################################### diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc index 81cd8225e..7893fce58 100644 --- a/srsepc/src/mbms-gw/mbms-gw.cc +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "srsepc/hdr/mbms-gw/mbms-gw.h" #include "srslte/upper/gtpu.h" @@ -195,7 +196,7 @@ mbms_gw::init_sgi_mb_if(mbms_gw_args_t *args) } ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.255"); + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); if (ioctl(sgi_mb_sock, SIOCSIFNETMASK, &ifr) < 0) { m_mbms_gw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); close(m_sgi_mb_if); @@ -285,6 +286,7 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) uint8_t version; srslte::gtpu_header_t header; in_addr_t baddr = inet_addr("172.16.0.255"); + in_addr_t saddr = inet_addr("172.16.0.254"); //Setup GTP-U header header.flags = 0x30; @@ -298,14 +300,45 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) m_mbms_gw_log->error("IPv4 min len: %d, drop msg len %d\n", 20, msg->N_bytes); return; } - version = msg->msg[0]>>4; - if(version !=4) + + //IP+UDP Headers + struct iphdr *iph = (struct iphdr *) msg->msg; + struct udphdr *udph = (struct udphdr *) (msg->msg + iph->ihl*4); + if(iph->version != 4) { m_mbms_gw_log->warning("IPv6 not supported yet.\n"); return; } + //Replace Destination IP with broadcast address - memcpy(&msg->msg[16],&baddr,4); + iph->daddr = baddr; + + //Replace Source IP with address in same subnet + iph->saddr = saddr; + + //Replace IP cheksum + iph->check = 0; + iph->check = in_cksum((uint16_t*)msg->msg,4*(msg->msg[0] & 0x0F)); + + //Set Pseudo Header + struct pseudo_hdr phdr; + phdr.src_addr = iph->saddr; + phdr.dst_addr = iph->daddr; + phdr.protocol = IPPROTO_UDP; + phdr.placeholder = 0; + phdr.udp_len = udph->len; + + //Set Pseudo Datagram + udph->check = 0; + int psize = sizeof(struct pseudo_hdr) + ntohs(udph->len); + uint8_t * pseudo_dgram = (uint8_t*) malloc(psize); + memcpy(pseudo_dgram, &phdr,sizeof(struct pseudo_hdr)); + memcpy(pseudo_dgram+sizeof(pseudo_hdr),udph,ntohs(udph->len)); + + //Recompute UDP checksum + udph->check = in_cksum((uint16_t*) pseudo_dgram, psize); + free(pseudo_dgram); + printf("UDP cksum %x",udph->check); //Write GTP-U header into packet if(!srslte::gtpu_write_header(&header, msg)) @@ -321,6 +354,33 @@ mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) else{ m_mbms_gw_log->console("Sent %d Bytes\n", msg->N_bytes); } +} + +uint16_t +mbms_gw::in_cksum(uint16_t *iphdr, int count) +{ + //RFC 1071 + uint32_t sum = 0; + uint16_t padd = 0; + uint16_t result; + while(count > 1) + { + sum+= *iphdr++; + count -= 2; + } + if( count > 0 ) + { + padd = * (uint8_t *) iphdr; + sum += padd; + } + /*Fold 32-bit sum to 16-bit*/ + // while(sum>>16) + // sum = (sum & 0xffff) + (sum >> 16); + sum = (sum>>16)+(sum & 0xFFFF); + sum = sum + (sum >> 16); + result = (uint16_t) ~sum; + return result; } + } //namespace srsepc diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 6cf2d4aa0..02aef933a 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -521,8 +521,10 @@ int main(int argc, char *argv[]) if (args.gui.enable) { ue->start_plot(); } - if(args.expert.mbms_service > -1){ - ue->mbms_service_start(args.expert.mbms_service, 4321); + if(args.expert.mbms_service > -1) { + serv = args.expert.mbms_service; + port = 14321; + mbms_service_start = true; } } int cnt=0;