Byeo

P4: Programming Protocol-Independent Packet Processors 2 본문

프로그래밍 (Programming)/논문 (Paper)

P4: Programming Protocol-Independent Packet Processors 2

BKlee 2023. 10. 28. 22:18
반응형

 해당 포스트는 SIgcomm' 14 CCR https://www.sigcomm.org/sites/default/files/ccr/papers/2014/July/0000000-0000004.pdf 를 번역해서 정리한 글입니다.

 

4. P4 언어 예제

  이 section에서는 예제를 통해 P4를 깊이 탐구해본다. Network는 core와 edge를 다르게 구분한다; end-hosts는 edge device와 연결되어 있고, 이 device는 high-bandwidth core와 연결되어 있는 구조이다. 모든 프로토콜은 이러한 구조를 지원하기 위해 디자인되어 왔으며, 특히 core에서 forwarding을 간단하게 만드는데 초점을 두었었다.

 

 Two-tier core와 연결되어 있는 edge에서의 ToR 스위치 L2 network 전개 사례를 고려해보자. 이 상황에서 우리는 end-host의 수가 계속 늘어나고 있으며, core의 L2 table이 넘치는 상황을 가정할 것이다. MPLS는 core를 간단하게 만들기 위한 옵션이지만, 다수의 tag를 이용한 label distribution 프로토콜을 구현하는 것은 부담스러운 일이다. 

 

 P4는 네트워크 구조에 변화를 최소화하는 custom solution을 표현할 수 있게 해준다. 우리는 위 문제를 해결하기 위해 toy example인 mTag를 예제로 들 것이다: 이 mTag는 PortLand의 계층적 라우팅 구조와 단순한 MPLS-like tags를 결합한 것이다. Core를 통과하는 경로는 4개의 1 byte fields로 구성되어 있는 32bit-tag로 인코딩 된다. 이 32-bit tag는 source route를 전달하거나 destination locator (PortLand Pseudo MAC)을 전달한다. 각 core switch 오로지 tag에서 1 byte를 검사만 하면 된다. 우리 예제에서는 tag가 첫 번째 Tor 스위치에서 추가된다. mTag 예제는 P4 언어에 집중할 수 있도록 고의적으로 단순하게 구현되었다. 실제 적용에서는 몇 배 더 복잡할 수 있다.

 

4.1 P4 concepts

  • Headers: header 정의는 순서와 fields의 구성을 설명한다. 이는 field의 크기와 field 값의 제약 조건을 포함한다.
  • Parsers: parser 정의는 header와 packet valid header 순서를 어떻게 정의할 것인지 명시한다.
  • Tables: Match+action table은 packet processing을 수행하는 매커니즘을 포함한다. P4 프로그램은 table에서 match가 될 fields와 실행되어야할 action을 정의한다.
  • Actions: P4는 단순한 protocol-independent primitives를 이용해서 복잡한 action을 구성할 수 있도록 지원한다. 이 복잡한 action은 match+action table에서 사용이 가능하다.
  • Control Programs: control program은 packet에게 적용될 match+action table의 순서를 결정한다. 간단한 명령형 프로그램이 match+action table 사이의 control flow를 설명한다.

 

4.2 Header Formats

 설계는 header format을 정의하는 것으로부터 시작한다. 각 헤더는 ordered list로 정의되며, 이름과 크기(bit)가 명시된다. 추가로, field에 값의 범위에 대한 제약이나, 가변 길이에 대해 최대 값을 지정하는 제약을 걸 수 있다. 예를 들어, 표준 Ethernet과 VLAN 헤더는 다음과 같다.

 mTag 헤더는 이 선언을 대체하지 않고 추가될 수 있다. 두 개의 계층을 지닌 스위치는 방향과 위치를 고려해 4개의 field중에서 1개를 검사하도록 프로그래밍 되어있다.

4.3 Packet Parser

 P4는 packet이 스위치를 거쳐가면서 header를 파싱할 때 state machine을 구성할 수 있다고 가정한다. 추출된 field의 값은 처리를 위해 match+action table로 보내진다. P4는 하나의 header에서 다음으로 전이(transition)의 집합으로 state machine을 기술한다 (오토마타를 듣지 않았어서 정확한 의미를 모르고 있음). 각 전이는 현재의 header의 값에 의해 trigger될 수 있다. 예를 들어, mTag의 state machine은 다음과 같이 표현할 수 있다.

 파싱 작업은 start 상태부터 시작하여 stop 상태에 명시적으로 도착할 때까지, 혹은 예외 상황이 발생할 때까지 계속된다. Header가 특정 state에 도달하면, state machine은 정의해 놓았던 header field (Section 4.2)에 따라 값을 추출하고 다음 transition을 결정하기 위해 처리한다. 그리고, 추출된 header는 match+action으로 전달된다.

 위의 mTag 예제는 parser는 4개의 state만을 갖고 있어 매우 단순하다. 실제 네트워크 세계에서는 백개가 넘는 더 많은 state를 요구할 것이다.

 

