From e239e94154beab5b78b1a61a975f9b207a2b6b83 Mon Sep 17 00:00:00 2001
From: Thomas Schlichter <thomas.schlichter@iis.fraunhofer.de>
Date: Thu, 17 May 2018 13:00:50 +0200
Subject: [PATCH] Fix PDCP and RLC for MBMS

Also add output of MBMS multicast IP packets to the network.

This commit was developed at Fraunhofer IIS (https://www.iis.fraunhofer.de) by Javier Morgade, Ph.D.
---
 openair2/LAYER2/PDCP_v10.1.0/pdcp.c | 68 +++++++++++++++++++++++++----
 openair2/LAYER2/RLC/rlc.h           |  2 +-
 openair2/LAYER2/RLC/rlc_rrc.c       |  6 ++-
 3 files changed, 66 insertions(+), 10 deletions(-)

diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index e12fb80e1b..04999bab38 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -30,6 +30,8 @@
 #define PDCP_C
 //#define DEBUG_PDCP_FIFO_FLUSH_SDU
 
+#define MBMS_MULTICAST_OUT
+
 #include "assertions.h"
 #include "hashtable.h"
 #include "pdcp.h"
@@ -66,6 +68,17 @@ extern int otg_enabled;
 #include "common/ran_context.h"
 extern RAN_CONTEXT_t RC;
 
+#ifdef MBMS_MULTICAST_OUT
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/ip.h>
+# include <netinet/udp.h>
+# include <unistd.h>
+
+static int mbms_socket = -1;
+#endif
+
 //-----------------------------------------------------------------------------
 /*
  * If PDCP_UNIT_TEST is set here then data flow between PDCP and RLC is broken
@@ -758,11 +771,26 @@ pdcp_data_ind(
   packet_forwarded = FALSE;
 #endif
 
+#ifdef MBMS_MULTICAST_OUT
+  if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
+    struct iphdr   *ip_header = (struct iphdr*)&sdu_buffer_pP->data[payload_offset];
+    struct udphdr *udp_header = (struct udphdr*)&sdu_buffer_pP->data[payload_offset + sizeof(struct iphdr)];
+    struct sockaddr_in dest_addr;
+
+    dest_addr.sin_family      = AF_INET;
+    dest_addr.sin_port        = udp_header->dest;
+    dest_addr.sin_addr.s_addr = ip_header->daddr;
+
+    sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
+    packet_forwarded = TRUE;
+  }
+#endif
+
   if (FALSE == packet_forwarded) {
     new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
 
     if (new_sdu_p) {
-      if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
+      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
         pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
       }
 
@@ -803,7 +831,6 @@ pdcp_data_ind(
       
       
     }
-  }
 
   /* Print octets of incoming data in hexadecimal form */
   LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
@@ -839,13 +866,14 @@ pdcp_data_ind(
 
   
 #if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
-  else {
-    AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
-                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
-  }
-
+    else {
+      AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
+                  PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
+    }
 #endif
 
+  }
+
   free_mem_block(sdu_buffer_pP, __func__);
 
   if (ctxt_pP->enb_flag) {
@@ -1458,8 +1486,12 @@ rrc_pdcp_config_asn1_req (
 
       for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
         MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
-        lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
+        if (MBMS_SessionInfo_p->sessionId_r9)
+          lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
+        else
+          lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
         mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
+//        mch_id = j;
 
         // can set the mch_id = i
         if (ctxt_pP->enb_flag) {
@@ -1480,6 +1512,14 @@ rrc_pdcp_config_asn1_req (
           }
         }
 
+        LOG_D(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
+          lc_id,
+          MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[0],
+          MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[1],
+          MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2],
+          drb_id,
+          action);
+
         pdcp_config_req_asn1 (
           ctxt_pP,
           NULL,  // unused for MBMS
@@ -2018,6 +2058,12 @@ void pdcp_layer_init(void)
 #endif
   }
 
+#ifdef MBMS_MULTICAST_OUT
+  mbms_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+  if (mbms_socket == -1)
+    LOG_W(PDCP, "Could not create RAW socket, MBMS packets will not be put to the network\n");
+#endif
+
   LOG_I(PDCP, "PDCP layer has been initialized\n");
 
   pdcp_output_sdu_bytes_to_write=0;
@@ -2068,6 +2114,12 @@ void pdcp_layer_cleanup (void)
 {
   list_free (&pdcp_sdu_list);
   hashtable_destroy(pdcp_coll_p);
+#ifdef MBMS_MULTICAST_OUT
+  if(mbms_socket != -1) {
+    close(mbms_socket);
+    mbms_socket = -1;
+  }
+#endif
 }
 
 #ifdef PDCP_USE_RT_FIFO
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index ff49b2d056..8c557188a2 100644
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -208,7 +208,7 @@ rlc_mbms_id_t        rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_
 #define rlc_mbms_ue_get_lcid_by_rb_id(uE_mOD,rB_iD) rlc_mbms_rbid2lcid_ue[uE_mOD][rB_iD]
 
 #define rlc_mbms_ue_set_lcid_by_rb_id(uE_mOD,rB_iD,lOG_cH_iD) do { \
-            AssertFatal(rB_iD<NB_RB_MAX, "INVALID RB ID %u", rB_iD); \
+            AssertFatal(rB_iD<NB_RB_MBMS_MAX, "INVALID RB ID %u", rB_iD); \
             rlc_mbms_rbid2lcid_ue[uE_mOD][rB_iD] = lOG_cH_iD; \
         } while (0);
 
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index aa00ffb773..8977e422b6 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -414,9 +414,13 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
 
       for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
         MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
-        mbms_session_id    = MBMS_SessionInfo_p->sessionId_r9->buf[0];
+        if (MBMS_SessionInfo_p->sessionId_r9)
+          mbms_session_id  = MBMS_SessionInfo_p->sessionId_r9->buf[0];
+        else
+          mbms_session_id  = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
         lc_id              = mbms_session_id;
         mbms_service_id    = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
+//        mbms_service_id    = j;
 
         // can set the mch_id = i
         if (ctxt_pP->enb_flag) {
-- 
GitLab