@@ -478,6 +478,8 @@ const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_START_CONTEXT + 1] =
478
478
[ETHTOOL_A_RSS_HFUNC ] = NLA_POLICY_MIN (NLA_U32 , 1 ),
479
479
[ETHTOOL_A_RSS_INDIR ] = { .type = NLA_BINARY , },
480
480
[ETHTOOL_A_RSS_HKEY ] = NLA_POLICY_MIN (NLA_BINARY , 1 ),
481
+ [ETHTOOL_A_RSS_INPUT_XFRM ] =
482
+ NLA_POLICY_MAX (NLA_U32 , RXH_XFRM_SYM_OR_XOR ),
481
483
};
482
484
483
485
static int
@@ -487,15 +489,21 @@ ethnl_rss_set_validate(struct ethnl_req_info *req_info, struct genl_info *info)
487
489
struct rss_req_info * request = RSS_REQINFO (req_info );
488
490
struct nlattr * * tb = info -> attrs ;
489
491
struct nlattr * bad_attr = NULL ;
492
+ u32 input_xfrm ;
490
493
491
494
if (request -> rss_context && !ops -> create_rxfh_context )
492
495
bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_CONTEXT ];
493
496
494
497
if (request -> rss_context && !ops -> rxfh_per_ctx_key ) {
495
498
bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_HFUNC ];
496
499
bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_HKEY ];
500
+ bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_INPUT_XFRM ];
497
501
}
498
502
503
+ input_xfrm = nla_get_u32_default (tb [ETHTOOL_A_RSS_INPUT_XFRM ], 0 );
504
+ if (input_xfrm & ~ops -> supported_input_xfrm )
505
+ bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_INPUT_XFRM ];
506
+
499
507
if (bad_attr ) {
500
508
NL_SET_BAD_ATTR (info -> extack , bad_attr );
501
509
return - EOPNOTSUPP ;
@@ -609,6 +617,33 @@ rss_set_prep_hkey(struct net_device *dev, struct genl_info *info,
609
617
return 0 ;
610
618
}
611
619
620
+ static int
621
+ rss_check_rxfh_fields_sym (struct net_device * dev , struct genl_info * info ,
622
+ struct rss_reply_data * data , bool xfrm_sym )
623
+ {
624
+ struct nlattr * * tb = info -> attrs ;
625
+ int i ;
626
+
627
+ if (!xfrm_sym )
628
+ return 0 ;
629
+ if (!data -> has_flow_hash ) {
630
+ NL_SET_ERR_MSG_ATTR (info -> extack , tb [ETHTOOL_A_RSS_INPUT_XFRM ],
631
+ "hash field config not reported" );
632
+ return - EINVAL ;
633
+ }
634
+
635
+ for (i = 1 ; i < __ETHTOOL_A_FLOW_CNT ; i ++ )
636
+ if (data -> flow_hash [i ] >= 0 &&
637
+ !ethtool_rxfh_config_is_sym (data -> flow_hash [i ])) {
638
+ NL_SET_ERR_MSG_ATTR (info -> extack ,
639
+ tb [ETHTOOL_A_RSS_INPUT_XFRM ],
640
+ "hash field config is not symmetric" );
641
+ return - EINVAL ;
642
+ }
643
+
644
+ return 0 ;
645
+ }
646
+
612
647
static void
613
648
rss_set_ctx_update (struct ethtool_rxfh_context * ctx , struct nlattr * * tb ,
614
649
struct rss_reply_data * data , struct ethtool_rxfh_param * rxfh )
@@ -627,16 +662,18 @@ rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
627
662
}
628
663
if (rxfh -> hfunc != ETH_RSS_HASH_NO_CHANGE )
629
664
ctx -> hfunc = rxfh -> hfunc ;
665
+ if (rxfh -> input_xfrm != RXH_XFRM_NO_CHANGE )
666
+ ctx -> input_xfrm = rxfh -> input_xfrm ;
630
667
}
631
668
632
669
static int
633
670
ethnl_rss_set (struct ethnl_req_info * req_info , struct genl_info * info )
634
671
{
672
+ bool indir_reset = false, indir_mod , xfrm_sym = false;
635
673
struct rss_req_info * request = RSS_REQINFO (req_info );
636
674
struct ethtool_rxfh_context * ctx = NULL ;
637
675
struct net_device * dev = req_info -> dev ;
638
676
struct ethtool_rxfh_param rxfh = {};
639
- bool indir_reset = false, indir_mod ;
640
677
struct nlattr * * tb = info -> attrs ;
641
678
struct rss_reply_data data = {};
642
679
const struct ethtool_ops * ops ;
@@ -666,7 +703,20 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
666
703
if (ret )
667
704
goto exit_free_indir ;
668
705
669
- rxfh .input_xfrm = RXH_XFRM_NO_CHANGE ;
706
+ rxfh .input_xfrm = data .input_xfrm ;
707
+ ethnl_update_u8 (& rxfh .input_xfrm , tb [ETHTOOL_A_RSS_INPUT_XFRM ], & mod );
708
+ /* For drivers which don't support input_xfrm it will be set to 0xff
709
+ * in the RSS context info. In all other case input_xfrm != 0 means
710
+ * symmetric hashing is requested.
711
+ */
712
+ if (!request -> rss_context || ops -> rxfh_per_ctx_key )
713
+ xfrm_sym = !!rxfh .input_xfrm ;
714
+ if (rxfh .input_xfrm == data .input_xfrm )
715
+ rxfh .input_xfrm = RXH_XFRM_NO_CHANGE ;
716
+
717
+ ret = rss_check_rxfh_fields_sym (dev , info , & data , xfrm_sym );
718
+ if (ret )
719
+ goto exit_clean_data ;
670
720
671
721
mutex_lock (& dev -> ethtool -> rss_lock );
672
722
if (request -> rss_context ) {
0 commit comments