@@ -57,6 +57,7 @@ struct ovs_len_tbl {
5757};
5858
5959#define OVS_ATTR_NESTED -1
60+ #define OVS_ATTR_VARIABLE -2
6061
6162static void update_range (struct sw_flow_match * match ,
6263 size_t offset , size_t size , bool is_mask )
@@ -304,6 +305,10 @@ size_t ovs_key_attr_size(void)
304305 + nla_total_size (28 ); /* OVS_KEY_ATTR_ND */
305306}
306307
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+
307312static const struct ovs_len_tbl ovs_tunnel_key_lens [OVS_TUNNEL_KEY_ATTR_MAX + 1 ] = {
308313 [OVS_TUNNEL_KEY_ATTR_ID ] = { .len = sizeof (u64 ) },
309314 [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]
315320 [OVS_TUNNEL_KEY_ATTR_TP_SRC ] = { .len = sizeof (u16 ) },
316321 [OVS_TUNNEL_KEY_ATTR_TP_DST ] = { .len = sizeof (u16 ) },
317322 [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 },
320326};
321327
322328/* 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] = {
349355 [OVS_KEY_ATTR_CT_LABEL ] = { .len = sizeof (struct ovs_key_ct_label ) },
350356};
351357
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+
352365static bool is_all_zero (const u8 * fp , size_t size )
353366{
354367 int i ;
@@ -388,7 +401,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
388401 }
389402
390403 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 ) ) {
392405 OVS_NLERR (log , "Key %d has unexpected len %d expected %d" ,
393406 type , nla_len (nla ), expected_len );
394407 return - EINVAL ;
@@ -473,29 +486,50 @@ static int genev_tun_opt_from_nlattr(const struct nlattr *a,
473486 return 0 ;
474487}
475488
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 ,
481490 struct sw_flow_match * match , bool is_mask ,
482491 bool log )
483492{
484- struct nlattr * tb [OVS_VXLAN_EXT_MAX + 1 ];
493+ struct nlattr * a ;
494+ int rem ;
485495 unsigned long opt_key_offset ;
486496 struct vxlan_metadata opts ;
487- int err ;
488497
489498 BUILD_BUG_ON (sizeof (opts ) > sizeof (match -> key -> tun_opts ));
490499
491- err = nla_parse_nested (tb , OVS_VXLAN_EXT_MAX , a , vxlan_opt_policy );
492- if (err < 0 )
493- return err ;
494-
495500 memset (& opts , 0 , sizeof (opts ));
501+ nla_for_each_nested (a , attr , rem ) {
502+ int type = nla_type (a );
496503
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+ }
499533
500534 if (!is_mask )
501535 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,
528562 return - EINVAL ;
529563 }
530564
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 ) ) {
533567 OVS_NLERR (log , "Tunnel attr %d has unexpected len %d expected %d" ,
534568 type , nla_len (a ), ovs_tunnel_key_lens [type ].len );
535569 return - EINVAL ;
@@ -1052,10 +1086,13 @@ static void nlattr_set(struct nlattr *attr, u8 val,
10521086
10531087 /* The nlattr stream should already have been validated */
10541088 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 {
10581094 memset (nla_data (nla ), val , nla_len (nla ));
1095+ }
10591096 }
10601097}
10611098
@@ -1922,8 +1959,7 @@ static int validate_set(const struct nlattr *a,
19221959 key_len /= 2 ;
19231960
19241961 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 ))
19271963 return - EINVAL ;
19281964
19291965 if (masked && !validate_masked (nla_data (ovs_key ), key_len ))
0 commit comments