@@ -477,6 +477,7 @@ const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_START_CONTEXT + 1] =
477
477
[ETHTOOL_A_RSS_CONTEXT ] = { .type = NLA_U32 , },
478
478
[ETHTOOL_A_RSS_HFUNC ] = NLA_POLICY_MIN (NLA_U32 , 1 ),
479
479
[ETHTOOL_A_RSS_INDIR ] = { .type = NLA_BINARY , },
480
+ [ETHTOOL_A_RSS_HKEY ] = NLA_POLICY_MIN (NLA_BINARY , 1 ),
480
481
};
481
482
482
483
static int
@@ -490,8 +491,10 @@ ethnl_rss_set_validate(struct ethnl_req_info *req_info, struct genl_info *info)
490
491
if (request -> rss_context && !ops -> create_rxfh_context )
491
492
bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_CONTEXT ];
492
493
493
- if (request -> rss_context && !ops -> rxfh_per_ctx_key )
494
+ if (request -> rss_context && !ops -> rxfh_per_ctx_key ) {
494
495
bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_HFUNC ];
496
+ bad_attr = bad_attr ?: tb [ETHTOOL_A_RSS_HKEY ];
497
+ }
495
498
496
499
if (bad_attr ) {
497
500
NL_SET_BAD_ATTR (info -> extack , bad_attr );
@@ -581,6 +584,31 @@ rss_set_prep_indir(struct net_device *dev, struct genl_info *info,
581
584
return err ;
582
585
}
583
586
587
+ static int
588
+ rss_set_prep_hkey (struct net_device * dev , struct genl_info * info ,
589
+ struct rss_reply_data * data , struct ethtool_rxfh_param * rxfh ,
590
+ bool * mod )
591
+ {
592
+ struct nlattr * * tb = info -> attrs ;
593
+
594
+ if (!tb [ETHTOOL_A_RSS_HKEY ])
595
+ return 0 ;
596
+
597
+ if (nla_len (tb [ETHTOOL_A_RSS_HKEY ]) != data -> hkey_size ) {
598
+ NL_SET_BAD_ATTR (info -> extack , tb [ETHTOOL_A_RSS_HKEY ]);
599
+ return - EINVAL ;
600
+ }
601
+
602
+ rxfh -> key_size = data -> hkey_size ;
603
+ rxfh -> key = kmemdup (data -> hkey , data -> hkey_size , GFP_KERNEL );
604
+ if (!rxfh -> key )
605
+ return - ENOMEM ;
606
+
607
+ ethnl_update_binary (rxfh -> key , rxfh -> key_size , tb [ETHTOOL_A_RSS_HKEY ],
608
+ mod );
609
+ return 0 ;
610
+ }
611
+
584
612
static void
585
613
rss_set_ctx_update (struct ethtool_rxfh_context * ctx , struct nlattr * * tb ,
586
614
struct rss_reply_data * data , struct ethtool_rxfh_param * rxfh )
@@ -592,6 +620,11 @@ rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
592
620
ethtool_rxfh_context_indir (ctx )[i ] = rxfh -> indir [i ];
593
621
ctx -> indir_configured = !!nla_len (tb [ETHTOOL_A_RSS_INDIR ]);
594
622
}
623
+ if (rxfh -> key ) {
624
+ memcpy (ethtool_rxfh_context_key (ctx ), rxfh -> key ,
625
+ data -> hkey_size );
626
+ ctx -> key_configured = !!rxfh -> key_size ;
627
+ }
595
628
if (rxfh -> hfunc != ETH_RSS_HASH_NO_CHANGE )
596
629
ctx -> hfunc = rxfh -> hfunc ;
597
630
}
@@ -629,6 +662,10 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
629
662
if (rxfh .hfunc == data .hfunc )
630
663
rxfh .hfunc = ETH_RSS_HASH_NO_CHANGE ;
631
664
665
+ ret = rss_set_prep_hkey (dev , info , & data , & rxfh , & mod );
666
+ if (ret )
667
+ goto exit_free_indir ;
668
+
632
669
rxfh .input_xfrm = RXH_XFRM_NO_CHANGE ;
633
670
634
671
mutex_lock (& dev -> ethtool -> rss_lock );
@@ -660,6 +697,8 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
660
697
661
698
exit_unlock :
662
699
mutex_unlock (& dev -> ethtool -> rss_lock );
700
+ kfree (rxfh .key );
701
+ exit_free_indir :
663
702
kfree (rxfh .indir );
664
703
exit_clean_data :
665
704
rss_cleanup_data (& data .base );
0 commit comments