...
전공교육 | 개발실습 | 부서교육 | 부서업무지원 | 기타 | |
---|---|---|---|---|---|
P | 과학데이터교육 일 3.2시간 이상 수강 | p4 tutorial실습 | |||
D | 과학데이터교육 일 3.2시간 이상 수강 | ECN 실습, QoS 실습, Firewall 실습, Link monitoring 실습, 단순한 계산기 구현 | |||
C | 과학데이터교육 일 3.2시간 이상 수강 | P4 튜토리얼을 끝내고 P4 언어로 간단한 계산기를 구현했다. | |||
A |
일일회고
23/02/20
- Fact : ECN, QoS, Firewall을 실습해보고 코드를 이해했다.
- Feelings : 글로만 배웠던 것들을 코딩을 통해 구현해 보니 신기했다.
- Finding : QoS가 무엇인지 처음 알게 되었고 Firewall에 블룸 필터의 개념을 확실히 알게 되었다.
- Future Action Plan : Link Monitoring 실습, P4 튜토리얼 내용 총 정리
- Feedbacks :
...
- Fact : Link monitoring실습을 하고 이해했다.
- Feelings : P4 튜토리얼을 모두 완료해서 뿌듯했다.
- Finding : P4라는 언어를 통해 SDN을 구성할 수 있다는 것을 어느정도 알 수 있었고 기존 네트워크 계층의 스위치, 라우터와 같은 하드웨어의 기능을 프로그래밍으로 구현할 수 있다는것을 알았다.
- Future Action Plan : 간단한 P4 프로그램 제작
- Feedbacks :
Memo
23/02/
...
22
- Fact : P4로 단순한 계산기를 구현해보고 실행해봤지만 생각대로 동작하지 않았다. 성과취합 추가분을 완성했다.
- Feelings : 보던거랑 실제로 생각해서 구현하는 거랑 난이도가 너무 달랐다.
- Finding : 아직 P4에 대해 1%도 알지 못한다는 것을 알았다.
- Future Action Plan : P4로 만든 단순한 계산기를 생각대로 동작되도록 수정
- Feedbacks :
23/02/23
- Fact : 어제 만든 P4 계산기를 설계대로 동작하도록 수정했다.
- Feelings : 문서를 찾아보는게 가장 정확한 방법이라는 것을 다시 한번 느꼇다.
- Finding : p4가 문제인줄 알고 p4코드만 계속 수정하다가 문서를 봤는데 생각보다 간단한 문제였다. 역시 모를때는 문서를 보는게 제일 정확하다
- Future Action Plan :
- Feedbacks :
23/02/24
- Fact : 문서 정리
- Feelings : 네트워크의 기본도 모르던 처음에 비해 많은 것을 얻은 것 같은 느낌이다.
- Finding : 생각보다 많은 것을 실습했고 많은 것을 얻은 것을 알 수 있었다.
- Future Action Plan :
- Feedbacks :
Memo
23/02/20
- 참고사항
- ECN란? https://aidencom.tistory.com/m/260
- ToS란? http://www.
- ECN란? https://aidencom.tistory.com/m/260
- ToS란? http://www.ktword.co.kr/test/view/view.php?m_temp1=2051
- DiffServ란? http://www.ktword.co.kr/test/view/view.php?m_temp1=7692051
- QoS란DiffServ란? http://www.ktword.co.kr/test/view/view.php?nav=2&no=2035&sh=Qosm_temp1=769
- QoS란? http://www.ktword.co.kr/test/view/view.php?nav=2&no=2035&sh=Qos
- 방화벽과 블룸필터 https://devureak.tistory.com/51
- 동영상 참고
출처 | 왜 | 내용 | 배운 점 및 기억해야할 점 | 비고 |
---|---|---|---|---|
과학데이터교육 인공지능 | 충북대 현장실습 직무교육 | 다양한 에이전트 아키텍처, 상태공간과 탐색문제1,2, 다양한 탐색 문제와 탐색 전략 |
23/02/21
- 참고사항
- 동영상 참고
출처 | 왜 | 내용 | 배운 점 및 기억해야할 점 | 비고 |
---|---|---|---|---|
과학데이터교육 인공지능 | 충북대 현장실습 직무교육 | 문제 해결과 탐색 알고리즘, 탐색 트리와 탐색 알고리즘, 너비 우선 탐색과 균일 비용 탐색, 깊이 우선과 깊이 우선 반복 심화 탐색, 양방향 탐색, 주요 탐색 전략 비교 |
배운 것 및 기억해야할 것
P4 튜토리얼 Explicit Congestion Notification(ECN)의 이해
사전조건
23/02/22
- 참고사항
- 사용자 정의 packet을 보낼수 있는 패키지 https://coding-wonderland.tistory.com/30?category=797866
- 동영상 참고
출처 | 왜 | 내용 | 배운 점 및 기억해야할 점 | 비고 |
---|---|---|---|---|
과학데이터교육 인공지능 | 충북대 현장실습 직무교육 | 휴리스틱 탐색법과 최적,최고 우선 탐색, 탐욕적 탐색과 A*탐색, 적대적 탐색, 게임트리의 탐색, 지식 표현과 추론 |
23/02/23
- 참고사항
23/02/24
- 참고사항
- -
배운 것 및 기억해야할 것
P4 튜토리얼 Explicit Congestion Notification(ECN)의 이해
사전조건
s1과 s2의 링크의 대역폭은 512kbps로 제한되어 있다. s1과 s2의 링크의 대역폭은 512kbps로 제한되어 있다. 이상태에서 s1과 s2의 통로를 h11↔h22가 UDP 통신을 하고 h1↔h2가 패킷을 주고 받는 조건이다.
...
코드 블럭 |
---|
/* -*- P4_16 -*- */ #include <core.p4> #include <v1model.p4> const bit<16> TYPE_IPV4 = 0x800; const bit<16> TYPE_PROBE = 0x812; #define MAX_HOPS 10 #define MAX_PORTS 8 /************************************************************************* *********************** H E A D E R S *********************************** *************************************************************************/ typedef bit<9> egressSpec_t; typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; typedef bit<48> time_t; header ethernet_t { macAddr_t dstAddr; macAddr_t 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; ip4Addr_t srcAddr; ip4Addr_t dstAddr; } // Top-level probe header, indicates how many hops this probe // packet has traversed so far. header probe_t { bit<8> hop_cnt; } // The data added to the probe by each switch at each hop. 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; } // Indicates the egress port the switch should send this probe // packet out of. There is one of these headers for each hop. header probe_fwd_t { bit<8> egress_spec; } struct parser_metadata_t { bit<8> remaining; } struct metadata { bit<8> egress_spec; parser_metadata_t parser_metadata; } struct headers { ethernet_t ethernet; ipv4_t ipv4; probe_t probe; probe_data_t[MAX_HOPS] probe_data; probe_fwd_t[MAX_HOPS] probe_fwd; } /************************************************************************* *********************** 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; } // 이더넷 헤더에서 ipv4 패킷인지 프로브 패킷인지 구분해서 헤더를 추출한다. state parse_ethernet { packet.extract(hdr.ethernet); transition select(hdr.ethernet.etherType) { TYPE_IPV4: parse_ipv4; TYPE_PROBE: parse_probe; default: accept; } } state parse_ipv4 { packet.extract(hdr.ipv4); transition accept; } //프로브 패킷이라면 probe 헤더에서 hop_cnt필드로 지나온 hop의 개수를 저장한다. 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; } } //지나온 홉에 개수에 따라 probe_data 헤더를 추출한다. probe_data의 bos가 1 즉, 마지막 probe_data까지 추출했다면 probe_fwd를 추출한다. 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; } } //probe_fwd를 추출한다. probe_fwd는 이 패킷이 지나갈 경로를 나타내는 헤더이다. 현재 지나온 hop의 개수에 맞게 다음 경로(port)를 추출하는 것이다. 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; } } } /************************************************************************* ************ 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(); } apply { if (hdr.ipv4.isValid()) { ipv4_lpm.apply(); } else if (hdr.probe.isValid()) { //다음 경로(port)를 설정한다. standard_metadata.egress_spec = (bit<9>)meta.egress_spec; //지나온 hop의 개수를 증가시킨다. hdr.probe.hop_cnt = hdr.probe.hop_cnt + 1; } } } /************************************************************************* **************** 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) { // count the number of bytes seen since the last probe //register는 각각의 스위치의 저장공간에 해당된다. register<bit<32>>(MAX_PORTS) byte_cnt_reg; // remember the time of the last probe register<time_t>(MAX_PORTS) last_time_reg; action set_swid(bit<7> swid) { hdr.probe_data[0].swid = swid; } table swid { actions = { set_swid; NoAction; } default_action = NoAction(); } apply { bit<32> byte_cnt; bit<32> new_byte_cnt; time_t last_time; time_t cur_time = standard_metadata.egress_global_timestamp; // increment byte cnt for this packet's port byte_cnt_reg.read(byte_cnt, (bit<32>)standard_metadata.egress_port); byte_cnt = byte_cnt + standard_metadata.packet_length; // reset the byte count when a probe packet passes through 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()) { // fill out probe fields 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; } } } /************************************************************************* ************* 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.probe); packet.emit(hdr.probe_data); packet.emit(hdr.probe_fwd); } } /************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/ V1Switch( MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser() ) main; |
...
맨 밑줄이 프로브 패킷의 첫 시작이므로 윗 줄로 갈수록 각 포트에서 전송된 바이트가 점점 증가하는 것을 볼 수 있다.
P4로 만든 간단한 계산기
설계
코드 블럭 |
---|
header calc_t{
bit<2> operator;
bit<7> operand1;
bit<7> operand2;
bit<7> result;
bit<1> padding;
} |
사진과 같은 간단한 토폴로지를 이용해서 h1에서 h2로 연산자(0→ 더하기, 1→ 빼기, 2→ 곱하기)와 operand1,2를 헤더에 담아 보내면 s1에서 result에 해당하는 연산의 값을 저장하여 h2에 전달한다.
코드 구현
코드 블럭 |
---|
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>
//새로운 헤더의 임시 타입넘버
const bit<16> TYPE_CALC = 0x1213;
/*************************************************************************
*********************** 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 calc_t{
bit<2> operator;
bit<7> operand1;
bit<7> operand2;
bit<7> result;
bit<1> padding;
}
struct metadata {
/* empty */
}
struct headers {
ethernet_t ethernet;
calc_t calc;
}
/*************************************************************************
*********************** 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_CALC:parse_calc;
default:accept;
}
}
state parse_calc{
packet.extract(hdr.calc);
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 calc_operand(macAddr_t dstAddr,egressSpec_t port, bit<2> operator) {
if (operator==0){
hdr.calc.result=hdr.calc.operand1+hdr.calc.operand2;
}
else if (operator==1){
hdr.calc.result=hdr.calc.operand1-hdr.calc.operand2;
}
else if (operator==2){
hdr.calc.result=hdr.calc.operand1*hdr.calc.operand2;
}
standard_metadata.egress_spec = port;
hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
hdr.ethernet.dstAddr = dstAddr;
}
table operator_exact {
key = {
hdr.calc.operator: exact;
}
actions = {
calc_operand;
drop;
NoAction;
}
size = 1024;
default_action = drop();
}
apply {
if (hdr.calc.isValid()) {
operator_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 { }
}
/*************************************************************************
*********************** D E P A R S E R *******************************
*************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) {
apply {
packet.emit(hdr.ethernet);
packet.emit(hdr.calc);
}
}
/*************************************************************************
*********************** S W I T C H *******************************
*************************************************************************/
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main; |
1차 실행결과
h1에서 h2로 패킷을 보내도 h2에서 받은 패킷의 헤더를 파싱해보면 result에 초기값이 들어있다.
패킷을 보내는 과정을 제대로 손봐야 할것 같다.
코드 수정
simple_calc.p4
코드 블럭 | ||
---|---|---|
| ||
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>
const bit<16> TYPE_CALC = 0x1213;
/*************************************************************************
*********************** 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 calc_t{//각 필드의 비트값을 1byte로 수정
bit<8> operator;
bit<8> operand1;
bit<8> operand2;
bit<8> result;
}
struct metadata {
/* empty */
}
struct headers {
ethernet_t ethernet;
calc_t calc;
}
...동일
/*************************************************************************
************** 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 calc_operand(macAddr_t dstAddr,egressSpec_t port, bit<8> operator) {//operator의 bit를 1byte로 수정
if (operator==0){
hdr.calc.result=hdr.calc.operand1+hdr.calc.operand2;
}
else if (operator==1){
hdr.calc.result=hdr.calc.operand1-hdr.calc.operand2;
}
else if (operator==2){
hdr.calc.result=hdr.calc.operand1*hdr.calc.operand2;
}
else if (operator==3){
hdr.calc.result=hdr.calc.operand1+hdr.calc.operand2;
}
standard_metadata.egress_spec = port;
hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
hdr.ethernet.dstAddr = dstAddr;
}
...동일 |
send.py
h1에서 h2로 패킷을 보낼 때 사용하는 파이썬 스크립트
코드 블럭 | ||
---|---|---|
| ||
#!/usr/bin/env python3
import argparse
import random
import socket
from Calc_header import Calc
from scapy.all import *
TYPE_CALC = 0x1213
def get_if():
ifs=get_if_list()
iface=None # "h1-eth0"
for i in get_if_list():
if "eth0" in i:
iface=i
break;
if not iface:
print("Cannot find eth0 interface")
exit(1)
return iface
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--operator', type=int, help="0:+, 1:-, 2:*, 3:/")
parser.add_argument('--oper1', type=int, help="operand1")
parser.add_argument('--oper2', type=int, help='operand2')
args = parser.parse_args()
operator = args.operator
oper1 = args.oper1
oper2=args.oper2
iface = get_if()
pkt = Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff')
pkt = pkt / Calc(operator=operator,operand1=oper1,operand2=oper2)
pkt.show2()
sendp(pkt, iface=iface, verbose=False)
if __name__ == '__main__':
main() |
receive.py
h2에서 h1의 패킷을 받아서 출력하는 스크립트 파일
코드 블럭 |
---|
#!/usr/bin/env python3
import os
import sys
from scapy.all import (
TCP,
FieldLenField,
FieldListField,
IntField,
IPOption,
ShortField,
get_if_list,
sniff
)
from scapy.layers.inet import _IPOption_HDR
from Calc_header import Calc
def get_if():
ifs=get_if_list()
iface=None
for i in get_if_list():
if "eth0" in i:
iface=i
break;
if not iface:
print("Cannot find eth0 interface")
exit(1)
return iface
def handle_pkt(pkt):
print("got a packet")
pkt.show2()
def main():
ifaces = [i for i in os.listdir('/sys/class/net/') if 'eth' in i]
iface = ifaces[0]
print("sniffing on %s" % iface)
sys.stdout.flush()
sniff(iface = iface,
prn = lambda x: handle_pkt(x))
if __name__ == '__main__':
main()
|
calc_header.py
simplecalc.p4에서 구현한대로 만들 헤더, 이를 사용해서 send.py에서는 임의로 만든 calc헤더가 담긴 패킷을 보낼 수 있으며 receive.py에서는 받은 패킷을 clac헤더의 필드에 맞게 파싱하여 출력할수 있다.
코드 블럭 | ||
---|---|---|
| ||
from scapy.all import *
TYPE_MYTUNNEL = 0x1213
class Calc(Packet):
name = "Calc"
fields_desc = [
ByteField("operator", 0),
ByteField("operand1", 0),
ByteField("operand2", 0),
ByteField("result", 0)
]
bind_layers(Ether, Calc, type=TYPE_MYTUNNEL) |
topology.json
설계한 토폴로지
코드 블럭 | ||
---|---|---|
| ||
{
"hosts": {
"h1": {"ip": "10.0.1.1/24", "mac": "08:00:00:00:01:11",
"commands":["route add default gw 10.0.1.10 dev eth0",
"arp -i eth0 -s 10.0.1.10 08:00:00:00:01:00"]},
"h2": {"ip": "10.0.2.2/24", "mac": "08:00:00:00:02:22",
"commands":["route add default gw 10.0.1.10 dev eth0",
"arp -i eth0 -s 10.0.1.10 08:00:00:00:01:00"]}
},
"switches": {
"s1": { "runtime_json" : "pod-topo/s1-runtime.json" }
},
"links": [
["h1", "s1-p1"], ["h2","s1-p2"]
]
}
|
s1-runtime.json
s1의 포워딩 테이블 정적 정의
코드 블럭 | ||
---|---|---|
| ||
{
"target": "bmv2",
"p4info": "build/basic.p4.p4info.txt",
"bmv2_json": "build/basic.json",
"table_entries": [
{
"table": "MyIngress.operator_exact",
"default_action": true,
"action_name": "MyIngress.drop",
"action_params": { }
},
{
"table": "MyIngress.operator_exact",
"match": {
"hdr.calc.operator": 0
},
"action_name": "MyIngress.calc_operand",
"action_params": {
"dstAddr": "08:00:00:00:02:22",
"port": 2,
"operator":0
}
},
{
"table": "MyIngress.operator_exact",
"match": {
"hdr.calc.operator": 1
},
"action_name": "MyIngress.calc_operand",
"action_params": {
"dstAddr": "08:00:00:00:02:22",
"port": 2,
"operator":1
}
},
{
"table": "MyIngress.operator_exact",
"match": {
"hdr.calc.operator": 2
},
"action_name": "MyIngress.calc_operand",
"action_params": {
"dstAddr": "08:00:00:00:02:22",
"port": 2,
"operator":2
}
},
{
"table": "MyIngress.operator_exact",
"match": {
"hdr.calc.operator": 3
},
"action_name": "MyIngress.calc_operand",
"action_params": {
"dstAddr": "08:00:00:00:02:22",
"port": 2,
"operator":3
}
}
]
}
|
2차 결과
h1에서 h2로 clac헤더의 operator필드에 1, operand1필드에 10 operand2필드에 6을 넣어서 패킷을 보냈을 때 h2에서 받은 패킷의 calc헤더의 result 필드가 16으로 바뀐것을 볼수있다.
operator를 1로 했을 때는 뺴기연산, operator를 2로 했을 때는 곱하기 연산의 결과가 result필드에 들어간것을 볼 수 있다.
수정 내용
p4에서 정의한 헤더와 보내는 패킷이 다른 것이 문제였다. p4의 파서는 패킷의 헤더를 처음부터 파싱하며 정의한 헤더에 맞게 파싱하기 때문에 헤더 정의를 잘못 했거나 정의에 맞지 않는 패킷을 보내면 p4에서는 패킷의 헤더를 잘못 파싱 할 수밖에 없다
그렇기 때문에 지금까지 bos같은 스택의 마지막인지를 확인하는 필드를 넣거나 몇개의 헤더가 추가적으로 있는지에 대한 필드를 넣거나해서 개수에 맞게 파싱을 한것을 알 수 있었다.