4.4 Table 명세

 다음으로, 프로그래머는 match+action 단계에서 header field를 어떻게 매칭시켜야 할지 기술해야 한다 (예를 들어, 정확히 일치해야 하는지? 범위인지? 혹은 와일드카드인지?). 그리고 match되었을 때 어떠한 action이 실행되어야 하는지도 기술해야 한다.

 

 우리의 간단한 예제 mTag에서는 edge 스위치가 L2 destination과 VLAN ID를 매치하고, 헤더에 추가할 mTag를 선택한다. 프로그래머는 이 필드들에 대해 매치를 정의하고 mTag header를 추가할 action을 정의한다. 

 reads 는 어떤 field가 매치되어야 하는지 선언하고 어떻게 매치할 것인지 타입 (exact, tenary, etc.) 등을 정의한다. actions 는 테이블에 의해 packet에게 적용될 수 있는 가능한 action들을 나열한다. max_size는 테이블이 얼마나 많은 엔트리들을 지원해야 하는지를 명시한다.

 

 이 테이블의 명시는 컴파일러가 얼마나 많은 양의 메모리를 필요로 하는지, 그리고 테이블을 어떤 메모리 (TCAM or SRAM)로 구현해야 할지 결정할 수 있도록 한다.

 

4.5 Action 명세

 P4는 기본적인 action들을 정의하고 있고, 이들을 이용해 복잡한 action들이 구성될 수 있다. 이 action 함수들은 table 명시와 구성을 쉽게 만들어준다. P4는 action 함수들이 병렬 처리될 것이라고 가정한다. 

 add_mtag 액션은 다음과 같이 구현될 수 있다.

 만약 action에 파라미터가 필요하다면, 런타임에 match table로부터 공급받을 수 있다. 

 이 예제에서는 스위치가 VLAN tag 다음에 mTag를 추가하며, VLAN 태그의 ethertype을 mTag에 복사한다. 그리고 해당 packet이 mTag임을 알 수 있도록 VLAN 태그의 Ethertype을 0xaaaa로 설정한다.

 

 P4의 기본 action은 다음과 같다.

  •  set_field: header의 특정 field에 값을 설정한다. Masked set도 허용한다.
  •  copy_field: 한 field를 다른 곳으로 복사한다.
  •  add_header: 특정 header instance를 valid로 설정한다.
  •  remove_header: packet에서 header를 제거한다.
  •  increment: 특정 field의 값을 증가시키거나 감소시킨다.
  •  checksum: 특정 header field의 집합으로부터 checksum을 계산한다. (e.g., IPv4 checksum)

 

 우리는 대부분의 스위치가 특정 header를 수정하거나 처리하는 등의 제한된 작업만 하고 있을 것으로 예상한다 (그래서 위의 action만으로도 충분하다?)

 

4.6 Control Program

 Table과 action이 정의되면, 이제 남은 작업은 table간 control flow를 정의해주는 것이다. Control flow는 함수, 조건, 그리고 table 참조의 집합으로 구성된 프로그램이다.

 

 Figure 4는 edge 스위치에서 mTag 구현의 control flow를 그래프 형태로 표현한 것이다. 파싱이 끝나면 soruce_check table에서 수신된 packet과 ingress port 사이에서의 일관성을 검사한다. 예를 들어, mTags는 core 스위치와 연결된 포트에서만 보여야 한다. 또한, source_check는 packet에서 mTags를 떼어냄과 동시에 packet의 metadata에 mTag가 있었는지 여부를 기록한다. 파이프라인에서 그 뒤의 테이블들은 packet을 다시 태깅하는 것을 피하기 위해 이 metadata를 매치해볼 것이다.

 local_switching 테이블이 그 다음 실행된다. 만약 이 테이블에서 "misses" 처리된다면, 이는 packet이 locally connected host로 향하는 packet이 아님을 의미한다. 이 경우에는, mTag_table에서 packet이 처리된다. 마지막으로 local과 core 컨트롤 둘 다, 알려지지 않은 목적지로 향하는 packet들이 있음을 SDN controller에게 알리는 egress_check를 거치게 된다.

 

 이 packet 처리 파이프라인의 명령형 표현은 다음과 같다.

 

5. P4 프로그램 컴파일

 P4 프로그램을 구현하고 실행하기 위해서는, target-independent description을 target 스위치의 하드웨어 혹은 소프트웨어 플랫폼에 맞도록 매핑해야 한다. 이 과정에서는 target의 자원을 할당하고 장치에 대한 적절한 설정을 생성하는 과정이 수반된다.

 5.1 Packet Parser 컴파일

 programmable parser를 갖고 있는 장비에서는 컴파일러가 parser description을 parsing state machine으로 해석하고, fixed parser를 갖고 있는 경우에는 컴파일러가 단순하게 parser description이 target의 parser와 일치하는지만 확인한다. 

 Table 2는 section 4.3의 vlan과 mTag에 대한 상태 테이블 엔트리를 보여준다. 각 엔트리는 현재 상태, match할 field의 값, 그리고 다음 상태를 의미한다. (다른 정보는 여기서는 나타내지 않음)

 

