Hello,
On Mon, 5 Feb 2024, Terin Stock wrote:
> The IPVS subsystem allows for configuration from userspace programs
> using the generic netlink interface. However, the program is currently
> unable to react to changes in the configuration of services or
> destinations made on the system without polling over all configuration
> in IPVS.
>
> Adds an "events" multicast group for the IPVS generic netlink family,
> allowing for userspace programs to monitor changes made by any other
> netlink client (or legacy tools using the IPVS socket options). As
> service and destination statistics are separate from configuration,
> those netlink attributes are excluded in events.
>
> Signed-off-by: Terin Stock <terin@xxxxxxxxxxxxxx>
> ---
> include/uapi/linux/ip_vs.h | 2 +
> net/netfilter/ipvs/ip_vs_ctl.c | 107 +++++++++++++++++++++++++++++----
> 2 files changed, 96 insertions(+), 13 deletions(-)
>
> diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h
> index 1ed234e7f251..0aa119ebaf85 100644
> --- a/include/uapi/linux/ip_vs.h
> +++ b/include/uapi/linux/ip_vs.h
> @@ -299,6 +299,8 @@ struct ip_vs_daemon_user {
> #define IPVS_GENL_NAME "IPVS"
> #define IPVS_GENL_VERSION 0x1
>
> +#define IPVS_GENL_MCAST_EVENT_NAME "events"
> +
> struct ip_vs_flags {
> __u32 flags;
> __u32 mask;
> diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
> index 143a341bbc0a..ced232361d02 100644
> --- a/net/netfilter/ipvs/ip_vs_ctl.c
> +++ b/net/netfilter/ipvs/ip_vs_ctl.c
> @@ -64,6 +64,11 @@ int ip_vs_get_debug_level(void)
>
>
> /* Protos */
> +static struct genl_family ip_vs_genl_family;
> +static int ip_vs_genl_fill_service(struct sk_buff *skb,
> + struct ip_vs_service *svc, bool stats);
> +static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest,
> + bool stats);
> static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup);
>
>
> @@ -960,6 +965,62 @@ void ip_vs_stats_free(struct ip_vs_stats *stats)
> }
> }
>
> +static int ip_vs_genl_service_event(u8 event, struct ip_vs_service *svc)
> +{
> + struct sk_buff *msg;
> + void *hdr;
> +
> + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
> + if (!msg)
> + return -ENOMEM;
> +
> + hdr = genlmsg_put(msg, 0, 0, &ip_vs_genl_family, 0, event);
> + if (!hdr)
> + goto free_msg;
> +
> + if (ip_vs_genl_fill_service(msg, svc, false))
> + goto free_msg;
> +
> + genlmsg_end(msg, hdr);
> + genlmsg_multicast(&ip_vs_genl_family, msg, 0, 0, GFP_ATOMIC);
May be genlmsg_multicast_netns because the rules are per netns?
As result, may be on net cleanup such events should not be generated,
see 'bool cleanup'.
And to use GFP_KERNEL because all configuration happens in process
context? On module removal, ip_vs_unregister_nl_ioctl() is called before
the rules are flushed, not sure if we should add some check or it is not
fatal to post events for unregistered genl family?
Also, IP_VS_SO_SET_FLUSH can flush rules and now it will not be
reported.
I also worry that such events slowdown the configuration
process for setups with many rules which do not use listeners.
Should we enable it with some sysctl var? Currently, many CPU cycles are
spent before we notice that there are no listeners.
Regards
--
Julian Anastasov <ja@xxxxxx>
|