@@ -229,7 +229,7 @@ struct action_xlate_ctx {
229229
230230static 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 * );
233233static 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
357362static 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 );
361366static 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,
23062312static struct flow_miss *
23072313flow_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+
24282453static void
24292454handle_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
25212549handle_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,
33193356static struct subfacet *
33203357subfacet_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,
45624601static void
45634602action_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