@@ -684,6 +684,18 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
684
684
return -1 ;
685
685
}
686
686
687
+ struct nftnl_skb_parms {
688
+ bool report ;
689
+ };
690
+ #define NFT_CB (skb ) (*(struct nftnl_skb_parms*)&((skb)->cb))
691
+
692
+ static void nft_notify_enqueue (struct sk_buff * skb , bool report ,
693
+ struct list_head * notify_list )
694
+ {
695
+ NFT_CB (skb ).report = report ;
696
+ list_add_tail (& skb -> list , notify_list );
697
+ }
698
+
687
699
static void nf_tables_table_notify (const struct nft_ctx * ctx , int event )
688
700
{
689
701
struct sk_buff * skb ;
@@ -715,8 +727,7 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
715
727
goto err ;
716
728
}
717
729
718
- nfnetlink_send (skb , ctx -> net , ctx -> portid , NFNLGRP_NFTABLES ,
719
- ctx -> report , GFP_KERNEL );
730
+ nft_notify_enqueue (skb , ctx -> report , & ctx -> net -> nft .notify_list );
720
731
return ;
721
732
err :
722
733
nfnetlink_set_err (ctx -> net , ctx -> portid , NFNLGRP_NFTABLES , - ENOBUFS );
@@ -1468,8 +1479,7 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
1468
1479
goto err ;
1469
1480
}
1470
1481
1471
- nfnetlink_send (skb , ctx -> net , ctx -> portid , NFNLGRP_NFTABLES ,
1472
- ctx -> report , GFP_KERNEL );
1482
+ nft_notify_enqueue (skb , ctx -> report , & ctx -> net -> nft .notify_list );
1473
1483
return ;
1474
1484
err :
1475
1485
nfnetlink_set_err (ctx -> net , ctx -> portid , NFNLGRP_NFTABLES , - ENOBUFS );
@@ -2807,8 +2817,7 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
2807
2817
goto err ;
2808
2818
}
2809
2819
2810
- nfnetlink_send (skb , ctx -> net , ctx -> portid , NFNLGRP_NFTABLES ,
2811
- ctx -> report , GFP_KERNEL );
2820
+ nft_notify_enqueue (skb , ctx -> report , & ctx -> net -> nft .notify_list );
2812
2821
return ;
2813
2822
err :
2814
2823
nfnetlink_set_err (ctx -> net , ctx -> portid , NFNLGRP_NFTABLES , - ENOBUFS );
@@ -3837,8 +3846,7 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
3837
3846
goto err ;
3838
3847
}
3839
3848
3840
- nfnetlink_send (skb , ctx -> net , portid , NFNLGRP_NFTABLES , ctx -> report ,
3841
- gfp_flags );
3849
+ nft_notify_enqueue (skb , ctx -> report , & ctx -> net -> nft .notify_list );
3842
3850
return ;
3843
3851
err :
3844
3852
nfnetlink_set_err (ctx -> net , portid , NFNLGRP_NFTABLES , - ENOBUFS );
@@ -4959,8 +4967,7 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
4959
4967
goto err ;
4960
4968
}
4961
4969
4962
- nfnetlink_send (skb , net , portid , NFNLGRP_NFTABLES , ctx -> report ,
4963
- GFP_KERNEL );
4970
+ nft_notify_enqueue (skb , ctx -> report , & ctx -> net -> nft .notify_list );
4964
4971
return ;
4965
4972
err :
4966
4973
nfnetlink_set_err (net , portid , NFNLGRP_NFTABLES , - ENOBUFS );
@@ -6275,7 +6282,7 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
6275
6282
goto err ;
6276
6283
}
6277
6284
6278
- nfnetlink_send (skb , net , portid , NFNLGRP_NFTABLES , report , gfp );
6285
+ nft_notify_enqueue (skb , report , & net -> nft . notify_list );
6279
6286
return ;
6280
6287
err :
6281
6288
nfnetlink_set_err (net , portid , NFNLGRP_NFTABLES , - ENOBUFS );
@@ -7085,8 +7092,7 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
7085
7092
goto err ;
7086
7093
}
7087
7094
7088
- nfnetlink_send (skb , ctx -> net , ctx -> portid , NFNLGRP_NFTABLES ,
7089
- ctx -> report , GFP_KERNEL );
7095
+ nft_notify_enqueue (skb , ctx -> report , & ctx -> net -> nft .notify_list );
7090
7096
return ;
7091
7097
err :
7092
7098
nfnetlink_set_err (ctx -> net , ctx -> portid , NFNLGRP_NFTABLES , - ENOBUFS );
@@ -7695,6 +7701,41 @@ static void nf_tables_commit_release(struct net *net)
7695
7701
mutex_unlock (& net -> nft .commit_mutex );
7696
7702
}
7697
7703
7704
+ static void nft_commit_notify (struct net * net , u32 portid )
7705
+ {
7706
+ struct sk_buff * batch_skb = NULL , * nskb , * skb ;
7707
+ unsigned char * data ;
7708
+ int len ;
7709
+
7710
+ list_for_each_entry_safe (skb , nskb , & net -> nft .notify_list , list ) {
7711
+ if (!batch_skb ) {
7712
+ new_batch :
7713
+ batch_skb = skb ;
7714
+ len = NLMSG_GOODSIZE - skb -> len ;
7715
+ list_del (& skb -> list );
7716
+ continue ;
7717
+ }
7718
+ len -= skb -> len ;
7719
+ if (len > 0 && NFT_CB (skb ).report == NFT_CB (batch_skb ).report ) {
7720
+ data = skb_put (batch_skb , skb -> len );
7721
+ memcpy (data , skb -> data , skb -> len );
7722
+ list_del (& skb -> list );
7723
+ kfree_skb (skb );
7724
+ continue ;
7725
+ }
7726
+ nfnetlink_send (batch_skb , net , portid , NFNLGRP_NFTABLES ,
7727
+ NFT_CB (batch_skb ).report , GFP_KERNEL );
7728
+ goto new_batch ;
7729
+ }
7730
+
7731
+ if (batch_skb ) {
7732
+ nfnetlink_send (batch_skb , net , portid , NFNLGRP_NFTABLES ,
7733
+ NFT_CB (batch_skb ).report , GFP_KERNEL );
7734
+ }
7735
+
7736
+ WARN_ON_ONCE (!list_empty (& net -> nft .notify_list ));
7737
+ }
7738
+
7698
7739
static int nf_tables_commit (struct net * net , struct sk_buff * skb )
7699
7740
{
7700
7741
struct nft_trans * trans , * next ;
@@ -7897,6 +7938,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
7897
7938
}
7898
7939
}
7899
7940
7941
+ nft_commit_notify (net , NETLINK_CB (skb ).portid );
7900
7942
nf_tables_gen_notify (net , skb , NFT_MSG_NEWGEN );
7901
7943
nf_tables_commit_release (net );
7902
7944
@@ -8721,6 +8763,7 @@ static int __net_init nf_tables_init_net(struct net *net)
8721
8763
INIT_LIST_HEAD (& net -> nft .tables );
8722
8764
INIT_LIST_HEAD (& net -> nft .commit_list );
8723
8765
INIT_LIST_HEAD (& net -> nft .module_list );
8766
+ INIT_LIST_HEAD (& net -> nft .notify_list );
8724
8767
mutex_init (& net -> nft .commit_mutex );
8725
8768
net -> nft .base_seq = 1 ;
8726
8769
net -> nft .validate_state = NFT_VALIDATE_SKIP ;
@@ -8737,6 +8780,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)
8737
8780
mutex_unlock (& net -> nft .commit_mutex );
8738
8781
WARN_ON_ONCE (!list_empty (& net -> nft .tables ));
8739
8782
WARN_ON_ONCE (!list_empty (& net -> nft .module_list ));
8783
+ WARN_ON_ONCE (!list_empty (& net -> nft .notify_list ));
8740
8784
}
8741
8785
8742
8786
static struct pernet_operations nf_tables_net_ops = {
0 commit comments