Skip to content

Commit e84173d

Browse files
committed
ofproto-dpif: Separately track the initial VLAN TCI of arriving packets.
In an upcoming commit, VLAN splinters can cause the VLAN TCI of a packet received on an interface to differ from the logical VLAN TCI. That is, a packet that is received on a Linux VLAN network device has no VLAN (so its initial VLAN TCI is 0) but we logically treat it as if it has the VLAN associated with the VLAN device. This is only desirable for use with VLAN splinters and should be reverted when this feature is no longer needed. I'm breaking it out here only to make the series easier to review.
1 parent b95fc6b commit e84173d

1 file changed

Lines changed: 79 additions & 31 deletions

File tree

ofproto/ofproto-dpif.c

Lines changed: 79 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ struct action_xlate_ctx {
229229

230230
static void action_xlate_ctx_init(struct action_xlate_ctx *,
231231
struct ofproto_dpif *, const struct flow *,
232-
const struct ofpbuf *);
232+
ovs_be16 initial_tci, const struct ofpbuf *);
233233
static struct ofpbuf *xlate_actions(struct action_xlate_ctx *,
234234
const union ofp_action *in, size_t n_in);
235235

@@ -352,12 +352,17 @@ struct subfacet {
352352
struct nlattr *actions; /* Datapath actions. */
353353

354354
bool installed; /* Installed in datapath? */
355+
356+
/* This value is normally the same as ->facet->flow.vlan_tci. Only VLAN
357+
* splinters can cause it to differ. This value should be removed when
358+
* the VLAN splinters feature is no longer needed. */
359+
ovs_be16 initial_tci; /* Initial VLAN TCI value. */
355360
};
356361

357362
static struct subfacet *subfacet_create(struct ofproto_dpif *, struct facet *,
358363
enum odp_key_fitness,
359364
const struct nlattr *key,
360-
size_t key_len);
365+
size_t key_len, ovs_be16 initial_tci);
361366
static struct subfacet *subfacet_find(struct ofproto_dpif *,
362367
const struct nlattr *key, size_t key_len,
363368
const struct flow *);
@@ -2217,6 +2222,7 @@ struct flow_miss {
22172222
enum odp_key_fitness key_fitness;
22182223
const struct nlattr *key;
22192224
size_t key_len;
2225+
ovs_be16 initial_tci;
22202226
struct list packets;
22212227
};
22222228

@@ -2306,7 +2312,8 @@ process_special(struct ofproto_dpif *ofproto, const struct flow *flow,
23062312
static struct flow_miss *
23072313
flow_miss_create(struct hmap *todo, const struct flow *flow,
23082314
enum odp_key_fitness key_fitness,
2309-
const struct nlattr *key, size_t key_len)
2315+
const struct nlattr *key, size_t key_len,
2316+
ovs_be16 initial_tci)
23102317
{
23112318
uint32_t hash = flow_hash(flow, 0);
23122319
struct flow_miss *miss;
@@ -2323,6 +2330,7 @@ flow_miss_create(struct hmap *todo, const struct flow *flow,
23232330
miss->key_fitness = key_fitness;
23242331
miss->key = key;
23252332
miss->key_len = key_len;
2333+
miss->initial_tci = initial_tci;
23262334
list_init(&miss->packets);
23272335
return miss;
23282336
}
@@ -2368,7 +2376,8 @@ handle_flow_miss(struct ofproto_dpif *ofproto, struct flow_miss *miss,
23682376
}
23692377

23702378
subfacet = subfacet_create(ofproto, facet,
2371-
miss->key_fitness, miss->key, miss->key_len);
2379+
miss->key_fitness, miss->key, miss->key_len,
2380+
miss->initial_tci);
23722381

23732382
LIST_FOR_EACH_SAFE (packet, next_packet, list_node, &miss->packets) {
23742383
list_remove(&packet->list_node);
@@ -2425,6 +2434,22 @@ handle_flow_miss(struct ofproto_dpif *ofproto, struct flow_miss *miss,
24252434
}
24262435
}
24272436

