본문 바로가기

프로젝트/LTE,5G 네트워크 구축

오픈 소스 기반의 사용자 중심 MAC 스케줄러 설계 및 구현

지난 2021년 6월부터 2022년 6월까지 약 1년간 네트워크 연구실에서 진행했던 프로젝트이다.

 

본 프로젝트의 결과물로 한국통신학회(KICS)가 주관하는 2022 하계 종합학술대회에 학부논문으로 게재했다.

해당 논문은 https://journal-home.s3.ap-northeast-2.amazonaws.com/site/2022s/abs/0670.pdf에서 확인할 수 있다.

 

네트워크 수업조차 듣지 않았을 때 무작정 시작해서 처음 네트워크를 이해할 때 굉장히 힘들었던 기억이 난다.

이동통신에 관련해서 Netmanias와 표준등을 읽어보며 팀원들과 함께 공부했었는데 사실 아직도 이해하지 못하는 것이 더 많다...

 

아무튼 우리의 프로젝트 주제는 오픈소스를 활용해 사용자 중심의 MAC스케줄러를 구현하는 것이었다.

 

우선 오픈소스를 활용해 LTE/5G 네트워크 망 자체를 구축해야 했다.

이때 사용한 오픈소스는 프랑스의 네트워크 연구기관인 OAI에서 제공하는 것을 사용했다.

 

프로젝트 주제


우선 프로젝트위 주제를 이해하기 위해 네트워크 구조를 이해할 필요가 있다.

https://tjdahr25.tistory.com/69?category=106483

 

4G(LTE)와 5G(NR)의 구조

나는 현재 학교의 네트워크 연구실에서 5G 네트워크 구축을 주제로 하는 프로젝트를 진행하고 있다. 모바일 네트워크를 구축함에 있어서 전체적인 구조를 파악하고 있어야 하기 때문에 각 네트

tjdahr25.tistory.com

 

UE는 PDN(인터넷)과 통신하기 위해서 기지국이 정해놓은 QoS정책에 따라 사용할 수 있는 무선자원의 양을 할당받고 통신하게 된다. 이게 우리가 흔히 말하는 과금정책이다. 통신사에 매달 내는 요금에 따라 우리가 사용할 수 있는 데이터의 양이 다른 것이 바로 이것 때문이다.

 

그렇다면 각 UE들에게 차등적인 자원분배를 해주는 곳은 어디일까?

바로 기지국이다. 기지국은 여러 Layer로 이루어져있는데 이들 중 MAC Layer에서 이 스케줄링 기능을 담당한다.

기지국의 MAC Layer에서는 해당 기지국이 사용할 수 있는 전체 자원을 가장 효율적으로 자신들에게 연결된 UE들에게 분배해주려고 노력한다. 때문에 여러 스케줄링 알고리즘을 사용하고 있는데, 우리가 흔히아는 RoundRobin(RR), Proportional Fair(PF)등이 이에 해당한다. 요즘은 가중치가 적용된 PF를 주로 사용하는 것으로 알고 있다.

 

어쨌든 기지국은 UE들에게 효율적으로 자원을 낭비없이 분배해주는 것이 중요하다.

또한 각 UE가 필요한 만큼만의 자원을 할당해준다면 더 많은 UE들을 효율적으로 관리할 수 있을것이다.

 

우리의 프로젝트 주제는 여기서 시작되었다.

가중치(Weight)과 Rate를 적절히 제한해서 사용자가 사용하는 애플리케이션에 따라 차등적인 자원을 분배해줄 수 있다면 우리가 원하는 이상적인 스케줄링이 완성될 것이다.

 

OAI에서 제공해주는 오픈소스에는 RR과 PF스케줄링 알고리즘이 구현되어있고, 우리가 구상하는 스케줄링을 이 오픈소스를 분석하고 수정하면서 완성시키는 것이 프로젝트의 주제이다.

 

 

OpenAirInterface (OAI)


https://openairinterface.org/

 

OpenAirInterface – 5G software alliance for democratising wireless innovation

Biot, France, June 24, 2022 - The OpenAirInterface Software Alliance... Read More

openairinterface.org

 

프랑스의 비영리 연구기관 단체이다. 

이곳에서는 LTE/5G 네트워크 망을 구축할 수 있는 오픈소스를 제공해준다.

https://gitlab.eurecom.fr/oai/openairinterface5g

 

oai / openairinterface5G

