62
62
63
63
int ovs_net_id __read_mostly ;
64
64
65
+ /* Check if need to build a reply message.
66
+ * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
67
+ static bool ovs_must_notify (struct genl_info * info ,
68
+ const struct genl_multicast_group * grp )
69
+ {
70
+ return info -> nlhdr -> nlmsg_flags & NLM_F_ECHO ||
71
+ netlink_has_listeners (genl_info_net (info )-> genl_sock , 0 );
72
+ }
73
+
65
74
static void ovs_notify (struct genl_family * family ,
66
75
struct sk_buff * skb , struct genl_info * info )
67
76
{
@@ -746,27 +755,36 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
746
755
747
756
/* Must be called with ovs_mutex. */
748
757
static struct sk_buff * ovs_flow_cmd_alloc_info (struct sw_flow * flow ,
749
- struct genl_info * info )
758
+ struct genl_info * info ,
759
+ bool always )
750
760
{
761
+ struct sk_buff * skb ;
751
762
size_t len ;
752
763
764
+ if (!always && !ovs_must_notify (info , & ovs_dp_flow_multicast_group ))
765
+ return NULL ;
766
+
753
767
len = ovs_flow_cmd_msg_size (ovsl_dereference (flow -> sf_acts ));
754
768
755
- return genlmsg_new_unicast (len , info , GFP_KERNEL );
769
+ skb = genlmsg_new_unicast (len , info , GFP_KERNEL );
770
+ if (!skb )
771
+ return ERR_PTR (- ENOMEM );
772
+
773
+ return skb ;
756
774
}
757
775
758
776
/* Must be called with ovs_mutex. */
759
777
static struct sk_buff * ovs_flow_cmd_build_info (struct sw_flow * flow ,
760
778
struct datapath * dp ,
761
779
struct genl_info * info ,
762
- u8 cmd )
780
+ u8 cmd , bool always )
763
781
{
764
782
struct sk_buff * skb ;
765
783
int retval ;
766
784
767
- skb = ovs_flow_cmd_alloc_info (flow , info );
768
- if (!skb )
769
- return ERR_PTR ( - ENOMEM ) ;
785
+ skb = ovs_flow_cmd_alloc_info (flow , info , always );
786
+ if (!skb || IS_ERR ( skb ) )
787
+ return skb ;
770
788
771
789
retval = ovs_flow_cmd_fill_info (flow , dp , skb , info -> snd_portid ,
772
790
info -> snd_seq , 0 , cmd );
@@ -850,7 +868,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
850
868
goto err_flow_free ;
851
869
}
852
870
853
- reply = ovs_flow_cmd_build_info (flow , dp , info , OVS_FLOW_CMD_NEW );
871
+ reply = ovs_flow_cmd_build_info (flow , dp , info ,
872
+ OVS_FLOW_CMD_NEW , false);
854
873
} else {
855
874
/* We found a matching flow. */
856
875
/* Bail out if we're not allowed to modify an existing flow.
@@ -876,19 +895,23 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
876
895
rcu_assign_pointer (flow -> sf_acts , acts );
877
896
ovs_nla_free_flow_actions (old_acts );
878
897
}
879
- reply = ovs_flow_cmd_build_info (flow , dp , info , OVS_FLOW_CMD_NEW );
898
+ reply = ovs_flow_cmd_build_info (flow , dp , info ,
899
+ OVS_FLOW_CMD_NEW , false);
880
900
881
901
/* Clear stats. */
882
902
if (a [OVS_FLOW_ATTR_CLEAR ])
883
903
ovs_flow_stats_clear (flow );
884
904
}
885
905
ovs_unlock ();
886
906
887
- if (!IS_ERR (reply ))
888
- ovs_notify (& dp_flow_genl_family , reply , info );
889
- else
890
- genl_set_err (& dp_flow_genl_family , sock_net (skb -> sk ), 0 ,
891
- 0 , PTR_ERR (reply ));
907
+ if (reply ) {
908
+ if (!IS_ERR (reply ))
909
+ ovs_notify (& dp_flow_genl_family , reply , info );
910
+ else
911
+ genl_set_err (& dp_flow_genl_family , sock_net (skb -> sk ), 0 ,
912
+ 0 , PTR_ERR (reply ));
913
+ }
914
+
892
915
return 0 ;
893
916
894
917
err_flow_free :
@@ -935,7 +958,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
935
958
goto unlock ;
936
959
}
937
960
938
- reply = ovs_flow_cmd_build_info (flow , dp , info , OVS_FLOW_CMD_NEW );
961
+ reply = ovs_flow_cmd_build_info (flow , dp , info , OVS_FLOW_CMD_NEW , true );
939
962
if (IS_ERR (reply )) {
940
963
err = PTR_ERR (reply );
941
964
goto unlock ;
@@ -982,22 +1005,25 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
982
1005
goto unlock ;
983
1006
}
984
1007
985
- reply = ovs_flow_cmd_alloc_info (flow , info );
986
- if (! reply ) {
987
- err = - ENOMEM ;
1008
+ reply = ovs_flow_cmd_alloc_info (flow , info , false );
1009
+ if (IS_ERR ( reply ) ) {
1010
+ err = PTR_ERR ( reply ) ;
988
1011
goto unlock ;
989
1012
}
990
1013
991
1014
ovs_flow_tbl_remove (& dp -> table , flow );
992
1015
993
- err = ovs_flow_cmd_fill_info (flow , dp , reply , info -> snd_portid ,
994
- info -> snd_seq , 0 , OVS_FLOW_CMD_DEL );
995
- BUG_ON (err < 0 );
996
-
1016
+ if (reply ) {
1017
+ err = ovs_flow_cmd_fill_info (flow , dp , reply , info -> snd_portid ,
1018
+ info -> snd_seq , 0 ,
1019
+ OVS_FLOW_CMD_DEL );
1020
+ BUG_ON (err < 0 );
1021
+ }
997
1022
ovs_flow_free (flow , true);
998
1023
ovs_unlock ();
999
1024
1000
- ovs_notify (& dp_flow_genl_family , reply , info );
1025
+ if (reply )
1026
+ ovs_notify (& dp_flow_genl_family , reply , info );
1001
1027
return 0 ;
1002
1028
unlock :
1003
1029
ovs_unlock ();
0 commit comments