5.2 Control Program 컴파일

 Section 4.6에서 보였던 명령형 control-flow 표현은 스위치의 논리적인 전달 방식을 명시하기에 편리하지만, table 사이의 의존성 및 동시성 기회를 명시적으로 밝혀내기는 어렵다. 우리는 그래서 이 의존성과 packet header를 처리하는 과정에서 병렬로 실행할 수 있는 기회가 있는지 분석하고 밝혀내는 컴파일러를 쓴다. 최종적으로, 컴파일러는 스위치를 위한 target configuration을 생성한다. software switch (OvS), fixed function switch, multicore software switch, NPU, RMT 등의 다양한 target을 대상으로 한다.

 

 Section 3에서 이야기된 것처럼, 컴파일러는 두 가지 단계를 따른다. 첫 단계에서는 P4 control program을 table간 의존성을 분석할 수 있는 intermediate(중간단계) table dependency graph 표현으로 변환한다. 두 번째 단계에서는, Target-specific back-end는 이 TDG를 스위치에 적합한 자원으로 매핑한다.

 

 다음으로 우리의 mTag 예제가 다양한 종류의 스위치에서 어떻게 구현될 수 있는지 간단하게 다룬다.

 Software switch: 소프트웨어 스위치는 매우 유연하다. table 개수, table 설정, softwaee 하에서의 parsing 등 유연성이 높다. 컴파일러는 곧바로 mTag table graph를 스위치 table에 매핑한다. 컴파일러는 table type 정보를 사용하여 table의 크기와 matching 기준 (exact, prefix, wildcard) 등을 설정한다. 또한, 컴파일러는 소프트웨어 자료구조를 이용하여 tenary 혹은 prefix 매칭을 최적화할 수도 있다.

 Hardware switch with RAM and TCAM: edge 스위치에의 mTag_table의 경우, 컴파일러는 RAM을 이용해 효율적으로 exact-matching 수행하기 위하여 hashing을 설정할 수 있다. 반면에 tag bit의 일부만 매칭하는 core mTag forwarding table의 경우에는 TCAM을 사용할 수 있다.

 Switches supporting parallel tables: 컴파일러는 데이터 의존성을 감지하고 table을 병렬 혹은 일렬로 배치한다. mTag 예제에서는 mTag_table과 local_switching table이 mTag를 설정하는 action까지는 병렬적으로 실행될 수 있다. 

 Switches that apply actions at the end of the pipeline: action을 오로지 파이프라인의 마지막에서만 처리하는 스위치의 경우에는 컴파일러가 intermediate(중간단계)에서 최종 write을 수행하기 위해 사용될 메타데이터를 생성하라고 지시할 수 있다. mTag 예제에서는 mTag가 추가될 지 혹은 삭제될 지 메타데이터로 표현될 수 있다. 

 Switches with a few tables: 컴파일러는 많은 양의 P4 table을 물리적으로 공간이 더 작은 table에 매핑할 수 있다. mTag 예제에서는 local 스위칭이 mTag table과 결합될 수 있다. 컨트롤러가 런타임에 새로운 규칙을 추가한다면, 컴파일러의 룰 번역기가 룰을 두 개의 P4 table에 구성하여 하나의 물리적인 table을 생성해낼 수 있다.

 

6. 결론

 SDN은 하나의 control plane이 전체 네트워크 스위치를 직접 제아한다. OpenFlow는 vendor와 무관한 API를 제공함으로써 이 목표를 달성했다. 그러나 오늘날의 OpenFlow는 fixed-function swtich를 대상으로 하고 있고, 이는 사전에 정의된 header field만 인식하고 사전에 정의된 제한된 action만 지정할 수 있다는 단점이 있다. 결국 control plane은 control application의 요구를 잘 충족하기 위해서 packet이 어떻게 처리되어야 하는지를 표현하는데 한계가 있는 것이다.

 

 우리는 기능이 명시된, 혹은 바뀔 수도 있는 유연한 스위치를 위해 한 발 더 나아갈 수 있는 방법을 제안했다. 프로그래머는 세부 구현에 대한 걱정 없이 forwarding plane이 packet을 어떻게 처리해야 할지 결정할 수 있다. 컴파일러는 명령형 구조를 다양한 스위치를 대상으로 매핑할 수 있는 TDG로 전환하여 준다.

 

 우리는 이것이 OpenFlow 2.0의 제안을 위한 첫 단계임을 강조한다. 이 논문에서는 여전히 스위치의 많은 부분이 정의되지 않은 채로 남아있다 (e.g., congestion-control primitives, queuing disciplines, traffic monitoring). 그러나, 우리는 이러한 configuration 언어와 특정 대상으로 low-level configruation을 생성해주는 컴파일러를 갖는 접근은 더 많은 유연함을 제공하는 미래의 스위치로 이끌고, SDN의 잠재력을 풀어낼 수 있을 것이다.

 

반응형
Comments