@@ -785,7 +785,8 @@ static int net_shaper_parent_from_leaves(int leaves_count,
785785}
786786
787787static int __net_shaper_group (struct net_shaper_binding * binding ,
788- int leaves_count , struct net_shaper * leaves ,
788+ bool update_node , int leaves_count ,
789+ struct net_shaper * leaves ,
789790 struct net_shaper * node ,
790791 struct netlink_ext_ack * extack )
791792{
@@ -831,12 +832,14 @@ static int __net_shaper_group(struct net_shaper_binding *binding,
831832 }
832833 }
833834
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 ;
835+ if (update_node ) {
836+ /* For newly created node scope shaper, the following will
837+ * update the handle, due to id allocation.
838+ */
839+ ret = net_shaper_pre_insert (binding , & node -> handle , extack );
840+ if (ret )
841+ return ret ;
842+ }
840843
841844 for (i = 0 ; i < leaves_count ; ++ i ) {
842845 leaf_handle = leaves [i ].handle ;
@@ -864,7 +867,8 @@ static int __net_shaper_group(struct net_shaper_binding *binding,
864867 */
865868 if (new_node && parent )
866869 parent -> leaves ++ ;
867- net_shaper_commit (binding , 1 , node );
870+ if (update_node )
871+ net_shaper_commit (binding , 1 , node );
868872 net_shaper_commit (binding , leaves_count , leaves );
869873 return 0 ;
870874
@@ -873,6 +877,64 @@ static int __net_shaper_group(struct net_shaper_binding *binding,
873877 return ret ;
874878}
875879
880+ static int net_shaper_pre_del_node (struct net_shaper_binding * binding ,
881+ const struct net_shaper * shaper ,
882+ struct netlink_ext_ack * extack )
883+ {
884+ struct net_shaper_hierarchy * hierarchy = net_shaper_hierarchy (binding );
885+ struct net_shaper * cur , * leaves , node = {};
886+ int ret , leaves_count = 0 ;
887+ unsigned long index ;
888+ bool update_node ;
889+
890+ if (!shaper -> leaves )
891+ return 0 ;
892+
893+ /* Fetch the new node information. */
894+ node .handle = shaper -> parent ;
895+ cur = net_shaper_lookup (binding , & node .handle );
896+ if (cur ) {
897+ node = * cur ;
898+ } else {
899+ /* A scope NODE shaper can be nested only to the NETDEV scope
900+ * shaper without creating the latter, this check may fail only
901+ * if the data is in inconsistent status.
902+ */
903+ if (WARN_ON_ONCE (node .handle .scope != NET_SHAPER_SCOPE_NETDEV ))
904+ return - EINVAL ;
905+ }
906+
907+ leaves = kcalloc (shaper -> leaves , sizeof (struct net_shaper ),
908+ GFP_KERNEL );
909+ if (!leaves )
910+ return - ENOMEM ;
911+
912+ /* Build the leaves arrays. */
913+ xa_for_each (& hierarchy -> shapers , index , cur ) {
914+ if (net_shaper_handle_cmp (& cur -> parent , & shaper -> handle ))
915+ continue ;
916+
917+ if (WARN_ON_ONCE (leaves_count == shaper -> leaves )) {
918+ ret = - EINVAL ;
919+ goto free ;
920+ }
921+
922+ leaves [leaves_count ++ ] = * cur ;
923+ }
924+
925+ /* When re-linking to the netdev shaper, avoid the eventual, implicit,
926+ * creation of the new node, would be surprising since the user is
927+ * doing a delete operation.
928+ */
929+ update_node = node .handle .scope != NET_SHAPER_SCOPE_NETDEV ;
930+ ret = __net_shaper_group (binding , update_node , leaves_count ,
931+ leaves , & node , extack );
932+
933+ free :
934+ kfree (leaves );
935+ return ret ;
936+ }
937+
876938int net_shaper_nl_delete_doit (struct sk_buff * skb , struct genl_info * info )
877939{
878940 struct net_shaper_hierarchy * hierarchy ;
@@ -905,9 +967,9 @@ int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info)
905967 }
906968
907969 if (handle .scope == NET_SHAPER_SCOPE_NODE ) {
908- /* TODO: implement support for scope NODE delete. */
909- ret = - EINVAL ;
910- goto unlock ;
970+ ret = net_shaper_pre_del_node ( binding , shaper , info -> extack );
971+ if ( ret )
972+ goto unlock ;
911973 }
912974
913975 ret = __net_shaper_delete (binding , shaper , info -> extack );
@@ -1027,7 +1089,7 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info)
10271089 }
10281090 }
10291091
1030- ret = __net_shaper_group (binding , leaves_count , leaves , & node ,
1092+ ret = __net_shaper_group (binding , true, leaves_count , leaves , & node ,
10311093 info -> extack );
10321094 if (ret )
10331095 goto free_msg ;
0 commit comments