Commit 6fb3e962 authored by Lionel Gauthier's avatar Lionel Gauthier

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@6063 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent b005d788
......@@ -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_ */
......@@ -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);
}
......@@ -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);
}
......
......@@ -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: {
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment