@@ -424,7 +424,7 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
424424 [OVS_KEY_ATTR_DP_HASH ] = { .len = sizeof (u32 ) },
425425 [OVS_KEY_ATTR_TUNNEL ] = { .len = OVS_ATTR_NESTED ,
426426 .next = ovs_tunnel_key_lens , },
427- [OVS_KEY_ATTR_MPLS ] = { .len = sizeof ( struct ovs_key_mpls ) },
427+ [OVS_KEY_ATTR_MPLS ] = { .len = OVS_ATTR_VARIABLE },
428428 [OVS_KEY_ATTR_CT_STATE ] = { .len = sizeof (u32 ) },
429429 [OVS_KEY_ATTR_CT_ZONE ] = { .len = sizeof (u16 ) },
430430 [OVS_KEY_ATTR_CT_MARK ] = { .len = sizeof (u32 ) },
@@ -1628,10 +1628,25 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
16281628
16291629 if (attrs & (1 << OVS_KEY_ATTR_MPLS )) {
16301630 const struct ovs_key_mpls * mpls_key ;
1631+ u32 hdr_len ;
1632+ u32 label_count , label_count_mask , i ;
16311633
16321634 mpls_key = nla_data (a [OVS_KEY_ATTR_MPLS ]);
1633- SW_FLOW_KEY_PUT (match , mpls .top_lse ,
1634- mpls_key -> mpls_lse , is_mask );
1635+ hdr_len = nla_len (a [OVS_KEY_ATTR_MPLS ]);
1636+ label_count = hdr_len / sizeof (struct ovs_key_mpls );
1637+
1638+ if (label_count == 0 || label_count > MPLS_LABEL_DEPTH ||
1639+ hdr_len % sizeof (struct ovs_key_mpls ))
1640+ return - EINVAL ;
1641+
1642+ label_count_mask = GENMASK (label_count - 1 , 0 );
1643+
1644+ for (i = 0 ; i < label_count ; i ++ )
1645+ SW_FLOW_KEY_PUT (match , mpls .lse [i ],
1646+ mpls_key [i ].mpls_lse , is_mask );
1647+
1648+ SW_FLOW_KEY_PUT (match , mpls .num_labels_mask ,
1649+ label_count_mask , is_mask );
16351650
16361651 attrs &= ~(1 << OVS_KEY_ATTR_MPLS );
16371652 }
@@ -2114,13 +2129,18 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
21142129 ether_addr_copy (arp_key -> arp_sha , output -> ipv4 .arp .sha );
21152130 ether_addr_copy (arp_key -> arp_tha , output -> ipv4 .arp .tha );
21162131 } else if (eth_p_mpls (swkey -> eth .type )) {
2132+ u8 i , num_labels ;
21172133 struct ovs_key_mpls * mpls_key ;
21182134
2119- nla = nla_reserve (skb , OVS_KEY_ATTR_MPLS , sizeof (* mpls_key ));
2135+ num_labels = hweight_long (output -> mpls .num_labels_mask );
2136+ nla = nla_reserve (skb , OVS_KEY_ATTR_MPLS ,
2137+ num_labels * sizeof (* mpls_key ));
21202138 if (!nla )
21212139 goto nla_put_failure ;
2140+
21222141 mpls_key = nla_data (nla );
2123- mpls_key -> mpls_lse = output -> mpls .top_lse ;
2142+ for (i = 0 ; i < num_labels ; i ++ )
2143+ mpls_key [i ].mpls_lse = output -> mpls .lse [i ];
21242144 }
21252145
21262146 if ((swkey -> eth .type == htons (ETH_P_IP ) ||
@@ -2406,13 +2426,14 @@ static inline void add_nested_action_end(struct sw_flow_actions *sfa,
24062426static int __ovs_nla_copy_actions (struct net * net , const struct nlattr * attr ,
24072427 const struct sw_flow_key * key ,
24082428 struct sw_flow_actions * * sfa ,
2409- __be16 eth_type , __be16 vlan_tci , bool log );
2429+ __be16 eth_type , __be16 vlan_tci ,
2430+ u32 mpls_label_count , bool log );
24102431
24112432static int validate_and_copy_sample (struct net * net , const struct nlattr * attr ,
24122433 const struct sw_flow_key * key ,
24132434 struct sw_flow_actions * * sfa ,
24142435 __be16 eth_type , __be16 vlan_tci ,
2415- bool log , bool last )
2436+ u32 mpls_label_count , bool log , bool last )
24162437{
24172438 const struct nlattr * attrs [OVS_SAMPLE_ATTR_MAX + 1 ];
24182439 const struct nlattr * probability , * actions ;
@@ -2463,7 +2484,7 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
24632484 return err ;
24642485
24652486 err = __ovs_nla_copy_actions (net , actions , key , sfa ,
2466- eth_type , vlan_tci , log );
2487+ eth_type , vlan_tci , mpls_label_count , log );
24672488
24682489 if (err )
24692490 return err ;
@@ -2478,7 +2499,7 @@ static int validate_and_copy_clone(struct net *net,
24782499 const struct sw_flow_key * key ,
24792500 struct sw_flow_actions * * sfa ,
24802501 __be16 eth_type , __be16 vlan_tci ,
2481- bool log , bool last )
2502+ u32 mpls_label_count , bool log , bool last )
24822503{
24832504 int start , err ;
24842505 u32 exec ;
@@ -2498,7 +2519,7 @@ static int validate_and_copy_clone(struct net *net,
24982519 return err ;
24992520
25002521 err = __ovs_nla_copy_actions (net , attr , key , sfa ,
2501- eth_type , vlan_tci , log );
2522+ eth_type , vlan_tci , mpls_label_count , log );
25022523 if (err )
25032524 return err ;
25042525
@@ -2864,6 +2885,7 @@ static int validate_and_copy_check_pkt_len(struct net *net,
28642885 const struct sw_flow_key * key ,
28652886 struct sw_flow_actions * * sfa ,
28662887 __be16 eth_type , __be16 vlan_tci ,
2888+ u32 mpls_label_count ,
28672889 bool log , bool last )
28682890{
28692891 const struct nlattr * acts_if_greater , * acts_if_lesser_eq ;
@@ -2912,7 +2934,7 @@ static int validate_and_copy_check_pkt_len(struct net *net,
29122934 return nested_acts_start ;
29132935
29142936 err = __ovs_nla_copy_actions (net , acts_if_lesser_eq , key , sfa ,
2915- eth_type , vlan_tci , log );
2937+ eth_type , vlan_tci , mpls_label_count , log );
29162938
29172939 if (err )
29182940 return err ;
@@ -2925,7 +2947,7 @@ static int validate_and_copy_check_pkt_len(struct net *net,
29252947 return nested_acts_start ;
29262948
29272949 err = __ovs_nla_copy_actions (net , acts_if_greater , key , sfa ,
2928- eth_type , vlan_tci , log );
2950+ eth_type , vlan_tci , mpls_label_count , log );
29292951
29302952 if (err )
29312953 return err ;
@@ -2952,7 +2974,8 @@ static int copy_action(const struct nlattr *from,
29522974static int __ovs_nla_copy_actions (struct net * net , const struct nlattr * attr ,
29532975 const struct sw_flow_key * key ,
29542976 struct sw_flow_actions * * sfa ,
2955- __be16 eth_type , __be16 vlan_tci , bool log )
2977+ __be16 eth_type , __be16 vlan_tci ,
2978+ u32 mpls_label_count , bool log )
29562979{
29572980 u8 mac_proto = ovs_key_mac_proto (key );
29582981 const struct nlattr * a ;
@@ -3065,25 +3088,36 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
30653088 !eth_p_mpls (eth_type )))
30663089 return - EINVAL ;
30673090 eth_type = mpls -> mpls_ethertype ;
3091+ mpls_label_count ++ ;
30683092 break ;
30693093 }
30703094
3071- case OVS_ACTION_ATTR_POP_MPLS :
3095+ case OVS_ACTION_ATTR_POP_MPLS : {
3096+ __be16 proto ;
30723097 if (vlan_tci & htons (VLAN_CFI_MASK ) ||
30733098 !eth_p_mpls (eth_type ))
30743099 return - EINVAL ;
30753100
3076- /* Disallow subsequent L2.5+ set and mpls_pop actions
3077- * as there is no check here to ensure that the new
3078- * eth_type is valid and thus set actions could
3079- * write off the end of the packet or otherwise
3080- * corrupt it.
3101+ /* Disallow subsequent L2.5+ set actions and mpls_pop
3102+ * actions once the last MPLS label in the packet is
3103+ * is popped as there is no check here to ensure that
3104+ * the new eth type is valid and thus set actions could
3105+ * write off the end of the packet or otherwise corrupt
3106+ * it.
30813107 *
30823108 * Support for these actions is planned using packet
30833109 * recirculation.
30843110 */
3085- eth_type = htons (0 );
3111+ proto = nla_get_be16 (a );
3112+ mpls_label_count -- ;
3113+
3114+ if (!eth_p_mpls (proto ) || !mpls_label_count )
3115+ eth_type = htons (0 );
3116+ else
3117+ eth_type = proto ;
3118+
30863119 break ;
3120+ }
30873121
30883122 case OVS_ACTION_ATTR_SET :
30893123 err = validate_set (a , key , sfa ,
@@ -3106,6 +3140,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
31063140
31073141 err = validate_and_copy_sample (net , a , key , sfa ,
31083142 eth_type , vlan_tci ,
3143+ mpls_label_count ,
31093144 log , last );
31103145 if (err )
31113146 return err ;
@@ -3176,6 +3211,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
31763211
31773212 err = validate_and_copy_clone (net , a , key , sfa ,
31783213 eth_type , vlan_tci ,
3214+ mpls_label_count ,
31793215 log , last );
31803216 if (err )
31813217 return err ;
@@ -3188,8 +3224,9 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
31883224
31893225 err = validate_and_copy_check_pkt_len (net , a , key , sfa ,
31903226 eth_type ,
3191- vlan_tci , log ,
3192- last );
3227+ vlan_tci ,
3228+ mpls_label_count ,
3229+ log , last );
31933230 if (err )
31943231 return err ;
31953232 skip_copy = true;
@@ -3219,14 +3256,18 @@ int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
32193256 struct sw_flow_actions * * sfa , bool log )
32203257{
32213258 int err ;
3259+ u32 mpls_label_count = 0 ;
32223260
32233261 * sfa = nla_alloc_flow_actions (min (nla_len (attr ), MAX_ACTIONS_BUFSIZE ));
32243262 if (IS_ERR (* sfa ))
32253263 return PTR_ERR (* sfa );
32263264
3265+ if (eth_p_mpls (key -> eth .type ))
3266+ mpls_label_count = hweight_long (key -> mpls .num_labels_mask );
3267+
32273268 (* sfa )-> orig_len = nla_len (attr );
32283269 err = __ovs_nla_copy_actions (net , attr , key , sfa , key -> eth .type ,
3229- key -> eth .vlan .tci , log );
3270+ key -> eth .vlan .tci , mpls_label_count , log );
32303271 if (err )
32313272 ovs_nla_free_flow_actions (* sfa );
32323273
0 commit comments