enum bit<16> EtherType {
VLAN = 0x8100,
QINQ = 0x9100,
MPLS = 0x8847,
IPV4 = 0x0800,
IPV6 = 0x86dd
}
MPLS
header Mpls_h {
bit<20> label;
bit<3> tc;
bit bos;
bit<8> ttl;
}
Mpls_h[10] mpls;
VLAN学习
字段
长度
含义
取值
TPID
2Byte
Tag Protocol Identifier(标签协议标识符),表示数据帧类型。
取值为0x8100时表示IEEE 802.1Q的VLAN数据帧。如果不支持802.1Q的设备收到这样的帧,会将其丢弃。
各设备厂商可以自定义该字段的值。当邻居设备将TPID值配置为非0x8100时, 为了能够识别这样的报文,实现互通,必须在本设备上修改TPID值,确保和邻居设备的TPID值配置一致。
PRI
3bit
Priority,表示数据帧的802.1p优先级。
取值范围为0~7,值越大优先级越高。当网络阻塞时,交换机优先发送优先级高的数据帧。
CFI
1bit
Canonical Format Indicator(标准格式指示位),表示MAC地址在不同的传输介质中是否以标准格式进行封装,用于兼容以太网和令牌环网。
CFI取值为0表示MAC地址以标准格式进行封装,为1表示以非标准格式封装。在以太网中,CFI的值为0。
VID
12bit
VLAN ID,表示该数据帧所属VLAN的编号。
VLAN ID取值范围是0~4095。由于0和4095为协议保留取值,所以VLAN ID的有效取值范围是1~4094。
重循环recirculate
修改ig_tm_md.ucast_egress_port
将ig_tm_md.bypass_egress设为1
设 ig_dprsr_md.drop_ctl[0:0] = 0;
action recirculate_for_consume(packet_type_t packet_type, PortId_t recirc_port) {
// Drop both data headers now that they've been consumed
hdr.d0.setInvalid();
hdr.d1.setInvalid();
// Send to recirculation port
ig_tm_md.ucast_egress_port = recirc_port;
ig_tm_md.bypass_egress = 1w1;
ig_dprsr_md.drop_ctl[0:0] = 0;
ig_md.switchml_md.packet_type = packet_type;
count_consume = true;
count_recirculate = true;
}
action recirculate_for_harvest(packet_type_t packet_type, PortId_t recirc_port) {
// Recirculate for harvest
ig_tm_md.ucast_egress_port = recirc_port;
ig_tm_md.bypass_egress = 1w1;
ig_dprsr_md.drop_ctl[0:0] = 0;
ig_md.switchml_md.packet_type = packet_type;
}
广播
将 ig_tm_md.mcast_grp_a设为g_md.switchml_md.mgid
将 ig_tm_md.level1_exclusion_id设为 null_level1_exclusion_id
将ig_tm_md.bypass_egress,ig_dprsr_md.drop_ctl[0:0]分别设为0,0
action broadcast() {
hdr.d1.setInvalid();
// Send to multicast group; egress will fill in destination IP and MAC address
ig_tm_md.mcast_grp_a = ig_md.switchml_md.mgid;
ig_tm_md.level1_exclusion_id = null_level1_exclusion_id; // don't exclude any nodes
ig_md.switchml_md.packet_type = packet_type_t.BROADCAST;
ig_tm_md.bypass_egress = 1w0;
ig_dprsr_md.drop_ctl[0:0] = 0;
count_broadcast = true;
}
查看进来的数据包是不是重循环的
if (ig_intr_md.resubmit_flag == 0)
将包设置为重循环
ig_dprsr_md.resubmit_type = 1;
设置包的转发端口
ig_tm_md.ucast_egress_port = N
手动设置table所在的stage
@pragma stage x
设置流量优先级
action set_qid(QueueId_t qid) {
ig_tm_md.qid = qid;
}
控制平面代码的写法
add_with_action_name,第一个参数是table匹配的参数,第二个参数用于给action传参ingress.tbl_do_update_cluster1_dst3_max.add_with_do_update_cluster1_dst3_max(port, port)
.add是为了给Register传参,表示条目下标
ingress.cluster1_dst0_min.add(port)
mod也是为了给Register传参,表示条目下标与对应的值
ingress.updateclusters_counter.mod(port, 0)
注意事项
- action中一般不要写if-else分支,否则会出现Conditional execution in actions unsupported on this target这个错误,把分支写在apply里
- V1MODEL的六个部分一定要严格与标准对应,不能缺少,参数形式也要对应
- struct headers 成员不能是bit和struct的混合,一定要统一