P4在table中使用ternary匹配

P4支持ternary匹配,也就是对于一个匹配字段,你可以用mask指定这个字段中的哪些bits是你关心的(1表示关心,0表示忽略),从而只匹配你关心的bits的值而忽略其他的值。

那在代码中怎么使用呢?话不多说,直接上代码(P4版本为 P4_16)!

control MyIngress(inout headers hdr,
                  inout metadata meta,
                  inout standard_metadata_t standard_metadata){
	action drop() {
		mark_to_drop(standard_metadata);
	}
	
	action your_action (bit<8> param1, bit<16> param2) {
		// your action logic here
	}
	
	table ipv4_ternary {
		key = {
		    hdr.ipv4.srcAddr: ternary; //ternary匹配ipv4的 src address
		    hdr.ipv4.dstAddr: ternary; //ternary匹配ipv4的 dst address
		}
		actions = {
		    your_action;
		    drop;
		}
		default_action = drop();
		
		//以下代码用于加入表项,同时也展示了如何使用ternary匹配的特性
		const entries = {
		    // 对于每一个ternary字段,表项的值由两部分组成:value &&& mask,先value后mask,顺序一定不能错!
		    // mask表示在这个字段上希望匹配哪些bits,1表示匹配,0表示忽略
		    // 若 匹配字段&mask = value 则匹配成功
	
			// 该表项表示匹配那些ip src address前24位为10.0.1的数据包,而忽略了ip src 
			// address的最后8位以及ip dst address
		    (0x0a000100 &&& 0xffffff00, 0x00000000 &&& 0x00000000): your_action(0x66, 0x8888);
	
			// 该表项表示匹配ip src address为10.0.2.x,且ip dst address为10.0.1.1的数据包
			// 如果mask全为1,则可以省略mask而只写value
			(0x0a000200 &&& 0xffffff00, 0x0a000101): your_action(0x11, 0x2222);
	
			// 最后,由于是ternary匹配,一个数据包可能匹配多条表项,因而表项之间需要有优先级
			// 以上述方式书写表项时,越早出现的表项优先级越高。
			// 当使用控制器动态的加入表项时,应该显式指定插入表项的优先级以确保正确性。
		}
	}
}

当然,除了以const entries的形式写入表项,还可以通过P4 Controller 来写入。以下为如何构造一个新的表项(Python):

table_entry = p4info_helper.buildTableEntry(
            table_name="MyIngress.ipv4_ternary",
            match_fields={
				"hdr.ipv4.srcAddr": (0x0a000200, 0xffffff00), # (value, mask)
				"hdr.ipv4.dstAddr": (0x0b000100, 0xffffff00)
			},
            action_name="MyIngress.your_action",
            action_params={
				"param1": 0x66,
				"param2": 0x1234
			},
            priority=1
)

通过控制器写入表项时要注意一点,如果你不关心某个字段,应该直接在match_fields中直接不写该字段而不是将mask全设为0,这与const entries是不一样的
比如,我们只想匹配src addr而忽略dst addr,我们应该这样写:

table_entry = p4info_helper.buildTableEntry(
            table_name="MyIngress.ipv4_ternary",
            match_fields={
				"hdr.ipv4.srcAddr": (0x0a000200, 0xffffff00)
			},
            action_name="MyIngress.your_action",
            action_params={
				"param1": 0x66,
				"param2": 0x1234
			},
            priority=1
)

而不是:

table_entry = p4info_helper.buildTableEntry(
            table_name="MyIngress.ipv4_ternary",
            match_fields={
				"hdr.ipv4.srcAddr": (0x0a000200, 0xffffff00),
				"hdr.ipv4.dstAddr": (0x00000000, 0x00000000) # 这一行应该被删除!
			},
            action_name="MyIngress.your_action",
            action_params={
				"param1": 0x66,
				"param2": 0x1234
			},
            priority=1
)

否则查询log会发现以下报错:

[bmv2] [E] [thread 11605] [P4Runtime] Invalid representation of ‘don’t care’ ternary match, omit match field instead of using 0 mask

你可能感兴趣的:(P4在table中使用ternary匹配)