Openairinterface 5G Wireless Implementation

gitlab.eurecom.fr

OAI에서 오픈소스를 관리하고 있는 gitlab이다. 이곳의 코드로 지나온 여러 버전으로 네트워크 망을 구축할 수 있다.

 

 

네트워크망 설계/구축


 

 

본 시스템의 구조는 다음과 같다.

 

OAI는 기본적으로 EPC의 엔티티들을 도커의 컨테이너 개념을 이용해 구축한다.

네트워크망 구축을 위해 총 4대의 장비가 필요하다.

 

1. PC#1

- 기지국(eNB)를 담당하는 PC이다.

2. PC#2

- EPC를 담당하는 PC이다. EPC에는 여러 엔티티들이 존재하는데, 본 시스템에서는 HSS, MME, S-GW 그리고 P-GW를 각각 도커의 컨테이너를 이용해 구축한다. 

3. UE

- 실제 네트워크 망에서 사용할 공기계가 필요하다. 우리는 프로젝트를 위해 Galaxy S20 2대를 사용했다.

4. USRP

- 실제 기지국(하드웨어)역할을 하는 장비이다. PC#1과 연결해서 빌드후에 실제 기지국처럼 작동한다.

 

 

실제 구축했던 모습이다. 위에 보이는 PC들이 가각 PC#1, PC#2이고 아래쪽에 보이는 장비들이 USRP와 UE 두 대이다.

 

 

 

PDN에서 UE로의 패킷 캡처


목적

본 스케줄링의 목적은 UE가 사용하고 있는 애플리케이션에 따라 기지국에서 차등적으로 자원을 분배해주는 것이다.

따라서 UE가 어떤 애플리케이션을 사용하고 있는지 기지국에서 알아야 한다.

 

그러나 좀 자세히 생각해보면 사실 말도 안되는 이야기이다.

UE가 사용하고 있는 애플리케이션이 무엇인지 탐지하는 것과 해당 애플리케이션이 어느정도의 자원을 요구하는지는 기지국에서 미리 전처리를 해놓고 알고 있어야 하는데 수억개가 넘는 애플리케이션이 나와있는 시점에서 이는 사실 불가능하다.

 

따라서 본 프로젝트에서는 특정 애플리케이션(Youtube)에 대해서만 진행하기로 했다. 어떤 UE가 Youtube를 사용중이라면가중치를 높여 더욱 더 높은 자원을 할당받을 수 있도록 하는 것이다.

 

그렇다면 현재 실제로 운영되고 있는 기지국은 어떻게 처리할까?

삼성 네트워크 사업부에서 수십년간 연구해오신 박사님과 미팅할 기회가 있었다. 우리는 이부분에 대해 박사님께 질문을 했었는데, 답변은 다음과 같았다.

각 UE가 필요한 자원의 양을 알아서 기지국에서 그만큼만 주면 정말 좋긴 한데 사실 그럴 수는 없다고 한다. Youtube만 해도 UE와 주고받는 패킷의 양이 매우 들쭉날쭉하기 때문에 힘들다고 하셨다. 따라서 기지국은 가지고 있는 자원의 양을 현재 자신에게 붙어있는 UE의 개수로 나누어 제공한다고 한다. 

실제로 사람들이 많이 모인 곳에 가면 데이터가 잘 안터지는 경우가 있다. 이는 위와같은 이유이다.

 

다시 돌아와서, 어쨌든 우리는 기지국에서 UE에게 차등적인 자원을 분배해주기 위한 기준 애플리케이션(Youtube)을 미리 전처리 해두었다. 

 

Youtube는 MPEG-DASH방식을 이용한다.

*DASH방식에 대해선 다음링크에 자세히 설명되어 있다.

https://tjdahr25.tistory.com/36

 

CH2 : Application Layer (6)

* 이 글에 관련된 모든 내용은 Computer Networking A Top-Down Approach 7th에서 가져온 내용이다. * Internet Video 최근 Netflix, YouTube등 비디오에 대한 수요가 높아지면서 이에 따른 네트워크상의 처리문제..

tjdahr25.tistory.com

때문에 Youtube는 여러 서버를 가지고 있고 이를 사용하는 UE는 항상 일정한 서버와 통신하지 않는다. 

따라서 현재 우리가 진행하고 있는 지역의 주변 Youtube 서버의 IP들을 알 필요가 있었다.

 

