@@ -424,7 +424,7 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
424
424
[OVS_KEY_ATTR_DP_HASH ] = { .len = sizeof (u32 ) },
425
425
[OVS_KEY_ATTR_TUNNEL ] = { .len = OVS_ATTR_NESTED ,
426
426
.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 },
428
428
[OVS_KEY_ATTR_CT_STATE ] = { .len = sizeof (u32 ) },
429
429
[OVS_KEY_ATTR_CT_ZONE ] = { .len = sizeof (u16 ) },
430
430
[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,
1628
1628
1629
1629
if (attrs & (1 << OVS_KEY_ATTR_MPLS )) {
1630
1630
const struct ovs_key_mpls * mpls_key ;
1631
+ u32 hdr_len ;
1632
+ u32 label_count , label_count_mask , i ;
1631
1633
1632
1634
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 );
1635
1650
1636
1651
attrs &= ~(1 << OVS_KEY_ATTR_MPLS );
1637
1652
}
@@ -2114,13 +2129,18 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
2114
2129
ether_addr_copy (arp_key -> arp_sha , output -> ipv4 .arp .sha );
2115
2130
ether_addr_copy (arp_key -> arp_tha , output -> ipv4 .arp .tha );
2116
2131
} else if (eth_p_mpls (swkey -> eth .type )) {
2132
+ u8 i , num_labels ;
2117
2133
struct ovs_key_mpls * mpls_key ;
2118
2134
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 ));
2120
2138
if (!nla )
2121
2139
goto nla_put_failure ;
2140
+
2122
2141
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 ];
2124
2144
}
2125
2145
2126
2146
if ((swkey -> eth .type == htons (ETH_P_IP ) ||
@@ -2406,13 +2426,14 @@ static inline void add_nested_action_end(struct sw_flow_actions *sfa,
2406
2426
static int __ovs_nla_copy_actions (struct net * net , const struct nlattr * attr ,
2407
2427
const struct sw_flow_key * key ,
2408
2428
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 );
2410
2431
2411
2432
static int validate_and_copy_sample (struct net * net , const struct nlattr * attr ,
2412
2433
const struct sw_flow_key * key ,
2413
2434
struct sw_flow_actions * * sfa ,
2414
2435
__be16 eth_type , __be16 vlan_tci ,
2415
- bool log , bool last )
2436
+ u32 mpls_label_count , bool log , bool last )
2416
2437
{
2417
2438
const struct nlattr * attrs [OVS_SAMPLE_ATTR_MAX + 1 ];
2418
2439
const struct nlattr * probability , * actions ;
@@ -2463,7 +2484,7 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
2463
2484
return err ;
2464
2485
2465
2486
err = __ovs_nla_copy_actions (net , actions , key , sfa ,
2466
- eth_type , vlan_tci , log );
2487
+ eth_type , vlan_tci , mpls_label_count , log );
2467
2488
2468
2489
if (err )
2469
2490
return err ;
@@ -2478,7 +2499,7 @@ static int validate_and_copy_clone(struct net *net,
2478
2499
const struct sw_flow_key * key ,
2479
2500
struct sw_flow_actions * * sfa ,
2480
2501
__be16 eth_type , __be16 vlan_tci ,
2481
- bool log , bool last )
2502
+ u32 mpls_label_count , bool log , bool last )
2482
2503
{
2483
2504
int start , err ;
2484
2505
u32 exec ;
@@ -2498,7 +2519,7 @@ static int validate_and_copy_clone(struct net *net,
2498
2519
return err ;
2499
2520
2500
2521
err = __ovs_nla_copy_actions (net , attr , key , sfa ,
2501
- eth_type , vlan_tci , log );
2522
+ eth_type , vlan_tci , mpls_label_count , log );
2502
2523
if (err )
2503
2524
return err ;
2504
2525
@@ -2864,6 +2885,7 @@ static int validate_and_copy_check_pkt_len(struct net *net,
2864
2885
const struct sw_flow_key * key ,
2865
2886
struct sw_flow_actions * * sfa ,
2866
2887
__be16 eth_type , __be16 vlan_tci ,
2888
+ u32 mpls_label_count ,
2867
2889
bool log , bool last )
2868
2890
{
2869
2891
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,
2912
2934
return nested_acts_start ;
2913
2935
2914
2936
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 );
2916
2938
2917
2939
if (err )
2918
2940
return err ;
@@ -2925,7 +2947,7 @@ static int validate_and_copy_check_pkt_len(struct net *net,
2925
2947
return nested_acts_start ;
2926
2948
2927
2949
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 );
2929
2951
2930
2952
if (err )
2931
2953
return err ;
@@ -2952,7 +2974,8 @@ static int copy_action(const struct nlattr *from,
2952
2974
static int __ovs_nla_copy_actions (struct net * net , const struct nlattr * attr ,
2953
2975
const struct sw_flow_key * key ,
2954
2976
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 )
2956
2979
{
2957
2980
u8 mac_proto = ovs_key_mac_proto (key );
2958
2981
const struct nlattr * a ;
@@ -3065,25 +3088,36 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3065
3088
!eth_p_mpls (eth_type )))
3066
3089
return - EINVAL ;
3067
3090
eth_type = mpls -> mpls_ethertype ;
3091
+ mpls_label_count ++ ;
3068
3092
break ;
3069
3093
}
3070
3094
3071
- case OVS_ACTION_ATTR_POP_MPLS :
3095
+ case OVS_ACTION_ATTR_POP_MPLS : {
3096
+ __be16 proto ;
3072
3097
if (vlan_tci & htons (VLAN_CFI_MASK ) ||
3073
3098
!eth_p_mpls (eth_type ))
3074
3099
return - EINVAL ;
3075
3100
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.
3081
3107
*
3082
3108
* Support for these actions is planned using packet
3083
3109
* recirculation.
3084
3110
*/
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
+
3086
3119
break ;
3120
+ }
3087
3121
3088
3122
case OVS_ACTION_ATTR_SET :
3089
3123
err = validate_set (a , key , sfa ,
@@ -3106,6 +3140,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3106
3140
3107
3141
err = validate_and_copy_sample (net , a , key , sfa ,
3108
3142
eth_type , vlan_tci ,
3143
+ mpls_label_count ,
3109
3144
log , last );
3110
3145
if (err )
3111
3146
return err ;
@@ -3176,6 +3211,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3176
3211
3177
3212
err = validate_and_copy_clone (net , a , key , sfa ,
3178
3213
eth_type , vlan_tci ,
3214
+ mpls_label_count ,
3179
3215
log , last );
3180
3216
if (err )
3181
3217
return err ;
@@ -3188,8 +3224,9 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3188
3224
3189
3225
err = validate_and_copy_check_pkt_len (net , a , key , sfa ,
3190
3226
eth_type ,
3191
- vlan_tci , log ,
3192
- last );
3227
+ vlan_tci ,
3228
+ mpls_label_count ,
3229
+ log , last );
3193
3230
if (err )
3194
3231
return err ;
3195
3232
skip_copy = true;
@@ -3219,14 +3256,18 @@ int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3219
3256
struct sw_flow_actions * * sfa , bool log )
3220
3257
{
3221
3258
int err ;
3259
+ u32 mpls_label_count = 0 ;
3222
3260
3223
3261
* sfa = nla_alloc_flow_actions (min (nla_len (attr ), MAX_ACTIONS_BUFSIZE ));
3224
3262
if (IS_ERR (* sfa ))
3225
3263
return PTR_ERR (* sfa );
3226
3264
3265
+ if (eth_p_mpls (key -> eth .type ))
3266
+ mpls_label_count = hweight_long (key -> mpls .num_labels_mask );
3267
+
3227
3268
(* sfa )-> orig_len = nla_len (attr );
3228
3269
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 );
3230
3271
if (err )
3231
3272
ovs_nla_free_flow_actions (* sfa );
3232
3273
0 commit comments