Skip to content

Commit 2c4eaa8

Browse files
committed
ethport: EthFlowFlags => EthFlowDef_Prepare variant
1 parent 47abf17 commit 2c4eaa8

File tree

12 files changed

+169
-199
lines changed

12 files changed

+169
-199
lines changed

csrc/dpdk/ethdev.h

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,63 +7,6 @@
77
#include <rte_ethdev.h>
88
#include <rte_flow.h>
99

10-
/**
11-
* @brief Bit flags for rte_flow preferences.
12-
* @see https://doc.dpdk.org/guides/nics/overview.html "rte_flow items availability"
13-
*
14-
* Bits 0-23 are to describe hardware capabilities.
15-
* Bits 24-31 are to describe API level behaviors.
16-
*/
17-
typedef enum EthFlowFlags {
18-
/**
19-
* @brief How to generate flow items for pass-through face.
20-
* 0 = empty pattern.
21-
* 1 = @c RTE_FLOW_ITEM_TYPE_ETH with EtherType=ARP.
22-
*/
23-
EthFlowFlagsPassthruArp = RTE_BIT32(0),
24-
25-
/**
26-
* @brief How to generate VXLAN flow items.
27-
* 0 = prefer @c RTE_FLOW_ITEM_TYPE_VXLAN and @c RTE_FLOW_ITEM_TYPE_ETH .
28-
* 1 = prefer @c RTE_FLOW_ITEM_TYPE_RAW .
29-
*/
30-
EthFlowFlagsVxRaw = RTE_BIT32(8),
31-
32-
/** @brief Bitmask to indicate how to generate GTP-U flow items. */
33-
EthFlowFlagsGtpMask = RTE_GENMASK32(13, 12),
34-
35-
/** @brief Generate GTP-U flow item as @c RTE_FLOW_ITEM_TYPE_GTPU . */
36-
EthFlowFlagsGtpGtpu = RTE_SHIFT_VAL32(0, 12),
37-
/** @brief Generate GTP-U flow item as @c RTE_FLOW_ITEM_TYPE_GTP . */
38-
EthFlowFlagsGtpGtp = RTE_SHIFT_VAL32(1, 12),
39-
/** @brief Generate GTP-U flow item as @c RTE_FLOW_ITEM_TYPE_RAW . */
40-
EthFlowFlagsGtpRaw = RTE_SHIFT_VAL32(2, 12),
41-
42-
/**
43-
* @brief How to generate actions when RSS is used.
44-
* 0 = keep MARK action.
45-
* 1 = skip MARK action.
46-
*/
47-
EthFlowFlagsRssUnmarked = RTE_BIT32(16),
48-
49-
/**
50-
* @brief How to generate actions for Ethernet face.
51-
* 0 = keep MARK action.
52-
* 1 = skip MARK action.
53-
*/
54-
EthFlowFlagsEtherUnmarked = RTE_BIT32(17),
55-
56-
/** @brief Whether the ethdev is flow isolated. */
57-
EthFlowFlagsIsolated = RTE_BIT32(24),
58-
59-
/** @brief Whether the flow has MARK action set to FaceID. */
60-
EthFlowFlagsMarked = RTE_BIT32(25),
61-
62-
/** @brief Whether rte_flow is unsupported and should not be attempted. */
63-
EthFlowFlagsDisabled = RTE_BIT32(31),
64-
} __rte_packed EthFlowFlags;
65-
static_assert(sizeof(EthFlowFlags) == sizeof(uint32_t), "");
66-
6710
/** @brief Retrieve whether an Ethernet device is DOWN. */
6811
static inline bool
6912
EthDev_IsDown(uint16_t port) {

csrc/ethface/face.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ EthRxFlow_RxBurst(RxGroup* rxg, RxGroupBurstCtx* ctx,
2222
if (mayHaveUnmatched) {
2323
// RCU lock is inherited from RxLoop_Run
2424
PdumpEthPortUnmatchedCtx_Init(&unmatch, rxf->port);
25+
} else {
26+
POISON(&unmatch);
2527
}
2628

2729
for (uint16_t i = 0; i < ctx->nRx; ++i) {
@@ -86,19 +88,41 @@ EthRxFlow_RxBurst_CheckFull(RxGroup* rxg, RxGroupBurstCtx* ctx) {
8688

8789
struct rte_flow*
8890
EthFace_SetupFlow(EthFacePriv* priv, const uint16_t queues[], int nQueues, const EthLocator* loc,
89-
EthFlowFlags flowFlags, struct rte_flow_error* error) {
90-
EthFlowDef def;
91-
EthFlowDef_Prepare(&def, loc, &flowFlags, priv->faceID, queues, nQueues);
92-
93-
struct rte_flow* flow = rte_flow_create(priv->port, &def.attr, def.pattern, def.actions, error);
94-
if (flow == NULL) {
95-
EthFlowDef_UpdateError(&def, error);
96-
return NULL;
91+
bool isolated, struct rte_flow_error* error) {
92+
EthFlowDefResult dres = 0;
93+
struct rte_flow* flow = NULL;
94+
for (uint32_t variant = 0; variant < EthFlowDef_MaxVariant; ++variant) {
95+
EthFlowDef def;
96+
dres = EthFlowDef_Prepare(&def, loc, variant, priv->faceID, queues, nQueues);
97+
if (!(dres & EthFlowDefResultValid)) {
98+
return NULL;
99+
}
100+
101+
int vres = rte_flow_validate(priv->port, &def.attr, def.pattern, def.actions, error);
102+
if (vres == -ENOSYS) {
103+
return NULL;
104+
}
105+
106+
char msg[128];
107+
snprintf(msg, sizeof(msg), "SetupFlow variant=%" PRIu32 " flowdef-result=%d" N_LOG_ERROR_ERRNO,
108+
variant, (int)dres, vres);
109+
EthFlowDef_DebugPrint(&def, msg);
110+
if (vres != 0) {
111+
EthFlowDef_UpdateError(&def, error);
112+
continue;
113+
}
114+
115+
flow = rte_flow_create(priv->port, &def.attr, def.pattern, def.actions, error);
116+
if (flow == NULL) {
117+
EthFlowDef_UpdateError(&def, error);
118+
return NULL;
119+
}
120+
break;
97121
}
98122

99123
RxGroup_RxBurstFunc rxBurst = EthRxFlow_RxBurst_CheckFull;
100-
if (flowFlags & EthFlowFlagsMarked) {
101-
if (flowFlags & EthFlowFlagsIsolated) {
124+
if (dres & EthFlowDefResultMarked) {
125+
if (isolated) {
102126
rxBurst = EthRxFlow_RxBurst_Isolated_CheckOffload;
103127
} else {
104128
rxBurst = EthRxFlow_RxBurst_Unisolated_CheckOffload;

csrc/ethface/face.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ typedef struct EthFacePriv {
3232
/** @brief Setup rte_flow on EthDev for hardware dispatching. */
3333
__attribute__((nonnull)) struct rte_flow*
3434
EthFace_SetupFlow(EthFacePriv* priv, const uint16_t queues[], int nQueues, const EthLocator* loc,
35-
EthFlowFlags flowFlags, struct rte_flow_error* error);
35+
bool isolated, struct rte_flow_error* error);
3636

3737
/** @brief Setup RX for memif. */
3838
__attribute__((nonnull)) void

csrc/ethface/flowdef.c

Lines changed: 86 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ N_LOG_INIT(EthFlowDef);
99

1010
__attribute__((nonnull)) static inline void
1111
AppendItem(EthFlowDef* flow, size_t* i, enum rte_flow_item_type typ, const void* spec,
12-
const void* mask, __rte_unused size_t size) {
12+
const void* mask, size_t size) {
1313
flow->pattern[*i].type = typ;
1414
flow->pattern[*i].spec = spec;
1515
flow->pattern[*i].mask = mask;
16+
flow->patternSpecLen[*i] = size;
1617
++(*i);
1718
NDNDPDK_ASSERT(*i < RTE_DIM(flow->pattern));
1819
}
@@ -45,23 +46,25 @@ PrepareVxlan(const EthLocator* loc, struct rte_vxlan_hdr* vxlanSpec,
4546
PutEtherHdr((uint8_t*)innerEthSpec, loc->innerRemote, loc->innerLocal, 0, EtherTypeNDN);
4647
}
4748

48-
__attribute__((nonnull)) static inline void
49-
GeneratePattern(EthFlowDef* flow, size_t specLen[], const EthLocator* loc, EthLocatorClass c,
50-
EthFlowFlags flowFlags) {
49+
__attribute__((nonnull)) static inline EthFlowDefResult
50+
GeneratePattern(EthFlowDef* flow, const EthLocator* loc, EthLocatorClass c, int variant) {
5151
size_t i = 0;
5252
#define APPEND(typ, field) \
5353
AppendItem(flow, &i, RTE_FLOW_ITEM_TYPE_##typ, &flow->field##Spec, &flow->field##Mask, \
54-
(specLen[i] = sizeof(flow->field##Spec)))
54+
sizeof(flow->field##Spec))
5555

5656
if (c.passthru) {
57-
if (flowFlags & EthFlowFlagsPassthruArp) {
58-
MASK(flow->ethMask.hdr.ether_type);
59-
flow->ethSpec.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP);
60-
APPEND(ETH, eth);
61-
} else {
62-
flow->attr.priority = 1;
57+
switch (variant) {
58+
case 0:
59+
flow->attr.priority = 1;
60+
return EthFlowDefResultValid;
61+
case 1:
62+
MASK(flow->ethMask.hdr.ether_type);
63+
flow->ethSpec.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP);
64+
APPEND(ETH, eth);
65+
return EthFlowDefResultValid;
6366
}
64-
return;
67+
return 0;
6568
}
6669

6770
MASK(flow->ethMask.hdr.dst_addr);
@@ -83,7 +86,7 @@ GeneratePattern(EthFlowDef* flow, size_t specLen[], const EthLocator* loc, EthLo
8386
// don't mask EtherType for IPv4/IPv6 - rejected by i40e driver
8487
MASK(flow->ethMask.hdr.ether_type);
8588
MASK(flow->vlanMask.hdr.eth_proto);
86-
return;
89+
return variant == 0 ? EthFlowDefResultValid : 0;
8790
}
8891
// i40e and several other drivers reject ETH+IP combination, so clear ETH spec
8992
flow->pattern[0].spec = NULL;
@@ -109,40 +112,43 @@ GeneratePattern(EthFlowDef* flow, size_t specLen[], const EthLocator* loc, EthLo
109112

110113
switch (c.tunnel) {
111114
case 'V': {
112-
if (flowFlags & EthFlowFlagsVxRaw) {
113-
struct {
114-
struct rte_vxlan_hdr vxlan;
115-
struct rte_ether_hdr eth;
116-
} __rte_aligned(2) spec = {0}, mask = {0};
117-
PrepareVxlan(loc, &spec.vxlan, &mask.vxlan, &spec.eth, &mask.eth);
118-
static_assert(sizeof(spec) == 4 + 16 + 2, "");
119-
PrepareRawItem(flow, 4, 16, RTE_PTR_ADD(&spec, 4), RTE_PTR_ADD(&mask, 4));
120-
APPEND(RAW, raw);
121-
} else {
122-
PrepareVxlan(loc, &flow->vxlanSpec.hdr, &flow->vxlanMask.hdr, &flow->innerEthSpec.hdr,
123-
&flow->innerEthMask.hdr);
124-
APPEND(VXLAN, vxlan);
125-
APPEND(ETH, innerEth);
115+
switch (variant) {
116+
case 0:
117+
PrepareVxlan(loc, &flow->vxlanSpec.hdr, &flow->vxlanMask.hdr, &flow->innerEthSpec.hdr,
118+
&flow->innerEthMask.hdr);
119+
APPEND(VXLAN, vxlan);
120+
APPEND(ETH, innerEth);
121+
return EthFlowDefResultValid;
122+
case 1: {
123+
struct {
124+
struct rte_vxlan_hdr vxlan;
125+
struct rte_ether_hdr eth;
126+
} __rte_aligned(2) spec = {0}, mask = {0};
127+
PrepareVxlan(loc, &spec.vxlan, &mask.vxlan, &spec.eth, &mask.eth);
128+
static_assert(sizeof(spec) == 4 + 16 + 2, "");
129+
PrepareRawItem(flow, 4, 16, RTE_PTR_ADD(&spec, 4), RTE_PTR_ADD(&mask, 4));
130+
APPEND(RAW, raw);
131+
return EthFlowDefResultValid;
132+
}
133+
default:
134+
return 0;
126135
}
127-
break;
128136
}
129137
case 'G': {
130138
EthGtpHdr spec = {0}, mask = {0};
131139
PutGtpHdr((uint8_t*)&spec, true, loc->ulTEID, loc->ulQFI);
132140

133-
switch (flowFlags & EthFlowFlagsGtpMask) {
134-
case EthFlowFlagsGtpGtpu: {
141+
switch (variant) {
142+
case 0:
135143
APPEND(GTPU, gtp);
136144
goto FILL_GTP_ITEM;
137-
}
138-
case EthFlowFlagsGtpGtp: {
145+
case 1:
139146
APPEND(GTP, gtp);
140147
FILL_GTP_ITEM:
141148
flow->gtpSpec.hdr = spec.hdr;
142149
MASK(flow->gtpMask.hdr.teid);
143-
break;
144-
}
145-
case EthFlowFlagsGtpRaw: {
150+
return EthFlowDefResultValid;
151+
case 2:
146152
// In i40e driver, RAW item can have up to I40E_FDIR_MAX_FLEX_LEN=16 uint16 words, of
147153
// which up to I40E_FDIR_BITMASK_NUM_WORD=2 words may have a "bit mask" i.e. mask other
148154
// than 0000 and FFFF, see i40e_flow_store_flex_mask(). We use bit masks on the first and
@@ -155,11 +161,13 @@ GeneratePattern(EthFlowDef* flow, size_t specLen[], const EthLocator* loc, EthLo
155161
static_assert(sizeof(spec) == 16);
156162
PrepareRawItem(flow, 0, 16, &spec, &mask);
157163
APPEND(RAW, raw);
158-
break;
159-
}
164+
return EthFlowDefResultValid;
165+
default:
166+
return 0;
160167
}
161-
break;
162168
}
169+
default:
170+
return variant == 0 ? EthFlowDefResultValid : 0;
163171
}
164172

165173
#undef APPEND
@@ -173,9 +181,9 @@ MaskSpecOctets(uint8_t* spec, const uint8_t* mask, size_t len) {
173181
}
174182

175183
__attribute__((nonnull)) static inline void
176-
CleanPattern(EthFlowDef* flow, size_t specLen[]) {
184+
CleanPattern(EthFlowDef* flow) {
177185
for (int i = 0;; ++i) {
178-
size_t itemLen = specLen[i];
186+
size_t itemLen = flow->patternSpecLen[i];
179187
struct rte_flow_item* item = &flow->pattern[i];
180188
switch (item->type) {
181189
case RTE_FLOW_ITEM_TYPE_END:
@@ -207,11 +215,9 @@ AppendAction(EthFlowDef* flow, size_t* i, enum rte_flow_action_type typ, const v
207215
NDNDPDK_ASSERT(*i < RTE_DIM(flow->pattern));
208216
}
209217

210-
__attribute__((nonnull)) static inline EthFlowFlags
211-
GenerateActions(EthFlowDef* flow, EthLocatorClass c, EthFlowFlags flowFlags, uint32_t mark,
218+
__attribute__((nonnull)) static inline EthFlowDefResult
219+
GenerateActions(EthFlowDef* flow, EthLocatorClass c, int variant, uint32_t mark,
212220
const uint16_t queues[], int nQueues) {
213-
EthFlowFlags addFlowFlags = 0;
214-
215221
size_t i = 0;
216222
#define APPEND(typ, field) AppendAction(flow, &i, RTE_FLOW_ACTION_TYPE_##typ, &flow->field##Act)
217223

@@ -228,19 +234,44 @@ GenerateActions(EthFlowDef* flow, EthLocatorClass c, EthFlowFlags flowFlags, uin
228234
APPEND(RSS, rss);
229235
}
230236

231-
if (!(((flowFlags & EthFlowFlagsRssUnmarked) && nQueues > 1) ||
232-
((flowFlags & EthFlowFlagsEtherUnmarked) && !c.udp))) {
233-
flow->markAct.id = mark;
234-
APPEND(MARK, mark);
235-
addFlowFlags |= EthFlowFlagsMarked;
237+
if (variant == 1) {
238+
return 0;
236239
}
237240

241+
flow->markAct.id = mark;
242+
APPEND(MARK, mark);
243+
return EthFlowDefResultMarked;
238244
#undef APPEND
239-
return addFlowFlags;
240245
}
241246

242-
__attribute__((nonnull)) static inline void
243-
PrintDef(const EthFlowDef* flow, size_t specLen[]) {
247+
EthFlowDefResult
248+
EthFlowDef_Prepare(EthFlowDef* flow, const EthLocator* loc, int variant, uint32_t mark,
249+
const uint16_t queues[], int nQueues) {
250+
NDNDPDK_ASSERT(variant < EthFlowDef_MaxVariant);
251+
EthLocatorClass c = EthLocator_Classify(loc);
252+
*flow = (const EthFlowDef){
253+
.attr.ingress = 1,
254+
};
255+
256+
EthFlowDefResult res = GeneratePattern(flow, loc, c, variant / 2);
257+
if (!(res & EthFlowDefResultValid)) {
258+
return 0;
259+
}
260+
261+
CleanPattern(flow);
262+
res |= GenerateActions(flow, c, variant % 2, mark, queues, nQueues);
263+
return res;
264+
}
265+
266+
__attribute__((nonnull)) void
267+
EthFlowDef_DebugPrint(const EthFlowDef* flow, const char* msg) {
268+
if (!N_LOG_ENABLED(DEBUG)) {
269+
return;
270+
}
271+
272+
N_LOGD("%s", msg);
273+
N_LOGD("^ attr group=%" PRIu32 " priority=%" PRIu32, flow->attr.group, flow->attr.priority);
274+
244275
for (int i = 0;; ++i) {
245276
const struct rte_flow_item* item = &flow->pattern[i];
246277
enum {
@@ -250,9 +281,9 @@ PrintDef(const EthFlowDef* flow, size_t specLen[]) {
250281
char b16Spec[b16BufSize] = {'-', 0};
251282
char b16Mask[b16BufSize] = {'-', 0};
252283
if (item->spec != NULL && item->mask != NULL) {
253-
NDNDPDK_ASSERT(specLen[i] <= 64);
254-
Base16_Encode(b16Spec, sizeof(b16Spec), item->spec, specLen[i]);
255-
Base16_Encode(b16Mask, sizeof(b16Mask), item->mask, specLen[i]);
284+
NDNDPDK_ASSERT(flow->patternSpecLen[i] <= 64);
285+
Base16_Encode(b16Spec, sizeof(b16Spec), item->spec, flow->patternSpecLen[i]);
286+
Base16_Encode(b16Mask, sizeof(b16Mask), item->mask, flow->patternSpecLen[i]);
256287
}
257288
const char* typeName = NULL;
258289
if (rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR, &typeName, sizeof(&typeName),
@@ -293,25 +324,6 @@ PrintDef(const EthFlowDef* flow, size_t specLen[]) {
293324
}
294325
}
295326

296-
void
297-
EthFlowDef_Prepare(EthFlowDef* flow, const EthLocator* loc, EthFlowFlags* flowFlags, uint32_t mark,
298-
const uint16_t queues[], int nQueues) {
299-
EthLocatorClass c = EthLocator_Classify(loc);
300-
*flow = (const EthFlowDef){0};
301-
flow->attr.ingress = 1;
302-
303-
size_t specLen[RTE_DIM(flow->pattern)];
304-
GeneratePattern(flow, specLen, loc, c, *flowFlags);
305-
CleanPattern(flow, specLen);
306-
*flowFlags |= GenerateActions(flow, c, *flowFlags, mark, queues, nQueues);
307-
308-
if (N_LOG_ENABLED(DEBUG)) {
309-
N_LOGD("Prepare loc=%p flow-flags=%08" PRIx32, loc, *flowFlags);
310-
N_LOGD("^ attr group=%" PRIu32 " priority=%" PRIu32, flow->attr.group, flow->attr.priority);
311-
PrintDef(flow, specLen);
312-
}
313-
}
314-
315327
void
316328
EthFlowDef_UpdateError(const EthFlowDef* flow, struct rte_flow_error* error) {
317329
ptrdiff_t offset = RTE_PTR_DIFF(error->cause, flow);

0 commit comments

Comments
 (0)