미리 Youtube 서버의 IP를 알고 있다면 PDN과 UE사이의 패킷을 캡쳐해 해당 IP가 src나 dst쪽에 있다는 것을 확인만 한다면 해당 UE가 Youtube를 이용하고 있다는 것을 알 수 있기 때문이다.

 

패킷 캡처

패킷 캡처는 EPC의 P-GW에서 이루어진다. 실제로 P-GW는 UE와 PDN사이에 흐르는 패킷을 탐지하는 역할을 한다.

PDN과 UE사이의 패킷을 캡처하고 분석한 P-GW는 해당 UE가 Youtube를 사용하는지에 대한 여부를 안 후, 기지국에게 전달해야 한다. 

 

패킷캡처를 위해 C의 PCAP 라이브러리를 사용했다. 이 라이브러리는 패킷 캡처 프로그래밍을 할 때 사용한다.

또한 UE의 Youtube 사용 여부를 기지국에게 전달해주기 위해 Socket을 이용해 통신 프로그래밍을 했다.

 

Socket Programming에 대한 내용은 여기에 자세히 있다.

https://tjdahr25.tistory.com/category/%EC%BB%B4%ED%93%A8%ED%84%B0%20%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/%EC%86%8C%EC%BC%93%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

 

'컴퓨터 네트워크/소켓 프로그래밍' 카테고리의 글 목록

 

tjdahr25.tistory.com

 

UE와 PDN사이에 흐르는 패킷은 GPRS 터널링 프로토콜(GTP)로 분류된다. 이 GTP는 UDP의 Payload안에 존재하기 때문에 해당 패킷의 Source IP와 Destination IP를 분석하여 해당 UE가 어떤 특정 애플리케이션을 이용하고 있는지에 대한 여부를 알 수 있다.

 

while(1) {
        int res = pcap_next_ex(handle, &header, &packet);
        if (res == 0) continue;
        if (res == -1 || res == -2) exit(1);
        packet += 14;
 
        IPH *ih;
        ih = (IPH *)packet;
        strcpy(message, "");
        if (ih -> Protocol == 0x11) { // 0x11 = UDP
          packet += 36;
          IPH *tmp;
          tmp = (IPH *)packet;
          char src[BUFSIZE], dst[BUFSIZE];
          sprintf(src,"[%s", inet_ntoa(tmp->SrcAdd));
          strcat(message, src);
   
          strcat(message, ",");
          sprintf(dst,"%s]", inet_ntoa(tmp->DstAdd));
          strcat(message, dst);  
          write(sock, message, strlen(message));
        }
    }

패킷 분석을 위해 C의 PCAP 패킷 관리 라이브러리를 이용하여 패킷을 분석했다. 모든 패킷을 감지하면 많은 Overhead가 발생할 수 있기 때문에 우선 UDP패킷으로 거른 뒤에 GTP형식에 맞춰 전처리를 하고 eNB에게 이 내용을 전달한다.

 

처음으로 받은 IP Packet의 헤더에는 밑단 프로토콜의 정보가 있는데 0x11은 UDP를 의미한다.

 

P-GW로부터 해당 UE의 Youtube 사용 여부를 받는 기지국의 코드는 다음과 같다.

while( (str_len=read(clnt_sock,message, BUFSIZE)) != 0){
        tmp = string(message);
        tmp = tmp.substr(0, tmp.length()-1);
        for(int i=0;i<tmp.length();i++){
            if(tmp[i]=='['){
                src = "", dst ="";
                sflag = true, dflag = false;
            }
            else if(tmp[i]==','){
                sflag = false, dflag = true;
            }
            else if(tmp[i]==']'){
 
                if(!check_ip(src)) continue; // 해당 패킷의 src또는 dst가 UE와 Youtube인지 확인
 
                for(int i=0;i<4;i++){
                    if(dst==UE_IP[i]){
                        if(UE[i].find(src) == UE[i].end()){
                            UE[i].insert({src, true});
                        }
                        break;
                    }
                }
            }
            else{
                if(sflag) src+=tmp[i];
                if(dflag) dst+=tmp[i];
            }
        }
    }

 

 

이로써 모든 준비가 마쳐졌다.

이제 남은 일은 기지국에서 해당 UE가 Youtube를 사용중이면 가중치를 늘려주어 스케줄링을 하면 된다.

 

스케줄링


스케줄링을 이해하기 앞서 Weight과 Rate을 알아야 한다.

 

