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) {