Skip to content

Commit 6ab0ba4

Browse files
author
Mihai Budiu
authored
Support header stacks in lookahead (#2468)
* Support header stacks in lookahead
1 parent 37a1590 commit 6ab0ba4

28 files changed

+739
-58
lines changed

midend/expandLookahead.cpp

+27-36
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,47 @@ limitations under the License.
2020

2121
namespace P4 {
2222

23-
void DoExpandLookahead::expandSetValid(const IR::Expression* base, const IR::Type* type,
24-
IR::IndexedVector<IR::StatOrDecl>* output) {
25-
if (type->is<IR::Type_Struct>()) {
26-
auto st = type->to<IR::Type_Struct>();
27-
for (auto f : st->fields) {
28-
auto t = typeMap->getTypeType(f->type, true);
29-
if (t == nullptr)
30-
return;
31-
auto mem = new IR::Member(base, f->name);
32-
expandSetValid(mem, t, output);
33-
}
34-
} else if (type->is<IR::Type_Header>()) {
35-
auto setValid = new IR::Member(base, IR::Type_Header::setValid);
36-
auto mc = new IR::MethodCallExpression(setValid);
37-
output->push_back(new IR::MethodCallStatement(mc));
38-
}
39-
}
40-
41-
const IR::Expression* DoExpandLookahead::expand(
42-
const IR::PathExpression* base, const IR::Type* type, unsigned* offset) {
23+
void DoExpandLookahead::expand(
24+
const IR::PathExpression* bitvector, // source value containing all bits
25+
const IR::Type* type, // type that is being extracted from source
26+
unsigned* offset, // current bit offset in source
27+
const IR::Expression* destination, // result is assigned to this expression
28+
IR::IndexedVector<IR::StatOrDecl>* output) { // add here new assignments
4329
if (type->is<IR::Type_Struct>() || type->is<IR::Type_Header>()) {
44-
auto vec = new IR::IndexedVector<IR::NamedExpression>();
30+
if (type->is<IR::Type_Header>()) {
31+
auto setValid = new IR::Member(destination, IR::Type_Header::setValid);
32+
auto mc = new IR::MethodCallExpression(setValid);
33+
output->push_back(new IR::MethodCallStatement(mc));
34+
}
4535
auto st = type->to<IR::Type_StructLike>();
4636
for (auto f : st->fields) {
4737
auto t = typeMap->getTypeType(f->type, true);
4838
if (t == nullptr)
4939
continue;
50-
auto e = expand(base, t, offset);
51-
vec->push_back(new IR::NamedExpression(f->srcInfo, f->name, e));
40+
auto member = new IR::Member(destination, f->name);
41+
expand(bitvector, t, offset, member, output);
5242
}
53-
auto type = st->getP4Type()->to<IR::Type_Name>();
54-
return new IR::StructExpression(
55-
base->srcInfo, type, type, *vec);
5643
} else if (type->is<IR::Type_Bits>() || type->is<IR::Type_Boolean>()) {
5744
unsigned size = type->width_bits();
5845
BUG_CHECK(size > 0, "%1%: unexpected size %2%", type, size);
5946
const IR::Expression* expression =
60-
new IR::Slice(base->clone(), *offset - 1, *offset - size);
47+
new IR::Slice(bitvector->clone(), *offset - 1, *offset - size);
6148
auto tb = type->to<IR::Type_Bits>();
6249
if (!tb || tb->isSigned)
6350
expression = new IR::Cast(type, expression);
6451
*offset -= size;
65-
return expression;
52+
auto assignment = new IR::AssignmentStatement(
53+
bitvector->srcInfo, destination, expression);
54+
output->push_back(assignment);
55+
} else if (auto ts = type->to<IR::Type_Stack>()) {
56+
unsigned elements = ts->getSize();
57+
auto etype = ts->elementType;
58+
for (unsigned i = 0; i < elements; i++) {
59+
auto member = new IR::ArrayIndex(destination, new IR::Constant(i));
60+
expand(bitvector, etype, offset, member, output);
61+
}
6662
} else {
67-
::error("%1%: unexpected type in lookahead argument", type);
68-
return nullptr;
63+
::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected type in lookahead argument", type);
6964
}
7065
}
7166

@@ -129,12 +124,8 @@ const IR::Node* DoExpandLookahead::postorder(IR::AssignmentStatement* statement)
129124
auto result = new IR::BlockStatement;
130125
result->push_back(ei->statement);
131126

132-
expandSetValid(statement->left->clone(), ei->origType, &result->components);
133-
auto init = expand(ei->tmp->clone(), ei->origType, &ei->width);
134-
if (init == nullptr)
135-
return statement;
136-
auto assignment = new IR::AssignmentStatement(statement->srcInfo, statement->left, init);
137-
result->push_back(assignment);
127+
expand(ei->tmp->clone(), ei->origType, &ei->width,
128+
statement->left->clone(), &result->components);
138129
return result;
139130
}
140131

midend/expandLookahead.h

+9-6
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ namespace P4 {
2727
/// Given an assignment like
2828
/// a = lookahead<T>();
2929
/// this is transformed into
30-
/// bit<X> tmp = lookahead<sizeof<T>>();
31-
/// a = { tmp[f1,f0], tmp[f2, f1+1], ... }
30+
/// bit<sizeof(T)> tmp = lookahead<bit<sizeof(T)>>();
31+
/// a.m.setValid(); // for header fields
32+
/// a.m0 = tmp[f1,f0];
33+
/// a.m1 = tmp[f2, f1+1];
34+
/// ...
3235
class DoExpandLookahead : public Transform {
3336
P4::ReferenceMap* refMap;
3437
P4::TypeMap* typeMap;
@@ -41,10 +44,10 @@ class DoExpandLookahead : public Transform {
4144
const IR::PathExpression* tmp; // temporary used for result
4245
};
4346

44-
const IR::Expression* expand(
45-
const IR::PathExpression* base, const IR::Type* type, unsigned* offset);
46-
void expandSetValid(const IR::Expression* base, const IR::Type* type,
47-
IR::IndexedVector<IR::StatOrDecl>* output);
47+
void expand(
48+
const IR::PathExpression* bitvector, const IR::Type* type, unsigned* offset,
49+
const IR::Expression* destination,
50+
IR::IndexedVector<IR::StatOrDecl>* output);
4851
ExpansionInfo* convertLookahead(const IR::MethodCallExpression* expression);
4952

5053
public:

testdata/p4_14_samples_outputs/09-IPv4OptionsUnparsed-midend.p4

-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout
7676
@name(".parse_ipv4") state parse_ipv4 {
7777
tmp = packet.lookahead<bit<160>>();
7878
tmp_hdr_0.setValid();
79-
tmp_hdr_0.setValid();
8079
tmp_hdr_0.version = tmp[159:156];
8180
tmp_hdr_0.ihl = tmp[155:152];
8281
tmp_hdr_0.diffserv = tmp[151:144];

testdata/p4_14_samples_outputs/TLV_parsing-midend.p4

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout
113113
@name(".parse_ipv4_option_timestamp") state parse_ipv4_option_timestamp {
114114
tmp_0 = packet.lookahead<bit<16>>();
115115
tmp_hdr_0.setValid();
116-
tmp_hdr_0.setValid();
117116
tmp_hdr_0.value = tmp_0[15:8];
118117
tmp_hdr_0.len = tmp_0[7:0];
119118
packet.extract<ipv4_option_timestamp_t>(hdr.ipv4_option_timestamp, ((bit<32>)tmp_0[7:0] << 3) + 32w4294967280);

testdata/p4_14_samples_outputs/issue576-midend.p4

-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout
6868
packet.extract<simpleipv4_t>(hdr.sh.next);
6969
tmp = packet.lookahead<bit<160>>();
7070
tmp_hdr_1.setValid();
71-
tmp_hdr_1.setValid();
7271
tmp_hdr_1.version = tmp[159:156];
7372
tmp_hdr_1.ihl = tmp[155:152];
7473
tmp_hdr_1.diffserv = tmp[151:144];
@@ -84,7 +83,6 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout
8483
packet.extract<ipv4_t>(hdr.h.next, ((bit<32>)tmp[155:152] << 5) + 32w4294967136);
8584
tmp_0 = packet.lookahead<bit<160>>();
8685
tmp_hdr_2.setValid();
87-
tmp_hdr_2.setValid();
8886
tmp_hdr_2.version = tmp_0[159:156];
8987
tmp_hdr_2.ihl = tmp_0[155:152];
9088
tmp_hdr_2.diffserv = tmp_0[151:144];

testdata/p4_14_samples_outputs/issue781-midend.p4

-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout
4747
@name(".start") state start {
4848
tmp = packet.lookahead<bit<160>>();
4949
tmp_hdr_0.setValid();
50-
tmp_hdr_0.setValid();
5150
tmp_hdr_0.version = tmp[159:156];
5251
tmp_hdr_0.ihl = tmp[155:152];
5352
tmp_hdr_0.diffserv = tmp[151:144];
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
Copyright (c) Intel Corp.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#include <v1model.p4>
18+
19+
header h1 {
20+
bit<8> f1;
21+
}
22+
23+
struct h {
24+
h1[3] h;
25+
}
26+
27+
struct m {
28+
bit<8> h_count;
29+
}
30+
31+
parser MyParser(packet_in b, out h hdrs, inout m meta, inout standard_metadata_t std) {
32+
state start {
33+
h l;
34+
l = b.lookahead<h>();
35+
transition select(l.h[0].f1, l.h[1].f1, l.h[2].f1) {
36+
(1, _, _) : one;
37+
(0, 1, _) : two;
38+
(0, 0, 1) : three;
39+
default: many;
40+
}
41+
}
42+
43+
state one {
44+
b.extract(hdrs.h.next);
45+
meta.h_count = 1;
46+
transition accept;
47+
}
48+
49+
state two {
50+
b.extract(hdrs.h.next);
51+
b.extract(hdrs.h.next);
52+
meta.h_count = 2;
53+
transition accept;
54+
}
55+
56+
state three {
57+
b.extract(hdrs.h.next);
58+
b.extract(hdrs.h.next);
59+
b.extract(hdrs.h.next);
60+
meta.h_count = 2;
61+
transition accept;
62+
}
63+
64+
state many {
65+
meta.h_count = 255;
66+
transition accept;
67+
}
68+
}
69+
70+
control MyVerifyChecksum(inout h hdr, inout m meta) {
71+
apply {}
72+
}
73+
control MyIngress(inout h hdr, inout m meta, inout standard_metadata_t std) {
74+
apply { }
75+
}
76+
control MyEgress(inout h hdr, inout m meta, inout standard_metadata_t std) {
77+
apply { }
78+
}
79+
80+
control MyComputeChecksum(inout h hdr, inout m meta) {
81+
apply {}
82+
}
83+
control MyDeparser(packet_out b, in h hdr) {
84+
apply { }
85+
}
86+
87+
V1Switch(MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser()) main;

testdata/p4_16_samples_outputs/calc-ebpf-midend.p4

-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ parser Parser(packet_in packet, out headers hdr) {
3939
state check_p4calc {
4040
tmp_3 = packet.lookahead<bit<128>>();
4141
tmp.setValid();
42-
tmp.setValid();
4342
tmp.p = tmp_3[127:120];
4443
tmp.four = tmp_3[119:112];
4544
tmp.ver = tmp_3[111:104];
@@ -49,7 +48,6 @@ parser Parser(packet_in packet, out headers hdr) {
4948
tmp.res = tmp_3[31:0];
5049
tmp_4 = packet.lookahead<bit<128>>();
5150
tmp_0.setValid();
52-
tmp_0.setValid();
5351
tmp_0.p = tmp_4[127:120];
5452
tmp_0.four = tmp_4[119:112];
5553
tmp_0.ver = tmp_4[111:104];
@@ -59,7 +57,6 @@ parser Parser(packet_in packet, out headers hdr) {
5957
tmp_0.res = tmp_4[31:0];
6058
tmp_5 = packet.lookahead<bit<128>>();
6159
tmp_1.setValid();
62-
tmp_1.setValid();
6360
tmp_1.p = tmp_5[127:120];
6461
tmp_1.four = tmp_5[119:112];
6562
tmp_1.ver = tmp_5[111:104];

testdata/p4_16_samples_outputs/checksum1-bmv2-midend.p4

-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ parser parserI(packet_in pkt, out headers hdr, inout metadata meta, inout standa
7878
state parse_ipv4 {
7979
tmp_4 = pkt.lookahead<bit<8>>();
8080
tmp.setValid();
81-
tmp.setValid();
8281
tmp.version = tmp_4[7:4];
8382
tmp.ihl = tmp_4[3:0];
8483
pkt.extract<ipv4_t>(hdr.ipv4, (bit<32>)(((bit<9>)tmp_4[3:0] << 2) + 9w492 << 3));

testdata/p4_16_samples_outputs/crc32-bmv2-midend.p4

-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ parser MyParser(packet_in packet, out headers hdr, inout metadata meta, inout st
4343
state check_p4calc {
4444
tmp_3 = packet.lookahead<bit<128>>();
4545
tmp.setValid();
46-
tmp.setValid();
4746
tmp.p = tmp_3[127:120];
4847
tmp.four = tmp_3[119:112];
4948
tmp.ver = tmp_3[111:104];
@@ -53,7 +52,6 @@ parser MyParser(packet_in packet, out headers hdr, inout metadata meta, inout st
5352
tmp.res = tmp_3[31:0];
5453
tmp_4 = packet.lookahead<bit<128>>();
5554
tmp_0.setValid();
56-
tmp_0.setValid();
5755
tmp_0.p = tmp_4[127:120];
5856
tmp_0.four = tmp_4[119:112];
5957
tmp_0.ver = tmp_4[111:104];
@@ -63,7 +61,6 @@ parser MyParser(packet_in packet, out headers hdr, inout metadata meta, inout st
6361
tmp_0.res = tmp_4[31:0];
6462
tmp_5 = packet.lookahead<bit<128>>();
6563
tmp_1.setValid();
66-
tmp_1.setValid();
6764
tmp_1.p = tmp_5[127:120];
6865
tmp_1.four = tmp_5[119:112];
6966
tmp_1.ver = tmp_5[111:104];

testdata/p4_16_samples_outputs/issue1025-bmv2-midend.p4

-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ parser parserI(packet_in pkt, out headers hdr, inout metadata meta, inout standa
7171
state parse_ipv4 {
7272
tmp_2 = pkt.lookahead<bit<8>>();
7373
tmp.setValid();
74-
tmp.setValid();
7574
tmp.version = tmp_2[7:4];
7675
tmp.ihl = tmp_2[3:0];
7776
pkt.extract<ipv4_t>(hdr.ipv4, (bit<32>)((bit<9>)tmp_2[3:0] << 3));

testdata/p4_16_samples_outputs/issue1560-bmv2-midend.p4

-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ parser parserI(packet_in pkt, out headers hdr, inout metadata meta, inout standa
7979
state parse_ipv4 {
8080
tmp_4 = pkt.lookahead<bit<8>>();
8181
tmp.setValid();
82-
tmp.setValid();
8382
tmp.version = tmp_4[7:4];
8483
tmp.ihl = tmp_4[3:0];
8584
pkt.extract<ipv4_t>(hdr.ipv4, (bit<32>)(((bit<9>)tmp_4[3:0] << 2) + 9w492 << 3));

testdata/p4_16_samples_outputs/issue1765-bmv2-midend.p4

-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ parser parserI(packet_in pkt, out headers hdr, inout metadata meta, inout standa
7979
state parse_ipv4 {
8080
tmp_4 = pkt.lookahead<bit<8>>();
8181
tmp.setValid();
82-
tmp.setValid();
8382
tmp.version = tmp_4[7:4];
8483
tmp.ihl = tmp_4[3:0];
8584
pkt.extract<ipv4_t>(hdr.ipv4, (bit<32>)(((bit<9>)tmp_4[3:0] << 2) + 9w492 << 3));

0 commit comments

Comments
 (0)