...
전공교육 | 개발실습 | 부서교육 | 부서업무지원 | 기타 | |
---|---|---|---|---|---|
P | 교육센터 진행 특강 참여 | P4 튜토리얼 완강 및 복습 | |||
D | |||||
C | |||||
A |
일일회고
2/20
- INT란?
- MRI는 INT의 축소판 및 간편한 방법이라고 생각하면 된다. 튜토리얼 예시 같은 경우 토폴로지를 S1,S2,S3의 스위치가 있고, S1 = h1,h11. S2 = h2,h22. S3=h3 이렇게 연결 되어있으며, 각각의 스위치는 서로 연결 되어 있다. 그러하여 h1 → h2로 패킷을 보낼시에 MRI에 측정되는 SwitchTrace는 2개이며, 카운트 또한 2로 나오게 되는것이다.
코드 블럭 title MRI(Multi-Hop Route Inspection) header ipv4_option_t { //MRI를 이용하기 위한 헤더 선언// bit<1> copyFlag; bit<2> optClass; bit<5> option; bit<8> optionLength; } header mri_t { // mri작동을 위한 count수 설정을 통해 스위치 수 카운트 // bit<16> count; } header switch_t { //MRI를 이용하면서 지나는 switch의 이름과 qdepth를 저장하기 위한 헤더 선언// switchID_t swid; qdepth_t qdepth; } state parse_ipv4_option { //패킷을 수신한 후에 분석을 위해 헤더를 하나씩 분해 할 경우에 MRI 헤더가 있을 경우에 parse_mri를 이용// packet.extract(hdr.ipv4_option); transition select(hdr.ipv4_option.option) { IPV4_OPTION_MRI: parse_mri; default: accept; } } state parse_mri { //mri 패킷 수신후 헤더를 분해하여 parse_swtrace의 상태로 보내는 함수 // packet.extract(hdr.mri); meta.parser_metadata.remaining = hdr.mri.count; transition select(meta.parser_metadata.remaining) { 0 : accept; default: parse_swtrace; } } state parse_swtrace { //parse_swtrace로 보내진 패킷의 헤더의 값을 수정 후 0이 될때까지 반복하는 상태 함수// packet.extract(hdr.swtraces.next); meta.parser_metadata.remaining = meta.parser_metadata.remaining - 1; transition select(meta.parser_metadata.remaining) { 0 : accept; default: parse_swtrace; } } action add_swtrace(switchID_t swid) { //switch를 지날때의 스위치의 이름과 수를 저장하기 위한 함수// hdr.mri.count = hdr.mri.count + 1; hdr.swtraces.push_front(1); // According to the P4_16 spec, pushed elements are invalid, so we need // to call setValid(). Older bmv2 versions would mark the new header(s) // valid automatically (P4_14 behavior), but starting with version 1.11, // bmv2 conforms with the P4_16 spec. hdr.swtraces[0].setValid(); hdr.swtraces[0].swid = swid; hdr.swtraces[0].qdepth = (qdepth_t)standard_metadata.deq_qdepth; hdr.ipv4.ihl = hdr.ipv4.ihl + 2; hdr.ipv4_option.optionLength = hdr.ipv4_option.optionLength + 8; hdr.ipv4.totalLen = hdr.ipv4.totalLen + 8; } table swtrace { actions = { add_swtrace; NoAction; } default_action = NoAction(); }
- Source Routing
- Source Routing이란?
코드 블럭 title Source Routing header srcRoute_t { //Source Routing을 위한 헤더 선언// bit<1> bos; bit<15> port; } state parse_ethernet { // 이전의 경우는 이더넷 헤더 분석후 IPV4로 갔지만 소스 라운팅 헤터가 생김으로써 소스라우팅 헤더를 먼저 분석 한 후 헤더가 없을 시에 IPV4로 진행된다. packet.extract(hdr.ethernet); transition select(hdr.ethernet.etherType) { TYPE_SRCROUTING: parse_srcRouting; default: accept; } } state parse_srcRouting { packet.extract(hdr.srcRoutes.next); transition select(hdr.srcRoutes.last.bos) { 1: parse_ipv4; default: parse_srcRouting; } } action srcRoute_nhop() { //소스 라우팅에서 카운트를 통해 헤더 분석시에 필요한 갯수를 저장한다.// standard_metadata.egress_spec = (bit<9>)hdr.srcRoutes[0].port; hdr.srcRoutes.pop_front(1); } action srcRoute_finish() { hdr.ethernet.etherType = TYPE_IPV4; } apply { //nhop에 따라서 ipv4가 유효할경우에 ipv4 액션으로 넘어가게 한다.// if (hdr.srcRoutes[0].isValid()){ if (hdr.srcRoutes[0].bos == 1){ srcRoute_finish(); } srcRoute_nhop(); if (hdr.ipv4.isValid()){ update_ttl(); } }else{ drop(); } }
2/21
- Load Balancing
- 로드 밸런싱(Load Balancing)이란? - 수 많은 트래픽들을 처리하기 위해서 균등하게 모든 사용자에게 트래픽을 배분하여 제공해서 네트워크 과부하를 막는 기능.
코드 블럭 title Load Balancing //5 tuple에 hash알고리즘을 적용하고, 결과를 mata.ecmp_select에 저장하는 행동, ecmp_nhop 테이블은 이를 이용하여 전송 // action set_ecmp_select(bit<16> ecmp_base, bit<32> ecmp_count) { hash(meta.ecmp_select, HashAlgorithm.crc16, ecmp_base, { hdr.ipv4.srcAddr, hdr.ipv4.dstAddr, hdr.ipv4.protocol, hdr.tcp.srcPort, hdr.tcp.dstPort }, ecmp_count); } // ipv4가 유효하고, ttl이 0에 도달하지 않았을 경우 전송을 실시한다. // apply { if (hdr.ipv4.isValid() && hdr.ipv4.ttl > 0) { ecmp_group.apply(); ecmp_nhop.apply(); } }
- QOS(Quality Of Service)
- QOS란?
코드 블럭 title QoS //트래픽 클래스에 따라 액션을 분류하여 전송할 수 있도록 여러 경우를 나누어 함수 선언// /* Default Forwarding */ action default_forwarding() { hdr.ipv4.diffserv = 0; } /* Expedited Forwarding */ action expedited_forwarding() { hdr.ipv4.diffserv = 46; } /* Voice Admit */ action voice_admit() { hdr.ipv4.diffserv = 44; } /* Assured Forwarding */ /* Class 1 Low drop probability */ action af_11() { hdr.ipv4.diffserv = 10; } /* Class 1 Med drop probability */ action af_12() { hdr.ipv4.diffserv = 12; } /* Class 1 High drop probability */ action af_13() { hdr.ipv4.diffserv = 14; } /* Class 2 Low drop probability */ action af_21() { hdr.ipv4.diffserv = 18; } /* Class 2 Med drop probability */ action af_22() { hdr.ipv4.diffserv = 20; } /* Class 2 High drop probability */ action af_23() { hdr.ipv4.diffserv = 22; } /* Class 3 Low drop probability */ action af_31() { hdr.ipv4.diffserv = 26; } /* Class 3 Med drop probability */ action af_32() { hdr.ipv4.diffserv = 28; } /* Class 3 High drop probability */ action af_33() { hdr.ipv4.diffserv = 30; } /* Class 4 Low drop probability */ action af_41() { hdr.ipv4.diffserv = 34; } /* Class 4 Med drop probability */ action af_42() { hdr.ipv4.diffserv = 36; } /* Class 4 High drop probability */ action af_43() { hdr.ipv4.diffserv = 38; }
2/22
Tutorial에서 제공하는 예제의 토폴로지는 스위치 4개, 호스트 4개로 구성되어 있다. 그 중에 h1-h2는 s1과 연결, h3-h4는 s2와 연결 되어있는데, 이 예제에서는 s1에 p4를 이용한 스위치를 두고, bloom 방식의 firewall을 이용하여 h1,h2는 외부에 패킷을 보내 통신을 할 수 있지만, h3-h4는 h1-h2에 먼저 패킷을 보내서 통신을 할 수는 없다. 이것이 방화벽이라는 걸 알려주는 예제이다.
코드 블럭 title FireWall // bloom 필터를 이용하여 방화벽을 구현하기 위한 함수 // apply { if (hdr.ipv4.isValid()){ ipv4_lpm.apply(); if (hdr.tcp.isValid()){ direction = 0; // default if (check_ports.apply().hit) { // test and set the bloom filter if (direction == 0) { compute_hashes(hdr.ipv4.srcAddr, hdr.ipv4.dstAddr, hdr.tcp.srcPort, hdr.tcp.dstPort); } else { compute_hashes(hdr.ipv4.dstAddr, hdr.ipv4.srcAddr, hdr.tcp.dstPort, hdr.tcp.srcPort); } // Packet comes from internal network if (direction == 0){ //호스트에서 나가는 패킷인 경우 // If there is a syn we update the bloom filter and add the entry if (hdr.tcp.syn == 1){ bloom_filter_1.write(reg_pos_one, 1); bloom_filter_2.write(reg_pos_two, 1); } } // Packet comes from outside else if (direction == 1){ //호스트에서 들어오는 패킷인 경우 // Read bloom filter cells to check if there are 1's bloom_filter_1.read(reg_val_one, reg_pos_one); bloom_filter_2.read(reg_val_two, reg_pos_two); // only allow flow to pass if both entries are set if (reg_val_one != 1 || reg_val_two != 1){ drop(); } } } } } }
2/23
- Link Monitoring
패킷을 보낼시에 스위치별 포트별 전송 속도 및 정보를 알기 위한 기능. 네트워크 관리를 위한 기능.
코드 블럭 title Link_Monitor // 최상위 프로브 헤더이며, 홉 카운트를 저장합니다. header probe_t { bit<8> hop_cnt; } // 각 홉에서 스위치에 의해 프로브에 추가된 데이터를 저장하는 헤더. header probe_data_t { bit<1> bos; bit<7> swid; bit<8> port; bit<32> byte_cnt; time_t last_time; time_t cur_time; } // 스위치가 송신하는 출력 포트를 저장하는 헤더. header probe_fwd_t { bit<8> egress_spec; } --------------------------------------------------------------------------------------------------------- // 패킷을 받고 스위치에서 패킷을 분석 할때 헤더에 따라서 행해야 하는 행동을 지시하는 Parser부분에 추가한 // 헤더들에 맞게 상태 함수를 추가하여준다. state parse_probe { packet.extract(hdr.probe); // 최상위 프로브 헤더 meta.parser_metadata.remaining = hdr.probe.hop_cnt + 1; transition select(hdr.probe.hop_cnt) { 0: parse_probe_fwd; default: parse_probe_data; } } state parse_probe_data { // 프로브 데이터 헤더 packet.extract(hdr.probe_data.next); transition select(hdr.probe_data.last.bos) { 1: parse_probe_fwd; default: parse_probe_data; } } state parse_probe_fwd { // 출력 포트를 저장하는 헤더. packet.extract(hdr.probe_fwd.next); meta.parser_metadata.remaining = meta.parser_metadata.remaining - 1; // extract the forwarding data meta.egress_spec = hdr.probe_fwd.last.egress_spec; transition select(meta.parser_metadata.remaining) { 0: accept; default: parse_probe_fwd; } } --------------------------------------------------------------------------------------------------------- apply { bit<32> byte_cnt; bit<32> new_byte_cnt; time_t last_time; time_t cur_time = standard_metadata.egress_global_timestamp; // 패킷 포트에 대한 bit의 cnt 증가 byte_cnt_reg.read(byte_cnt, (bit<32>)standard_metadata.egress_port); byte_cnt = byte_cnt + standard_metadata.packet_length; // 바이트 카운트를 리셋 new_byte_cnt = (hdr.probe.isValid()) ? 0 : byte_cnt; byte_cnt_reg.write((bit<32>)standard_metadata.egress_port, new_byte_cnt); if (hdr.probe.isValid()) { // 프로브 필드 입력 hdr.probe_data.push_front(1); hdr.probe_data[0].setValid(); if (hdr.probe.hop_cnt == 1) { hdr.probe_data[0].bos = 1; } else { hdr.probe_data[0].bos = 0; } // set switch ID field swid.apply(); hdr.probe_data[0].port = (bit<8>)standard_metadata.egress_port; hdr.probe_data[0].byte_cnt = byte_cnt; // read / update the last_time_reg last_time_reg.read(last_time, (bit<32>)standard_metadata.egress_port); last_time_reg.write((bit<32>)standard_metadata.egress_port, cur_time); hdr.probe_data[0].last_time = last_time; hdr.probe_data[0].cur_time = cur_time; } }