Weight은 가중치 이다. 일정한 자원의 양을 분배해줄 때 어느 UE에게 어느정도의 반복을 해줄 것인지를 결정한다.

우리가 흔히아는 Round Robin 방식은 모두 가중치가 1로 일정한 것이다.

 

Rate는 자원의 양을 의미한다. 만약 Rate제한을 10Mbps로 제한했다면 해당 UE는 한 프레임내에 기지국으로부터 받을 수 있는 자원의 양이 10Mpbs이다. 

 

우리는 Weight과 Rate 두가지 관점에서 스케줄링을 작성했다. 이유는 뒤에서 말하겠다.

 

1. Weight Scheduling Algorithm

기본적으로 OAI에서 제공해주는 RR스케줄링 방식의 코드를 수정해서 적용했다.

어떤 UE가 Youtube를 사용중인 것이 확인이 된다면 해당 UE에게 적용되는 가중치를 1늘리는 방식으로 구현했다.

1.      update weight_standard if UE uses application that requires a lot of resources
2.      reset all the weight_UE to zero {0,0,0,0}
3.      while UE_id to last UE_id in UE_sched
4.        if all the users's weight_UE are more than weight_standard
5.          reset all the weight_UE to zero {0,0,0,0}
6.        end if
7.        if the user's weight is more than weight_standard
8.          move to next user
9.        end if
10.	  allocate the resource
11.    end while

Weight 알고리즘의 pseudo code

 

2. Rate Scheduling Algorithm

Rate제한을 적용한 알고리즘은 각 UE가 한 프레임당 받는 누적 TBS(자원의 양)를 제한하는 것이다. 이로써 사용자의 UE에게 속도제한을 걸 수 있고 위의 Weight 적용 모드와 함께 사용될 수 있다.

이 알고리즘에서는 각 UE의 MCS를 고려해서 한 subframe당 TBS를 계산한다. 이때 TBS를 누적한 값이 미리 설정해둔 제한 값보다 크다면 해당 UE에 대해서는 더이상 자원할당이 이루어지지 않는 방식으로 구현했다.

 

1.  	if every 100 frame, (frame%100==0 && subframe==0)
2.  	  reset all users's total_allocated_TBS to zero 
3.  	end if
4.  	while UE_id to last UE_id in UE_list
5.  	  if total_allocated_TBS is not more than TBS_limit for the user
6.  	    store UE_id to UE_sched
7.  	  end if
8.  	end while
9.  	while UE_id to last UE_id in UE_sched
10.	  allocate the resource
11.	  calculate mcs
12.	  calculate tbs
13.	  add the user's tbs to total_allocated_TBS
14.	  if the user's total_allocated_TBS is more than TBS_limit
15.	    delete the user from the UE_sched
16.	  end if
17.	end while

Rate 알고리즘의 pseudo code

 

 

 

이 두 알고리즘을 모두 이해하고 의문점이 생겼다면 당신은 네트워크 고수입니다!

한가지 의문점이 생긴다. 보통의 기지국들은 UE에게 일정 속도를 보장해주기 위해 최대 Rate이 아닌 최소 Rate을 보장해주지 않는가?

 

본 프로젝트의 목적은 높은 데이터양을 요구하는 애플리케이션을 사용하는 UE에게 더 자원을 많이 할당해주는 것인데, 이를 보장하기 위해선 최소 Rate을 정해놓는 것이 바람직할 것이다.

 

그러나 위에서 말했듯이 이는 실제로 매우 힘들다. 따라서 기지국이 가지고 있는 자원의 양을 붙은 UE의 개수로 나누어서 적용하는 것이다. 

 

또한 이것이 우리가 Weight 알고리즘과 Rate 알고리즘(최대제한)을 모두 구현한 이유이다.

아무리 많은 가중치를 할당받은 UE라도 최대 Rate제한을 걸어놓는다면 해당 UE가 기지국의 자원을 독점하는 것을 막을 수 있다. 어떤 UE의 자원독점을 막는다면 다른 UE의 Rate를 보장해주는 꼴이 되기 때문에 우리는 이러한 방식을 이용했다.

 

위의 알고리즘을 모두 적용한 코드는 다음과 같다. 이는 eNB의 MAC Layer의 스케줄러 중에서도 다운링크에 대한 함수이다.

