diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h
index 5f27a0fe69ea20b1673c6e8110f28f1c3d68983d..292dc1775dc93bd7ecd30b328e10075b5d93a6ed 100644
--- a/openair2/COMMON/mac_messages_types.h
+++ b/openair2/COMMON/mac_messages_types.h
@@ -49,6 +49,7 @@
 #define CCCH_SDU_SIZE                           (512)
 #define MCCH_SDU_SIZE                           (512)
 
+
 //-------------------------------------------------------------------------------------------//
 // Messages between RRC and MAC layers
 typedef struct RrcMacInSyncInd_s {
diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h
index 3997d579bd309dde38f9bc7801011604c5dccc12..e81e3bea64dcf672357e9fb92b593a5230d1c9a7 100644
--- a/openair2/COMMON/platform_types.h
+++ b/openair2/COMMON/platform_types.h
@@ -87,6 +87,10 @@ typedef boolean_t             srb_flag_t;
 #define  SRB_FLAG_NO          FALSE
 #define  SRB_FLAG_YES         TRUE
 
+typedef boolean_t             sl_discovery_flag_t;
+#define  SL_DISCOVERY_FLAG_NO          FALSE
+#define  SL_DISCOVERY_FLAG_YES         TRUE
+
 typedef enum link_direction_e {
   UNKNOWN_DIR          = 0,
   DIR_UPLINK           = 1,
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index be0bff8f73f50fad80a7a39d8ea6766a045582c5..c57ebfc47a164abba02b267aa1b84e29cc2c1a8e 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -86,6 +86,7 @@
 #define RAR_PAYLOAD_SIZE_MAX 128
 
 #define SCH_PAYLOAD_SIZE_MAX 4096
+#define DCH_PAYLOAD_SIZE_MAX 4096
 /// Logical channel ids from 36-311 (Note BCCH is not specified in 36-311, uses the same as first DRB)
 
 #if defined(Rel10) || defined(Rel14)
@@ -442,6 +443,8 @@ typedef struct {
 #define MCH_SCHDL_INFO 3
 /*!\brief LCID of Carrier component activation/deactivation */
 #define CC_ACT_DEACT 27
+//TTN (for D2D)
+#define SL_DISCOVERY 8 //LCID (fake)
 #endif
 
 // ULSCH LCHAN IDs
@@ -488,6 +491,13 @@ typedef struct {
   uint16_t Pdu_size;
 } __attribute__ ((__packed__)) ULSCH_PDU;
 
+
+/*! \brief Uplink SCH PDU Structure */
+typedef struct {
+  int8_t payload[DCH_PAYLOAD_SIZE_MAX];         /*!< \brief SACH payload */
+  uint16_t Pdu_size;
+} __attribute__ ((__packed__)) ULDCH_PDU;
+
 #include "PHY/impl_defs_top.h"
 
 /*!\brief  UE ULSCH scheduling states*/
@@ -1367,6 +1377,8 @@ typedef struct {
 #ifdef Rel14
   int sltx_active;
   SLSCH_t slsch;
+  SLDCH_t sldch;
+  ULDCH_PDU sldch_pdu;
   ULSCH_PDU slsch_pdu;
   int slsch_lcid;
 #endif
diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h
index 58083b934eb7b9e33f356fe1059b27567c814d8e..cf5d772afe5c3f674811446861887487c20649f1 100644
--- a/openair2/LAYER2/MAC/proto.h
+++ b/openair2/LAYER2/MAC/proto.h
@@ -453,7 +453,8 @@ void ue_send_sl_sdu(module_id_t module_idP,
 		    sub_frame_t subframeP,
 		    uint8_t* sdu,
 		    uint16_t sdu_len,
-		    uint8_t eNB_index
+		    uint8_t eNB_index,
+	       sl_discovery_flag_t sl_discovery_flag
 		    );
 
 #if defined(Rel10) || defined(Rel14)
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index 9cab4281d55e0474503f7a9df441f6029d3dfb40..4cd78baca785301e9a87e9ef9e319d5cd0d3cc04 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -749,13 +749,16 @@ void ue_send_sl_sdu(module_id_t module_idP,
 		    sub_frame_t subframeP,
 		    uint8_t* sdu,
 		    uint16_t sdu_len,
-		    uint8_t eNB_index
+		    uint8_t eNB_index,
+		    sl_discovery_flag_t sl_discovery_flag
 		    ) {
 
   int rlc_sdu_len;
   char *rlc_sdu;
   uint32_t destinationL2Id =0x00000000;
 
+  if (sl_discovery_flag == SL_DISCOVERY_FLAG_NO) {
+
   // Notes: 1. no control elements are supported yet
   //        2. we exit with error if LCID != 3
   //        3. we exit with error if E=1 (more than one SDU/CE)
@@ -792,6 +795,23 @@ void ue_send_sl_sdu(module_id_t module_idP,
 		   rlc_sdu_len,
 		   1,
 		   NULL);
+  } else { //SL_DISCOVERY
+
+     LOG_I( MAC, "SL DISCOVERY \n");
+    //call mac_rrc_data_ind
+     uint16_t len;
+     mac_rrc_data_ind(module_idP,
+                      CC_id,
+                      frameP,subframeP,
+                      UE_mac_inst[module_idP].crnti,
+                      SL_DISCOVERY,
+                      sdu, //(uint8_t*)&UE_mac_inst[Mod_id].SL_Discovery[0].Rx_buffer.Payload[0],
+                      len,
+                      ENB_FLAG_NO,
+                      eNB_index,
+                      0);
+
+  }
 }
 
 
@@ -2728,8 +2748,25 @@ SLSS_t *ue_get_slss(module_id_t Mod_id,int CC_id,frame_t frame_tx,sub_frame_t su
 }
 
 SLDCH_t *ue_get_sldch(module_id_t Mod_id,int CC_id,frame_t frame_tx,sub_frame_t subframe_tx) {
+/*  int sdu_length;
+    UE_MAC_INST *ue = &UE_mac_inst[Mod_id];
+    SLDCH_t *sldch = &UE_mac_inst[Mod_id].sldch;
+   LOG_I(MAC, "[ue_get_sldch]");
+   int sdu_length = mac_rrc_data_req(Mod_id,
+            CC_id,
+            frame_tx,
+            SL_DISCOVERY,
+            1,
+            (char*)(ue->sldch_pdu.payload), //&UE_mac_inst[Mod_id].SL_Discovery[0].Tx_buffer.Payload[0],
+            0,
+            0, //eNB_indexP
+            0);
+
 
-  return((SLDCH_t*)NULL);
+   if (sdu_length >0 ) return (&ue->sldch);
+   else
+   */
+   return((SLDCH_t*)NULL);
 }
 
 
diff --git a/openair2/RRC/LITE/L2_interface.c b/openair2/RRC/LITE/L2_interface.c
index 07d75d097008c89ea328ff6bfca3fecb6fc00ab5..7b4ad57a2f9dcbdc60ad2afd8586c71a54d09dc1 100644
--- a/openair2/RRC/LITE/L2_interface.c
+++ b/openair2/RRC/LITE/L2_interface.c
@@ -324,6 +324,18 @@ mac_rrc_data_req(
 
   } else {  //This is an UE
 
+#ifdef Rel14
+     LOG_D(RRC,"[UE %d] Frame %d Filling SL DISCOVERY SRB_ID %d\n",Mod_idP,frameP,Srb_id);
+     LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size);
+
+   //TTN (for D2D)
+     if ((Srb_id & RAB_OFFSET) == SL_DISCOVERY){
+        memcpy(&buffer_pP[0],&UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.Payload[0],UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size);
+        uint8_t Ret_size=UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size;
+        //      msg("[RRC][UE %d] Sending SL_Discovery\n",Mod_id);
+        return(Ret_size);
+     }
+#endif
 
     LOG_D(RRC,"[UE %d] Frame %d Filling CCCH SRB_ID %d\n",Mod_idP,frameP,Srb_id);
     LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size);
@@ -500,6 +512,11 @@ mac_rrc_data_ind(
 #endif
     }
 
+    //TTN (for D2D)
+    if((srb_idP & RAB_OFFSET) == SL_DISCOVERY) {
+       decode_SL_Discovery_Message(&ctxt, eNB_indexP, sduP, sdu_lenP);
+    }
+
 #endif // Rel10 || Rel14
 
   } else { // This is an eNB
@@ -545,6 +562,7 @@ mac_rrc_data_ind(
 
 }
 
+
 //-------------------------------------------------------------------------------------------//
 // this function is Not USED anymore
 void mac_sync_ind(module_id_t Mod_idP,uint8_t Status)
diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h
index e39520e520702257690ec218b3a3521e03d0c443..cda0815d3310cecc4619d2e29529f3b556860073 100644
--- a/openair2/RRC/LITE/defs.h
+++ b/openair2/RRC/LITE/defs.h
@@ -87,6 +87,7 @@
 #define GROUP_COMMUNICATION_RELEASE_RSP     8
 #define PC5S_ESTABLISH_REQ                  9
 #define PC5S_ESTABLISH_RSP                  10
+#define PC5_DISCOVERY_ANNOUNCEMENT          11
 
 
 typedef enum {
@@ -131,6 +132,14 @@ struct PC5SEstablishRsp{
    uint8_t status;
 };
 
+//example of PC5_DSICOVERY ANNOUNCEMENT (for testing only)
+typedef struct  {
+   uint8_t msg_type;
+   uint32_t discoveryGroupId;
+   //AnnouncerInfo
+   uint32_t proSeUEId;
+}  __attribute__((__packed__)) PC5DiscoveryAnnouncement;
+
 struct sidelink_ctrl_element {
    unsigned short type;
    union {
@@ -139,13 +148,14 @@ struct sidelink_ctrl_element {
       Group_Communication_Status_t group_comm_release_rsp;
       //struct DirectCommunicationReleaseReq  direct_comm_release_req;
       SL_UE_STATE_t ue_state;
-      //struct GroupCommunicationReleaseReq group_comm_release_req;
       int slrb_id;
       struct PC5SEstablishReq pc5s_establish_req;
       struct PC5SEstablishRsp pc5s_establish_rsp;
+      PC5DiscoveryAnnouncement pc5_discovery_announcement;
    } sidelinkPrimitive;
 };
 
+
 //global variables
 extern struct sockaddr_in clientaddr;
 extern int slrb_id;
@@ -730,6 +740,8 @@ typedef struct UE_RRC_INST_s {
   uint32_t groupL2Id;
   //destination L2 Id
   uint32_t destinationL2Id;
+  //sl_discovery..
+  SRB_INFO SL_Discovery[NB_CNX_UE];
 #endif
 
 #if defined(Rel10) || defined(Rel14)
diff --git a/openair2/RRC/LITE/proto.h b/openair2/RRC/LITE/proto.h
index f349090aa2ed5335fcf9b5a3d5e6de3856b43e2f..684ecc5d28fbd02b8fc6227000e923d79555487a 100644
--- a/openair2/RRC/LITE/proto.h
+++ b/openair2/RRC/LITE/proto.h
@@ -89,6 +89,14 @@ rrc_ue_decode_dcch(
   const uint8_t                eNB_indexP
 );
 
+#ifdef Rel14
+int decode_SL_DISCOVERY_Message(
+  const protocol_ctxt_t* const ctxt_pP,
+  const uint8_t                eNB_index,
+  uint8_t*               const Sdu,
+  const uint8_t                Sdu_len);
+#endif
+
 /** \brief Generate/Encodes RRCConnnectionRequest message at UE
     \param ctxt_pP Running context
     \param eNB_index Index of corresponding eNB/CH*/
diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c
index 587599e3a1870124cff708c258b29067f5518ed2..a3c39fdc42a6c1e2431313eea7b680f14aa7e63b 100644
--- a/openair2/RRC/LITE/rrc_UE.c
+++ b/openair2/RRC/LITE/rrc_UE.c
@@ -4721,6 +4721,15 @@ void *rrc_ue_task( void *args_p )
         RRC_MAC_MCCH_DATA_IND (msg_p).sdu_size,
         RRC_MAC_MCCH_DATA_IND (msg_p).mbsfn_sync_area);
       break;
+
+  /*  //TTN (for D2D)
+    case RRC_MAC_SL_DISCOVERY_DATA_IND:
+       LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, msg_name,
+             RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).frame, RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).enb_index);
+       PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, M_RNTI, RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).frame, 0,RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).enb_index);
+       //send to ProSeApp
+       break;
+*/
 # endif
 
       /* PDCP messages */
@@ -5792,6 +5801,20 @@ void *rrc_control_socket_thread_fct(void *arg)
          }
          break;
 
+
+      case PC5_DISCOVERY_ANNOUNCEMENT:
+
+ #ifdef DEBUG_CTRL_SOCKET
+           LOG_I(RRC,"[PC5DiscoveryAnnouncement] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
+           LOG_I(RRC,"[PC5DiscoveryAnnouncement] type: %d\n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5_discovery_announcement.msg_type);
+           LOG_I(RRC,"[PC5DiscoveryAnnouncement] discoveryGroupId: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5_discovery_announcement.discoveryGroupId);
+           LOG_I(RRC,"[PC5DiscoveryAnnouncement] proSeUEId: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5_discovery_announcement.proSeUEId);
+ #endif
+        //prepare SL_Discovery buffer
+         memcpy((void*)&UE_rrc_inst[module_id].SL_Discovery[0].Tx_buffer.Payload[0], (void*)receive_buf, n);
+         UE_rrc_inst[module_id].SL_Discovery[0].Tx_buffer.payload_size = n;
+
+         break;
       default:
          break;
       }
@@ -5801,4 +5824,39 @@ void *rrc_control_socket_thread_fct(void *arg)
 }
 
 
+//-----------------------------------------------------------------------------
+int decode_SL_DISCOVERY_Message(
+  const protocol_ctxt_t* const ctxt_pP,
+  const uint8_t                eNB_index,
+  uint8_t*               const Sdu,
+  const uint8_t                Sdu_len)
+{
+
+   int prose_addr_len;
+   char send_buf[BUFSIZE];
+   int n;
+
+   //from the main program, listen for the incoming messages from control socket (ProSe App)
+   prose_addr_len = sizeof(prose_app_addr);
+
+   //Store in Rx_buffer
+   memcpy((void*)&UE_rrc_inst[ctxt_pP->module_id].SL_Discovery[0].Rx_buffer.Payload[0], (void*)Sdu, Sdu_len);
+   UE_rrc_inst[ctxt_pP->module_id].SL_Discovery[0].Rx_buffer.payload_size = Sdu_len;
+
+   memset(send_buf, 0, BUFSIZE);
+   //send to ProSeApp
+   memcpy((void *)send_buf, (void*)Sdu, Sdu_len);
+   prose_addr_len = sizeof(prose_app_addr);
+   n = sendto(ctrl_sock_fd, (char *)send_buf, Sdu_len, 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
+//         free(sl_ctrl_msg_send);
+   if (n < 0){
+      LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
+      exit(EXIT_FAILURE);
+   }
+
+
+
+  return(0);
+}
+
 #endif
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index 2ed153a873769dddb4cec453e2f9ca62b1ca0bd9..ec7a5f24613f90140e3fa339076feb41e21bae24 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -785,7 +785,8 @@ void ue_stub_rx_handler(unsigned int num_bytes, char *rx_buffer) {
 		   pdu->header.absSF%10,
 		   pdu->payload,
 		   slsch->payload_length,
-		   0);
+		   0,
+		   SL_DISCOVERY_FLAG_NO);
     break;
   }
 }