2437+
static enum odp_key_fitness
2438+
ofproto_dpif_extract_flow_key(const struct ofproto_dpif *ofproto OVS_UNUSED,
2439+
const struct nlattr *key, size_t key_len,
2440+
struct flow *flow, ovs_be16 *initial_tci)
2441+
{
2442+
enum odp_key_fitness fitness;
2443+
2444+
fitness = odp_flow_key_to_flow(key, key_len, flow);
2445+
if (fitness == ODP_FIT_ERROR) {
2446+
return fitness;
2447+
}
2448+
*initial_tci = flow->vlan_tci;
2449+
2450+
return fitness;
2451+
}
2452+
24282453
static void
24292454
handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
24302455
size_t n_upcalls)
@@ -2450,11 +2475,14 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
24502475
for (upcall = upcalls; upcall < &upcalls[n_upcalls]; upcall++) {
24512476
enum odp_key_fitness fitness;
24522477
struct flow_miss *miss;
2478+
ovs_be16 initial_tci;
24532479
struct flow flow;
24542480

24552481
/* Obtain metadata and check userspace/kernel agreement on flow match,
24562482
* then set 'flow''s header pointers. */
2457-
fitness = odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
2483+
fitness = ofproto_dpif_extract_flow_key(ofproto,
2484+
upcall->key, upcall->key_len,
2485+
&flow, &initial_tci);
24582486
if (fitness == ODP_FIT_ERROR) {
24592487
continue;
24602488
}
@@ -2470,7 +2498,7 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
24702498

24712499
/* Add other packets to a to-do list. */
24722500
miss = flow_miss_create(&todo, &flow, fitness,
2473-
upcall->key, upcall->key_len);
2501+
upcall->key, upcall->key_len, initial_tci);
24742502
list_push_back(&miss->packets, &upcall->packet->list_node);
24752503
}
24762504