DevAssert(UE_list->head >= 0);
  DevAssert(n_rbg_sched > 0);
  const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
  const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
  const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
  UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
  custom_t *custom_var = &RC.mac[Mod_id]->custom_var;
 
  int TBS_active = custom_var->TBS_active;
  int weight_active = custom_var->weight_active;
 
 
  if(frame%100==0 && subframe==0){
    for (int UE_i = UE_list->head; UE_i >= 0; UE_i = UE_list->next[UE_i])
      printf("[%d.%d] UE_id[%d] total_TBS=%d\n",frame, subframe, UE_i, UE_info->UE_template[CC_id][UE_i].total_allocated_tbs);
  }
 
 
  if(frame%100==0 && subframe==0) {
      for (int UE_i = UE_list->head; UE_i >= 0; UE_i = UE_list->next[UE_i])
        UE_info->UE_template[CC_id][UE_i].total_allocated_tbs = 0;
  }
 
  // DEBUG
  uint32_t TBS_limit[4] = {0, 0, 0, 0}; // 10M 7M 5M 1M
  int weight_standard[4]={1,1,1,1};
 
  for(int i=0;i<4;i++){
    TBS_limit[i] = custom_var->TBS_limit[i];
    weight_standard[i] = custom_var->weight_standard[i];
    weight_standard[i] += 1*custom_var->youtube_user[i];
  }
 
  if(frame%100==0 && subframe==0){
    printf("TBS:%d/ %d %d %d %d\n", TBS_active, TBS_limit[0],TBS_limit[1],TBS_limit[2],TBS_limit[3]);
    printf("weight:%d/ %d %d %d %d\n", weight_active, weight_standard[0],weight_standard[1],weight_standard[2],weight_standard[3]);
    printf("youtube_user:%d %d %d %d\n", custom_var->youtube_user[0],custom_var->youtube_user[1],custom_var->youtube_user[2],custom_var->youtube_user[3]);
  }
 
  int rbg = 0;
  for (; !rbgalloc_mask[rbg]; rbg++)
    ; /* fast-forward to first allowed RBG */
 
  /* just start with the UE after the one we had last time. If it does not
   * exist, this will start at the head */
  int *start_ue = data;
  *start_ue = next_ue_list_looped(UE_list, *start_ue);
 
  int UE_id = *start_ue;
  UE_list_t UE_sched;
  int *cur_UE = &UE_sched.head;
  int num_ue = 0;
  // Allocate retransmissions, and mark UEs with new transmissions
  do {
    // check whether there are HARQ retransmissions
    const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
    const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
    UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
    const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
    if (round != 8) {
      bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe,
                                                UE_id, rbg, &n_rbg_sched,
                                                rbgalloc_mask);
      if (r) {
        /* if there are no more RBG to give, return */
        if (n_rbg_sched <= 0)
          return 0;
        max_num_ue--;
        if (max_num_ue == 0)
          return n_rbg_sched;
        for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
      }
    } else {
      if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0 && (TBS_limit[UE_id] > UE_info->UE_template[CC_id][UE_id].total_allocated_tbs && TBS_active==1) ) {
        *cur_UE = UE_id;
        cur_UE = &UE_sched.next[UE_id];
        num_ue++;
      }
    }
    UE_id = next_ue_list_looped(UE_list, UE_id);
  } while (UE_id != *start_ue);
  *cur_UE = -1; // mark end
 
  if (UE_sched.head < 0)
    return n_rbg_sched; // no UE has a transmission
 // after allocating retransmissions: pre-allocate CCE, compute number of
  // requested RBGs
  max_num_ue = min(max_num_ue, n_rbg_sched);
  int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request
  cur_UE = &UE_sched.head;
  while (*cur_UE >= 0 && max_num_ue > 0) {
    const int UE_id = *cur_UE;
    const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
    const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
    if (idx < 0) {
      LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id);
      // SKIP this UE in the list by marking the next as the current
      *cur_UE = UE_sched.next[UE_id];
      continue;
    }
    UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
    const int mcs = cqi_to_mcs[cqi];
    UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs;
    const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total;
    rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize);
    max_num_ue--;
    cur_UE = &UE_sched.next[UE_id]; // go to next
  }
  *cur_UE = -1; // not all UEs might be allocated, mark end
 
  // DEBUG
  for (int UE_i = UE_sched.head; UE_i >= 0; UE_i = UE_sched.next[UE_i]){
    printf("[%d.%d] UE_id[%d]/num_ue=%d, mcs=%d, buffer=%d, rb_required=%d\n",frame,subframe, UE_i, num_ue, UE_info->eNB_UE_stats[CC_id][UE_i].dlsch_mcs1, UE_info->UE_template[CC_id][UE_i].dl_buffer_total, rb_required[UE_i]);
  }
