lkml.org 
[lkml]   [2019]   [Feb]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH net-next v3 07/21] ethtool: implement EVENT notifications
    Date
    Three types of netlink notifications are introduced:

    - ETHA_EVENT_NEWDEV to notify about newly registered network devices
    - ETHA_EVENT_DELDEV to notify about unregistered network devices
    - ETHA_EVENT_RENAMEDEV to notify about renamed network device

    The notifications are triggered by NETDEV_REGISTER, NETDEV_UNREGISTER and
    NETDEV_CHANGENAME notifiers.

    These notifications are intended for applications and daemons monitoring
    ethtool events to allow updating the list of existing devices without
    having to open another socket for rtnetlink.

    Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
    ---
    Documentation/networking/ethtool-netlink.txt | 27 ++++++++
    include/uapi/linux/ethtool_netlink.h | 37 +++++++++++
    net/ethtool/netlink.c | 65 ++++++++++++++++++++
    3 files changed, 129 insertions(+)

    diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
    index 205ae4462e9e..b79c26b5e92b 100644
    --- a/Documentation/networking/ethtool-netlink.txt
    +++ b/Documentation/networking/ethtool-netlink.txt
    @@ -125,6 +125,8 @@ which the request applies.
    List of message types
    ---------------------

    + ETHNL_CMD_EVENT notification only
    +
    All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
    to indicate the type.

    @@ -136,9 +138,34 @@ messages marked as "response only" in the table above. "Get" messages with
    NLM_F_DUMP flags and no device identification dump the information for all
    devices supporting the request.

    +Type ETHNL_CMD_EVENT is special, these messages are never used in userspace
    +requests or kernel replies. They are only sent by kernel to sockets listening
    +to "monitor" multicast group to inform userspace about certain events.
    +
    Later sections describe the format and semantics of these request messages.


    +EVENT
    +-----
    +
    +EVENT messages are only used in kernel multicast notifications. Atributes
    +correspond to specific event types, the same type can appear multiple times.
    +
    + ETHA_EVENT_NEWDEV (nested) new device was registered
    + ETHA_NEWDEV_DEV (nested) new device
    + ETHA_EVENT_DELDEV (nested) device was unregistered
    + ETHA_DELDEV_DEV (nested) removed device
    + ETHA_EVENT_RENAMEDEV (nested) device was renamed
    + ETHA_RENAMEDEV_DEV (nested) renamed device
    +
    +For ETHA_EVENT_RENAMEDEV, the name ETHA_RENAME_DEV/ETHA_DEV_NAME is the new
    +name after the rename.
    +
    +Userspace application must expect multiple events to be present in one message
    +and also multiple events of the same type (e.g. two or more newly registered
    +devices).
    +
    +
    Request translation
    -------------------

    diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
    index b662d75a0636..7e192ad8ce3a 100644
    --- a/include/uapi/linux/ethtool_netlink.h
    +++ b/include/uapi/linux/ethtool_netlink.h
    @@ -7,6 +7,7 @@

    enum {
    ETHNL_CMD_NOOP,
    + ETHNL_CMD_EVENT, /* only for notifications */

    __ETHNL_CMD_CNT,
    ETHNL_CMD_MAX = (__ETHNL_CMD_CNT - 1)
    @@ -55,6 +56,42 @@ enum {
    ETHA_BITSET_MAX = (__ETHA_BITSET_CNT - 1)
    };

    +/* events */
    +
    +enum {
    + ETHA_NEWDEV_UNSPEC,
    + ETHA_NEWDEV_DEV, /* nest - ETHA_DEV_* */
    +
    + __ETHA_NEWDEV_CNT,
    + ETHA_NEWDEV_MAX = (__ETHA_NEWDEV_CNT - 1)
    +};
    +
    +enum {
    + ETHA_DELDEV_UNSPEC,
    + ETHA_DELDEV_DEV, /* nest - ETHA_DEV_* */
    +
    + __ETHA_DELDEV_CNT,
    + ETHA_DELDEV_MAX = (__ETHA_DELDEV_CNT - 1)
    +};
    +
    +enum {
    + ETHA_RENAMEDEV_UNSPEC,
    + ETHA_RENAMEDEV_DEV, /* nest - ETHA_DEV_* */
    +
    + __ETHA_RENAMEDEV_CNT,
    + ETHA_RENAMEDEV_MAX = (__ETHA_RENAMEDEV_CNT - 1)
    +};
    +
    +enum {
    + ETHA_EVENT_UNSPEC,
    + ETHA_EVENT_NEWDEV, /* nest - ETHA_NEWDEV_* */
    + ETHA_EVENT_DELDEV, /* nest - ETHA_DELDEV_* */
    + ETHA_EVENT_RENAMEDEV, /* nest - ETHA_RENAMEDEV_* */
    +
    + __ETHA_EVENT_CNT,
    + ETHA_EVENT_MAX = (__ETHA_EVENT_CNT - 1)
    +};
    +
    /* generic netlink info */
    #define ETHTOOL_GENL_NAME "ethtool"
    #define ETHTOOL_GENL_VERSION 1
    diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
    index a5fa54c2b743..ee3424cd1f90 100644
    --- a/net/ethtool/netlink.c
    +++ b/net/ethtool/netlink.c
    @@ -148,6 +148,67 @@ void ethtool_notify(struct net_device *dev, struct netlink_ext_ack *extack,
    }
    EXPORT_SYMBOL(ethtool_notify);

    +/* size of NEWDEV/DELDEV notification */
    +static inline unsigned int dev_notify_size(void)
    +{
    + return nla_total_size(dev_ident_size());
    +}
    +
    +static void ethnl_notify_devlist(struct netdev_notifier_info *info,
    + u16 ev_type, u16 dev_attr)
    +{
    + struct net_device *dev = netdev_notifier_info_to_dev(info);
    + struct sk_buff *skb;
    + struct nlattr *nest;
    + void *ehdr;
    + int ret;
    +
    + skb = genlmsg_new(dev_notify_size(), GFP_KERNEL);
    + if (!skb)
    + return;
    + ehdr = genlmsg_put(skb, 0, ++ethnl_bcast_seq, &ethtool_genl_family, 0,
    + ETHNL_CMD_EVENT);
    + if (!ehdr)
    + goto out_skb;
    + nest = ethnl_nest_start(skb, ev_type);
    + if (!nest)
    + goto out_skb;
    + ret = ethnl_fill_dev(skb, dev, dev_attr);
    + if (ret < 0)
    + goto out_skb;
    + nla_nest_end(skb, nest);
    + genlmsg_end(skb, ehdr);
    +
    + genlmsg_multicast(&ethtool_genl_family, skb, 0, ETHNL_MCGRP_MONITOR,
    + GFP_KERNEL);
    + return;
    +out_skb:
    + nlmsg_free(skb);
    +}
    +
    +static int ethnl_netdev_event(struct notifier_block *this, unsigned long event,
    + void *ptr)
    +{
    + switch (event) {
    + case NETDEV_REGISTER:
    + ethnl_notify_devlist(ptr, ETHA_EVENT_NEWDEV, ETHA_NEWDEV_DEV);
    + break;
    + case NETDEV_UNREGISTER:
    + ethnl_notify_devlist(ptr, ETHA_EVENT_DELDEV, ETHA_DELDEV_DEV);
    + break;
    + case NETDEV_CHANGENAME:
    + ethnl_notify_devlist(ptr, ETHA_EVENT_RENAMEDEV,
    + ETHA_RENAMEDEV_DEV);
    + break;
    + }
    +
    + return NOTIFY_DONE;
    +}
    +
    +static struct notifier_block ethnl_netdev_notifier = {
    + .notifier_call = ethnl_netdev_event,
    +};
    +
    /* genetlink setup */

    static const struct genl_ops ethtool_genl_ops[] = {
    @@ -179,6 +240,10 @@ static int __init ethnl_init(void)
    if (ret < 0)
    panic("ethtool: could not register genetlink family\n");

    + ret = register_netdevice_notifier(&ethnl_netdev_notifier);
    + if (ret < 0)
    + panic("ethtool: could not register netdev notifier\n");
    +
    return 0;
    }

    --
    2.20.1
    \
     
     \ /
      Last update: 2019-02-18 19:23    [W:7.152 / U:0.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site