@@ -2521,21 +2549,28 @@ static void
25212549
handle_userspace_upcall(struct ofproto_dpif *ofproto,
25222550
struct dpif_upcall *upcall)
25232551
{
2524-
struct flow flow;
25252552
struct user_action_cookie cookie;
2553+
enum odp_key_fitness fitness;
2554+
ovs_be16 initial_tci;
2555+
struct flow flow;
25262556

25272557
memcpy(&cookie, &upcall->userdata, sizeof(cookie));
25282558

2559+
fitness = ofproto_dpif_extract_flow_key(ofproto, upcall->key,
2560+
upcall->key_len, &flow,
2561+
&initial_tci);
2562+
if (fitness == ODP_FIT_ERROR) {
2563+
return;
2564+
}
2565+
25292566
if (cookie.type == USER_ACTION_COOKIE_SFLOW) {
25302567
if (ofproto->sflow) {
2531-
odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
2532-
dpif_sflow_received(ofproto->sflow, upcall->packet, &flow, &cookie);
2568+
dpif_sflow_received(ofproto->sflow, upcall->packet, &flow,
2569+
&cookie);
25332570
}
25342571
ofpbuf_delete(upcall->packet);
2535-
25362572
} else if (cookie.type == USER_ACTION_COOKIE_CONTROLLER) {
25372573
COVERAGE_INC(ofproto_dpif_ctlr_action);
2538-
odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
25392574
send_packet_in_action(ofproto, upcall->packet, upcall->userdata,
25402575
&flow, false);
25412576
} else {
@@ -2947,7 +2982,8 @@ facet_account(struct ofproto_dpif *ofproto, struct facet *facet)
29472982
if (facet->has_learn || facet->has_normal) {
29482983
struct action_xlate_ctx ctx;
29492984

2950-
action_xlate_ctx_init(&ctx, ofproto, &facet->flow, NULL);
2985+
action_xlate_ctx_init(&ctx, ofproto, &facet->flow,
2986+
facet->flow.vlan_tci, NULL);
29512987
ctx.may_learn = true;
29522988
ofpbuf_delete(xlate_actions(&ctx, facet->rule->up.actions,
29532989
facet->rule->up.n_actions));
@@ -3135,7 +3171,8 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct facet *facet)
31353171
struct ofpbuf *odp_actions;
31363172
bool should_install;
31373173

3138-
action_xlate_ctx_init(&ctx, ofproto, &facet->flow, NULL);
3174+
action_xlate_ctx_init(&ctx, ofproto, &facet->flow,
3175+
subfacet->initial_tci, NULL);
31393176
odp_actions = xlate_actions(&ctx, new_rule->up.actions,
31403177
new_rule->up.n_actions);
31413178
actions_changed = (subfacet->actions_len != odp_actions->size
@@ -3281,7 +3318,7 @@ flow_push_stats(const struct rule_dpif *rule,
32813318
push.bytes = bytes;
32823319
push.used = used;
32833320

3284-
action_xlate_ctx_init(&push.ctx, ofproto, flow, NULL);
3321+
action_xlate_ctx_init(&push.ctx, ofproto, flow, flow->vlan_tci, NULL);
32853322
push.ctx.resubmit_hook = push_resubmit;
32863323
ofpbuf_delete(xlate_actions(&push.ctx,
32873324
rule->up.actions, rule->up.n_actions));
@@ -3319,7 +3356,7 @@ subfacet_find__(struct ofproto_dpif *ofproto,
33193356
static struct subfacet *
33203357
subfacet_create(struct ofproto_dpif *ofproto, struct facet *facet,
33213358
enum odp_key_fitness key_fitness,
3322-
const struct nlattr *key, size_t key_len)
3359+
const struct nlattr *key, size_t key_len, ovs_be16 initial_tci)
33233360
{
33243361
uint32_t key_hash = odp_flow_key_hash(key, key_len);
33253362
struct subfacet *subfacet;
@@ -3346,6 +3383,7 @@ subfacet_create(struct ofproto_dpif *ofproto, struct facet *facet,
33463383
subfacet->key_len = key_len;
33473384
}
33483385
subfacet->installed = false;
3386+
subfacet->initial_tci = initial_tci;
33493387

33503388
return subfacet;
33513389
}
@@ -3413,7 +3451,8 @@ subfacet_make_actions(struct ofproto_dpif *p, struct subfacet *subfacet,
34133451
struct ofpbuf *odp_actions;
34143452
struct action_xlate_ctx ctx;
34153453

3416-
action_xlate_ctx_init(&ctx, p, &facet->flow, packet);
3454+
action_xlate_ctx_init(&ctx, p, &facet->flow, subfacet->initial_tci,
3455+
packet);
34173456
odp_actions = xlate_actions(&ctx, rule->up.actions, rule->up.n_actions);
34183457
facet->tags = ctx.tags;
34193458
facet->may_install = ctx.may_set_up_flow;
@@ -3690,7 +3729,7 @@ rule_execute(struct rule *rule_, const struct flow *flow,
36903729
struct ofpbuf *odp_actions;
36913730
size_t size;
36923731

3693-
action_xlate_ctx_init(&ctx, ofproto, flow, packet);
3732+
action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, packet);
36943733
odp_actions = xlate_actions(&ctx, rule->up.actions, rule->up.n_actions);
36953734
size = packet->size;
36963735
if (execute_odp_actions(ofproto, flow, odp_actions->data,
@@ -4562,10 +4601,13 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
45624601
static void
45634602
action_xlate_ctx_init(struct action_xlate_ctx *ctx,
45644603
struct ofproto_dpif *ofproto, const struct flow *flow,
4565-
const struct ofpbuf *packet)
4604+
ovs_be16 initial_tci, const struct ofpbuf *packet)
45664605
{
45674606
ctx->ofproto = ofproto;
45684607
ctx->flow = *flow;
4608+
ctx->base_flow = ctx->flow;
4609+
ctx->base_flow.tun_id = 0;
4610+
ctx->base_flow.vlan_tci = initial_tci;
45694611
ctx->packet = packet;
45704612
ctx->may_learn = packet != NULL;
45714613
ctx->resubmit_hook = NULL;
@@ -4586,8 +4628,6 @@ xlate_actions(struct action_xlate_ctx *ctx,
45864628
ctx->nf_output_iface = NF_OUT_DROP;
45874629
ctx->recurse = 0;
45884630
ctx->original_priority = ctx->flow.priority;
4589-
ctx->base_flow = ctx->flow;
4590-
ctx->base_flow.tun_id = 0;
45914631
ctx->table_id = 0;
45924632
ctx->exit = false;
45934633

@@ -5289,7 +5329,7 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
52895329
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
52905330
odp_flow_key_from_flow(&key, flow);
52915331

5292-
action_xlate_ctx_init(&ctx, ofproto, flow, packet);
5332+
action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, packet);
52935333
odp_actions = xlate_actions(&ctx, ofp_actions, n_ofp_actions);
52945334
dpif_execute(ofproto->dpif, key.data, key.size,
52955335
odp_actions->data, odp_actions->size, packet);
@@ -5492,6 +5532,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
54925532
struct ofpbuf odp_key;
54935533
struct ofpbuf *packet;
54945534
struct rule_dpif *rule;
5535+
ovs_be16 initial_tci;
54955536
struct ds result;
54965537
struct flow flow;
54975538
char *s;
@@ -5501,6 +5542,17 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
55015542
ds_init(&result);
55025543

55035544
dpname = strtok_r(args, " ", &save_ptr);
5545+
if (!dpname) {
5546+
unixctl_command_reply(conn, 501, "Bad command syntax");
5547+
goto exit;
5548+
}
5549+
5550+
ofproto = ofproto_dpif_lookup(dpname);
5551+
if (!ofproto) {
5552+
unixctl_command_reply(conn, 501, "Unknown ofproto (use ofproto/list "
5553+
"for help)");
5554+
goto exit;
5555+
}
55045556
arg1 = strtok_r(NULL, " ", &save_ptr);
55055557
arg2 = strtok_r(NULL, " ", &save_ptr);
55065558
arg3 = strtok_r(NULL, " ", &save_ptr);
@@ -5518,8 +5570,10 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
55185570
}
55195571

55205572
/* Convert odp_key to flow. */
5521-
error = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
5522-
if (error) {
5573+
error = ofproto_dpif_extract_flow_key(ofproto, odp_key.data,
5574+
odp_key.size, &flow,
5575+
&initial_tci);
5576+
if (error == ODP_FIT_ERROR) {
55235577
unixctl_command_reply(conn, 501, "Invalid flow");
55245578
goto exit;
55255579
}
@@ -5558,18 +5612,12 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
55585612
free(s);
55595613

55605614
flow_extract(packet, priority, tun_id, in_port, &flow);
5615+
initial_tci = flow.vlan_tci;
55615616
} else {
55625617
unixctl_command_reply(conn, 501, "Bad command syntax");
55635618
goto exit;
55645619
}
55655620

5566-
ofproto = ofproto_dpif_lookup(dpname);
5567-
if (!ofproto) {
5568-
unixctl_command_reply(conn, 501, "Unknown ofproto (use ofproto/list "
5569-
"for help)");
5570-
goto exit;
5571-
}
5572-
55735621
ds_put_cstr(&result, "Flow: ");
55745622
flow_format(&result, &flow);
55755623
ds_put_char(&result, '\n');
@@ -5582,7 +5630,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
55825630

55835631
trace.result = &result;
55845632
trace.flow = flow;
5585-
action_xlate_ctx_init(&trace.ctx, ofproto, &flow, packet);
5633+
action_xlate_ctx_init(&trace.ctx, ofproto, &flow, initial_tci, packet);
55865634
trace.ctx.resubmit_hook = trace_resubmit;
55875635
odp_actions = xlate_actions(&trace.ctx,
55885636
rule->up.actions, rule->up.n_actions);

0 commit comments

Comments
 (0)