int weight_UE[4] = {0,0,0,0};
 
  /* for one UE after the next: allocate resources */
  cur_UE = &UE_sched.head;
  while (*cur_UE >= 0) {
     bool init = true;
   
    for (int UE_i = UE_sched.head; UE_i >= 0; UE_i = UE_sched.next[UE_i]){
      if(weight_UE[UE_i] < weight_standard[UE_i]) {init=false;}
    }
    if(init){
      for(int i=0;i<4;i++)
        weight_UE[i]=0;
    }
 
    const int UE_id = *cur_UE;
 
 
    // skip
    if(weight_UE[UE_id] >= weight_standard[UE_id] && weight_active==1) {
      cur_UE = UE_sched.next[*cur_UE] < 0 ? &UE_sched.head : &UE_sched.next[*cur_UE];
      continue;
    }
 
 
    UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
    ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
    rbgalloc_mask[rbg] = 0;
    const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
    ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
    rb_required[UE_id] -= sRBG;
 
    weight_UE[UE_id]++;
 
    int mcs = UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1;
    uint32_t tbs = get_TBS_DL(mcs, rb_required[UE_id]);
    UE_info->UE_template[CC_id][UE_id].total_allocated_tbs += tbs;
 
    printf("\t allocate: UE_id=%d, RGB=%d TBS=%d, total_TBS=%d\n",UE_id, sRBG, tbs, UE_info->UE_template[CC_id][UE_id].total_allocated_tbs);
 
    if (rb_required[UE_id] <= 0 || (TBS_limit[UE_id] <= UE_info->UE_template[CC_id][UE_id].total_allocated_tbs && TBS_active==1) ) {
      *cur_UE = UE_sched.next[*cur_UE];
      if (*cur_UE < 0)
        cur_UE = &UE_sched.head;
    } else {
      cur_UE = UE_sched.next[*cur_UE] < 0 ? &UE_sched.head : &UE_sched.next[*cur_UE];
    }
 
    n_rbg_sched--;
    if (n_rbg_sched <= 0)
      break;
    for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
  }
  return n_rbg_sched;

측정 결과


성능 측정은 두가지 방식을 이용했다.

 

1. Benchbee

우선 스케줄링의 정확성 확인을 위해 네트워크 성능을 측정해주는 어플을 이용했다. 위 그림은 UE의 Rate제한을 각각 5Mbps, 10Mpbs로 제한했을 때의 모습이다.

 

우리의 프로젝트 목표는 Youtube사용자의 가중치를 늘려주는 것이다. 따라서 유튜브를 킨 상태에서는 Benchbee를 동시에 켜서 볼 수가 없어서 eNB의 로그를 이용해 TBS를 확인하고 Thorouput을 계산했다. 

 

2. 로그 이용

기록되었던 로그를 이용해 엑셀로 그래프를 그렸다.

UE0과 UE1의 가중치(weight)비율을 1:3으로 설정했을 때 나온 결과이다. 그래프를 보면, 1:3의 가중치를 이용해 자원이 할당된 결과의 그래프를 볼 수 있다. 각 UE에게 만약 같은 가중치를 주게 되면 Round Robin방식의 알고리즘이 되는 것이고, 다른 가중치를 주게되면 같은 양의 자원을 해당 UE에게 얼마의 가중치만큼 반복하여 줄 것인지를 결정하는 것이다. 따라서 UE0과 UE1의 가중치를 1:3으로 설정했을 때 전체적인 성능을 나타내는 throughput 그래프 또한 1:3의 비율을 가지는 것을 확인할 수 있다.

