...
전공교육 | 개발실습 | 부서교육 | 부서업무지원 | 기타 | |
---|---|---|---|---|---|
P | 과학데이터교육 일 3.2시간 이상 수강 | p4 tutorial실습 | 우수성과취합 마무리 | ||
D | 텍스트 데이터분석 수강, 인공지능 부분 수강 | basic forwarding 실습, basic tunnel 실습,P4runtime실습, mri 실습,소스라우트 실습, 부하분산 실습 | 우수성과 취합 마무리 및 검토 | ||
C | 텍스트 데이터분석 수강, 인공지능 부분 수강 | basic forwarding 실습, basic tunnel 실습,P4runtime실습, mri 실습,소스라우트 실습, 부하분산 실습 및 이해 | 우수성과 취합 마무리 및 검토 | ||
A |
일일회고
23/02/13
- Fact : P4 실습환경을 구축하고 기본적인 forwarding 을 실습해보았다, 우수성과취합을 진행했다.
- Feelings : 새로운 언어를 배우는 것은 언제나 어렵지만 c언어와 비슷한 면이 있어서 다행이다.
- Finding : 네트워크를 효율적으로 관리하는 프로그래밍 언어가 있다는 것을 처음 알았다.
- Future Action Plan : 우수성과 취합, P4 튜토리얼을 보면서 다음 내용 실습
- Feedbacks :
...
- Fact : P4 튜토리얼의 P4runtime과 mri를 실습해보고 이해하였다.
- Feelings : 생각보다 경로를 추척하기 위한 mri의 구조가 단순해서 놀랐다.
- Finding : 첫날에 들었던 INT의 축소된 버전을 해보면서 어떤식으로 경로를 모니터링 할 수 있는지 알았다.
- Future Action Plan : P4 소스포워딩
- Feedbacks :
23/02/17
- Fact : P4 튜토리얼의 P4sourceroute와 P4 loadbalancing을 실습해보고 이해하였다.
- Feelings : 어느정도 기본적인 P4 코드를 짤 수 있을 것 같다.
- Finding : 새로운 소스라우트와 로드밸런싱을 배웠다.
- Future Action Plan : P4의 남은 튜토리얼 수행
- Feedbacks :
Memo
23/02/13
- 참고사항
- P4 튜토리얼 https://github.com/p4lang/tutorials
- P4 실습환경 구축
- https://github.com/p4lang/tutorials/tree/master/exercises/basic P4 basic forwarding 튜토리얼 실습
- P4 언어 공식 문서 https://p4.org/specs/
- 동영상 참고
...
출처 | 왜 | 내용 | 배운 점 및 기억해야할 점 | 비고 |
---|---|---|---|---|
과학데이터교육 텍스트데이터분석 | 충북대 현장실습 직무교육 | 데이터 시각화, 정형-비정형 데이터 분석 모델 기획, 공공 데이터 분석, 분석 목적 인사이트 도출, 예측 및 데이터 평가 | 텍스트데이터분석 수강 끝 |
23/02/17
- 참고사항
- 동영상 참고
출처 | 왜 | 내용 | 배운 점 및 기억해야할 점 | 비고 |
---|---|---|---|---|
과학데이터교육 인공지능 | 충북대 현장실습 직무교육 | 인공지능의 소개, 인공지능의 발달사, 에이전트 정의 및 지능형 에이전트, 에이전트 환경과 에이전트 아키텍처 | 4차시까지 수강 |
...
코드 블럭 | ||
---|---|---|
| ||
/* -*- P4_16 -*- */ #include <core.p4> #include <v1model.p4> const bit<16> TYPE_IPV4 = 0x800; /************************************************************************* *********************** H E A D E R S *********************************** *************************************************************************/ typedef bit<9> egressSpec_t; typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; //ethernet의 기본 헤더 header ethernet_t { macAddr_t dstAddr; macAddr_t srcAddr; bit<16> etherType; } //IPv4의 기본 헤더 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; ipv4_t ipv4; } /************************************************************************* *********************** P A R S E R *********************************** *************************************************************************/ //패킷에서 헤더를 분리 //packet_in packet은 스위치에 들어오는 패킷 //out headers hdr은 패킷에서 분리된 헤더들이 각각 저장될 변수같은것 //start 상태로 시작해서 모든 헤더 분리가 정상적으로 끝난다면 accept 상태로 이동해서 정상종료, 아니라면 ignore 상태로 이동 parser MyParser(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { //패킷을 처음으로 전달받아서 시작된 상태 state start { //parse_ethernet으로 상태 이동 transition parse_ethernet; } state parse_ethernet { //패킷에서 ethernet헤더에 맞게 분리/추출 packet.extract(hdr.ethernet); //패킷에서 분리된 ethernet 헤더에서 etherType 값이 위에서 정의된 TYPE_IPV4 0x800라면 parse_ipv4 상태로 이동, 0x800이 아닌 상태(default)라면 accept상태로 이동 -> 즉 c언어의 switch 같은 문법 transition select(hdr.ethernet.etherType) { TYPE_IPV4: parse_ipv4; default: accept; } } state parse_ipv4 { //패킷에서 추가적으로 ipv4 헤더 분리/추출 packet.extract(hdr.ipv4); //패킷에서 추출 후에 accept 상태로 이동 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 ******************* *************************************************************************/ //table을 참조하면서 패킷이 다음으로 이동할 경로 설정 control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { //table에 match되는 ipv4의 dstAddr이 없다면 패킷을 삭제한다. action drop() { mark_to_drop(standard_metadata); } //table에 match되는 ipv4의 dstAddr이 있다면 실행되는 action으로 알맞은 dstAddr와 port를 인수로 전달받는다. action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { //해당 스위치/호스트에서 송신할때 쓰는 포트를 설정 //standard_metadata는 v1model 아키텍처에 의해 전달받은 구조체이며 패킷의 다양한 정보가 들어있다. 특히 standard_metadata.egress_spec는 패킷이 이동할 출력포트를 지정한다. standard_metadata.egress_spec = port; //이더넷의 헤더안의 srtAddr과 dstAddr을 알맞게 설정한다. hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; hdr.ethernet.dstAddr = dstAddr; //패킷이 이동할 때마다 ipv4의 ttl을 1씩 줄어들게한다. hdr.ipv4.ttl = hdr.ipv4.ttl - 1; } //테이블을 정의한다. table ipv4_lpm { //테이블의 key와 match되는 방식을 설정한다. key = { hdr.ipv4.dstAddr: lpm; } //테이블의 모든 액션을 정의한다. actions = { ipv4_forward; drop; NoAction; } size = 1024; //기본 액션을 정의한다. default_action = drop(); } //컨트롤 실행 apply { //ipv4가 유효하다면 테이블 매칭을 실행한다. if (hdr.ipv4.isValid()) { ipv4_lpm.apply(); } } } /************************************************************************* **************** 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 ************** *************************************************************************/ //ipv4 헤더의 내용이 변경되었으므로 체크섬 값도 그에 맞게 변경 control MyComputeChecksum(inout headers hdr, inout metadata meta) { apply { update_checksum( hdr.ipv4.isValid(), { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffserv, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }, hdr.ipv4.hdrChecksum, HashAlgorithm.csum16); } } /************************************************************************* *********************** D E P A R S E R ******************************* *************************************************************************/ //새롭게 변경된 헤더들을 패킷으로 다시 묶음 control MyDeparser(packet_out packet, in headers hdr) { apply { packet.emit(hdr.ethernet); packet.emit(hdr.ipv4); } } /************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/ //v1model의 기본적인 switch 아키텍처 V1Switch( MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser() ) main; |
...
코드 블럭 |
---|
/* -*- P4_16 -*- */ #include <core.p4> #include <v1model.p4> //새로운 사용자 설정 이더넷 타입 추가 const bit<16> TYPE_MYTUNNEL = 0x1212; const bit<16> TYPE_IPV4 = 0x800; /************************************************************************* *********************** 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 myTunnel_t { bit<16> proto_id; bit<16> dst_id; } 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; myTunnel_t myTunnel; 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) { //이더넷타입이 새로 만든 타입이라면 parse_myTunnel로 헤더 분리 이더넷타입에 따른 파서를 수행한다. TYPE_MYTUNNEL: parse_myTunnel; TYPE_IPV4: parse_ipv4; default: accept; } } state parse_myTunnel { //터널링 헤더 분리 packet.extract(hdr.myTunnel); //이후에 터널링 헤더 안의 proto_id가 ipv4라면 ipv4 헤더도 분리 transition select(hdr.myTunnel.proto_id) { TYPE_IPV4: parse_ipv4; default: accept; } } 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); } action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { standard_metadata.egress_spec = port; hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; hdr.ethernet.dstAddr = dstAddr; hdr.ipv4.ttl = hdr.ipv4.ttl - 1; } table ipv4_lpm { key = { hdr.ipv4.dstAddr: lpm; } actions = { ipv4_forward; drop; NoAction; } size = 1024; default_action = drop(); } //터널링에 사용되는 action, 터널의 다음 터널이 존재하는목적지 포트를 인수로 받는다 action myTunnel_forward(egressSpec_t port) { //나가는 포트를 설정 standard_metadata.egress_spec = port; } //새로운 테이블 설정 table myTunnel_exact { key = { //터널링 헤더의 dst_id를 key로 설정하고 구별 방법을 exact로 설정 hdr.myTunnel.dst_id: exact; } actions = { //알맞는 action 설정 myTunnel_forward; drop; } size = 1024; default_action = drop(); } apply { //ipv4헤더가 유효하고 터널링 헤더가 유효하지 않다면 ipv4테이블로 포워딩을 진행한다. if (hdr.ipv4.isValid() && !hdr.myTunnel.isValid()) { // Process only non-tunneled IPv4 packets ipv4_lpm.apply(); } //터널링헤더가 유효하다면 터널링 테이블로 포워딩 if (hdr.myTunnel.isValid()) { // process tunneled packets myTunnel_exact.apply(); } } } /************************************************************************* **************** 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 { update_checksum( hdr.ipv4.isValid(), { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffserv, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }, hdr.ipv4.hdrChecksum, HashAlgorithm.csum16); } } /************************************************************************* *********************** D E P A R S E R ******************************* *************************************************************************/ control MyDeparser(packet_out packet, in headers hdr) { apply { packet.emit(hdr.ethernet); //터널링 헤드도 같이 디파서 한다. packet.emit(hdr.myTunnel); packet.emit(hdr.ipv4); } } /************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/ V1Switch( MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser() ) main; |
...
토폴로지의 모든 스위치를 모두 돌아서 h1→h2로 패킷전송이 성공했다.
P4 튜토리얼 Load balancing의 이해
사전 조건
간단한 버전의 Equal-Cost Multipath Forwarding을 기반으로 한 형태의 로드 밸런싱을 구현합니다. 구현할 스위치는 두 개의 테이블을 사용하여 임의로 두 개의 대상 호스트 중 하나로 패킷을 전달합니다. 첫 번째 테이블은 해시 함수(소스 및 대상 IP 주소, IP 프로토콜, 소스 및 대상 TCP 포트로 구성된 5-튜플에 적용됨)를 사용하여 두 호스트 중 하나를 선택합니다. 두 번째 테이블은 계산된 해시 값을 사용하여 선택한 호스트로 패킷을 전달합니다.
튜토리얼 코드 리뷰
코드 블럭 |
---|
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>
/*************************************************************************
*********************** H E A D E R S ***********************************
*************************************************************************/
header ethernet_t {
bit<48> dstAddr;
bit<48> srcAddr;
bit<16> etherType;
}
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;
bit<32> srcAddr;
bit<32> dstAddr;
}
//tcp 헤더
header tcp_t {
bit<16> srcPort;
bit<16> dstPort;
bit<32> seqNo;
bit<32> ackNo;
bit<4> dataOffset;
bit<3> res;
bit<3> ecn;
bit<6> ctrl;
bit<16> window;
bit<16> checksum;
bit<16> urgentPtr;
}
//ecmp 선택자
struct metadata {
bit<14> ecmp_select;
}
struct headers {
ethernet_t ethernet;
ipv4_t ipv4;
tcp_t tcp;
}
/*************************************************************************
*********************** 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) {
0x800: parse_ipv4;
default: accept;
}
}
state parse_ipv4 {
packet.extract(hdr.ipv4);
transition select(hdr.ipv4.protocol) {
6: parse_tcp;
default: accept;
}
}
state parse_tcp {
packet.extract(hdr.tcp);
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);
}
action set_ecmp_select(bit<16> ecmp_base, bit<32> ecmp_count) {
//소스 및 대상 IP 주소, IP 프로토콜, 소스 및 대상 TCP 포트로 해쉬값을 얻고 ecmp_select에 저장한다.
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);
}
action set_nhop(bit<48> nhop_dmac, bit<32> nhop_ipv4, bit<9> port) {//나갈 포드를 지정한다.
hdr.ethernet.dstAddr = nhop_dmac;
hdr.ipv4.dstAddr = nhop_ipv4;
standard_metadata.egress_spec = port;
hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
}
table ecmp_group {//어떤 ecmp 그룹인지를 판별한다.
key = {
hdr.ipv4.dstAddr: lpm;
}
actions = {
drop;
set_ecmp_select;
}
size = 1024;
}
table ecmp_nhop {//ecmp그룹에 맞는 목적지, 경로를 지정한다.
key = {
meta.ecmp_select: exact;
}
actions = {
drop;
set_nhop;
}
size = 2;
}
apply {
if (hdr.ipv4.isValid() && hdr.ipv4.ttl > 0) {
ecmp_group.apply();
ecmp_nhop.apply();
}
}
}
/*************************************************************************
**************** 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) {
//이더넷의 srcAddr을 수정한다.
action rewrite_mac(bit<48> smac) {
hdr.ethernet.srcAddr = smac;
}
action drop() {
mark_to_drop(standard_metadata);
}
table send_frame {//나가는 포트에 맞게 이더넷 헤더 수정
key = {
standard_metadata.egress_port: exact;
}
actions = {
rewrite_mac;
drop;
}
size = 256;
}
apply {
send_frame.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 {
update_checksum(
hdr.ipv4.isValid(),
{ hdr.ipv4.version,
hdr.ipv4.ihl,
hdr.ipv4.diffserv,
hdr.ipv4.totalLen,
hdr.ipv4.identification,
hdr.ipv4.flags,
hdr.ipv4.fragOffset,
hdr.ipv4.ttl,
hdr.ipv4.protocol,
hdr.ipv4.srcAddr,
hdr.ipv4.dstAddr },
hdr.ipv4.hdrChecksum,
HashAlgorithm.csum16);
}
}
/*************************************************************************
*********************** D E P A R S E R *******************************
*************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) {
apply {
packet.emit(hdr.ethernet);
packet.emit(hdr.ipv4);
packet.emit(hdr.tcp);
}
}
/*************************************************************************
*********************** S W I T C H *******************************
*************************************************************************/
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
|
튜토리얼 실행결과
h1에서 자기 자신에게 보낼 패킷을 보내면 패킷의 TCP 헤더에 따라 목적지 호스트가 바뀌는 것을 볼 수 있다.