LCOV - code coverage report
Current view: top level - net/ethtool - linkinfo.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 67 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 4 0.0 %
Branches: 0 52 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : 
       3                 :            : #include "netlink.h"
       4                 :            : #include "common.h"
       5                 :            : 
       6                 :            : struct linkinfo_req_info {
       7                 :            :         struct ethnl_req_info           base;
       8                 :            : };
       9                 :            : 
      10                 :            : struct linkinfo_reply_data {
      11                 :            :         struct ethnl_reply_data         base;
      12                 :            :         struct ethtool_link_ksettings   ksettings;
      13                 :            :         struct ethtool_link_settings    *lsettings;
      14                 :            : };
      15                 :            : 
      16                 :            : #define LINKINFO_REPDATA(__reply_base) \
      17                 :            :         container_of(__reply_base, struct linkinfo_reply_data, base)
      18                 :            : 
      19                 :            : static const struct nla_policy
      20                 :            : linkinfo_get_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {
      21                 :            :         [ETHTOOL_A_LINKINFO_UNSPEC]             = { .type = NLA_REJECT },
      22                 :            :         [ETHTOOL_A_LINKINFO_HEADER]             = { .type = NLA_NESTED },
      23                 :            :         [ETHTOOL_A_LINKINFO_PORT]               = { .type = NLA_REJECT },
      24                 :            :         [ETHTOOL_A_LINKINFO_PHYADDR]            = { .type = NLA_REJECT },
      25                 :            :         [ETHTOOL_A_LINKINFO_TP_MDIX]            = { .type = NLA_REJECT },
      26                 :            :         [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL]       = { .type = NLA_REJECT },
      27                 :            :         [ETHTOOL_A_LINKINFO_TRANSCEIVER]        = { .type = NLA_REJECT },
      28                 :            : };
      29                 :            : 
      30                 :          0 : static int linkinfo_prepare_data(const struct ethnl_req_info *req_base,
      31                 :            :                                  struct ethnl_reply_data *reply_base,
      32                 :            :                                  struct genl_info *info)
      33                 :            : {
      34                 :          0 :         struct linkinfo_reply_data *data = LINKINFO_REPDATA(reply_base);
      35                 :          0 :         struct net_device *dev = reply_base->dev;
      36                 :          0 :         int ret;
      37                 :            : 
      38                 :          0 :         data->lsettings = &data->ksettings.base;
      39                 :            : 
      40         [ #  # ]:          0 :         ret = ethnl_ops_begin(dev);
      41         [ #  # ]:          0 :         if (ret < 0)
      42                 :            :                 return ret;
      43                 :          0 :         ret = __ethtool_get_link_ksettings(dev, &data->ksettings);
      44         [ #  # ]:          0 :         if (ret < 0 && info)
      45         [ #  # ]:          0 :                 GENL_SET_ERR_MSG(info, "failed to retrieve link settings");
      46         [ #  # ]:          0 :         ethnl_ops_complete(dev);
      47                 :            : 
      48                 :            :         return ret;
      49                 :            : }
      50                 :            : 
      51                 :          0 : static int linkinfo_reply_size(const struct ethnl_req_info *req_base,
      52                 :            :                                const struct ethnl_reply_data *reply_base)
      53                 :            : {
      54                 :          0 :         return nla_total_size(sizeof(u8)) /* LINKINFO_PORT */
      55                 :            :                 + nla_total_size(sizeof(u8)) /* LINKINFO_PHYADDR */
      56                 :            :                 + nla_total_size(sizeof(u8)) /* LINKINFO_TP_MDIX */
      57                 :            :                 + nla_total_size(sizeof(u8)) /* LINKINFO_TP_MDIX_CTRL */
      58                 :            :                 + nla_total_size(sizeof(u8)) /* LINKINFO_TRANSCEIVER */
      59                 :          0 :                 + 0;
      60                 :            : }
      61                 :            : 
      62                 :          0 : static int linkinfo_fill_reply(struct sk_buff *skb,
      63                 :            :                                const struct ethnl_req_info *req_base,
      64                 :            :                                const struct ethnl_reply_data *reply_base)
      65                 :            : {
      66                 :          0 :         const struct linkinfo_reply_data *data = LINKINFO_REPDATA(reply_base);
      67                 :            : 
      68   [ #  #  #  # ]:          0 :         if (nla_put_u8(skb, ETHTOOL_A_LINKINFO_PORT, data->lsettings->port) ||
      69                 :            :             nla_put_u8(skb, ETHTOOL_A_LINKINFO_PHYADDR,
      70         [ #  # ]:          0 :                        data->lsettings->phy_address) ||
      71                 :            :             nla_put_u8(skb, ETHTOOL_A_LINKINFO_TP_MDIX,
      72         [ #  # ]:          0 :                        data->lsettings->eth_tp_mdix) ||
      73                 :            :             nla_put_u8(skb, ETHTOOL_A_LINKINFO_TP_MDIX_CTRL,
      74         [ #  # ]:          0 :                        data->lsettings->eth_tp_mdix_ctrl) ||
      75                 :            :             nla_put_u8(skb, ETHTOOL_A_LINKINFO_TRANSCEIVER,
      76                 :          0 :                        data->lsettings->transceiver))
      77                 :          0 :                 return -EMSGSIZE;
      78                 :            : 
      79                 :            :         return 0;
      80                 :            : }
      81                 :            : 
      82                 :            : const struct ethnl_request_ops ethnl_linkinfo_request_ops = {
      83                 :            :         .request_cmd            = ETHTOOL_MSG_LINKINFO_GET,
      84                 :            :         .reply_cmd              = ETHTOOL_MSG_LINKINFO_GET_REPLY,
      85                 :            :         .hdr_attr               = ETHTOOL_A_LINKINFO_HEADER,
      86                 :            :         .max_attr               = ETHTOOL_A_LINKINFO_MAX,
      87                 :            :         .req_info_size          = sizeof(struct linkinfo_req_info),
      88                 :            :         .reply_data_size        = sizeof(struct linkinfo_reply_data),
      89                 :            :         .request_policy         = linkinfo_get_policy,
      90                 :            : 
      91                 :            :         .prepare_data           = linkinfo_prepare_data,
      92                 :            :         .reply_size             = linkinfo_reply_size,
      93                 :            :         .fill_reply             = linkinfo_fill_reply,
      94                 :            : };
      95                 :            : 
      96                 :            : /* LINKINFO_SET */
      97                 :            : 
      98                 :            : static const struct nla_policy
      99                 :            : linkinfo_set_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {
     100                 :            :         [ETHTOOL_A_LINKINFO_UNSPEC]             = { .type = NLA_REJECT },
     101                 :            :         [ETHTOOL_A_LINKINFO_HEADER]             = { .type = NLA_NESTED },
     102                 :            :         [ETHTOOL_A_LINKINFO_PORT]               = { .type = NLA_U8 },
     103                 :            :         [ETHTOOL_A_LINKINFO_PHYADDR]            = { .type = NLA_U8 },
     104                 :            :         [ETHTOOL_A_LINKINFO_TP_MDIX]            = { .type = NLA_REJECT },
     105                 :            :         [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL]       = { .type = NLA_U8 },
     106                 :            :         [ETHTOOL_A_LINKINFO_TRANSCEIVER]        = { .type = NLA_REJECT },
     107                 :            : };
     108                 :            : 
     109                 :          0 : int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info)
     110                 :            : {
     111                 :          0 :         struct nlattr *tb[ETHTOOL_A_LINKINFO_MAX + 1];
     112                 :          0 :         struct ethtool_link_ksettings ksettings = {};
     113                 :          0 :         struct ethtool_link_settings *lsettings;
     114                 :          0 :         struct ethnl_req_info req_info = {};
     115                 :          0 :         struct net_device *dev;
     116                 :          0 :         bool mod = false;
     117                 :          0 :         int ret;
     118                 :            : 
     119                 :          0 :         ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
     120                 :            :                           ETHTOOL_A_LINKINFO_MAX, linkinfo_set_policy,
     121                 :            :                           info->extack);
     122         [ #  # ]:          0 :         if (ret < 0)
     123                 :            :                 return ret;
     124                 :          0 :         ret = ethnl_parse_header(&req_info, tb[ETHTOOL_A_LINKINFO_HEADER],
     125                 :            :                                  genl_info_net(info), info->extack, true);
     126         [ #  # ]:          0 :         if (ret < 0)
     127                 :            :                 return ret;
     128                 :          0 :         dev = req_info.dev;
     129                 :          0 :         ret = -EOPNOTSUPP;
     130         [ #  # ]:          0 :         if (!dev->ethtool_ops->get_link_ksettings ||
     131         [ #  # ]:          0 :             !dev->ethtool_ops->set_link_ksettings)
     132                 :          0 :                 goto out_dev;
     133                 :            : 
     134                 :          0 :         rtnl_lock();
     135         [ #  # ]:          0 :         ret = ethnl_ops_begin(dev);
     136         [ #  # ]:          0 :         if (ret < 0)
     137                 :          0 :                 goto out_rtnl;
     138                 :            : 
     139                 :          0 :         ret = __ethtool_get_link_ksettings(dev, &ksettings);
     140         [ #  # ]:          0 :         if (ret < 0) {
     141         [ #  # ]:          0 :                 if (info)
     142         [ #  # ]:          0 :                         GENL_SET_ERR_MSG(info, "failed to retrieve link settings");
     143                 :          0 :                 goto out_ops;
     144                 :            :         }
     145                 :          0 :         lsettings = &ksettings.base;
     146                 :            : 
     147         [ #  # ]:          0 :         ethnl_update_u8(&lsettings->port, tb[ETHTOOL_A_LINKINFO_PORT], &mod);
     148         [ #  # ]:          0 :         ethnl_update_u8(&lsettings->phy_address, tb[ETHTOOL_A_LINKINFO_PHYADDR],
     149                 :            :                         &mod);
     150                 :          0 :         ethnl_update_u8(&lsettings->eth_tp_mdix_ctrl,
     151         [ #  # ]:          0 :                         tb[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL], &mod);
     152                 :          0 :         ret = 0;
     153         [ #  # ]:          0 :         if (!mod)
     154                 :          0 :                 goto out_ops;
     155                 :            : 
     156                 :          0 :         ret = dev->ethtool_ops->set_link_ksettings(dev, &ksettings);
     157         [ #  # ]:          0 :         if (ret < 0)
     158         [ #  # ]:          0 :                 GENL_SET_ERR_MSG(info, "link settings update failed");
     159                 :            :         else
     160                 :          0 :                 ethtool_notify(dev, ETHTOOL_MSG_LINKINFO_NTF, NULL);
     161                 :            : 
     162                 :          0 : out_ops:
     163         [ #  # ]:          0 :         ethnl_ops_complete(dev);
     164                 :          0 : out_rtnl:
     165                 :          0 :         rtnl_unlock();
     166                 :          0 : out_dev:
     167                 :          0 :         dev_put(dev);
     168                 :          0 :         return ret;
     169                 :            : }

Generated by: LCOV version 1.14