...
이처럼 mri를 통해 패킷이 지나온 경로에 대한 정보를 알 수 있고 더 확장된 개념인 INT를 통해 패킷이 지나온 경로에 대한 다양한 정보를 얻고 네트워크 경로 상의 어느 부분이 장애가 있다던가 속도가 느리다던가를 분석할 수 있다는 것을 알 수 있었다.
P4 튜토리얼 sourceroute의 이해
사전 조건
소스 라우팅
ㅇ 패킷을 보내기 전에,
- 송신측에서 수신측까지 가는 모든 경로를 리스트로 만들어두어,
- 이를 패킷의 헤더에 넣어 보내는 방식
스위치에서 포워딩 테이블을 이용해서 패킷을 전달해주는것이 아닌 패킷자체에 어떤 스위치를 거쳐갈것인지를 넣어서 패킷을 전달한다.
튜토리얼 코드 리뷰
코드 블럭 |
---|
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>
const bit<16> TYPE_IPV4 = 0x800;
const bit<16> TYPE_SRCROUTING = 0x1234;
#define MAX_HOPS 9
/*************************************************************************
*********************** H E A D E R S ***********************************
*************************************************************************/
typedef bit<9> egressSpec_t;
typedef bit<48> macAddr_t;
typedef bit<32> ip4Addr_t;
header ethernet_t {
macAddr_t dstAddr;
macAddr_t srcAddr;
bit<16> etherType;
}
//패킷의 이동 경로를 저장할 헤더이다.
header srcRoute_t {
bit<1> bos;
bit<15> port;
}
header ipv4_t {
bit<4> version;
bit<4> ihl;
bit<8> diffserv;
bit<16> totalLen;
bit<16> identification;
bit<3> flags;
bit<13> fragOffset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdrChecksum;
ip4Addr_t srcAddr;
ip4Addr_t dstAddr;
}
struct metadata {
/* empty */
}
//패킷 헤더에 패킷 경로 헤더를 추가
struct headers {
ethernet_t ethernet;
srcRoute_t[MAX_HOPS] srcRoutes;
ipv4_t ipv4;
}
/*************************************************************************
*********************** P A R S E R ***********************************
*************************************************************************/
parser MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
state start {
transition parse_ethernet;
}
state parse_ethernet {
packet.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType) {
TYPE_SRCROUTING: parse_srcRouting;
default: accept;
}
}
//소스라우팅 헤더가 있다면 bos(스택의 바닥)까지 경로를 추출한다.
state parse_srcRouting {
packet.extract(hdr.srcRoutes.next);
transition select(hdr.srcRoutes.last.bos) {
1: parse_ipv4;
default: parse_srcRouting;
}
}
state parse_ipv4 {
packet.extract(hdr.ipv4);
transition accept;
}
}
/*************************************************************************
************ C H E C K S U M V E R I F I C A T I O N *************
*************************************************************************/
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
apply { }
}
/*************************************************************************
************** I N G R E S S P R O C E S S I N G *******************
*************************************************************************/
control MyIngress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
action drop() {
mark_to_drop(standard_metadata);
}
//소스라우팅 헤더의 스택에서 경로 하나를 pop한다.
action srcRoute_nhop() {
standard_metadata.egress_spec = (bit<9>)hdr.srcRoutes[0].port;
hdr.srcRoutes.pop_front(1);
}
//패킷에 지정한 모든 경로를 다 돌았다면 패킷 헤더(이더넷 헤더타입)을 ipv4로 바꾼다.
action srcRoute_finish() {
hdr.ethernet.etherType = TYPE_IPV4;
}
action update_ttl(){
hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
}
apply {
if (hdr.srcRoutes[0].isValid()){
if (hdr.srcRoutes[0].bos == 1){//이번 경로가 마지막이라면 패킷을 ipv4로 바꾼다.
srcRoute_finish();
}
srcRoute_nhop();//경로를 pop
if (hdr.ipv4.isValid()){
update_ttl();
}
}else{
drop();
}
}
}
/*************************************************************************
**************** E G R E S S P R O C E S S I N G *******************
*************************************************************************/
control MyEgress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
apply { }
}
/*************************************************************************
************* C H E C K S U M C O M P U T A T I O N **************
*************************************************************************/
control MyComputeChecksum(inout headers hdr, inout metadata meta) {
apply { }
}
/*************************************************************************
*********************** D E P A R S E R *******************************
*************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) {
apply {
packet.emit(hdr.ethernet);
packet.emit(hdr.srcRoutes);
packet.emit(hdr.ipv4);
}
}
/*************************************************************************
*********************** S W I T C H *******************************
*************************************************************************/
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
|
튜토리얼 실행결과
토폴로지의 모든 스위치를 모두 돌아서 h1→h2로 패킷전송이 성공했다.