@@ -57,6 +57,7 @@ struct ovs_len_tbl {
57
57
};
58
58
59
59
#define OVS_ATTR_NESTED -1
60
+ #define OVS_ATTR_VARIABLE -2
60
61
61
62
static void update_range (struct sw_flow_match * match ,
62
63
size_t offset , size_t size , bool is_mask )
@@ -304,6 +305,10 @@ size_t ovs_key_attr_size(void)
304
305
+ nla_total_size (28 ); /* OVS_KEY_ATTR_ND */
305
306
}
306
307
308
+ static const struct ovs_len_tbl ovs_vxlan_ext_key_lens [OVS_VXLAN_EXT_MAX + 1 ] = {
309
+ [OVS_VXLAN_EXT_GBP ] = { .len = sizeof (u32 ) },
310
+ };
311
+
307
312
static const struct ovs_len_tbl ovs_tunnel_key_lens [OVS_TUNNEL_KEY_ATTR_MAX + 1 ] = {
308
313
[OVS_TUNNEL_KEY_ATTR_ID ] = { .len = sizeof (u64 ) },
309
314
[OVS_TUNNEL_KEY_ATTR_IPV4_SRC ] = { .len = sizeof (u32 ) },
@@ -315,8 +320,9 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
315
320
[OVS_TUNNEL_KEY_ATTR_TP_SRC ] = { .len = sizeof (u16 ) },
316
321
[OVS_TUNNEL_KEY_ATTR_TP_DST ] = { .len = sizeof (u16 ) },
317
322
[OVS_TUNNEL_KEY_ATTR_OAM ] = { .len = 0 },
318
- [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS ] = { .len = OVS_ATTR_NESTED },
319
- [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS ] = { .len = OVS_ATTR_NESTED },
323
+ [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS ] = { .len = OVS_ATTR_VARIABLE },
324
+ [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS ] = { .len = OVS_ATTR_NESTED ,
325
+ .next = ovs_vxlan_ext_key_lens },
320
326
};
321
327
322
328
/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
@@ -349,6 +355,13 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
349
355
[OVS_KEY_ATTR_CT_LABEL ] = { .len = sizeof (struct ovs_key_ct_label ) },
350
356
};
351
357
358
+ static bool check_attr_len (unsigned int attr_len , unsigned int expected_len )
359
+ {
360
+ return expected_len == attr_len ||
361
+ expected_len == OVS_ATTR_NESTED ||
362
+ expected_len == OVS_ATTR_VARIABLE ;
363
+ }
364
+
352
365
static bool is_all_zero (const u8 * fp , size_t size )
353
366
{
354
367
int i ;
@@ -388,7 +401,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
388
401
}
389
402
390
403
expected_len = ovs_key_lens [type ].len ;
391
- if (nla_len (nla ) != expected_len && expected_len != OVS_ATTR_NESTED ) {
404
+ if (! check_attr_len ( nla_len (nla ), expected_len ) ) {
392
405
OVS_NLERR (log , "Key %d has unexpected len %d expected %d" ,
393
406
type , nla_len (nla ), expected_len );
394
407
return - EINVAL ;
@@ -473,29 +486,50 @@ static int genev_tun_opt_from_nlattr(const struct nlattr *a,
473
486
return 0 ;
474
487
}
475
488
476
- static const struct nla_policy vxlan_opt_policy [OVS_VXLAN_EXT_MAX + 1 ] = {
477
- [OVS_VXLAN_EXT_GBP ] = { .type = NLA_U32 },
478
- };
479
-
480
- static int vxlan_tun_opt_from_nlattr (const struct nlattr * a ,
489
+ static int vxlan_tun_opt_from_nlattr (const struct nlattr * attr ,
481
490
struct sw_flow_match * match , bool is_mask ,
482
491
bool log )
483
492
{
484
- struct nlattr * tb [OVS_VXLAN_EXT_MAX + 1 ];
493
+ struct nlattr * a ;
494
+ int rem ;
485
495
unsigned long opt_key_offset ;
486
496
struct vxlan_metadata opts ;
487
- int err ;
488
497
489
498
BUILD_BUG_ON (sizeof (opts ) > sizeof (match -> key -> tun_opts ));
490
499
491
- err = nla_parse_nested (tb , OVS_VXLAN_EXT_MAX , a , vxlan_opt_policy );
492
- if (err < 0 )
493
- return err ;
494
-
495
500
memset (& opts , 0 , sizeof (opts ));
501
+ nla_for_each_nested (a , attr , rem ) {
502
+ int type = nla_type (a );
496
503
497
- if (tb [OVS_VXLAN_EXT_GBP ])
498
- opts .gbp = nla_get_u32 (tb [OVS_VXLAN_EXT_GBP ]);
504
+ if (type > OVS_VXLAN_EXT_MAX ) {
505
+ OVS_NLERR (log , "VXLAN extension %d out of range max %d" ,
506
+ type , OVS_VXLAN_EXT_MAX );
507
+ return - EINVAL ;
508
+ }
509
+
510
+ if (!check_attr_len (nla_len (a ),
511
+ ovs_vxlan_ext_key_lens [type ].len )) {
512
+ OVS_NLERR (log , "VXLAN extension %d has unexpected len %d expected %d" ,
513
+ type , nla_len (a ),
514
+ ovs_vxlan_ext_key_lens [type ].len );
515
+ return - EINVAL ;
516
+ }
517
+
518
+ switch (type ) {
519
+ case OVS_VXLAN_EXT_GBP :
520
+ opts .gbp = nla_get_u32 (a );
521
+ break ;
522
+ default :
523
+ OVS_NLERR (log , "Unknown VXLAN extension attribute %d" ,
524
+ type );
525
+ return - EINVAL ;
526
+ }
527
+ }
528
+ if (rem ) {
529
+ OVS_NLERR (log , "VXLAN extension message has %d unknown bytes." ,
530
+ rem );
531
+ return - EINVAL ;
532
+ }
499
533
500
534
if (!is_mask )
501
535
SW_FLOW_KEY_PUT (match , tun_opts_len , sizeof (opts ), false);
@@ -528,8 +562,8 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
528
562
return - EINVAL ;
529
563
}
530
564
531
- if (ovs_tunnel_key_lens [ type ]. len != nla_len (a ) &&
532
- ovs_tunnel_key_lens [type ].len != OVS_ATTR_NESTED ) {
565
+ if (! check_attr_len ( nla_len (a ),
566
+ ovs_tunnel_key_lens [type ].len ) ) {
533
567
OVS_NLERR (log , "Tunnel attr %d has unexpected len %d expected %d" ,
534
568
type , nla_len (a ), ovs_tunnel_key_lens [type ].len );
535
569
return - EINVAL ;
@@ -1052,10 +1086,13 @@ static void nlattr_set(struct nlattr *attr, u8 val,
1052
1086
1053
1087
/* The nlattr stream should already have been validated */
1054
1088
nla_for_each_nested (nla , attr , rem ) {
1055
- if (tbl && tbl [nla_type (nla )].len == OVS_ATTR_NESTED )
1056
- nlattr_set (nla , val , tbl [nla_type (nla )].next );
1057
- else
1089
+ if (tbl [nla_type (nla )].len == OVS_ATTR_NESTED ) {
1090
+ if (tbl [nla_type (nla )].next )
1091
+ tbl = tbl [nla_type (nla )].next ;
1092
+ nlattr_set (nla , val , tbl );
1093
+ } else {
1058
1094
memset (nla_data (nla ), val , nla_len (nla ));
1095
+ }
1059
1096
}
1060
1097
}
1061
1098
@@ -1922,8 +1959,7 @@ static int validate_set(const struct nlattr *a,
1922
1959
key_len /= 2 ;
1923
1960
1924
1961
if (key_type > OVS_KEY_ATTR_MAX ||
1925
- (ovs_key_lens [key_type ].len != key_len &&
1926
- ovs_key_lens [key_type ].len != OVS_ATTR_NESTED ))
1962
+ !check_attr_len (key_len , ovs_key_lens [key_type ].len ))
1927
1963
return - EINVAL ;
1928
1964
1929
1965
if (masked && !validate_masked (nla_data (ovs_key ), key_len ))
0 commit comments