@@ -75,6 +75,24 @@ net_shaper_ops(struct net_shaper_binding *binding)
7575 return NULL ;
7676}
7777
78+ /* Count the number of [multi] attributes of the given type. */
79+ static int net_shaper_list_len (struct genl_info * info , int type )
80+ {
81+ struct nlattr * attr ;
82+ int rem , cnt = 0 ;
83+
84+ nla_for_each_attr_type (attr , type , genlmsg_data (info -> genlhdr ),
85+ genlmsg_len (info -> genlhdr ), rem )
86+ cnt ++ ;
87+ return cnt ;
88+ }
89+
90+ static int net_shaper_handle_size (void )
91+ {
92+ return nla_total_size (nla_total_size (sizeof (u32 )) +
93+ nla_total_size (sizeof (u32 )));
94+ }
95+
7896static int net_shaper_fill_binding (struct sk_buff * msg ,
7997 const struct net_shaper_binding * binding ,
8098 u32 type )
@@ -472,6 +490,74 @@ static int net_shaper_parse_info(struct net_shaper_binding *binding,
472490 return 0 ;
473491}
474492
493+ /* Fetch the existing leaf and update it with the user-provided
494+ * attributes.
495+ */
496+ static int net_shaper_parse_leaf (struct net_shaper_binding * binding ,
497+ const struct nlattr * attr ,
498+ const struct genl_info * info ,
499+ const struct net_shaper * node ,
500+ struct net_shaper * shaper )
501+ {
502+ struct nlattr * tb [NET_SHAPER_A_WEIGHT + 1 ];
503+ bool exists ;
504+ int ret ;
505+
506+ ret = nla_parse_nested (tb , NET_SHAPER_A_WEIGHT , attr ,
507+ net_shaper_leaf_info_nl_policy , info -> extack );
508+ if (ret < 0 )
509+ return ret ;
510+
511+ ret = net_shaper_parse_info (binding , tb , info , shaper , & exists );
512+ if (ret < 0 )
513+ return ret ;
514+
515+ if (shaper -> handle .scope != NET_SHAPER_SCOPE_QUEUE ) {
516+ NL_SET_BAD_ATTR (info -> extack , tb [NET_SHAPER_A_HANDLE ]);
517+ return - EINVAL ;
518+ }
519+
520+ if (!exists )
521+ net_shaper_default_parent (& shaper -> handle , & shaper -> parent );
522+ return 0 ;
523+ }
524+
525+ /* Alike net_parse_shaper_info(), but additionally allow the user specifying
526+ * the shaper's parent handle.
527+ */
528+ static int net_shaper_parse_node (struct net_shaper_binding * binding ,
529+ struct nlattr * * tb ,
530+ const struct genl_info * info ,
531+ struct net_shaper * shaper )
532+ {
533+ bool exists ;
534+ int ret ;
535+
536+ ret = net_shaper_parse_info (binding , tb , info , shaper , & exists );
537+ if (ret )
538+ return ret ;
539+
540+ if (shaper -> handle .scope != NET_SHAPER_SCOPE_NODE &&
541+ shaper -> handle .scope != NET_SHAPER_SCOPE_NETDEV ) {
542+ NL_SET_BAD_ATTR (info -> extack , tb [NET_SHAPER_A_HANDLE ]);
543+ return - EINVAL ;
544+ }
545+
546+ if (tb [NET_SHAPER_A_PARENT ]) {
547+ ret = net_shaper_parse_handle (tb [NET_SHAPER_A_PARENT ], info ,
548+ & shaper -> parent );
549+ if (ret )
550+ return ret ;
551+
552+ if (shaper -> parent .scope != NET_SHAPER_SCOPE_NODE &&
553+ shaper -> parent .scope != NET_SHAPER_SCOPE_NETDEV ) {
554+ NL_SET_BAD_ATTR (info -> extack , tb [NET_SHAPER_A_PARENT ]);
555+ return - EINVAL ;
556+ }
557+ }
558+ return 0 ;
559+ }
560+
475561static int net_shaper_generic_pre (struct genl_info * info , int type )
476562{
477563 struct net_shaper_nl_ctx * ctx = (struct net_shaper_nl_ctx * )info -> ctx ;
@@ -670,6 +756,123 @@ static int __net_shaper_delete(struct net_shaper_binding *binding,
670756 return 0 ;
671757}
672758
759+ static int net_shaper_handle_cmp (const struct net_shaper_handle * a ,
760+ const struct net_shaper_handle * b )
761+ {
762+ /* Must avoid holes in struct net_shaper_handle. */
763+ BUILD_BUG_ON (sizeof (* a ) != 8 );
764+
765+ return memcmp (a , b , sizeof (* a ));
766+ }
767+
768+ static int net_shaper_parent_from_leaves (int leaves_count ,
769+ const struct net_shaper * leaves ,
770+ struct net_shaper * node ,
771+ struct netlink_ext_ack * extack )
772+ {
773+ struct net_shaper_handle parent = leaves [0 ].parent ;
774+ int i ;
775+
776+ for (i = 1 ; i < leaves_count ; ++ i ) {
777+ if (net_shaper_handle_cmp (& leaves [i ].parent , & parent )) {
778+ NL_SET_ERR_MSG_FMT (extack , "All the leaves shapers must have the same old parent" );
779+ return - EINVAL ;
780+ }
781+ }
782+
783+ node -> parent = parent ;
784+ return 0 ;
785+ }
786+
787+ static int __net_shaper_group (struct net_shaper_binding * binding ,
788+ int leaves_count , struct net_shaper * leaves ,
789+ struct net_shaper * node ,
790+ struct netlink_ext_ack * extack )
791+ {
792+ const struct net_shaper_ops * ops = net_shaper_ops (binding );
793+ struct net_shaper_handle leaf_handle ;
794+ struct net_shaper * parent = NULL ;
795+ bool new_node = false;
796+ int i , ret ;
797+
798+ if (node -> handle .scope == NET_SHAPER_SCOPE_NODE ) {
799+ new_node = node -> handle .id == NET_SHAPER_ID_UNSPEC ;
800+
801+ if (!new_node && !net_shaper_lookup (binding , & node -> handle )) {
802+ /* The related attribute is not available when
803+ * reaching here from the delete() op.
804+ */
805+ NL_SET_ERR_MSG_FMT (extack , "Node shaper %d:%d does not exists" ,
806+ node -> handle .scope , node -> handle .id );
807+ return - ENOENT ;
808+ }
809+
810+ /* When unspecified, the node parent scope is inherited from
811+ * the leaves.
812+ */
813+ if (node -> parent .scope == NET_SHAPER_SCOPE_UNSPEC ) {
814+ ret = net_shaper_parent_from_leaves (leaves_count ,
815+ leaves , node ,
816+ extack );
817+ if (ret )
818+ return ret ;
819+ }
820+
821+ } else {
822+ net_shaper_default_parent (& node -> handle , & node -> parent );
823+ }
824+
825+ if (node -> parent .scope == NET_SHAPER_SCOPE_NODE ) {
826+ parent = net_shaper_lookup (binding , & node -> parent );
827+ if (!parent ) {
828+ NL_SET_ERR_MSG_FMT (extack , "Node parent shaper %d:%d does not exists" ,
829+ node -> parent .scope , node -> parent .id );
830+ return - ENOENT ;
831+ }
832+ }
833+
834+ /* For newly created node scope shaper, the following will update
835+ * the handle, due to id allocation.
836+ */
837+ ret = net_shaper_pre_insert (binding , & node -> handle , extack );
838+ if (ret )
839+ return ret ;
840+
841+ for (i = 0 ; i < leaves_count ; ++ i ) {
842+ leaf_handle = leaves [i ].handle ;
843+
844+ ret = net_shaper_pre_insert (binding , & leaf_handle , extack );
845+ if (ret )
846+ goto rollback ;
847+
848+ if (!net_shaper_handle_cmp (& leaves [i ].parent , & node -> handle ))
849+ continue ;
850+
851+ /* The leaves shapers will be nested to the node, update the
852+ * linking accordingly.
853+ */
854+ leaves [i ].parent = node -> handle ;
855+ node -> leaves ++ ;
856+ }
857+
858+ ret = ops -> group (binding , leaves_count , leaves , node , extack );
859+ if (ret < 0 )
860+ goto rollback ;
861+
862+ /* The node's parent gains a new leaf only when the node itself
863+ * is created by this group operation
864+ */
865+ if (new_node && parent )
866+ parent -> leaves ++ ;
867+ net_shaper_commit (binding , 1 , node );
868+ net_shaper_commit (binding , leaves_count , leaves );
869+ return 0 ;
870+
871+ rollback :
872+ net_shaper_rollback (binding );
873+ return ret ;
874+ }
875+
673876int net_shaper_nl_delete_doit (struct sk_buff * skb , struct genl_info * info )
674877{
675878 struct net_shaper_hierarchy * hierarchy ;
@@ -714,6 +917,153 @@ int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info)
714917 return ret ;
715918}
716919
920+ static int net_shaper_group_send_reply (struct net_shaper_binding * binding ,
921+ const struct net_shaper_handle * handle ,
922+ struct genl_info * info ,
923+ struct sk_buff * msg )
924+ {
925+ void * hdr ;
926+
927+ hdr = genlmsg_iput (msg , info );
928+ if (!hdr )
929+ goto free_msg ;
930+
931+ if (net_shaper_fill_binding (msg , binding , NET_SHAPER_A_IFINDEX ) ||
932+ net_shaper_fill_handle (msg , handle , NET_SHAPER_A_HANDLE ))
933+ goto free_msg ;
934+
935+ genlmsg_end (msg , hdr );
936+
937+ return genlmsg_reply (msg , info );
938+
939+ free_msg :
940+ /* Should never happen as msg is pre-allocated with enough space. */
941+ WARN_ONCE (true, "calculated message payload length (%d)" ,
942+ net_shaper_handle_size ());
943+ nlmsg_free (msg );
944+ return - EMSGSIZE ;
945+ }
946+
947+ int net_shaper_nl_group_doit (struct sk_buff * skb , struct genl_info * info )
948+ {
949+ struct net_shaper * * old_nodes , * leaves , node = {};
950+ struct net_shaper_hierarchy * hierarchy ;
951+ struct net_shaper_binding * binding ;
952+ int i , ret , rem , leaves_count ;
953+ int old_nodes_count = 0 ;
954+ struct sk_buff * msg ;
955+ struct nlattr * attr ;
956+
957+ if (GENL_REQ_ATTR_CHECK (info , NET_SHAPER_A_LEAVES ))
958+ return - EINVAL ;
959+
960+ binding = net_shaper_binding_from_ctx (info -> ctx );
961+
962+ /* The group operation is optional. */
963+ if (!net_shaper_ops (binding )-> group )
964+ return - EOPNOTSUPP ;
965+
966+ net_shaper_lock (binding );
967+ leaves_count = net_shaper_list_len (info , NET_SHAPER_A_LEAVES );
968+ if (!leaves_count ) {
969+ NL_SET_BAD_ATTR (info -> extack ,
970+ info -> attrs [NET_SHAPER_A_LEAVES ]);
971+ ret = - EINVAL ;
972+ goto unlock ;
973+ }
974+
975+ leaves = kcalloc (leaves_count , sizeof (struct net_shaper ) +
976+ sizeof (struct net_shaper * ), GFP_KERNEL );
977+ if (!leaves ) {
978+ ret = - ENOMEM ;
979+ goto unlock ;
980+ }
981+ old_nodes = (void * )& leaves [leaves_count ];
982+
983+ ret = net_shaper_parse_node (binding , info -> attrs , info , & node );
984+ if (ret )
985+ goto free_leaves ;
986+
987+ i = 0 ;
988+ nla_for_each_attr_type (attr , NET_SHAPER_A_LEAVES ,
989+ genlmsg_data (info -> genlhdr ),
990+ genlmsg_len (info -> genlhdr ), rem ) {
991+ if (WARN_ON_ONCE (i >= leaves_count ))
992+ goto free_leaves ;
993+
994+ ret = net_shaper_parse_leaf (binding , attr , info ,
995+ & node , & leaves [i ]);
996+ if (ret )
997+ goto free_leaves ;
998+ i ++ ;
999+ }
1000+
1001+ /* Prepare the msg reply in advance, to avoid device operation
1002+ * rollback on allocation failure.
1003+ */
1004+ msg = genlmsg_new (net_shaper_handle_size (), GFP_KERNEL );
1005+ if (!msg )
1006+ goto free_leaves ;
1007+
1008+ hierarchy = net_shaper_hierarchy_setup (binding );
1009+ if (!hierarchy ) {
1010+ ret = - ENOMEM ;
1011+ goto free_msg ;
1012+ }
1013+
1014+ /* Record the node shapers that this group() operation can make
1015+ * childless for later cleanup.
1016+ */
1017+ for (i = 0 ; i < leaves_count ; i ++ ) {
1018+ if (leaves [i ].parent .scope == NET_SHAPER_SCOPE_NODE &&
1019+ net_shaper_handle_cmp (& leaves [i ].parent , & node .handle )) {
1020+ struct net_shaper * tmp ;
1021+
1022+ tmp = net_shaper_lookup (binding , & leaves [i ].parent );
1023+ if (!tmp )
1024+ continue ;
1025+
1026+ old_nodes [old_nodes_count ++ ] = tmp ;
1027+ }
1028+ }
1029+
1030+ ret = __net_shaper_group (binding , leaves_count , leaves , & node ,
1031+ info -> extack );
1032+ if (ret )
1033+ goto free_msg ;
1034+
1035+ /* Check if we need to delete any node left alone by the new leaves
1036+ * linkage.
1037+ */
1038+ for (i = 0 ; i < old_nodes_count ; ++ i ) {
1039+ struct net_shaper * tmp = old_nodes [i ];
1040+
1041+ if (-- tmp -> leaves > 0 )
1042+ continue ;
1043+
1044+ /* Errors here are not fatal: the grouping operation is
1045+ * completed, and user-space can still explicitly clean-up
1046+ * left-over nodes.
1047+ */
1048+ __net_shaper_delete (binding , tmp , info -> extack );
1049+ }
1050+
1051+ ret = net_shaper_group_send_reply (binding , & node .handle , info , msg );
1052+ if (ret )
1053+ GENL_SET_ERR_MSG_FMT (info , "Can't send reply" );
1054+
1055+ free_leaves :
1056+ kfree (leaves );
1057+
1058+ unlock :
1059+ net_shaper_unlock (binding );
1060+ return ret ;
1061+
1062+ free_msg :
1063+ kfree_skb (msg );
1064+ goto free_leaves ;
1065+ }
1066+
7171067static void net_shaper_flush (struct net_shaper_binding * binding )
7181068{
7191069 struct net_shaper_hierarchy * hierarchy = net_shaper_hierarchy (binding );
0 commit comments