diff --git a/openair-cn/SGI/sgi.h b/openair-cn/SGI/sgi.h index 80f58137319ac0426ee7b66d3db7dbbd80999a23..76cb3838ce07fb6b43117c0919dc278451c19ff2 100755 --- a/openair-cn/SGI/sgi.h +++ b/openair-cn/SGI/sgi.h @@ -40,6 +40,24 @@ #include <pthread.h> #include <stdio.h> +#ifdef ENABLE_USE_NETFILTER_FOR_SGI +#warning "ENABLE_USE_NETFILTER_FOR_SGI" +#define SGI_SOCKET_RAW 1 +#define SGI_SOCKET_BIND_TO_IF 1 +#undef SGI_MARKING +#undef SGI_PACKET_RX_RING +#undef SGI_SOCKET_UDP +#else +#warning "DISABLE_USE_NETFILTER_FOR_SGI" +//#define SGI_SOCKET_RAW 1 +#undef SGI_SOCKET_RAW +#define SGI_SOCKET_DGRAM 1 +#define SGI_SOCKET_BIND_TO_IF 1 +#undef SGI_PACKET_RX_RING +#undef SGI_MARKING +#undef SGI_SOCKET_UDP +#endif + #ifdef ENABLE_USE_PCAP_FOR_SGI #include <pcap.h> #endif @@ -167,6 +185,7 @@ typedef struct sgi_addr_mapping_s { typedef struct sgi_data_s { int sd[SGI_MAX_EPS_BEARERS_PER_USER]; + unsigned int if_index[SGI_MAX_EPS_BEARERS_PER_USER]; int sd6; char *interface_name; int interface_name_len; @@ -261,6 +280,8 @@ void sgi_send_arp_request(sgi_data_t *sgi_dataP, char* dst_ip_addrP); //----------------------------------------------------------------------------- int sgi_create_sockets(sgi_data_t *sgi_data_p); int sgi_send_data(uint8_t *buffer, uint32_t length, sgi_data_t *sgi_dataP, Teid_t originating_sgw_S1u_teidP); +int sgi_dgram_send_data(uint8_t *buffer_pP, uint32_t length, sgi_data_t *sgi_data_pP, Teid_t originating_sgw_S1u_teidP); + #ifdef SGI_TEST unsigned short in_cksum(unsigned short *addr, int len); void sgi_test_send_ping(sgi_data_t *sgi_dataP, uint32_t markP, uint64_t src_mac_addrP, uint64_t dst_mac_addrP, char* src_ip_addrP, char* dst_ip_addrP); @@ -277,4 +298,5 @@ void sgi_forward_ip_packet(sgi_data_t *sgi_dataP, struct ether_header *ehP, int #ifdef ENABLE_USE_RAW_SOCKET_FOR_SGI void sgi_process_raw_packet(sgi_data_t *sgi_dataP, unsigned char* dataP, int packet_sizeP); #endif +void sgi_process_dgram_packet(sgi_data_t *sgi_dataP, unsigned char* dataP, int packet_sizeP); #endif /* SGI_H_ */ diff --git a/openair-cn/SGI/sgi_egress.c b/openair-cn/SGI/sgi_egress.c index 01bdecace1a8badb3ab19c20dd0ab9beeeee2761..5a96258f593ce9df1def7079f963bdc62020ee88 100755 --- a/openair-cn/SGI/sgi_egress.c +++ b/openair-cn/SGI/sgi_egress.c @@ -350,3 +350,50 @@ void sgi_process_raw_packet(sgi_data_t *sgi_data_pP, unsigned char* data_pP, int } #endif #endif +void sgi_process_dgram_packet(sgi_data_t *sgi_data_pP, unsigned char* data_pP, int packet_sizeP) +{ + Gtpv1uTunnelDataReq *gtpv1u_tunnel_data_req_p = NULL; + MessageDef *message_p = NULL; + unsigned char *message_payload_p = NULL ; + struct arphdr *arph_p = NULL; + struct iphdr *iph_p = NULL; + struct ipv6hdr *ip6h_p = NULL; + sgi_addr_mapping_t *addr_mapping_p = NULL; + struct in6_addr dest6_addr; + u_int32_t dest4_addr; + u_int32_t src4_addr; + struct in_addr in_dest_addr; + + sgi_print_hex_octets(data_pP, packet_sizeP); + + return; + message_p = itti_alloc_new_message(TASK_FW_IP, GTPV1U_TUNNEL_DATA_REQ); + if (message_p == NULL) { + SGI_IF_ERROR("%s OUT OF MEMORY DROP EGRESS PACKET\n", __FUNCTION__); + return; + } + AssertFatal(packet_sizeP > 20, "BAD IP PACKET SIZE"); + message_payload_p = itti_malloc(TASK_FW_IP, TASK_GTPV1_U, packet_sizeP + GTPU_HEADER_OVERHEAD_MAX); + if (message_payload_p == NULL) { + SGI_IF_ERROR("%s OUT OF MEMORY DROP EGRESS PACKET\n", __FUNCTION__); + return; + } + memcpy(message_payload_p + GTPU_HEADER_OVERHEAD_MAX, data_pP, packet_sizeP); + + gtpv1u_tunnel_data_req_p = &message_p->ittiMsg.gtpv1uTunnelDataReq; + gtpv1u_tunnel_data_req_p->S1u_enb_teid = addr_mapping_p->enb_S1U_teid; +//#warning forced S1u_enb_teid to 1 for testing, waiting for MODIFY_BEARER REQUEST +// gtpv1u_tunnel_data_req_p->S1u_enb_teid = 1; + gtpv1u_tunnel_data_req_p->local_S1u_teid = addr_mapping_p->sgw_S1U_teid; + gtpv1u_tunnel_data_req_p->length = packet_sizeP ; + gtpv1u_tunnel_data_req_p->offset = GTPU_HEADER_OVERHEAD_MAX; + gtpv1u_tunnel_data_req_p->buffer = message_payload_p; + SGI_IF_DEBUG("%s send GTPV1U_TUNNEL_DATA_REQ to GTPV1U S1u_enb_teid %u local_S1u_teid %u size %u\n", + __FUNCTION__, + gtpv1u_tunnel_data_req_p->S1u_enb_teid, + gtpv1u_tunnel_data_req_p->local_S1u_teid, + gtpv1u_tunnel_data_req_p->length); + + itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); + +} diff --git a/openair-cn/SGI/sgi_socket.c b/openair-cn/SGI/sgi_socket.c index dfcad2a646ae3e3370e08ef69d5e1259fc6a98db..5c282a57d54bde252f4f68b3f5a4706955723472 100644 --- a/openair-cn/SGI/sgi_socket.c +++ b/openair-cn/SGI/sgi_socket.c @@ -65,22 +65,6 @@ #include "sgi.h" #include "intertask_interface.h" -#ifdef ENABLE_USE_NETFILTER_FOR_SGI -#warning "ENABLE_USE_NETFILTER_FOR_SGI" -#define SGI_SOCKET_RAW 1 -#define SGI_SOCKET_BIND_TO_IF 1 -#undef SGI_MARKING -#undef SGI_PACKET_RX_RING -#undef SGI_SOCKET_UDP -#else -#warning "DISABLE_USE_NETFILTER_FOR_SGI" -#define SGI_SOCKET_RAW 1 -#define SGI_SOCKET_BIND_TO_IF 1 -#undef SGI_PACKET_RX_RING -#undef SGI_MARKING -#undef SGI_SOCKET_UDP -#endif - //static char sgi_command_buffer[256]; @@ -144,8 +128,8 @@ int sgi_create_vlan_interface(char *interface_nameP, int vlan_idP) { ret = sprintf(command_line, "sync"); if (ret > 0) ret = system(command_line); else return -1; - ret = sprintf(command_line, "ip -4 addr add 10.0.%d.2/24 dev %s", vlan_idP+200, vlan_interface_name); - if (ret > 0) ret = system(command_line); else return -1; + //ret = sprintf(command_line, "ip -4 addr add 10.0.%d.2/24 dev %s", vlan_idP+200, vlan_interface_name); + //if (ret > 0) ret = system(command_line); else return -1; return 0; } else { return -1; @@ -185,15 +169,19 @@ int sgi_create_sockets(sgi_data_t *sgi_data_p) // qci = 0 is for the default bearers QOS, Non-GBR /* Create a RAW IP socket and request for all internet IP traffic */ // work -//#define SGI_SOCKET_RAW for (i = 0; i < SGI_MAX_EPS_BEARERS_PER_USER; i++) { - sgi_create_vlan_interface(sgi_data_p->interface_name,i+SGI_MIN_EPS_BEARER_ID); - //sgi_data_p->sd[i] = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // works also +#if defined SGI_SOCKET_RAW sgi_data_p->sd[i] = socket(PF_PACKET, SOCK_RAW, htons(IPPROTO_RAW)); +#else +#if defined SGI_SOCKET_DGRAM + SGI_IF_DEBUG("Created socket PF_PACKET/SOCK_DGRAM/ETH_P_ALL\n",strerror(errno), errno); + sgi_data_p->sd[i] = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); +#endif +#endif //sgi_data_p->sd[i] = socket(AF_INET, SOCK_RAW, ETH_P_IP); //sgi_data_p->sd[i] = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); @@ -255,7 +243,7 @@ int sgi_create_sockets(sgi_data_t *sgi_data_p) sprintf(if_name, "%s.%d",sgi_data_p->interface_name,i+SGI_MIN_EPS_BEARER_ID); memset(&socket_address, 0, sizeof(struct sockaddr_ll)); - socket_address.sll_family = PF_PACKET; //always PF_PACKET + socket_address.sll_family = AF_PACKET; //always PF_PACKET //socket_address.sll_addr = ;// Filled when we want to tx //socket_address.sll_halen = ;// Filled when we want to tx @@ -263,9 +251,10 @@ int sgi_create_sockets(sgi_data_t *sgi_data_p) //socket_address.sll_hatype = ;// Filled when packet received //socket_address.sll_pkttype = ;// Filled when packet received - socket_address.sll_ifindex = if_nametoindex(if_name); - socket_address.sll_protocol = htons(ETH_P_IP);/* Protocol phy level */ - //socket_address.sll_protocol = htons(ETH_P_ALL); + sgi_data_p->if_index[i] = if_nametoindex(if_name); + socket_address.sll_ifindex = sgi_data_p->if_index[i]; + //LG 2014-11-07socket_address.sll_protocol = htons(ETH_P_IP);/* Protocol phy level */ + socket_address.sll_protocol = htons(ETH_P_ALL); // Now we can bind the socket to send the IP traffic if (bind(sgi_data_p->sd[i], (struct sockaddr *)&socket_address, sizeof(struct sockaddr_ll)) < 0) { @@ -279,7 +268,7 @@ int sgi_create_sockets(sgi_data_t *sgi_data_p) } -#ifndef SGI_UE_ETHER_TRAFFIC +#ifndef SGI_SOCKET_DGRAM if (sprintf(filename, "/sys/class/net/%s/address", sgi_data_p->interface_name) <= 0 ) { SGI_IF_ERROR("Build of file name /sys/class/net/sgi_if_name/address Failed (%s:%d)\n", strerror(errno), errno); goto error; @@ -633,6 +622,130 @@ int sgi_send_data(uint8_t *buffer_pP, uint32_t length, sgi_data_t *sgi_data_pP, } #endif +int sgi_dgram_send_data(uint8_t *buffer_pP, uint32_t length, sgi_data_t *sgi_data_pP, Teid_t originating_sgw_S1u_teidP) +{ + struct iphdr *iph_p = (struct iphdr *) buffer_pP; + struct ipv6hdr *ip6h_p = (struct ipv6hdr *) buffer_pP; + sgi_teid_mapping_t *mapping_p = NULL; + sgi_addr_mapping_t *addr_mapping_p = NULL; + hashtable_rc_t hash_rc; + struct in6_addr src6_addr; /* source address */ + struct in6_addr *src6_addr_p; /* source address */ + u_int32_t src4_addr; + + struct sockaddr_ll device; + + if (buffer_pP == NULL) { + SGI_IF_ERROR("sgi_send_data: received bad parameter\n"); + return -1; + } + + // get IP version of this packet + switch (iph_p->version) { + + //******************* + case 4: + //******************* + // The entry should be here but all signalling tied with RRC procedures not finished so + // a data packet can arrive before the MODIFY_BEARER REQUEST + sgi_data_pP->eh.ether_type = htons(ETHERTYPE_IP); + src4_addr = iph_p->saddr; + if (hashtable_get(sgi_data_pP->addr_v4_mapping, src4_addr, (void**)&addr_mapping_p) != HASH_TABLE_OK) { + hash_rc = hashtable_get(sgi_data_pP->teid_mapping, originating_sgw_S1u_teidP, (void**)&mapping_p); + if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { + SGI_IF_ERROR("%s Error unknown context SGW teid %d\n", __FUNCTION__, originating_sgw_S1u_teidP); + return -1; + } else { + if (mapping_p->is_outgoing_ipv4_packet_seen == 0) { + mapping_p->hw_addrlen = 0; // TO DO + mapping_p->is_outgoing_ipv4_packet_seen = 1; + mapping_p->in_add_captured.s_addr = src4_addr; + + addr_mapping_p = calloc(1, sizeof(sgi_addr_mapping_t)); + addr_mapping_p->is_outgoing_packet_seen = 1; + addr_mapping_p->enb_S1U_teid = mapping_p->enb_S1U_teid; + addr_mapping_p->sgw_S1U_teid = originating_sgw_S1u_teidP; + hashtable_insert(sgi_data_pP->addr_v4_mapping, src4_addr, (void*)addr_mapping_p); + SGI_IF_DEBUG("%s ASSOCIATED %d.%d.%d.%d to teid %d\n", + __FUNCTION__, NIPADDR(src4_addr), originating_sgw_S1u_teidP); + } else { + SGI_IF_ERROR("Error IPv4 address already registered for teid %d\n", originating_sgw_S1u_teidP); + return -1; + } + } + } else { + hash_rc = hashtable_get(sgi_data_pP->teid_mapping, originating_sgw_S1u_teidP, (void**)&mapping_p); + } + break; + + + + //******************* + case 6: + sgi_data_pP->eh.ether_type = htons(ETHERTYPE_IPV6); + if (obj_hashtable_get(sgi_data_pP->addr_v6_mapping, &src6_addr, sizeof(struct in6_addr), (void**)&addr_mapping_p) != HASH_TABLE_OK) { + hash_rc = hashtable_get(sgi_data_pP->teid_mapping, originating_sgw_S1u_teidP, (void**)&mapping_p); + if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { + SGI_IF_ERROR("%s Error unknown context SGW teid %d\n", __FUNCTION__, originating_sgw_S1u_teidP); + return -1; + } else { + + if (mapping_p->is_outgoing_ipv6_packet_seen < MAX_DEFINED_IPV6_ADDRESSES_PER_UE) { + mapping_p->hw_addrlen = 0; + + memcpy(&mapping_p->in6_addr_captured[mapping_p->is_outgoing_ipv6_packet_seen].s6_addr, src6_addr.s6_addr, 16); + mapping_p->is_outgoing_ipv6_packet_seen +=1; + + addr_mapping_p = calloc(1, sizeof(sgi_addr_mapping_t)); + addr_mapping_p->is_outgoing_packet_seen = 1; + addr_mapping_p->enb_S1U_teid = mapping_p->enb_S1U_teid; + addr_mapping_p->sgw_S1U_teid = originating_sgw_S1u_teidP; + + src6_addr_p = malloc(sizeof(struct in6_addr)); + if (src6_addr_p == NULL) { + return -1; + } + memcpy(src6_addr_p->s6_addr, ip6h_p->saddr.s6_addr, 16); + obj_hashtable_insert(sgi_data_pP->addr_v6_mapping, src6_addr_p,sizeof(struct in6_addr), (void*)addr_mapping_p); + } else { + SGI_IF_ERROR("Error TOO MANY IPv6 address already registered for teid %d\n", originating_sgw_S1u_teidP); + return -1; + } + } + + } else { + hash_rc = hashtable_get(sgi_data_pP->teid_mapping, originating_sgw_S1u_teidP, (void**)&mapping_p); + } + break; + + default: + SGI_IF_WARNING("%s UNHANDLED IP VERSION: %X\n", __FUNCTION__, iph_p->version); + break; + } + memset(&device, 0, sizeof(device)); + device.sll_family = AF_PACKET; + device.sll_protocol = htons(ETH_P_ALL); + device.sll_ifindex = sgi_data_pP->if_index[mapping_p->eps_bearer_id - SGI_MIN_EPS_BEARER_ID]; + + + if (sendto(sgi_data_pP->sd[mapping_p->eps_bearer_id - SGI_MIN_EPS_BEARER_ID], + buffer_pP, + length, + 0, + (struct sockaddr *) &device, + sizeof (device)) < 0) { + SGI_IF_ERROR("%d Error during send to socket %d bearer id %d : (%s:%d)\n", + __LINE__, + sgi_data_pP->sd[mapping_p->eps_bearer_id - SGI_MIN_EPS_BEARER_ID], + mapping_p->eps_bearer_id, + strerror(errno), + errno); + return -1; + } + + + return 0; +} #ifdef SGI_TEST #include <stdio.h> @@ -836,7 +949,13 @@ void* sgi_sock_raw_fw_2_gtpv1u_thread(void* args_p) num_bytes = recvfrom(sgi_data_p->sd[socket_index], &sgi_data_p->recv_buffer[0][socket_index], SGI_BUFFER_RECV_LEN, 0, NULL, NULL); if (num_bytes > 0) { SGI_IF_DEBUG("recvfrom bearer id %d %d bytes\n", socket_index + SGI_MIN_EPS_BEARER_ID, num_bytes); +#ifdef SGI_SOCKET_RAW sgi_process_raw_packet(sgi_data_p, &sgi_data_p->recv_buffer[0][socket_index], num_bytes); +#else +#ifdef SGI_SOCKET_DGRAM + sgi_process_dgram_packet(sgi_data_p, &sgi_data_p->recv_buffer[0][socket_index], num_bytes); +#endif +#endif } else { SGI_IF_DEBUG("recvfrom bearer id %d %d (%s:%d)\n", socket_index + SGI_MIN_EPS_BEARER_ID, num_bytes, strerror(errno), errno); } diff --git a/openair-cn/SGI/sgi_task.c b/openair-cn/SGI/sgi_task.c index d70a8d300cbeb7a578aa88d1e1e0f1d90b53e073..9b66b4b1ee8e8bd9bcb49338d485a64037887f44 100644 --- a/openair-cn/SGI/sgi_task.c +++ b/openair-cn/SGI/sgi_task.c @@ -92,7 +92,13 @@ static void* sgi_task_thread(void *args_p) */ Gtpv1uTunnelDataInd *data_ind_p; data_ind_p = &received_message_p->ittiMsg.gtpv1uTunnelDataInd; +#ifdef SGI_SOCKET_RAW sgi_send_data(&data_ind_p->buffer[data_ind_p->offset], data_ind_p->length, sgi_data_p, data_ind_p->local_S1u_teid); +#else +#ifdef SGI_SOCKET_DGRAM + sgi_dgram_send_data(&data_ind_p->buffer[data_ind_p->offset], data_ind_p->length, sgi_data_p, data_ind_p->local_S1u_teid); +#endif +#endif /* Buffer is no longer needed, free it */ itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_ind_p->buffer); } @@ -121,8 +127,10 @@ static void* sgi_task_thread(void *args_p) { case ACTIVATE_MESSAGE: { sgi_data_p->hss_associated = 1; +#if !defined(ENABLE_USE_GTPU_IN_KERNEL) SGI_IF_DEBUG("HSS ASSOCIATED, CAN START VLANS (bug in freediameter)"); sgi_init_phase2(sgi_data_p); +#endif } break; default: { diff --git a/openair-cn/SGI/sgi_util.c b/openair-cn/SGI/sgi_util.c index 969179f6d84059652e64eb73bf8ad574519cfc56..35075ea982d6fa66cc1b74a2a5a8a4b94b9ae830 100755 --- a/openair-cn/SGI/sgi_util.c +++ b/openair-cn/SGI/sgi_util.c @@ -64,14 +64,14 @@ void sgi_print_hex_octets(unsigned char* dataP, unsigned long sizeP) } gettimeofday(&tv, &tz); - h = tv.tv_sec/3600/24; + h = (tv.tv_sec/3600) % 24; m = (tv.tv_sec / 60) % 60; s = tv.tv_sec % 60; snprintf(timeofday, 64, "%02d:%02d:%02d.%06d", h,m,s,tv.tv_usec); - SGI_IF_DEBUG("%s------+-------------------------------------------------|\n",timeofday); + SGI_IF_DEBUG("%s------+-------------------------------------------------+\n",timeofday); SGI_IF_DEBUG("%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday); - SGI_IF_DEBUG("%s------+-------------------------------------------------|\n",timeofday); + SGI_IF_DEBUG("%s------+-------------------------------------------------+\n",timeofday); for (octet_index = 0; octet_index < sizeP; octet_index++) { if ((octet_index % 16) == 0){ if (octet_index != 0) {