이 그래프를 보면, 각 UE에게 RATE의 제한을 10Mbps, 5Mbps로 설정하여 해당 Rate양의 이상으로는 자원할당을 해줄 수 없도록 구현한 결과를 볼 수 있다. 이때 제한한 Rate는 단위 frame당 해당 UE가 기지국으로부터 받을 수 있는 최대의 자원양을 의미한다. 이렇게 해당 UE의 최소 자원 할당량을 보장하는 방식이 아닌 최대 자원양을 할당 해줌으로써 상대적으로 너무 많은 가중치를 할당받은 특정 UE의 자원독점을 막을 수 있다. 전자의 방식은 실제 사용되고 있는 여러 기지국의 자원량을 보장하는 방식인데, 이는 기지국이 할당해줄 수 있는 전체 Rate양을 해당 기지국에 접속해있는 UE의 수로 나누어 대략적인 보장을 해주는 것이다. 본 시스템에서는 구현한 기지국이 보장해줄 수 있는 전체 자원의 양이 많지 않고 UE의 개수또한 적기 때문에 후자의 방식을 택했다.

 

두 가지 제한, 가중치와 Rate를 적절히 사용하여 특정 애플리케이션을 사용하는 UE에게 더 많은 가중치를 할당해 자원을 분배해주고, 특정 UE의 독점을 Rate제한으로 막을 수 있다.

 

 

 

결론


기존 OAI에서 제공하는 오픈소스에 Network slicing기능을 추가하기 위해 사용자가 이용하는 서비스에 따라 차별적인 MAC 스케줄링 기능을 구현하여, 2대 이상의 사용자 기기에 대해 사용자가 이용하는 서비스 별로 적절한 자원을 분배하고, 기존 OAI 5G 오픈 소스보다 향상된 throughput을 내는 것을 목표로 프로젝트를 시작했다. 

위의 기능을 구현하기 위해 5G 네트워크에서 사용자 중심의 효율적인 무선 자원 분배를 수행하는 Weight모드 및 Rate 모드 MAC 스케줄링 기법을 제안하였다. 제안한 스케줄링 방법은 OAI 오픈소스를 사용하여 직접 구현하였고 그 성능을 테스트 하였다. 그 결과 설계한 구현체에서 EPC에서 사용자의 Packet을 파악하고, 사용자 요구량에 따라 eNB는 Weight 적용 모드와 Rate 적용 모드에서 사용자에게 무선 자원을 할당한다. 이때, 적절한 Weight 또는 Rate 제한값은 각 UE가 이용하는 어플리케이션 서비스에 따라 설정된다.

먼저 Weight 적용 모드의 경우, 각 사용자마다 설정된 weight의 비율에 따라 하나의 frame안에서 번갈아 가면서 자원을 할당받는다. 실험 결과, UE0 : UE1 = 1 : 3의 weight 비율일 때, MAC scheduler는 UE0에 대해 자원을 한 번 할당하면 UE1에 대해서는 세 번 할당하여  1초당 할당 받은 TBS 역시 UE0에 비해 3배 높은 결과를 보이는 것을 알 수 있다. 

 

다음으로 Rate적용 모드는 사용자가 1초당 할당 받을 수 있는 최대 TBS의 값에 제한을 두는 방식이다. UE0와 UE1의 Rate를 각각 5Mbps와 10Mbps로 설정하여 성능을 검증한 결과, 제안하는 시스템에서는 Rate 적용 모드만을 사용했을 경우 eNB는 한 subframe 내에서 UE0과 UE1에 대해 1:1의 비율로 자원을 할당한다. 즉, 100 frame(1 second)이 되기 전 subframe 단위로 누적된 TBS값과 설정된 Rate를 비교하여 자원 할당 여부를 결정하는 방식으로 스케줄러가 작동한다. 실험 결과 그림 5와 같이 UE0는 5Mbps를 넘을 때, UE1은 10Mbps를 넘을 때, 각각의 UE에 대한 자원 할당이 중단되기 때문에 UE0과 UE1이 자신에게 주어진 일정 Throughput 이상으로 자원을 할당 받을 수 없게 된 것을 확인할 수 있었다.

 

이를 통해 많은 네트워크 자원을 요구하는 사용자에게 더 높은 비중으로 자원을 할당할 수 있고, 동시에 최대 자원 할당 제한을 둠으로써 적은 네트워크 자원을 요구하는 사용자에게도 최소한의 자원을 할당할 수 있다. 최종적으로 사용자 맞춤형 자원 할당을 가능케함으로써 낭비되는 무선 자원을 줄이고 효율적으로 네트워크 자원을 분배할 수 있도록 한다.

 

본 프로젝트에서 제안하는 스케줄러 및 4G LTE 기반 구현체는 추후 5G NR SA 테스트베드에 확장 적용할 예정이며, 이를 기반으로 OAI에서의 5G 네트워크 슬라이싱 기술을 구현하고자 한다.